#include "proxysql.h" #include "cpp.h" #include "SpookyV2.h" #define USLEEP_SQLITE_LOCKED 100 SQLite3_column::SQLite3_column(int a, const char *b) { datatype=a; if (b) { name=strdup(b); } else { name=strdup((char *)""); } } SQLite3_column::~SQLite3_column() { free(name); } SQLite3_row::SQLite3_row(int c) { sizes=(int *)malloc(sizeof(int)*c); fields=(char **)malloc(sizeof(char *)*c); memset(fields,0,sizeof(char *)*c); cnt=c; data=NULL; ds=0; } unsigned long long SQLite3_row::get_size() { unsigned long long s = sizeof(SQLite3_row); s += cnt * sizeof(int); s += cnt * sizeof(char *); s += ds; return s; } SQLite3_row::~SQLite3_row() { free(fields); free(sizes); if (data) { free(data); } } void SQLite3_row::add_fields(sqlite3_stmt *stmt) { int i; int t; int data_size=0; int data_ptr=0; // compute the length for (i=0;i::iterator it = resultset->rows.begin() ; it != resultset->rows.end(); ++it) { SQLite3_row *r=*it; ret=atoi(r->fields[0]); break; } } if (resultset) delete resultset; return ret; } int SQLite3DB::check_table_structure(char *table_name, char *table_def) { const char *q1="SELECT COUNT(*) FROM sqlite_master WHERE type=\"table\" AND name=\"%s\" AND sql=\"%s\""; int count=0; int l=strlen(q1)+strlen(table_name)+strlen(table_def)+1; sqlite3_stmt *statement; char *buff=(char *)calloc(1,l); sprintf(buff, q1, table_name , table_def); if(sqlite3_prepare_v2(db, buff, -1, &statement, 0) != SQLITE_OK) { proxy_debug(PROXY_DEBUG_SQLITE, 1, "SQLITE: Error on sqlite3_prepare_v2() running query \"%s\" : %s\n", buff, sqlite3_errmsg(db)); sqlite3_finalize(statement); free(buff); assert(0); } int result=0; while ((result=sqlite3_step(statement))==SQLITE_ROW) { count+=sqlite3_column_int(statement,0); } sqlite3_finalize(statement); free(buff); return count; } bool SQLite3DB::build_table(char *table_name, char *table_def, bool dropit) { bool rc; if (dropit) { const char *q2="DROP TABLE IF EXISTS %s"; int l=strlen(q2)+strlen(table_name)+1; char *buff=(char *)calloc(1,l); sprintf(buff,q2,table_name); proxy_debug(PROXY_DEBUG_SQLITE, 5, "SQLITE: dropping table: %s\n", buff); rc=execute(buff); free(buff); if (rc==false) return rc; } proxy_debug(PROXY_DEBUG_SQLITE, 5, "SQLITE: creating table: %s\n", table_def); rc=execute(table_def); return rc; } bool SQLite3DB::check_and_build_table(char *table_name, char *table_def) { int rci; bool rcb; rci=check_table_structure(table_name,table_def); if (rci) return true; rcb=build_table(table_name,table_def,true); return rcb; } void SQLite3DB::rdlock() { pthread_rwlock_rdlock(&rwlock); } void SQLite3DB::rdunlock() { pthread_rwlock_unlock(&rwlock); } void SQLite3DB::wrlock() { pthread_rwlock_wrlock(&rwlock); } void SQLite3DB::wrunlock() { pthread_rwlock_unlock(&rwlock); } uint64_t SQLite3_result::raw_checksum() { if (this->rows_count==0) return 0; uint64_t hash1, hash2; SpookyHash myhash; myhash.Init(19,3); for (std::vector::iterator it=rows.begin() ; it!=rows.end(); ++it) { SQLite3_row *r=*it; for (int i=0; ifields[i]) { myhash.Update(r->fields[i],r->sizes[i]); } else { myhash.Update("",0); } } } myhash.Final(&hash1, &hash2); return hash1; } char *SQLite3_result::checksum() { uint64_t hash1=raw_checksum(); char buf[128]; memset(buf,'0',128); uint32_t d32[2]; memcpy(&d32,&hash1,sizeof(hash1)); sprintf(buf,"0x%X%X", d32[0], d32[1]); return strdup(buf); } void SQLite3_result::dump_to_stderr() { if (columns == 0) return; size_t *columns_lengths = (size_t *)malloc(sizeof(size_t)*columns); int i = 0; for (i = 0; i::iterator it=column_definition.begin() ; it!=column_definition.end(); ++it) { SQLite3_column *r=*it; size_t len = strlen(r->name); if (len > columns_lengths[i]) { columns_lengths[i] = len; i++; } } for (std::vector::iterator it=rows.begin() ; it!=rows.end(); ++it) { SQLite3_row *r=*it; for (int i=0; ifields[i]) { if ((unsigned int)r->sizes[i] > columns_lengths[i]) { columns_lengths[i] = r->sizes[i]; } } else { if (columns_lengths[i] < 4) { columns_lengths[i] = 4; // NULL } } } } string s; s = "+"; for (i=0; i::iterator it=column_definition.begin() ; it!=column_definition.end(); ++it) { SQLite3_column *r=*it; size_t len = strlen(r->name); s.append(" "); s.append(r->name); unsigned int j; for (j=0; j < columns_lengths[i] - len + 1 ; j++) { s.append(" "); } s.append("|"); i++; } fprintf(stderr,"%s\n",s.c_str()); s = "+"; for (i=0; i::iterator it=rows.begin() ; it!=rows.end(); ++it) { SQLite3_row *r=*it; s = "|"; i = 0; for (int i=0; ifields[i]) { len = r->sizes[i]; s.append(r->fields[i]); } else { len = 4; s.append("NULL"); } unsigned int j; for (j=0; j < columns_lengths[i] - len + 1 ; j++) { s.append(" "); } s.append("|"); } fprintf(stderr,"%s\n",s.c_str()); } s = "+"; for (i=0; icolumns; if (src->enabled_mutex) { pthread_mutex_init(&m,NULL); enabled_mutex = true; } else { enabled_mutex = false; } for (std::vector::iterator it = src->column_definition.begin() ; it != src->column_definition.end(); ++it) { SQLite3_column *r=*it; add_column_definition(SQLITE_TEXT,r->name); } for (std::vector::iterator it = src->rows.begin() ; it != src->rows.end(); ++it) { SQLite3_row *r=*it; add_row(r); } } unsigned long long SQLite3_result::get_size() { unsigned long long s = sizeof(SQLite3_result); s += column_definition.size() * sizeof(SQLite3_column *); s += rows.size() * sizeof(SQLite3_row *); for (std::vector::iterator it = column_definition.begin() ; it != column_definition.end(); ++it) { SQLite3_column *r=*it; s+= sizeof(SQLite3_column) + strlen(r->name); } for (std::vector::iterator it = rows.begin() ; it != rows.end(); ++it) { SQLite3_row *r=*it; s += r->get_size(); } return s; } void SQLite3_result::add_column_definition(int a, const char *b) { SQLite3_column *cf=new SQLite3_column(a,b); column_definition.push_back(cf); } int SQLite3_result::add_row(sqlite3_stmt *stmt, bool skip) { int rc=sqlite3_step(stmt); if (rc!=SQLITE_ROW) return rc; if (skip==false) { SQLite3_row *row=new SQLite3_row(columns); row->add_fields(stmt); rows.push_back(row); rows_count++; } return SQLITE_ROW; } int SQLite3_result::add_row(char **_fields) { SQLite3_row *row=new SQLite3_row(columns); row->add_fields(_fields); if (enabled_mutex) { pthread_mutex_lock(&m); } rows.push_back(row); rows_count++; if (enabled_mutex) { pthread_mutex_unlock(&m); } return SQLITE_ROW; } int SQLite3_result::add_row(SQLite3_row *old_row) { SQLite3_row *row=new SQLite3_row(columns); row->add_fields(old_row->fields); rows.push_back(row); rows_count++; return SQLITE_ROW; } SQLite3_result::SQLite3_result(sqlite3_stmt *stmt) { rows_count=0; columns=sqlite3_column_count(stmt); for (int i=0; i 0 || limit > 0) { while (offset > 0 && rc==SQLITE_ROW) { rc = add_row(stmt, true); if (rc == SQLITE_ROW) fr++; offset--; } while (limit > 0 && rc==SQLITE_ROW) { rc = add_row(stmt, false); if (rc == SQLITE_ROW) fr++; limit--; } } else { while (rc == SQLITE_ROW) { rc=add_row(stmt, false); if (rc == SQLITE_ROW) fr++; } } while (rc == SQLITE_ROW) { rc=add_row(stmt, true); if (rc == SQLITE_ROW) fr++; } *found_rows = fr; } SQLite3_result::SQLite3_result(int num_columns, bool en_mutex) { rows_count=0; columns=num_columns; if (en_mutex) { pthread_mutex_init(&m,NULL); enabled_mutex = true; } else { enabled_mutex = false; } } SQLite3_result::~SQLite3_result() { for (std::vector::iterator it = column_definition.begin() ; it != column_definition.end(); ++it) { SQLite3_column *c=*it; delete c; } for (std::vector::iterator it = rows.begin() ; it != rows.end(); ++it) { SQLite3_row *r=*it; delete r; } } SQLite3_result::SQLite3_result() { columns=0; }