diff --git a/modules/db_text/dbt_base.c b/modules/db_text/dbt_base.c index 3df41bb98fe..7ca45638644 100644 --- a/modules/db_text/dbt_base.c +++ b/modules/db_text/dbt_base.c @@ -319,56 +319,6 @@ int dbt_query(db1_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v, return -1; } -/* - * Raw SQL query -- is not the case to have this method - */ -int dbt_raw_query(db1_con_t* _h, const str* _s, db1_res_t** _r) -{ - *_r = NULL; - int res = -1; - dbt_table_p _tbc = NULL; - int cols; - int n = 0; - db_key_t *result_cols = NULL; - - if(!_h) { - LM_ERR("H INVALID\n"); - return res; - } - - if(!_s) { - LM_ERR("S INVALID\n"); - return res; - } - - if(dbt_use_table(_h, _s) != 0) { - LM_ERR("USE INVALID %.*s\n", _s->len, _s->s); - return res; - } - - _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); - return res; - } - - cols = _tbc->nrcols; - result_cols = pkg_malloc(sizeof(db_key_t) * cols); - memset(result_cols, 0, sizeof(db_key_t) * cols); - for(n=0; n < cols; n++) { - result_cols[n] = &_tbc->colv[n]->name; - } - - dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); - - res = dbt_query(_h, NULL, NULL, NULL, result_cols, 0, cols, NULL, _r); - pkg_free(result_cols); - return res; - - -} - /* * Affected Rows */ diff --git a/modules/db_text/dbt_raw_query.c b/modules/db_text/dbt_raw_query.c new file mode 100644 index 00000000000..ad13600edf6 --- /dev/null +++ b/modules/db_text/dbt_raw_query.c @@ -0,0 +1,201 @@ +/* + * DBText module core functions + * + * Copyright (C) 2001-2003 FhG Fokus + * + * This file is part of Kamailio, a free SIP server. + * + * Kamailio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * Kamailio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define _GNU_SOURCE +#include + +#include "../../str.h" +#include "../../mem/mem.h" +#include "../../mem/shm_mem.h" + +#include "dbtext.h" +#include "dbt_res.h" +#include "dbt_api.h" +#include "dbt_raw_util.h" + + +int dbt_raw_query_select(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_ptr = NULL; + char* where_ptr = NULL; + char** tokens = NULL; + str table; + dbt_table_p _tbc = NULL; + int cols; + int n = 0; + int ncols = 0; + int nc = 0; + db_key_t *result_cols = NULL; + db_key_t* _k = NULL; + db_op_t* _op = NULL; + db_val_t* _v = NULL; + + fields_end_ptr = strcasestr(_s->s, " from "); + if(fields_end_ptr == NULL) + return res; + + len = fields_end_ptr - (_s->s + 6) + 1; + fields_ptr = pkg_malloc(len); + strncpy(fields_ptr, _s->s + 6, len); + fields_ptr[len] = '\0'; + fields_ptr = dbt_trim(fields_ptr); + + + + where_ptr = strcasestr(_s->s, " where "); + if(where_ptr == NULL) { + len = strlen(fields_end_ptr + 6); + } else { + len = where_ptr - (fields_end_ptr + 6); + nc = dbt_build_where(where_ptr + 7, &_k, &_op, &_v); + } + + 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; + + 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; + } + + tokens = dbt_str_split(fields_ptr, ',', &ncols); + pkg_free(fields_ptr); + fields_ptr = NULL; + if (!tokens) { + LM_ERR("error extracting tokens\n"); + goto error; + } + + if(ncols == 1 && strncmp(*tokens, "*", 1) == 0) { + cols = _tbc->nrcols; + result_cols = pkg_malloc(sizeof(db_key_t) * cols); + memset(result_cols, 0, sizeof(db_key_t) * cols); + for(n=0; n < cols; n++) { + result_cols[n] = &_tbc->colv[n]->name; + } + } else { + cols = ncols; + result_cols = pkg_malloc(sizeof(db_key_t) * cols); + memset(result_cols, 0, sizeof(db_key_t) * cols); + for(n=0; *(tokens + n); n++) { + result_cols[n]->s = *(tokens + n); + result_cols[n]->len = strlen(*(tokens + n)); + } + } + + + dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); + + res = dbt_query(_h, _k, _op, _v, result_cols, nc, cols, NULL, _r); + +error: + if(tokens) { + for (i = 0; *(tokens + i); i++) { + pkg_free(*(tokens + i)); + } + pkg_free(tokens); + } + if(fields_ptr) + pkg_free(fields_ptr); + + if(table_ptr) + pkg_free(table_ptr); + + dbt_clean_where(nc, _k, _op, _v); + + if(result_cols) { + pkg_free(result_cols); + } + + return res; +} + +int dbt_raw_query_update(db1_con_t* _h, str* _s, db1_res_t** _r) +{ + int res = -1; + + + + return res; +} + +int dbt_raw_query_delete(db1_con_t* _h, str* _s, db1_res_t** _r) +{ + int res = -1; + + + + 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; + + if(!_h) { + LM_ERR("invalid connection\n"); + return res; + } + + if(!_s) { + LM_ERR("sql query is null\n"); + return res; + } + + if(_s->s == NULL) { + LM_ERR("sql query is null\n"); + 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; +} diff --git a/modules/db_text/dbt_raw_query.h b/modules/db_text/dbt_raw_query.h new file mode 100644 index 00000000000..68103dab996 --- /dev/null +++ b/modules/db_text/dbt_raw_query.h @@ -0,0 +1,37 @@ +/* + * DBText library + * + * Copyright (C) 2001-2003 FhG Fokus + * + * This file is part of Kamailio, a free SIP server. + * + * Kamailio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * Kamailio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +#ifndef _DBT_RAW_QUERY_H_ +#define _DBT_RAW_QUERY_H_ + +#include "../../str.h" + + + +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); + +#endif + diff --git a/modules/db_text/dbt_raw_util.c b/modules/db_text/dbt_raw_util.c new file mode 100644 index 00000000000..58f55cf6f92 --- /dev/null +++ b/modules/db_text/dbt_raw_util.c @@ -0,0 +1,247 @@ +/* + * DBText library + * + * Copyright (C) 2001-2003 FhG Fokus + * + * This file is part of Kamailio, a free SIP server. + * + * Kamailio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * Kamailio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include +#include +#include + +#include "../../mem/mem.h" + +#include "dbt_raw_util.h" + +static const char* _regexp = "\\s*(and|or)?\\s*(\\w*)\\s*(>=|<=|<>|=|>|<)\\s*(')?([a-zA-Z0-9_-]*)(')?"; + +char** dbt_str_split(char* a_str, const char a_delim, int* c) +{ + char** result = 0; + size_t count = 0; + char* tmp = a_str; + char* last_comma = 0; + char delim[2]; + delim[0] = a_delim; + delim[1] = 0; + int len = 0; + + /* Count how many elements will be extracted. */ + while (*tmp) + { + if (a_delim == *tmp) + { + count++; + last_comma = tmp; + } + tmp++; + } + + /* Add space for trailing token. */ + count += last_comma < (a_str + strlen(a_str) - 1); + + *c = count; + + /* Add space for terminating null string so caller + knows where the list of returned strings ends. */ + count++; + + result = pkg_malloc(sizeof(char*) * count); + + if (result) + { + size_t idx = 0; + char* token = strtok(a_str, delim); + + while (token) + { + assert(idx < count); + len = strlen(token); + char* ptr = pkg_malloc( (len+1) * sizeof(char)); + memcpy(ptr, token, len); + ptr[len] = '\0'; + *(result + idx) = dbt_trim(ptr); + token = strtok(0, delim); + idx++; + } + assert(idx == count - 1); + *(result + idx) = 0; + } + + return result; +} + + +char* dbt_trim(char *str) +{ + size_t len = 0; + char *frontp = str; + char *endp = NULL; + + if( str == NULL ) { return NULL; } + if( str[0] == '\0' ) { return str; } + + len = strlen(str); + endp = str + len; + + /* Move the front and back pointers to address the first non-whitespace + * characters from each end. + */ + while( isspace(*frontp) ) { ++frontp; } + if( endp != frontp ) + { + while( isspace(*(--endp)) && endp != frontp ) {} + } + + if( str + len - 1 != endp ) + *(endp + 1) = '\0'; + else if( frontp != str && endp == frontp ) + *str = '\0'; + + /* Shift the string so that it starts at str so that if it's dynamically + * allocated, we can still free it on the returned pointer. Note the reuse + * of endp to mean the front of the string buffer now. + */ + endp = str; + if( frontp != str ) + { + while( *frontp ) { *endp++ = *frontp++; } + *endp = '\0'; + } + + + return str; +} + + +#define MAX_MATCH 7 +#define MAX_CLAUSES 12 + +void dbt_clean_where(int n, db_key_t* _k, db_op_t* _op, db_val_t* _v) +{ + int i; + if(_k) { + for(i=0; i < n; i++) { + pkg_free(_k[i]->s); + } + pkg_free(_k); + } + + if(_op) { + for(i=0; i < n; i++) { + pkg_free((char*)_op[i]); + } + pkg_free(_op); + } + + if(_v) { + for(i=0; i < n; i++) { + if(_v[i].type == DB1_STR) + pkg_free(_v[i].val.str_val.s); + } + pkg_free(_v); + } +} + +int dbt_build_where(char* where, db_key_t** _k, db_op_t** _o, db_val_t** _v) +{ + db_key_t* _k1 = NULL; + char** _o1 = NULL; + db_val_t* _v1 = NULL; + + *_k = NULL; + *_o = NULL; + *_v = NULL; + + int n, l; + int len = strlen(where); + + regex_t preg; + + if (regcomp(&preg, _regexp, REG_EXTENDED | REG_NEWLINE)) { + LM_ERR("error compiling regexp\n"); + return -1; + } + + _k1 = pkg_malloc(sizeof(db_key_t) * MAX_CLAUSES); + memset(_k1, 0, sizeof(db_key_t) * MAX_CLAUSES); + _o1 = pkg_malloc(sizeof(char*) * MAX_CLAUSES); + memset(_o1, 0, sizeof(db_op_t) * MAX_CLAUSES); + _v1 = pkg_malloc(sizeof(db_val_t) * MAX_CLAUSES); + memset(_v1, 0, sizeof(db_val_t) * MAX_CLAUSES); + + regmatch_t* matches = (regmatch_t*)pkg_malloc(sizeof(regmatch_t) * MAX_MATCH); + + int offset = 0; + int idx = -1; + while(offset < len) { + char* buffer = where + offset; + + if (regexec(&preg, buffer, MAX_MATCH, matches, REG_ICASE)) { + LM_ERR("error running regexp\n"); + break; + } + if(matches[0].rm_so == -1) { + break; + } + idx++; + + // TODO figure out a way to combine and / or + // needs changes in dbt_query / dbt_row_match + + l = matches[2].rm_eo - matches[2].rm_so; + _k1[idx] = pkg_malloc(sizeof(str)+l+1); + _k1[idx]->len = l; + _k1[idx]->s = (char*) (_k1[idx]+sizeof(str)); + strncpy(_k1[idx]->s, buffer+matches[2].rm_so, l); + _k1[idx]->s[l]='\0'; + + l = matches[3].rm_eo - matches[3].rm_so; + _o1[idx] = (char*) pkg_malloc(l+1); + 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) { + _v1[idx].type = DB1_INT; + _v1[idx].val.int_val = 0; + } else { + _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(n=0; n < MAX_MATCH; n++) { +// LM_ERR("MATCH RESULT %d - %d,%d\n", n, matches[n].rm_so, matches[n].rm_eo); +// } + + if(matches[0].rm_eo != -1) + offset += matches[0].rm_eo; + + } + regfree(&preg); + + *_k = _k1; + *_o = (db_op_t*)_o1; + *_v = _v1; + + return idx+1; +} diff --git a/modules/db_text/dbt_raw_util.h b/modules/db_text/dbt_raw_util.h new file mode 100644 index 00000000000..7c7f575c171 --- /dev/null +++ b/modules/db_text/dbt_raw_util.h @@ -0,0 +1,40 @@ +/* + * DBText library + * + * Copyright (C) 2001-2003 FhG Fokus + * + * This file is part of Kamailio, a free SIP server. + * + * Kamailio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * Kamailio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +#ifndef _DBT_RAW_UTIL_H_ +#define _DBT_RAW_UTIL_H_ + +#include "../../str.h" +#include "../../lib/srdb1/db_key.h" +#include "../../lib/srdb1/db_op.h" +#include "../../lib/srdb1/db_val.h" + + +char** dbt_str_split(char* a_str, const char a_delim, int* c); +char* dbt_trim(char *str); +int dbt_build_where(char* where, db_key_t** _k, db_op_t** _op, db_val_t** _v); +void dbt_clean_where(int n, db_key_t* _k, db_op_t* _op, db_val_t* _v); + +#endif + diff --git a/modules/db_text/dbtext.h b/modules/db_text/dbtext.h index 83bfcdc8ea7..92e62361a73 100644 --- a/modules/db_text/dbtext.h +++ b/modules/db_text/dbtext.h @@ -60,7 +60,7 @@ int dbt_query(db1_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v, /* * Raw SQL query */ -int dbt_raw_query(db1_con_t* _h, const str* _s, db1_res_t** _r); +int dbt_raw_query(db1_con_t* _h, str* _s, db1_res_t** _r); /*