src/evsql/query.c
branchnew-evsql
changeset 45 424ce5ab82fd
parent 44 9e76ee9729b6
child 48 8b019d191353
equal deleted inserted replaced
44:9e76ee9729b6 45:424ce5ab82fd
     1 
     1 
     2 #include "evsql.h"
     2 #include "evsql.h"
       
     3 #include "../lib/error.h"
       
     4 #include "../lib/misc.h"
       
     5 
       
     6 #include <stdlib.h>
       
     7 #include <assert.h>
     3 
     8 
     4 /*
     9 /*
     5  * Initialize params->types/values/lengths/formats, params->count, params->result_format based on the given args
    10  * Initialize params->types/values/lengths/formats, params->count, params->result_format based on the given args
     6  */
    11  */
     7 static int _evsql_query_params_init_pq (struct evsql_query_params_pq *params, size_t param_count, enum evsql_item_format result_format) {
    12 static int _evsql_query_params_init_pq (struct evsql_query_params_pq *params, size_t param_count, enum evsql_item_format result_format) {
     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