From 53fb42ad1ca108bfd579bf9846c73255cb33766c Mon Sep 17 00:00:00 2001 From: lazedo Date: Mon, 25 Jan 2016 10:46:05 +0000 Subject: [PATCH] db_text: implemented raw query for UPDATE/DELETE/REPLACE also fixes db_free_result for non select operations also improves replace by exiting on first match --- modules/db_text/dbt_base.c | 5 +- modules/db_text/dbt_raw_query.c | 326 ++++++++++++++++++++++++++++++-- modules/db_text/dbt_raw_query.h | 3 + modules/db_text/dbt_raw_util.c | 48 +++-- 4 files changed, 347 insertions(+), 35 deletions(-) diff --git a/modules/db_text/dbt_base.c b/modules/db_text/dbt_base.c index 4ab9a1652c0..54a2f38842a 100644 --- a/modules/db_text/dbt_base.c +++ b/modules/db_text/dbt_base.c @@ -122,12 +122,14 @@ void dbt_close(db1_con_t* _h) */ int dbt_free_result(db1_con_t* _h, db1_res_t* _r) { - if ((!_h) || (!_r)) + if ((!_h)) { LM_ERR("invalid parameter value\n"); return -1; } + if (!_r) + return 0; if(dbt_result_free((dbt_result_p)_r->ptr) < 0) { @@ -673,6 +675,7 @@ int dbt_replace(db1_con_t* _h, db_key_t* _k, db_val_t* _v, } ((dbt_con_p)_h->tail)->affected++; + break; } _drp = _drp->next; diff --git a/modules/db_text/dbt_raw_query.c b/modules/db_text/dbt_raw_query.c index ef625036364..f54065e0a55 100644 --- a/modules/db_text/dbt_raw_query.c +++ b/modules/db_text/dbt_raw_query.c @@ -167,29 +167,315 @@ int dbt_raw_query_select(db1_con_t* _h, str* _s, db1_res_t** _r) int dbt_raw_query_update(db1_con_t* _h, str* _s, db1_res_t** _r) { - int res = -1; + int res = -1; + int len; + char* table_ptr = NULL; + char* fields_end_ptr = NULL; + char* fields_start_ptr = NULL; + char* fields_ptr = NULL; + char* where_ptr = NULL; + char* table_start_ptr = NULL; + str table; + dbt_table_p _tbc = NULL; + int ncols = 0; + int nkeys = 0; + db_key_t* _k = NULL; + db_op_t* _op1 = NULL; + db_val_t* _kv = NULL; + db_key_t* _c = NULL; + db_op_t* _op2 = NULL; + db_val_t* _cv = NULL; + LM_DBG("SQLRAW : %.*s\n", _s->len, _s->s); + + table_start_ptr = _s->s + 6; + fields_start_ptr = strcasestr(_s->s, " set "); + if(fields_start_ptr == NULL) + return res; + + len = fields_start_ptr - table_start_ptr; + table_ptr = pkg_malloc(len); + strncpy(table_ptr, table_start_ptr, len); + table_ptr[len] = '\0'; + dbt_trim(table_ptr); + table.s = table_ptr; + table.len = len; + + where_ptr = strcasestr(_s->s, " where "); + fields_end_ptr = where_ptr; + len = fields_end_ptr - ( fields_start_ptr + 4) + 1; + fields_ptr = pkg_malloc(len); + strncpy(fields_ptr, fields_start_ptr + 4, len); + fields_ptr[len] = '\0'; + fields_ptr = dbt_trim(fields_ptr); + + ncols = dbt_build_where(fields_ptr, &_c, &_op2, &_cv); + if(ncols <0) { + LM_ERR("unexpected error buuilding fields\n"); + goto error; + } + + + if(where_ptr == NULL) { + LM_ERR("specify where clause to determine keys\n"); + goto error; + } + nkeys = dbt_build_where(where_ptr + 7, &_k, &_op1, &_kv); + if(nkeys < 1) { + LM_ERR("needsa at least one key\n"); + goto error; + } + + + LM_DBG("using table '%.*s'\n", table.len, table.s); + + if(dbt_use_table(_h, &table) != 0) { + LM_ERR("use table is invalid %.*s\n", table.len, table.s); + goto error; + } + + _tbc = dbt_db_get_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); + if(!_tbc) + { + LM_ERR("table %.*s does not exist!\n", CON_TABLE(_h)->len, CON_TABLE(_h)->s); + goto error; + } + + dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); + _tbc = NULL; + res = dbt_update(_h, _k, _op1, _kv, _c, _cv, nkeys, ncols); + +error: + + if(_tbc) + dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); + + if(fields_ptr) + pkg_free(fields_ptr); + + if(table_ptr) + pkg_free(table_ptr); + + dbt_clean_where(nkeys, _k, _op1, _kv); + dbt_clean_where(ncols, _c, _op2, _cv); + + return res; - return res; } int dbt_raw_query_delete(db1_con_t* _h, str* _s, db1_res_t** _r) { - int res = -1; + int res = -1; + int len; + char* table_ptr = NULL; + char* fields_end_ptr = NULL; + char* fields_ptr = NULL; + char* where_ptr = NULL; + str table; + dbt_table_p _tbc = NULL; + int nkeys = 0; + db_key_t* _k = NULL; + db_op_t* _op1 = NULL; + db_val_t* _kv = NULL; + LM_DBG("SQLRAW : %.*s\n", _s->len, _s->s); + fields_end_ptr = strcasestr(_s->s, " from "); + if(fields_end_ptr == NULL) + return res; - return res; + where_ptr = strcasestr(_s->s, " where "); + if(where_ptr == NULL) { + len = strlen(fields_end_ptr + 6); + } else { + len = where_ptr - (fields_end_ptr + 6); + nkeys = dbt_build_where(where_ptr + 7, &_k, &_op1, &_kv); + } + + table_ptr = pkg_malloc(len); + strncpy(table_ptr, fields_end_ptr + 6, len); + table_ptr[len] = '\0'; + dbt_trim(table_ptr); + + table.s = table_ptr; + table.len = len; + LM_DBG("using table '%.*s'\n", table.len, table.s); + + if(dbt_use_table(_h, &table) != 0) { + LM_ERR("use table is invalid %.*s\n", table.len, table.s); + goto error; + } + + _tbc = dbt_db_get_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); + if(!_tbc) + { + LM_ERR("table %.*s does not exist!\n", CON_TABLE(_h)->len, CON_TABLE(_h)->s); + goto error; + } + + dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); + _tbc = NULL; + res = dbt_delete(_h, _k, _op1, _kv, nkeys); + +error: + + if(_tbc) + dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); + + if(fields_ptr) + pkg_free(fields_ptr); + + if(table_ptr) + pkg_free(table_ptr); + + dbt_clean_where(nkeys, _k, _op1, _kv); + + return res; } +int dbt_raw_query_insert(db1_con_t* _h, str* _s, db1_res_t** _r) +{ + int res = -1; + + + + return res; +} + +int dbt_raw_query_replace(db1_con_t* _h, str* _s, db1_res_t** _r) +{ + int res = -1; + int i, len; + char* table_ptr = NULL; + char* fields_end_ptr = NULL; + char* fields_start_ptr = NULL; + char* fields_ptr = NULL; + char* where_ptr = NULL; + char* table_start_ptr = NULL; + str table; + dbt_table_p _tbc = NULL; + int cols; + int n = 0; + int ncols = 0; + int nkeys = 0; + db_key_t* _k = NULL; + db_op_t* _op1 = NULL; + db_val_t* _kv = NULL; + + db_key_t* _c = NULL; + db_op_t* _op2 = NULL; + db_val_t* _cv = NULL; + + db_key_t* _f = NULL; + db_val_t* _v = NULL; + + LM_DBG("SQLRAW : %.*s\n", _s->len, _s->s); + + table_start_ptr = _s->s + 7; + fields_start_ptr = strcasestr(_s->s, " set "); + if(fields_start_ptr == NULL) + return res; + + len = fields_start_ptr - table_start_ptr; + table_ptr = pkg_malloc(len); + strncpy(table_ptr, table_start_ptr, len); + table_ptr[len] = '\0'; + dbt_trim(table_ptr); + table.s = table_ptr; + table.len = len; + + where_ptr = strcasestr(_s->s, " where "); + fields_end_ptr = where_ptr; + len = fields_end_ptr - ( fields_start_ptr + 4) + 1; + fields_ptr = pkg_malloc(len); + strncpy(fields_ptr, fields_start_ptr + 4, len); + fields_ptr[len] = '\0'; + fields_ptr = dbt_trim(fields_ptr); + + ncols = dbt_build_where(fields_ptr, &_c, &_op2, &_cv); + if(ncols <0) { + LM_ERR("unexpected error buuilding fields\n"); + goto error; + } + + + if(where_ptr == NULL) { + LM_ERR("specify where clause to determine keys\n"); + goto error; + } + nkeys = dbt_build_where(where_ptr + 7, &_k, &_op1, &_kv); + if(nkeys < 1) { + LM_ERR("needsa at least one key\n"); + goto error; + } + + + LM_DBG("using table '%.*s'\n", table.len, table.s); + + if(dbt_use_table(_h, &table) != 0) { + LM_ERR("use table is invalid %.*s\n", table.len, table.s); + goto error; + } + + _tbc = dbt_db_get_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); + if(!_tbc) + { + LM_ERR("table %.*s does not exist!\n", CON_TABLE(_h)->len, CON_TABLE(_h)->s); + goto error; + } + + cols = nkeys + ncols; + _f = pkg_malloc(sizeof(db_key_t) * cols); + _v = pkg_malloc(sizeof(db_val_t) * cols); + for(n=0; n < nkeys; n++) { + _f[n] = _k[n]; + _v[n] = _kv[n]; + } + for(i=n; i < cols; i++) { + _f[i] = _c[i-n]; + _v[i] = _cv[i-n]; + } + + + dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); + _tbc = NULL; + res = dbt_replace(_h, _f, _v, cols, nkeys, 0); + +error: + + if(_tbc) + dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); + + if(fields_ptr) + pkg_free(fields_ptr); + + if(table_ptr) + pkg_free(table_ptr); + + dbt_clean_where(nkeys, _k, _op1, _kv); + dbt_clean_where(ncols, _c, _op2, _cv); + + if(_f) + pkg_free(_f); + if(_v) + pkg_free(_v); + + return res; + +} + + + + + /* * Raw SQL query -- is not the case to have this method */ int dbt_raw_query(db1_con_t* _h, str* _s, db1_res_t** _r) { *_r = NULL; - int res = -1; + int res = -1; if(!_h) { LM_ERR("invalid connection\n"); @@ -203,19 +489,23 @@ int dbt_raw_query(db1_con_t* _h, str* _s, db1_res_t** _r) if(_s->s == NULL) { LM_ERR("sql query is null\n"); - return res; + return res; } - dbt_trim(_s->s); - _s->len = strlen(_s->s); - - if(strncasecmp(_s->s, "select", 6) == 0) { - return dbt_raw_query_select(_h, _s, _r); - } else if(strncasecmp(_s->s, "update", 6) == 0) { - return dbt_raw_query_update(_h, _s, _r); - } else if(strncasecmp(_s->s, "delete", 6) == 0) { - return dbt_raw_query_delete(_h, _s, _r); - }; - - return res; + dbt_trim(_s->s); + _s->len = strlen(_s->s); + + if(strncasecmp(_s->s, "select", 6) == 0) { + return dbt_raw_query_select(_h, _s, _r); + } else if(strncasecmp(_s->s, "insert", 6) == 0) { + return dbt_raw_query_insert(_h, _s, _r); + } else if(strncasecmp(_s->s, "replace", 6) == 0) { + return dbt_raw_query_replace(_h, _s, _r); + } else if(strncasecmp(_s->s, "update", 6) == 0) { + return dbt_raw_query_update(_h, _s, _r); + } else if(strncasecmp(_s->s, "delete", 6) == 0) { + return dbt_raw_query_delete(_h, _s, _r); + }; + + return res; } diff --git a/modules/db_text/dbt_raw_query.h b/modules/db_text/dbt_raw_query.h index 68103dab996..afd4533fd3f 100644 --- a/modules/db_text/dbt_raw_query.h +++ b/modules/db_text/dbt_raw_query.h @@ -32,6 +32,9 @@ int dbt_raw_query_select(db1_con_t* _h, str* _s, db1_res_t** _r); int dbt_raw_query_update(db1_con_t* _h, str* _s, db1_res_t** _r); int dbt_raw_query_delete(db1_con_t* _h, str* _s, db1_res_t** _r); +int dbt_raw_query_insert(db1_con_t* _h, str* _s, db1_res_t** _r); +int dbt_raw_query_replace(db1_con_t* _h, str* _s, db1_res_t** _r); + #endif diff --git a/modules/db_text/dbt_raw_util.c b/modules/db_text/dbt_raw_util.c index 9b0e2d7e74b..2036efcfcee 100644 --- a/modules/db_text/dbt_raw_util.c +++ b/modules/db_text/dbt_raw_util.c @@ -31,8 +31,16 @@ #include "dbt_raw_util.h" -//static const char* _regexp = "\\s*(and|or)?\\s*(\\w*)\\s*(>=|<=|<>|=|>|<)\\s*(')?([a-zA-Z0-9_-]*)(')?"; -static const char* _regexp = "\\s*(and|or)?\\s*(\\w*)\\s*(>=|<=|<>|=|>|<)\\s*(['\"])?([^'\"]*)(['\"])?"; +static const char* _regexp = "\\s*(and|or|where|,)?\\s*(\\w*)\\s*(>=|<=|<>|=|>|<)\\s*([0-9\\.]+)?(\"([^\\\\\"]|\\\\\")*\")?"; + +void log_regerror(int errcode, regex_t *compiled) +{ + size_t length = regerror (errcode, compiled, NULL, 0); + char *buffer = pkg_malloc (length); + (void) regerror (errcode, compiled, buffer, length); + LM_ERR("error compiling regex : %s\n", buffer); + pkg_free(buffer); +} char** dbt_str_split(char* a_str, const char a_delim, int* c) { @@ -133,8 +141,8 @@ char* dbt_trim(char *str) } -#define MAX_MATCH 7 -#define MAX_CLAUSES 12 +#define MAX_MATCH 10 +#define MAX_CLAUSES 20 void dbt_clean_where(int n, db_key_t* _k, db_op_t* _op, db_val_t* _v) { @@ -180,10 +188,13 @@ int dbt_build_where(char* where, db_key_t** _k, db_op_t** _o, db_val_t** _v) *_o = NULL; *_v = NULL; + int res; + len = strlen(where); - if (regcomp(&preg, _regexp, REG_EXTENDED | REG_NEWLINE)) { - LM_ERR("error compiling regexp\n"); + res = regcomp(&preg, _regexp, REG_EXTENDED); + if(res) { + log_regerror(res, &preg); return -1; } @@ -204,7 +215,7 @@ int dbt_build_where(char* where, db_key_t** _k, db_op_t** _o, db_val_t** _v) char* buffer = where + offset; if (regexec(&preg, buffer, MAX_MATCH, matches, REG_ICASE)) { - LM_ERR("error running regexp\n"); + LM_ERR("error running regexp %i '%s'\n", idx, buffer); break; } if(matches[0].rm_so == -1) { @@ -227,23 +238,28 @@ int dbt_build_where(char* where, db_key_t** _k, db_op_t** _o, db_val_t** _v) strncpy(_o1[idx], buffer+matches[3].rm_so, l); _o1[idx][l]='\0'; - l = matches[5].rm_eo - matches[5].rm_so; - if(matches[4].rm_so == -1) { - strncpy(int_buf, buffer+matches[5].rm_so, l); + if(matches[5].rm_so == -1) { + l = matches[4].rm_eo - matches[4].rm_so; + strncpy(int_buf, buffer+matches[4].rm_so, l); int_buf[l] = '\0'; _v1[idx].type = DB1_INT; _v1[idx].val.int_val = atoi(int_buf); } else { + char *start = buffer+matches[5].rm_so+1; + int writer = 0, reader = 0; + l = matches[5].rm_eo - matches[5].rm_so - 2; _v1[idx].type = DB1_STR; _v1[idx].val.str_val.len = l; _v1[idx].val.str_val.s = pkg_malloc(l+1); - strncpy(_v1[idx].val.str_val.s, buffer+matches[5].rm_so, l); - } -/* - for(int n=0; n < MAX_MATCH; n++) { - LM_ERR("MATCH RESULT %d - %d,%d\n", n, matches[n].rm_so, matches[n].rm_eo); + + for(reader=0; reader < l; reader++) { + if(start[reader] == '\\' && start[reader+1] == '\"') + continue; + _v1[idx].val.str_val.s[writer++] = start[reader]; + } + _v1[idx].val.str_val.s[writer] = '\0'; + _v1[idx].val.str_val.len = writer; } -*/ if(matches[0].rm_eo != -1) offset += matches[0].rm_eo;