9 params->count = param_count; |
14 params->count = param_count; |
10 |
15 |
11 // allocate vertical storage for the parameters |
16 // allocate vertical storage for the parameters |
12 if (0 |
17 if (0 |
13 |
18 |
14 || !(query->params.types = calloc(query->params.count, sizeof(Oid))) |
19 || !(params->types = calloc(param_count, sizeof(Oid))) |
15 || !(query->params.values = calloc(query->params.count, sizeof(char *))) |
20 || !(params->values = calloc(param_count, sizeof(char *))) |
16 || !(query->params.lengths = calloc(query->params.count, sizeof(int))) |
21 || !(params->lengths = calloc(param_count, sizeof(int))) |
17 || !(query->params.formats = calloc(query->params.count, sizeof(int))) |
22 || !(params->formats = calloc(param_count, sizeof(int))) |
|
23 || !(params->item_vals = calloc(param_count, sizeof(union evsql_item_value))) |
18 ) |
24 ) |
19 ERROR("calloc"); |
25 ERROR("calloc"); |
20 |
26 |
21 // result format |
27 // result format |
22 switch (result_format) { |
28 switch (result_format) { |
23 case EVSQL_FMT_TEXT: |
29 case EVSQL_FMT_TEXT: |
24 params.result_format = 0; break; |
30 params->result_format = 0; break; |
25 |
31 |
26 case EVSQL_FMT_BINARY: |
32 case EVSQL_FMT_BINARY: |
27 params.result_format = 1; break; |
33 params->result_format = 1; break; |
28 |
34 |
29 default: |
35 default: |
30 FATAL("params.result_fmt: %d", result_format); |
36 FATAL("params.result_fmt: %d", result_format); |
31 } |
37 } |
32 |
38 |
72 // count the params |
78 // count the params |
73 for (param = params->list; param->info.type; param++) |
79 for (param = params->list; param->info.type; param++) |
74 count++; |
80 count++; |
75 |
81 |
76 // initialize params |
82 // initialize params |
77 evsql_query_params_init_pq(&query->params, count, params->result_format); |
83 _evsql_query_params_init_pq(&query->params, count, params->result_format); |
78 |
84 |
79 // transform |
85 // transform |
80 for (param = params->list, idx = 0; param->info.type; param++, idx++) { |
86 for (param = params->list, idx = 0; param->info.type; param++, idx++) { |
81 // `set for NULLs, otherwise not |
87 // `set for NULLs, otherwise not |
82 query->params.types[idx] = param->bytes ? 0 : EVSQL_PQ_ARBITRARY_TYPE_OID; |
88 query->params.types[idx] = param->bytes ? 0 : EVSQL_PQ_ARBITRARY_TYPE_OID; |
|
89 |
|
90 // scalar values |
|
91 query->params.item_vals[idx] = param->value; |
83 |
92 |
84 // values |
93 // values |
85 query->params.values[idx] = param->bytes; |
94 // point this at the value stored in the item_vals union if flagged as such |
|
95 query->params.values[idx] = param->flags.has_value ? (const char *) &query->params.item_vals[idx] : param->bytes; |
86 |
96 |
87 // lengths |
97 // lengths |
88 query->params.lengths[idx] = param->length; |
98 query->params.lengths[idx] = param->length; |
89 |
99 |
90 // formats, binary if length is nonzero, but text for NULLs |
100 // formats, binary if length is nonzero, but text for NULLs |
131 // count the params |
141 // count the params |
132 for (param = query_info->params; param->type; param++) |
142 for (param = query_info->params; param->type; param++) |
133 count++; |
143 count++; |
134 |
144 |
135 // initialize params |
145 // initialize params |
136 evsql_query_params_init_pq(&query->params, count, EVSQL_FMT_BINARY); |
146 _evsql_query_params_init_pq(&query->params, count, EVSQL_FMT_BINARY); |
137 |
147 |
138 // transform |
148 // transform |
139 for (param = params->params, idx = 0; param->info.type; param++, idx++) { |
149 for (param = query_info->params, idx = 0; param->type; param++, idx++) { |
140 // default type to 0 (implicit) |
150 // default type to 0 (implicit) |
141 query->params.types[idx] = 0; |
151 query->params.types[idx] = 0; |
142 |
152 |
143 // default format to binary |
153 // default format to binary |
144 query->params.formats[idx] = EVSQL_FMT_BINARY; |
154 query->params.formats[idx] = EVSQL_FMT_BINARY; |
145 |
155 |
146 // consume argument |
156 // consume argument |
147 switch (param->info.type) { |
157 switch (param->type) { |
148 case EVSQL_TYPE_NULL_: { |
158 case EVSQL_TYPE_NULL_: { |
149 // explicit type + text fmt |
159 // explicit type + text fmt |
150 query->params.types[idx] = EVSQL_PQ_ARBITRARY_TYPE_OID; |
160 query->params.types[idx] = EVSQL_PQ_ARBITRARY_TYPE_OID; |
151 query->params.values[idx] = NULL; |
161 query->params.values[idx] = NULL; |
152 query->params.lengths[idx] = 0; |
162 query->params.lengths[idx] = 0; |
155 |
165 |
156 case EVSQL_TYPE_BINARY: { |
166 case EVSQL_TYPE_BINARY: { |
157 struct evsql_item_binary item = va_arg(vargs, struct evsql_item_binary); |
167 struct evsql_item_binary item = va_arg(vargs, struct evsql_item_binary); |
158 |
168 |
159 // value + explicit len |
169 // value + explicit len |
160 query->params.values[idx] = item->ptr; |
170 query->params.values[idx] = item.ptr; |
161 query->params.lengths[idx] = item->len; |
171 query->params.lengths[idx] = item.len; |
162 } break; |
172 } break; |
163 |
173 |
164 case EVSQL_TYPE_STRING: { |
174 case EVSQL_TYPE_STRING: { |
165 const char *str = va_arg(vargs, const char *); |
175 const char *str = va_arg(vargs, const char *); |
166 |
176 |
169 query->params.lengths[idx] = 0; |
179 query->params.lengths[idx] = 0; |
170 query->params.formats[idx] = EVSQL_FMT_TEXT; |
180 query->params.formats[idx] = EVSQL_FMT_TEXT; |
171 } break; |
181 } break; |
172 |
182 |
173 case EVSQL_TYPE_UINT16: { |
183 case EVSQL_TYPE_UINT16: { |
174 uint16_t uval = va_arg(vargs, uint16_t); |
184 // XXX: uint16_t is passed as `int'? |
|
185 uint16_t uval = va_arg(vargs, int); |
175 |
186 |
176 if (uval != (int16_t) uval) |
187 if (uval != (int16_t) uval) |
177 ERROR("param $%zu: uint16 overflow: %d", idx + 1, uval); |
188 ERROR("param $%zu: uint16 overflow: %d", idx + 1, uval); |
178 |
189 |
179 // network-byte-order value + explicit len |
190 // network-byte-order value + explicit len |
180 query->params.values[idx] = htons(uval); |
191 query->params.item_vals[idx].uint16 = htons(uval); |
|
192 query->params.values[idx] = (const char *) &query->params.item_vals[idx]; |
181 query->params.lengths[idx] = sizeof(uint16_t); |
193 query->params.lengths[idx] = sizeof(uint16_t); |
182 } break; |
194 } break; |
183 |
195 |
184 case EVSQL_TYPE_UINT32: { |
196 case EVSQL_TYPE_UINT32: { |
185 uint32_t uval = va_arg(vargs, uint32_t); |
197 uint32_t uval = va_arg(vargs, uint32_t); |
186 |
198 |
187 if (uval != (int32_t) uval) |
199 if (uval != (int32_t) uval) |
188 ERROR("param $%zu: uint32 overflow: %ld", idx + 1, uval); |
200 ERROR("param $%zu: uint32 overflow: %ld", idx + 1, (unsigned long) uval); |
189 |
201 |
190 // network-byte-order value + explicit len |
202 // network-byte-order value + explicit len |
191 query->params.values[idx] = htonl(uval); |
203 query->params.item_vals[idx].uint32 = htonl(uval); |
|
204 query->params.values[idx] = (const char *) &query->params.item_vals[idx]; |
192 query->params.lengths[idx] = sizeof(uint32_t); |
205 query->params.lengths[idx] = sizeof(uint32_t); |
193 } break; |
206 } break; |
194 |
207 |
195 case EVSQL_TYPE_UINT64: { |
208 case EVSQL_TYPE_UINT64: { |
196 uint64_t uval = va_arg(vargs, uint64_t); |
209 uint64_t uval = va_arg(vargs, uint64_t); |
197 |
210 |
198 if (uval != (int64_t) uval) |
211 if (uval != (int64_t) uval) |
199 ERROR("param $%zu: uint16 overflow: %lld", idx + 1, uval); |
212 ERROR("param $%zu: uint16 overflow: %lld", idx + 1, (unsigned long long) uval); |
200 |
213 |
201 // network-byte-order value + explicit len |
214 // network-byte-order value + explicit len |
202 query->params.values[idx] = htonq(uval); |
215 query->params.item_vals[idx].uint64 = htonq(uval); |
|
216 query->params.values[idx] = (const char *) &query->params.item_vals[idx]; |
203 query->params.lengths[idx] = sizeof(uint64_t); |
217 query->params.lengths[idx] = sizeof(uint64_t); |
204 } break; |
218 } break; |
205 |
219 |
206 default: |
220 default: |
207 FATAL("param $%zu: invalid type: %d", idx + 1, param->info.type); |
221 FATAL("param $%zu: invalid type: %d", idx + 1, param->type); |
208 } |
222 } |
209 } |
223 } |
210 |
224 |
211 // execute it |
225 // execute it |
212 if (_evsql_query_enqueue(evsql, trans, query, command)) |
226 if (_evsql_query_enqueue(evsql, trans, query, query_info->sql)) |
213 goto error; |
227 goto error; |
214 |
228 |
215 // no error, fallthrough for va_end |
229 // no error, fallthrough for va_end |
216 err = 0; |
230 err = 0; |
217 |
231 |