Branch data Line data Source code
1 : : /******************************************************************************
2 : : ------------- Copyright (c) 2009-2023 H a r a l d A c h i t z ---------------
3 : : ---------- < h a r a l d dot a c h i t z at g m a i l dot c o m > ------------
4 : : ---- This Source Code Form is subject to the terms of the Mozilla Public -----
5 : : ---- License, v. 2.0. If a copy of the MPL was not distributed with this -----
6 : : ---------- file, You can obtain one at http://mozilla.org/MPL/2.0/. ----------
7 : : ******************************************************************************/
8 : :
9 : : #include <sl3/columns.hpp>
10 : : #include <sl3/error.hpp>
11 : :
12 : : #include <cassert>
13 : : #include <sqlite3.h>
14 : :
15 : : #include "utils.hpp"
16 : :
17 : : namespace sl3
18 : : {
19 : 110 : Columns::Columns (sqlite3_stmt* stmt)
20 : 110 : : _stmt (stmt)
21 : : {
22 : 110 : }
23 : :
24 : : int
25 : 1117 : Columns::count () const
26 : : {
27 : 1117 : return sqlite3_column_count (_stmt);
28 : : }
29 : :
30 : : std::string
31 : 130 : Columns::getName (int idx) const
32 : : {
33 : 130 : if (idx < 0 || !(idx < count ()))
34 : 3 : throw ErrOutOfRange ("column index out of range");
35 : :
36 : 127 : const char* name = sqlite3_column_name (_stmt, idx);
37 : 381 : return name ? std::string (name) : std::string ();
38 : : }
39 : :
40 : : DbValue
41 : 25 : Columns::getValue (int idx) const
42 : : {
43 : 25 : return getValue (idx, Type::Variant);
44 : : }
45 : :
46 : : DbValue
47 : 204 : Columns::getValue (int idx, Type type) const
48 : : {
49 : 204 : if (idx < 0 || !(idx < count ()))
50 : 6 : throw ErrOutOfRange ("column index out of range");
51 : :
52 : 198 : switch (sqlite3_column_type (_stmt, idx))
53 : : {
54 : 66 : case SQLITE_INTEGER:
55 : 66 : return DbValue (getInt64 (idx), type);
56 : : break;
57 : :
58 : 36 : case SQLITE_FLOAT:
59 : 36 : return DbValue (getReal (idx), type);
60 : : break;
61 : :
62 : 72 : case SQLITE_TEXT:
63 : 74 : return DbValue (getText (idx), type);
64 : : break;
65 : :
66 : 8 : case SQLITE_BLOB:
67 : 9 : return DbValue (getBlob (idx), type);
68 : : break;
69 : :
70 : : // return this one at the end
71 : : // some compiler detect unreachable code and warn
72 : 16 : case SQLITE_NULL:
73 : : // return DbValue (type);
74 : 16 : break;
75 : :
76 : : default: // LCOV_EXCL_START
77 : : throw ErrUnexpected ("should never reach this line");
78 : : break; // LCOV_EXCL_STOP
79 : : }
80 : : // some complains non reachable code.
81 : : // therefore, handle the Null value here
82 : 16 : return DbValue (type);
83 : : }
84 : :
85 : : std::vector<std::string>
86 : 43 : Columns::getNames () const
87 : : {
88 : 43 : std::vector<std::string> names;
89 : 43 : names.reserve (as_size_t (count ()));
90 : 163 : for (int i = 0; i < count (); ++i)
91 : : {
92 : 120 : names.emplace_back (getName (i));
93 : : }
94 : :
95 : 43 : return names;
96 : 0 : }
97 : :
98 : : DbValues
99 : 1 : Columns::getRow () const
100 : : {
101 : 1 : DbValues::container_type v;
102 : 6 : for (int i = 0; i < count (); ++i)
103 : : {
104 : 5 : v.push_back (getValue (i));
105 : : }
106 : 2 : return DbValues (std::move (v));
107 : 1 : }
108 : :
109 : : DbValues
110 : 60 : Columns::getRow (const Types& types) const
111 : : {
112 : 60 : if (types.size () != static_cast<size_t> (count ()))
113 : : {
114 : 2 : throw ErrTypeMisMatch ("types.size () != getColumnCount ()");
115 : : }
116 : :
117 : 58 : DbValues::container_type v;
118 : 217 : for (int i = 0; i < count (); ++i)
119 : : {
120 : 161 : v.push_back (getValue (i, types[as_size_t (i)]));
121 : : }
122 : 112 : return DbValues (std::move (v));
123 : 58 : }
124 : :
125 : : Type
126 : 24 : Columns::getType (int idx) const
127 : : {
128 : 24 : if (idx < 0 || !(idx < count ()))
129 : 3 : throw ErrOutOfRange ("column index out of range");
130 : :
131 : 21 : auto type = Type::Variant;
132 : :
133 : 21 : switch (sqlite3_column_type (_stmt, idx))
134 : : {
135 : 6 : case SQLITE_INTEGER:
136 : 6 : type = Type::Int;
137 : 6 : break;
138 : :
139 : 2 : case SQLITE_FLOAT:
140 : 2 : type = Type::Real;
141 : 2 : break;
142 : :
143 : 7 : case SQLITE_TEXT:
144 : 7 : type = Type::Text;
145 : 7 : break;
146 : :
147 : 3 : case SQLITE_BLOB:
148 : 3 : type = Type::Blob;
149 : 3 : break;
150 : :
151 : 3 : case SQLITE_NULL:
152 : 3 : type = Type::Null;
153 : 3 : break;
154 : :
155 : : default: // LCOV_EXCL_LINE
156 : : throw ErrUnexpected ("never reach"); // LCOV_EXCL_LINE
157 : : break; // LCOV_EXCL_LINE
158 : : }
159 : :
160 : 21 : return type;
161 : : }
162 : :
163 : : size_t
164 : 7 : Columns::getSize (int idx) const
165 : : {
166 : 7 : if (idx < 0 || !(idx < count ()))
167 : 2 : throw ErrOutOfRange ("column index out of range");
168 : :
169 : 5 : return as_size_t (sqlite3_column_bytes (_stmt, idx));
170 : : }
171 : :
172 : : std::string
173 : 80 : Columns::getText (int idx) const
174 : : {
175 : 80 : if (idx < 0 || !(idx < count ()))
176 : 2 : throw ErrOutOfRange ("column index out of range");
177 : :
178 : : const char* first
179 : 78 : = reinterpret_cast<const char*> (sqlite3_column_text (_stmt, idx));
180 : 78 : std::size_t s = as_size_t (sqlite3_column_bytes (_stmt, idx));
181 : 230 : return s > 0 ? std::string (first, s) : std::string ();
182 : : }
183 : :
184 : : int
185 : 8 : Columns::getInt (int idx) const
186 : : {
187 : 8 : if (idx < 0 || !(idx < count ()))
188 : 2 : throw ErrOutOfRange ("column index out of range");
189 : :
190 : 6 : return sqlite3_column_int (_stmt, idx);
191 : : }
192 : :
193 : : int64_t
194 : 69 : Columns::getInt64 (int idx) const
195 : : {
196 : 69 : if (idx < 0 || !(idx < count ()))
197 : 2 : throw ErrOutOfRange ("column index out of range");
198 : :
199 : 67 : return sqlite3_column_int64 (_stmt, idx);
200 : : }
201 : :
202 : : double
203 : 39 : Columns::getReal (int idx) const
204 : : {
205 : 39 : if (idx < 0 || !(idx < count ()))
206 : 2 : throw ErrOutOfRange ("column index out of range");
207 : :
208 : 37 : return sqlite3_column_double (_stmt, idx);
209 : : }
210 : :
211 : : Blob
212 : 12 : Columns::getBlob (int idx) const
213 : : {
214 : 12 : if (idx < 0 || !(idx < count ()))
215 : 2 : throw ErrOutOfRange ("column index out of range");
216 : :
217 : : using value_type = Blob::value_type;
218 : : const value_type* first
219 : 10 : = static_cast<const value_type*> (sqlite3_column_blob (_stmt, idx));
220 : 10 : std::size_t s = as_size_t (sqlite3_column_bytes (_stmt, idx));
221 : 26 : return s > 0 ? Blob (first, first + s) : Blob ();
222 : : }
223 : :
224 : : } // ns
|