#include #include #include #include #include #include #include #include "console.h" class sqlite{ sqlite3 * db; sqlite3_stmt * res; char * value; char * selectedModel; void constructor( char * filePath ) { this->value = "good"; this.connect( filePath ); } void connect( char * filePath ) { printf("\n\ntrying to connect.. %s\n\n", filePath); int rc = sqlite3_open( filePath, & this->db ); if ( rc != SQLITE_OK ) { printf( "Cannot open database: %s\n", sqlite3_errmsg( this->db ) ); sqlite3_close( this->db ); console->error( ( char * ) sqlite3_errmsg( this->db ) ); return; } rc = sqlite3_prepare_v2( this->db, "SELECT SQLITE_VERSION()", -1, & this->res, 0 ); if (rc != SQLITE_OK) { console->error( ( char * ) sqlite3_errmsg( this->db ) ); sqlite3_close( this->db ); return; } rc = sqlite3_step(this->res); /*if ( rc == SQLITE_ROW ) { printf( "%s\n", ( char * ) sqlite3_column_text( this->res, 0 ) ); } printf( "Success \n"); */ //return 1; } void free() { sqlite3_finalize( this->res ); sqlite3_close( this->db ); } void selectModel( char * className ) { this->selectedModel = className; /* printf("select className: %s\n", className); int classIndex = getClassIndexByClassName( this->selectedModel ); printf("class index: %i\n", classIndex); int propertyIndex = getPropertyIndexByPropertyName( classIndex, "username" ); int propertyCount = getPropertyCountByClassIndex( classIndex ); char ** propertyNames = getPropertiesByClassIndex( classIndex ); int * propertyOffsets = getPropertyOffsetsByClassIndex( classIndex ); printf("propertyIndex: %i\n\n", propertyIndex); for (int i = 0; i < propertyCount; ++i) { char * propertyName = propertyNames[i]; int propertyOffset = propertyOffsets[i]; printf("propertyName: %s offset: %i\n", propertyName, propertyOffset); } char * shortPointer = malloc( sizeof( char * ) * 100000 ); void * * voidArray = malloc( sizeof( void * ) * 100000 ); int structByteSize; getArrayByClassIndex( 100000, voidArray, shortPointer, &structByteSize, 0 ); */ } void createTable() { char * errorMessage = 0; char *sql = "DROP TABLE IF EXISTS user;" "CREATE TABLE user( id INT, username TEXT, userlevel INT, hash TEXT );"; int rc = sqlite3_exec(this->db, sql, 0, 0, &errorMessage); if ( rc != SQLITE_OK ) { printf( "SQL error: %s\n", errorMessage ); sqlite3_free( errorMessage ); sqlite3_close(this->db); } } /* // Fast but unsave -> sql injection void addRowsFast( array * insertArray ) { array * copy = insertArray; int classIndex = getClassIndexByClassName( this->selectedModel ); text * query = new text( "" ); query->append( "INSERT INTO " ); query->append( this->selectedModel ); sqlite3_stmt * result; char * * propertyNames = getPropertiesByClassIndex( classIndex ); int propertyCount = getPropertyCountByClassIndex( classIndex ); int * propertyOffsets = getPropertyOffsetsByClassIndex( classIndex ); int * datatypeIndices = getPropertyDatatypeIndexesByClassIndex( classIndex ); query->append( " ( " ); for (int propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex) { char * propertyName = propertyNames[propertyIndex]; int datatype = datatypeIndices[ propertyIndex ]; if( datatype > 0 ) { // join table because this is an class continue; } if( propertyIndex > 0 ) { query->append( ", " ); } query->append( propertyName ); } query->append( " ) " ); query->append(" VALUES " ); int insertItemCount = copy->total; char * voidArray = ( char * ) copy->items; //sqlite3_exec(result, "BEGIN TRANSACTION;", NULL, NULL, NULL); for (int i = 0; i < insertItemCount; ++i) { char * pointer = copy->get( i ); if( i > 0 ) { query->append( ", " ); } query->append( "( " ); for (int propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex) { char * propertyName = propertyNames[propertyIndex]; int datatype = datatypeIndices[ propertyIndex ]; if( datatype > 0 ) { // join table because this is an class continue; } int propertyOffset = propertyOffsets[propertyIndex]; int propertyDatatypeIndex = getPropertyDatatypeIndex( datatypeIndices, propertyIndex ); if( propertyIndex > 0 ) { query->append( ", " ); } if( propertyDatatypeIndex == -5 ) { int value = *( int * )(pointer + propertyOffset); char * textNumber = malloc( sizeof( char ) * 20 ); // Boost Spirit.Karma is faster sprintf( textNumber, "%d", value ); query->append( textNumber ); } else if( propertyDatatypeIndex == -3 ) { char * columnValueCopy = ( char * ) malloc( 8 ); char * value = ( char * ) ( pointer + propertyOffset ); strncpy( &columnValueCopy, value, 8 ); query->append( "'" ); query->append( columnValueCopy ); query->append( "'" ); } } query->append( " )" ); } //sqlite3_exec(result, "END TRANSACTION;", NULL, NULL, NULL); sqlite3_prepare_v2( this->db, query->buffer, -1, &result, 0 ); sqlite3_step( result ); sqlite3_finalize( result ); //printf("insert query: %s\n", query->buffer); } */ void addRows( array * insertArray ) { array * copy = insertArray; int classIndex = getClassIndexByClassName( this->selectedModel ); text * query = new text( "" ); query->append( "INSERT INTO " ); query->append( this->selectedModel ); sqlite3_stmt * result; char * * propertyNames = getPropertiesByClassIndex( classIndex ); int propertyCount = getPropertyCountByClassIndex( classIndex ); int * propertyOffsets = getPropertyOffsetsByClassIndex( classIndex ); int * datatypeIndices = getPropertyDatatypeIndexesByClassIndex( classIndex ); query->append( " ( " ); for (int propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex) { char * propertyName = propertyNames[propertyIndex]; int datatype = datatypeIndices[ propertyIndex ]; if( datatype > 0 ) { // join table because this is an class continue; } if( propertyIndex > 0 ) { query->append( ", " ); } query->append( propertyName ); } query->append( " ) " ); query->append( " VALUES ( " ); for (int propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex) { int datatype = datatypeIndices[ propertyIndex ]; if( datatype > 0 ) { // join table because this is an class continue; } if( propertyIndex > 0 ) { query->append( ", " ); } query->append( "?" ); } query->append(" ) " ); sqlite3_prepare_v2( this->db, query->value, -1, &result, 0 ); sqlite3_exec(this->db, this->selectedModel, NULL, NULL, 0); sqlite3_exec(this->db, "PRAGMA synchronous = OFF", NULL, NULL, 0); sqlite3_exec(this->db, "PRAGMA journal_mode = MEMORY", NULL, NULL, 0); int insertItemCount = copy->total; char * voidArray = ( char * ) copy->items; //sqlite3_exec(result, "BEGIN TRANSACTION;", NULL, NULL, NULL); for (int i = 0; i < insertItemCount; ++i) { char * pointer = copy->get( i ); this->updateRow( result, propertyCount, propertyNames, propertyOffsets, datatypeIndices, pointer ); sqlite3_step( result ); sqlite3_reset( result ); } //sqlite3_exec(result, "END TRANSACTION;", NULL, NULL, NULL); sqlite3_finalize( result ); //printf("insert query: %s\n", query->buffer); } void updateRow( sqlite3_stmt * result, int propertyCount, char * * propertyNames, int * propertyOffsets, int * datatypeIndices, char * pointer ) { for (int propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex) { char * propertyName = propertyNames[propertyIndex]; int propertyOffset = propertyOffsets[propertyIndex]; int propertyDatatypeIndex = getPropertyDatatypeIndex( datatypeIndices, propertyIndex ); //printf("propertyName: %s offset: %i datatype: %i propertyIndex: %i\n", propertyName, propertyOffset, propertyDatatypeIndex, propertyIndex); if( propertyDatatypeIndex == -5 ) { int value = *( int * )(pointer + propertyOffset); //printf("integer value: %i %i\n", propertyIndex + 1, value); sqlite3_bind_int( result, propertyIndex + 1, value ); } else if( propertyDatatypeIndex == -3 ) { //char * columnValueCopy = ( char * ) malloc( 8 ); uintptr_t * value = ( uintptr_t * ) ( pointer + propertyOffset ); //strncpy( &columnValueCopy, value, 8 ); //printf("char * value: %i %s\n", propertyIndex + 1, columnValueCopy); sqlite3_bind_text( result, propertyIndex + 1, (char *) *value, -1, SQLITE_TRANSIENT ); } } //printf("\n\n\n"); } void update( void * row ) { int classIndex = getClassIndexByClassName( this->selectedModel ); char ** propertyNames = getPropertiesByClassIndex( classIndex ); int propertyCount = getPropertyCountByClassIndex( classIndex ); int * propertyOffsets = getPropertyOffsetsByClassIndex( classIndex ); int * datatypeIndices = getPropertyDatatypeIndexesByClassIndex( classIndex ); int propertyIdOfIndex = -1; for ( int i = 0; i < propertyCount; ++i ) { char * propertyName = propertyNames[i]; //printf("propertyName: %s\n", propertyName); if( strcmp( propertyName, "id" ) == 0 ) { propertyIdOfIndex = i; break; } } if( propertyIdOfIndex == -1 ) { printf("Class '%s' does not have an id field. "); } int idOffset = propertyOffsets[ propertyIdOfIndex ]; char * pointer = row; int id = *( pointer + idOffset ); text * query = new text( "" ); //"UPDATE user set username = '?' where id=?; " query->append( "UPDATE " ); query->append( this->selectedModel ); query->append( " SET " ); int activePropertyCount = 0; // set propertyCount for (int propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex) { char * propertyName = propertyNames[propertyIndex]; int datatypeIndex = datatypeIndices[propertyIndex]; // todo properties that are classes like "array" if( datatypeIndex > 0 ) { continue; } activePropertyCount++; if( propertyIndex > 0 ) { query->append( ", " ); } query->append( propertyName ); query->append( " = ? " ); } query->append( " where id = ? " ); sqlite3_stmt * result; sqlite3_prepare_v2( this->db, query->value, -1, &result, 0 ); this->updateRow( result, propertyCount, propertyNames, propertyOffsets, datatypeIndices, pointer ); sqlite3_bind_int( result, activePropertyCount + 1, id ); //printf("propertyCount: %i %i\n", propertyCount, id ); sqlite3_step( result ); sqlite3_finalize( result ); //printf("update query: %s\n", query->buffer); } void addRow( void * row ) { int classIndex = getClassIndexByClassName( this->selectedModel ); text * query = new text( "" ); query->append( "INSERT INTO " ); query->append( this->selectedModel ); sqlite3_stmt * result; char * * propertyNames = getPropertiesByClassIndex( classIndex ); int propertyCount = getPropertyCountByClassIndex( classIndex ); int * propertyOffsets = getPropertyOffsetsByClassIndex( classIndex ); int * datatypeIndices = getPropertyDatatypeIndexesByClassIndex( classIndex ); char * pointer = row; query->append( " ( " ); for (int propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex) { char * propertyName = propertyNames[ propertyIndex ]; int datatype = datatypeIndices[ propertyIndex ]; if( datatype > 0 ) { // join table because this is an class continue; } if( propertyIndex > 0 ) { query->append( ", " ); } query->append( propertyName ); } query->append( " ) " ); query->append( " VALUES ( " ); for (int propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex) { int datatype = datatypeIndices[ propertyIndex ]; if( datatype > 0 ) { // set joined table id continue; } if( propertyIndex > 0 ) { query->append( ", " ); } query->append( "?" ); } query->append(" ) " ); // { sqlite3_prepare_v2( this->db, query->value, -1, &result, 0 ); this->updateRow( result, propertyCount, propertyNames, propertyOffsets, datatypeIndices, pointer ); sqlite3_step( result ); // } sqlite3_finalize( result ); //printf("query: %s\n", query->buffer); } struct array * fetchRows( char * sql ) { sqlite3_stmt * result; int rc = sqlite3_prepare_v2( this->db, sql, -1, &result, 0 ); if ( rc != SQLITE_OK ) { printf("Failed to execute statement: %s\n", sqlite3_errmsg( this->db ) ); } /* if ( rc != SQLITE_ROW ) { printf("not rows found\n\n"); } */ int rowIndex = 0; //printf("select className: %s\n", this->selectedModel); int classIndex = getClassIndexByClassName( this->selectedModel ); //printf("class index: %i\n", classIndex); int propertyIndex = getPropertyIndexByPropertyName( classIndex, "username" ); int propertyCount = getPropertyCountByClassIndex( classIndex ); char ** propertyNames = getPropertiesByClassIndex( classIndex ); int * propertyOffsets = getPropertyOffsetsByClassIndex( classIndex ); int * datatypeIndices = getPropertyDatatypeIndexesByClassIndex( classIndex ); char * shortPointer = malloc( sizeof( char * ) * 100000 ); void * * voidArray = malloc( sizeof( void * ) * 100000 ); int structByteSize; getArrayByClassIndex( 1000, voidArray, &structByteSize, classIndex ); shortPointer = ( char * ) shortPointer; while ( sqlite3_step( result ) != SQLITE_DONE ) { //if( rowsCount == 0 ) { int pointerIndex = ( rowIndex * ( structByteSize ) ); //==printf("pointerIndex: %i\n", pointerIndex); char * pointer = shortPointer + pointerIndex; int columnCount = sqlite3_data_count( result ); //printf("columnCount: %i\n\n", columnCount); for (int i = 0; i < columnCount; ++i) { const char * columnName = sqlite3_column_name( result, i ); const int propertyIndex = getPropertyIndexByPropertyName( classIndex, (char *)columnName ); int propertyDatatypeIndex = getPropertyDatatypeIndex( datatypeIndices, propertyIndex ); int propertyOffset = getPropertyOffsetByPropertyIndex( propertyOffsets, propertyIndex ); //printf("sqlite3 column index: %i\n", i); //printf("sqlite3 columnName: %s\n", columnName); //printf("class property index: %i\n", propertyIndex); //printf("class property offset: %i\n", propertyOffset); if( propertyDatatypeIndex == -5 ) { const int columnValue = sqlite3_column_int( result, i ); *( int * )( pointer + propertyOffset ) = columnValue; } else if( propertyDatatypeIndex == -3 ) { const char * columnValue = sqlite3_column_text( result, i ); char * columnValueCopy = malloc( strlen( columnValue ) ); strncpy( columnValueCopy, columnValue, strlen( columnValue ) ); //columnValueCopy[8] = "\0"; // something wrong here. memcpy( pointer + propertyOffset, &columnValueCopy, 8 ); } //printf("class property datatype: %i\n\n\n", propertyDatatypeIndex); } voidArray[rowIndex] = pointer; // printf("rowIndex: %i\n", rowIndex); rowIndex++; } struct array * rows = new array(); rows->items = voidArray; rows->total = rowIndex; return rows; } }