#ifndef SORM_H #define SORM_H #include #include #include #include #include #include #include #include #include "str.h" sqlite3 *db; sqlite3_stmt *stmt; char * sorm_last_query = NULL; char * sorm_last_query_expanded = NULL; nsecs_t _sorm_query_start = 0; nsecs_t _sorm_query_end = 0; nsecs_t _sorm_query_duration = 0; nsecs_t _sorm_result_format_start = 0; nsecs_t _sorm_result_format_end = 0; nsecs_t _sorm_result_format_duration = 0; int64_t sorm_row_count = 0; typedef struct sorm_t { sqlite3 * conn; int current_row; int current_column; char * csv; nsecs_t time_query_start; nsecs_t time_query_end; nsecs_t time_query_duration; nsecs_t time_result_format_start; nsecs_t time_result_format_end; nsecs_t time_result_format_duration; } sorm_t; typedef char * sorm_pk; typedef char * sorm_int; typedef char * sorm_ptr; typedef unsigned char * sorm_str; typedef double sorm_double; typedef double sorm_float; typedef bool sorm_bool; int sormc(char * path); void sormd(int db); char * sormpt(char * sql, int number); unsigned int sormcq(char * sql, char * out); unsigned int sormpc(char * sql); sqlite3_stmt * sormb(sorm_t* db, char * sql, ...); sorm_ptr sormq(int db, char * sql, ...); char * sorm_csvc(int db, sqlite3_stmt * stmt); char * sorm_csvd(int db, sqlite3_stmt * stmt); char * sorm_csv(int db,sqlite3_stmt * stmt); typedef enum sorm_query_t { SORM_UNKNOWN = 0, SORM_SELECT = 1, SORM_INSERT = 2, SORM_UPDATE = 3, SORM_DELETE = 4, SORM_CREATE = 5 } sorm_query_t; const int sorm_null = -1337; sorm_t ** sorm_instances = NULL; int sorm_instance_count = 0; int sormc(char * path){ // sorm connect printf("HIERR\n"); sorm_instance_count++; sorm_instance_count++; sorm_instances = realloc(sorm_instances,sorm_instance_count * sizeof(sorm_t *) + sorm_instance_count * sizeof(sorm_t)); printf("HIERR\n"); sorm_t * db = &sorm_instances[sorm_instance_count - 1]; printf("HIERR\n"); db->conn = NULL; printf("HIERR\n"); db->csv = NULL; db->current_column = 0; db->current_row = 0; db->time_query_duration = 0; db->time_query_end = 0; db->time_query_start = 0; db->time_result_format_duration = 0; db->time_result_format_end = 0; db->time_result_format_start = 0; if(sqlite3_open(path,&db->conn)) { fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db->conn)); return 0; } printf("DONE!\n"); return sorm_instance_count; } sorm_t * sormg(int ptr){ return &sorm_instances[ptr -1]; } char * sormgcsv(int ptr){ /* sorm get csv*/ sorm_t * db = sormg(ptr); return db->csv; } void sormd(int sorm){ sorm_t * db = sormg(sorm); if(sqlite3_close(db->conn)) { fprintf(stderr, "Error closing database: %s\n", sqlite3_errmsg(db->conn)); } if(sorm_last_query){ free(sorm_last_query); sorm_last_query = NULL; } if(sorm_last_query_expanded){ free(sorm_last_query_expanded); sorm_last_query_expanded = NULL; } } char * sormpt(char * sql, int number){ // param type char * sqlp = sql; char * result = NULL; int index = 0; while(*sqlp){ if(*sqlp == '%' || *sqlp == '?'){ sqlp++; switch(*sqlp){ case 'f': result = "double"; break; case 's': result = "text"; break; case 'd': result = "int"; break; case 'b': result = "blob"; break; default: result = "?"; break; } sqlp++; index++; } if(index == number){ return result; } if(*sqlp) sqlp++; } if(number > index){ printf("RETURNED\n"); return NULL; } return NULL; } unsigned int sormcq(char * sql, char * out){ // clean query // converts %s %i parameters to ? unsigned int count = 0; while(*sql){ if(*sql != '%' && *sql != '?') *out = *sql; else{ count++; sql++; *out = '?'; } out++; sql++; } *out = 0; return count; } unsigned int sormpc(char * sql){ int number = 0; while(sormpt(sql,number) != NULL) number++; printf("FOUND: %d\n",number); return number; } char * sormcts(int column_type){ if(column_type == SQLITE_INTEGER) return "integer"; else if(column_type == SQLITE_TEXT) return "text"; else if(column_type == SQLITE_FLOAT) return "float"; else if(column_type == SQLITE_NULL) return "null"; else if(column_type == SQLITE_BLOB) return "blob"; return "?"; } /* Execute 3.35s, Format: 36.77s Memory usage: 537 GB, 96.026 allocated, 96.024 freed, 2 in use. */ char * sorm_csvc(int db, sqlite3_stmt * stmt){ sormstr_t * str = sormstrn(512); unsigned int column_count = sqlite3_column_count(stmt); for(int i = 0; i < column_count; i++){ const char * column_name = sqlite3_column_name(stmt,i); sormstra(str,column_name); sormstra(str,"("); char column_type[1000] = ""; sprintf(column_type,"%s",sormcts(sqlite3_column_type(stmt,i))); sormstra(str,column_type); sormstra(str,")"); // if(i != column_count - 1) sormstra(str,";"); } return sormstrc(str); } char * sorm_csvd(int sorm, sqlite3_stmt * stmt) { sorm_t * db = sormg(sorm); int rc = SQLITE_ROW; int column_count = sqlite3_column_count(stmt); /* sormstrn(1) Execute 3.41s, Format: 36.77s Memory usage: 5 MB, 96.061 (re)allocated, 96.024 unqiue freed, 2 in use. sormstrn(512) Execute 3.68s, Format: 36.83s Memory usage: 537 GB, 96.026 allocated, 96.024 freed, 2 in use. sormstrn(256) xecute 3.42s, Format: 37.33s Memory usage: 6 MB, 96.052 (re)allocated, 96.024 unqiue freed, 2 in use. */ sormstr_t * str = sormstrn(512); while(rc == SQLITE_ROW){ sorm_row_count++; for(int field_index = 0; field_index < column_count; field_index++){ if(sqlite3_column_type(stmt,field_index) == SQLITE_INTEGER){ char temp[1000] = ""; sprintf(temp, "%lld",sqlite3_column_int64(stmt,field_index)); sormstra(str,temp); }else if(sqlite3_column_type(stmt,field_index) == SQLITE_FLOAT){ char temp[1000] = ""; sprintf(temp, "%f",sqlite3_column_double(stmt,field_index)); sormstra(str,temp); } else if(sqlite3_column_type(stmt,field_index) == SQLITE3_TEXT){ const char * temp = sqlite3_column_text(stmt,field_index); sormstra(str,temp); } else { // exit(1); } // if(field_index != column_count - 1) sormstra(str,";"); } sormstra(str,"\n"); rc = sqlite3_step(stmt); } char * text = sormstrc(str); if(*text) if(text[strlen(text)-1] == '\n') text[strlen(text)-1] = 0; return strdup(text); } char * sorm_csv(int sorm,sqlite3_stmt * stmt){ sorm_t * db = sormg(sorm); sorm_row_count = 0; char * column_names = sorm_csvc(sorm,stmt); char * data = sorm_csvd(sorm,stmt); char * result = (char *)malloc(strlen(column_names) + strlen(data) + 2); result[0] = 0; strcat(result,column_names); if(*column_names) strcat(result,"\n"); free(column_names); strcat(result,data); free(data); return result; } sqlite3_stmt * sormb(sorm_t* db, char * sql, ...){ // Bind parameters to statement and return amount of parameters int rc = 0; sqlite3_stmt * stmt; va_list args; va_start(args,sql); unsigned int number = 0; char * clean_query = (char *)malloc(strlen(sql) + 1); unsigned int parameter_count = sormcq(sql,clean_query); free(clean_query); return stmt; } char * sormm(sorm_t * db){ /* sormmemory */ return rmalloc_stats(); } sorm_ptr sormq(int sorm, char * sql, ...){ sorm_t * db = sormg(sorm); if(db->csv){ //free(db->csv); //db->csv = NULL; } _sorm_query_start = nsecs(); db->time_query_start = nsecs(); va_list args; va_start (args,sql); sqlite3_stmt * stmt; sorm_ptr result = NULL; char * clean_query = malloc(strlen(sql) + 1); unsigned int parameter_count = sormcq(sql,clean_query); int rc = sqlite3_prepare_v2(db->conn, clean_query, -1, &stmt, 0); if (rc != SQLITE_OK) { fprintf(stderr, "%s\n", sqlite3_errmsg(db->conn)); } free(clean_query); int number = 0; for(int i = 0; i < parameter_count; i++){ number++; char * column_type = sormpt(sql,number); int arg_index = number - 1; if(!strcmp(column_type, "int") || !strcmp(column_type, "integer") || !strcmp(column_type, "number")) { rc = sqlite3_bind_int(stmt, number, va_arg(args,int)); }else if(!strcmp(column_type, "int64")){ rc = sqlite3_bind_int64(stmt, number,va_arg(args,__uint64_t)); }else if(!strcmp(column_type, "double") || !strcmp(column_type, "dec") || !strcmp(column_type, "decimal") || !strcmp(column_type, "float")){ rc = sqlite3_bind_double(stmt, number,va_arg(args,double)); }else if(!strcmp(column_type, "blob")){ size_t size = (size_t)va_arg(args,size_t); unsigned char * data = va_arg(args,unsigned char *); rc = sqlite3_bind_blob(stmt, number, data, size, SQLITE_STATIC); }else if(!strcmp(column_type,"text") || !strcmp(column_type,"str") || !strcmp(column_type,"string")) { unsigned char * data = va_arg(args, unsigned char *); rc = sqlite3_bind_text(stmt, number, data, -1, SQLITE_STATIC); } if (rc != SQLITE_OK) { fprintf(stderr, "Failed to bind parameters: %s\n", sqlite3_errmsg(db->conn)); result = NULL; } } rc = sqlite3_step(stmt); if (rc != SQLITE_DONE && rc != SQLITE_ROW) { fprintf(stderr, "Execution failed: %s\n", sqlite3_errmsg(db->conn)); }else if(rc == SQLITE_DONE){ if(!sqlite3_strnicmp(sql,"SELECT",6)){ result = 0; }else { result = (sorm_ptr)sqlite3_last_insert_rowid(db->conn); } } else if (rc == SQLITE_ROW) { result = sorm_csv(sorm,stmt); } else{ fprintf(stderr, "Execution failed: %s\n", sqlite3_errmsg(db->conn)); } if(sorm_last_query){ free(sorm_last_query); } if(sorm_last_query){ free(sorm_last_query_expanded); } sorm_last_query = strdup(sqlite3_sql(stmt)); sorm_last_query_expanded = strdup(sqlite3_expanded_sql(stmt)); sqlite3_finalize(stmt); _sorm_query_end = nsecs(); _sorm_query_duration = _sorm_query_end - _sorm_query_start; db->time_query_end = nsecs(); db->time_query_duration = db->time_query_end - db->time_query_start; db->csv = result; return result; } char sormlc(char * sql){ // returns last char char last_char = 0; while(*sql){ if(*sql == ' ' || *sql == '\t' || *sql == '\n') continue ; //printf("%c\n",*sql); last_char = *sql; sql++; } return last_char; } int sormlv(char * csv){ size_t longest = 0; while(*csv){ char * found = strstr(csv,";"); if(found){ if(found - csv > longest) longest = found-csv; csv = csv + (found - csv) + 1; }else{ break; } } return longest; } sorm_query_t sormqt(char * sql){ while(*sql && isspace(*sql)) sql++; if(!sqlite3_strnicmp(sql,"select",6)) return SORM_SELECT; else if(!sqlite3_strnicmp(sql, "update",6)) return SORM_UPDATE; else if(!sqlite3_strnicmp(sql, "delete",6)) return SORM_DELETE; else if(!sqlite3_strnicmp(sql, "create",6)){ return SORM_CREATE; }else { return SORM_UNKNOWN; } } char * sormrq(FILE * f){ static char buffer[4097]; buffer[0] = 0; char * bufferp = buffer; char c; bool in_string = false; while((c = fgetc(f)) != EOF && strlen(buffer) != sizeof(buffer) -2){ *bufferp = c; if(c == '"') { in_string = !in_string; } if(!in_string && c == ';'){ break; } bufferp++; *bufferp = 0; } return strdup(buffer); } char * sormcsvn(char * csv){ if(!csv || !*csv) return NULL; char * pos = strstr(csv,";"); char * pos2 = strstr(csv,"\n"); if(pos2){ if(pos > pos2){ pos = pos2; } //pos = pos > pos2 ? pos2 : pos; } if(!pos || !*pos) return strdup(csv); int length = pos - csv; char * result = malloc(length + 2); strncpy(result,csv,length); result[length] = 0; //csv += strlen(result); return result; } char * sormfmt(char * csv){ _sorm_result_format_start = nsecs(); size_t longest = sormlv(csv); char * field; /* sormstrn(1) Execute 3.77s, Format: 36.40s Memory usage: 6 MB, 96.055 (re)allocated, 96.024 unqiue freed, 2 in use. sormstrn(longest); Execute 3.27s, Format: 36.61s Memory usage: 6 MB, 96.053 (re)allocated, 96.024 unqiue freed, 2 in use. sormstrn(longest * 2); xecute 3.42s, Format: 37.33s Memory usage: 6 MB, 96.052 (re)allocated, 96.024 unqiue freed, 2 in use. sormstrn(512); Execute 3.11s, Format: 36.45s Memory usage: 6 MB, 96.048 (re)allocated, 96.024 unqiue freed, 2 in use. */ sormstr_t * str = sormstrn(longest + 2); while(*csv && (field = sormcsvn(csv))){ sormstra(str,field); for(int i = 0; i < longest - strlen(field); i++) sormstra(str," "); csv += strlen(field); while( *csv == ';' || *csv == '\n'){ if(*csv == '\n') sormstra(str, "\n"); csv++; } free(field); } _sorm_result_format_end = nsecs(); _sorm_result_format_duration = _sorm_result_format_end - _sorm_result_format_start; return sormstrc(str); } void apply_colors(char * csv){ char * end; bool even = false; while(*csv){ printf("%s\n",csv); end = strstr(csv,"\n"); char * line; if(end) { line = (char *)malloc(end -csv + 1024); strncpy(line,csv,end-csv); }else{ line = (char *)malloc(strlen(csv) + 1024); strcpy(line, csv); } if(even){ printf("%s","\033[37m"); } printf("%s\n",line); free(line); if(even){ printf("%s","\033[0m"); } even = !even; csv += end-csv; if(*csv && *(csv + 1)) csv++; } } void sormfmtd(char * csv){ char * formatted = sormfmt(csv); printf("%s\n",formatted); free(formatted); } #endif