src/util.c
changeset 56 9dfc861273e5
parent 38 1fd4da071575
child 58 02e539965ef4
equal deleted inserted replaced
42:40a3b13ffc9d 56:9dfc861273e5
       
     1 #include <stdlib.h>
       
     2 #include <assert.h>
       
     3 
       
     4 #include "internal.h"
       
     5 #include "lib/log.h"
       
     6 #include "lib/misc.h"
       
     7 
       
     8 #define _PARAM_TYPE_CASE(typenam) case EVSQL_PARAM_ ## typenam: return #typenam
       
     9 
       
    10 #define _PARAM_VAL_BUF_MAX 120
       
    11 #define _PARAM_VAL_CASE(typenam, ...) case EVSQL_PARAM_ ## typenam: if (param->data_raw) ret = snprintf(buf, _PARAM_VAL_BUF_MAX, __VA_ARGS__); else return "(null)"; break
       
    12 
       
    13 const char *evsql_param_type (const struct evsql_query_param *param) {
       
    14     switch (param->type) {
       
    15         _PARAM_TYPE_CASE (INVALID   );
       
    16         _PARAM_TYPE_CASE (NULL_     );
       
    17         _PARAM_TYPE_CASE (BINARY    );
       
    18         _PARAM_TYPE_CASE (STRING    );
       
    19         _PARAM_TYPE_CASE (UINT16    );
       
    20         _PARAM_TYPE_CASE (UINT32    );
       
    21         _PARAM_TYPE_CASE (UINT64    );
       
    22         default: return "???";
       
    23     }
       
    24 }
       
    25 
       
    26 
       
    27 static const char *evsql_param_val (const struct evsql_query_param *param) {
       
    28     static char buf[_PARAM_VAL_BUF_MAX];
       
    29     int ret;
       
    30 
       
    31     switch (param->type) {
       
    32         _PARAM_VAL_CASE (INVALID,   "???"                               );
       
    33         _PARAM_VAL_CASE (NULL_,     "(null)"                            );
       
    34         _PARAM_VAL_CASE (BINARY,    "%zu:%s",   param->length, "..."    );
       
    35         _PARAM_VAL_CASE (STRING,    "%s",       param->data_raw         );
       
    36         _PARAM_VAL_CASE (UINT16,    "%hu",      (unsigned short int)     ntohs(param->data.uint16)  );
       
    37         _PARAM_VAL_CASE (UINT32,    "%lu",      (unsigned long int)      ntohl(param->data.uint32)  );
       
    38         _PARAM_VAL_CASE (UINT64,    "%llu",     (unsigned long long int) ntohq(param->data.uint64)  );
       
    39         default: return "???";
       
    40     }
       
    41 
       
    42     return buf;
       
    43 }
       
    44 
       
    45 int evsql_params_clear (struct evsql_query_params *params) {
       
    46     struct evsql_query_param *param;
       
    47 
       
    48     for (param = params->list; param->type; param++) 
       
    49         param->data_raw = NULL;
       
    50 
       
    51     return 0;
       
    52 }
       
    53 
       
    54 int evsql_param_null   (struct evsql_query_params *params, size_t param) {
       
    55     struct evsql_query_param *p = &params->list[param];
       
    56 
       
    57     p->data_raw = NULL;
       
    58 
       
    59     return 0;
       
    60 }
       
    61 
       
    62 int evsql_param_binary (struct evsql_query_params *params, size_t param, const char *ptr, size_t len) {
       
    63     struct evsql_query_param *p = &params->list[param];
       
    64     
       
    65     assert(p->type == EVSQL_PARAM_BINARY);
       
    66 
       
    67     p->data_raw = ptr;
       
    68     p->length = len;
       
    69 
       
    70     return 0;
       
    71 }
       
    72 
       
    73 int evsql_param_string (struct evsql_query_params *params, size_t param, const char *ptr) {
       
    74     struct evsql_query_param *p = &params->list[param];
       
    75     
       
    76     assert(p->type == EVSQL_PARAM_STRING);
       
    77 
       
    78     p->data_raw = ptr;
       
    79     p->length = 0;
       
    80 
       
    81     return 0;
       
    82 }
       
    83 
       
    84 int evsql_param_uint16 (struct evsql_query_params *params, size_t param, uint16_t uval) {
       
    85     struct evsql_query_param *p = &params->list[param];
       
    86     
       
    87     assert(p->type == EVSQL_PARAM_UINT16);
       
    88 
       
    89     p->data.uint16 = htons(uval);
       
    90     p->data_raw = (const char *) &p->data.uint16;
       
    91     p->length = sizeof(uval);
       
    92 
       
    93     return 0;
       
    94 }
       
    95 
       
    96 int evsql_param_uint32 (struct evsql_query_params *params, size_t param, uint32_t uval) {
       
    97     struct evsql_query_param *p = &params->list[param];
       
    98     
       
    99     assert(p->type == EVSQL_PARAM_UINT32);
       
   100 
       
   101     p->data.uint32 = htonl(uval);
       
   102     p->data_raw = (const char *) &p->data.uint32;
       
   103     p->length = sizeof(uval);
       
   104 
       
   105     return 0;
       
   106 }
       
   107 
       
   108 void evsql_query_debug (const char *sql, const struct evsql_query_params *params) {
       
   109     const struct evsql_query_param *param;
       
   110     size_t param_count = 0, idx = 0;
       
   111 
       
   112     // count the params
       
   113     for (param = params->list; param->type; param++) 
       
   114         param_count++;
       
   115     
       
   116     DEBUG("sql:     %s", sql);
       
   117     DEBUG("params:  %zu", param_count);
       
   118 
       
   119     for (param = params->list; param->type; param++) {
       
   120         DEBUG("\t%2zu : %8s = %s", ++idx, evsql_param_type(param), evsql_param_val(param));
       
   121     }
       
   122 }
       
   123 
       
   124 const char *evsql_result_error (const struct evsql_result_info *res) {
       
   125     if (!res->error)
       
   126         return "No error";
       
   127 
       
   128     switch (res->evsql->type) {
       
   129         case EVSQL_EVPQ:
       
   130             if (!res->result.pq)
       
   131                 return "unknown error (no result)";
       
   132             
       
   133             return PQresultErrorMessage(res->result.pq);
       
   134 
       
   135         default:
       
   136             FATAL("res->evsql->type");
       
   137     }
       
   138 
       
   139 }
       
   140 
       
   141 size_t evsql_result_rows (const struct evsql_result_info *res) {
       
   142     switch (res->evsql->type) {
       
   143         case EVSQL_EVPQ:
       
   144             return PQntuples(res->result.pq);
       
   145 
       
   146         default:
       
   147             FATAL("res->evsql->type");
       
   148     }
       
   149 }
       
   150 
       
   151 size_t evsql_result_cols (const struct evsql_result_info *res) {
       
   152     switch (res->evsql->type) {
       
   153         case EVSQL_EVPQ:
       
   154             return PQnfields(res->result.pq);
       
   155 
       
   156         default:
       
   157             FATAL("res->evsql->type");
       
   158     }
       
   159 }
       
   160 
       
   161 size_t evsql_result_affected (const struct evsql_result_info *res) {
       
   162     switch (res->evsql->type) {
       
   163         case EVSQL_EVPQ:
       
   164             return strtol(PQcmdTuples(res->result.pq), NULL, 10);
       
   165 
       
   166         default:
       
   167             FATAL("res->evsql->type");
       
   168     }
       
   169 }
       
   170 
       
   171 int evsql_result_binary (const struct evsql_result_info *res, size_t row, size_t col, const char **ptr, size_t *size, int nullok) {
       
   172     *ptr = NULL;
       
   173 
       
   174     switch (res->evsql->type) {
       
   175         case EVSQL_EVPQ:
       
   176             if (PQgetisnull(res->result.pq, row, col)) {
       
   177                 if (nullok)
       
   178                     return 0;
       
   179                 else
       
   180                     ERROR("[%zu:%zu] field is null", row, col);
       
   181             }
       
   182 
       
   183             if (PQfformat(res->result.pq, col) != 1)
       
   184                 ERROR("[%zu:%zu] PQfformat is not binary: %d", row, col, PQfformat(res->result.pq, col));
       
   185     
       
   186             *size = PQgetlength(res->result.pq, row, col);
       
   187             *ptr  = PQgetvalue(res->result.pq, row, col);
       
   188 
       
   189             return 0;
       
   190 
       
   191         default:
       
   192             FATAL("res->evsql->type");
       
   193     }
       
   194 
       
   195 error:
       
   196     return -1;
       
   197 }
       
   198 
       
   199 int evsql_result_binlen (const struct evsql_result_info *res, size_t row, size_t col, const char **ptr, size_t size, int nullok) {
       
   200     size_t real_size = 0;
       
   201 
       
   202     if (evsql_result_binary(res, row, col, ptr, &real_size, nullok))
       
   203         goto error;
       
   204     
       
   205     if (*ptr == NULL) {
       
   206         assert(nullok);
       
   207         return 0;
       
   208     }
       
   209 
       
   210     if (size && real_size != size)
       
   211         ERROR("[%zu:%zu] field size mismatch: %zu -> %zu", row, col, size, real_size);
       
   212      
       
   213     return 0;
       
   214 
       
   215 error:
       
   216     return -1;
       
   217 }
       
   218 
       
   219 int evsql_result_string (const struct evsql_result_info *res, size_t row, size_t col, const char **ptr, int nullok) {
       
   220     size_t real_size;
       
   221 
       
   222     if (evsql_result_binary(res, row, col, ptr, &real_size, nullok))
       
   223         goto error;
       
   224 
       
   225     assert(real_size == strlen(*ptr));
       
   226     
       
   227     return 0;
       
   228 
       
   229 error:
       
   230     return -1;
       
   231 }
       
   232 
       
   233 int evsql_result_uint16 (const struct evsql_result_info *res, size_t row, size_t col, uint16_t *uval, int nullok) {
       
   234     const char *data;
       
   235     int16_t sval;
       
   236 
       
   237     if (evsql_result_binlen(res, row, col, &data, sizeof(*uval), nullok))
       
   238         goto error;
       
   239     
       
   240     if (!data)
       
   241         return 0;
       
   242 
       
   243     sval = ntohs(*((int16_t *) data));
       
   244 
       
   245     if (sval < 0)
       
   246         ERROR("negative value for unsigned: %d", sval);
       
   247 
       
   248     *uval = sval;
       
   249     
       
   250     return 0;
       
   251 
       
   252 error:
       
   253     return nullok ? 0 : -1;
       
   254 }
       
   255 
       
   256 int evsql_result_uint32 (const struct evsql_result_info *res, size_t row, size_t col, uint32_t *uval, int nullok) {
       
   257     const char *data;
       
   258     int32_t sval;
       
   259 
       
   260     if (evsql_result_binlen(res, row, col, &data, sizeof(*uval), nullok))
       
   261         goto error;
       
   262     
       
   263     if (!data)
       
   264         return 0;
       
   265 
       
   266     sval = ntohl(*(int32_t *) data);
       
   267 
       
   268     if (sval < 0)
       
   269         ERROR("negative value for unsigned: %d", sval);
       
   270 
       
   271     *uval = sval;
       
   272     
       
   273     return 0;
       
   274 
       
   275 error:
       
   276     return nullok ? 0 : -1;
       
   277 }
       
   278 
       
   279 int evsql_result_uint64 (const struct evsql_result_info *res, size_t row, size_t col, uint64_t *uval, int nullok) {
       
   280     const char *data;
       
   281     int64_t sval;
       
   282 
       
   283     if (evsql_result_binlen(res, row, col, &data, sizeof(*uval), nullok))
       
   284         goto error;
       
   285     
       
   286     if (!data)
       
   287         return 0;
       
   288 
       
   289     sval = ntohq(*(int64_t *) data);
       
   290 
       
   291     if (sval < 0)
       
   292         ERROR("negative value for unsigned: %ld", sval);
       
   293 
       
   294     *uval = sval;
       
   295     
       
   296     return 0;
       
   297 
       
   298 error:
       
   299     return nullok ? 0 : -1;
       
   300 }
       
   301 
       
   302 void evsql_result_free (const struct evsql_result_info *res) {
       
   303     switch (res->evsql->type) {
       
   304         case EVSQL_EVPQ:
       
   305             return PQclear(res->result.pq);
       
   306 
       
   307         default:
       
   308             FATAL("res->evsql->type");
       
   309     }
       
   310 }
       
   311 
       
   312 const char *evsql_conn_error (struct evsql_conn *conn) {
       
   313     switch (conn->evsql->type) {
       
   314         case EVSQL_EVPQ:
       
   315             if (!conn->engine.evpq)
       
   316                 return "unknown error (no conn)";
       
   317             
       
   318             return evpq_error_message(conn->engine.evpq);
       
   319 
       
   320         default:
       
   321             FATAL("res->evsql->type");
       
   322     }
       
   323 }
       
   324 
       
   325 const char *evsql_trans_error (struct evsql_trans *trans) {
       
   326     if (trans->conn == NULL)
       
   327         return "unknown error (no trans conn)";
       
   328 
       
   329     return evsql_conn_error(trans->conn);
       
   330 }
       
   331