소스 검색

Merge pull request #146 from lazedo/lazedo/db_text_raw_query

db_text : proper db_raw_query support
Daniel-Constantin Mierla 10 년 전
부모
커밋
e2dcb543ba
6개의 변경된 파일526개의 추가작업 그리고 51개의 파일을 삭제
  1. 0 50
      modules/db_text/dbt_base.c
  2. 201 0
      modules/db_text/dbt_raw_query.c
  3. 37 0
      modules/db_text/dbt_raw_query.h
  4. 247 0
      modules/db_text/dbt_raw_util.c
  5. 40 0
      modules/db_text/dbt_raw_util.h
  6. 1 1
      modules/db_text/dbtext.h

+ 0 - 50
modules/db_text/dbt_base.c

@@ -319,56 +319,6 @@ clean:
 	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
  */

+ 201 - 0
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 <string.h>
+
+#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;
+}

+ 37 - 0
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
+

+ 247 - 0
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 <sys/types.h>
+#include <string.h>
+#include <regex.h>
+#include <ctype.h>
+
+#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;
+}

+ 40 - 0
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
+

+ 1 - 1
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);
 
 
 /*