Files
c-prime/application/sqlite.c
2025-11-17 10:28:09 +01:00

818 lines
16 KiB
C
Executable File

#include <classConfiguration.h>
#include <stdlib.h>
#include <sqlite3.h>
#include <stdio.h>
#include <string.h>
#include <array.h>
#include <text.h>
#include "console.h"
#include "application.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->buffer, -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->buffer, -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->buffer, -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;
}
}