2
0
Эх сурвалжийг харах

Merge pull request #485 from kamailio/lazedo/db_text

db_text: implemented raw query for UPDATE/DELETE/REPLACE
lazedo 9 жил өмнө
parent
commit
bffa9b32e5

+ 4 - 1
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;

+ 308 - 18
modules/db_text/dbt_raw_query.c

@@ -167,29 +167,315 @@ error:
 
 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;
 }

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

+ 32 - 16
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;