2 public import static "ecere"
3 public import static "EDA"
11 static void UnusedFunction()
19 a.OnEdit(null,null,0,0,0,0,0);
20 a.OnDisplay(null,0,0,0,0,0,0);
21 a.OnGetDataFromString(null);
22 a.OnUnserialize(null);
27 extern int __ecereVMethodID_class_OnGetString;
28 extern int __ecereVMethodID_class_OnGetDataFromString;
29 extern int __ecereVMethodID_class_OnCompare;
30 extern int __ecereVMethodID_class_OnSerialize;
31 extern int __ecereVMethodID_class_OnUnserialize;
32 extern int __ecereVMethodID_class_OnFree;
35 static int CollationCompare(Class type, int count1, void * data1, int count2, void * data2)
37 if(type.type == normalClass || type.type == noHeadClass)
39 Instance inst1, inst2;
41 SerialBuffer buffer1 { size = count1, count = count1, buffer = data1 };
42 SerialBuffer buffer2 { size = count2, count = count2, buffer = data2 };
44 type._vTbl[__ecereVMethodID_class_OnUnserialize](type, &inst1, buffer1);
45 type._vTbl[__ecereVMethodID_class_OnUnserialize](type, &inst2, buffer2);
47 result = type._vTbl[__ecereVMethodID_class_OnCompare](type, inst1, inst2);
49 buffer1.buffer = null;
50 buffer2.buffer = null;
57 else if(type.type == structClass)
59 void * inst1, * inst2;
61 SerialBuffer buffer1 { size = count1, count = count1, buffer = data1 };
62 SerialBuffer buffer2 { size = count2, count = count2, buffer = data2 };
64 inst1 = new0 byte[type.structSize];
65 inst2 = new0 byte[type.structSize];
66 type._vTbl[__ecereVMethodID_class_OnUnserialize](type, inst1, buffer1);
67 type._vTbl[__ecereVMethodID_class_OnUnserialize](type, inst2, buffer2);
69 result = type._vTbl[__ecereVMethodID_class_OnCompare](type, inst1, inst2);
71 buffer1.buffer = null;
72 buffer2.buffer = null;
80 return type._vTbl[__ecereVMethodID_class_OnCompare](type, data1, data2);
83 class SQLiteField : Field
88 public LinkElement<SQLiteField> link;
105 int GetLength() { return length; }
116 class SQLiteDatabase : Database
119 AVLTree<String> collations { };
126 uint ObjectsCount(ObjectType type)
132 bool RenameObject(ObjectType type, const String name, const String rename)
138 bool DeleteObject(ObjectType type, const String name)
144 Table OpenTable(const String name, OpenOptions options)
148 int nRows = 0, nCols = 0;
150 SQLiteTable table = null;
151 if(options.type == tablesList)
153 SQLiteField field { name = CopyString("Name"), type = class(String), num = -1, sqliteType = SQLITE_TEXT };
154 strcpy(command, "SELECT name FROM sqlite_master WHERE type='table' AND name!='eda_table_fields';");
155 table = SQLiteTable { db = this, specialStatement = CopyString(command) };
158 table.fields.Add(field);
160 else if(options.type == fieldsList)
164 sprintf(command, "SELECT Name, Type, Length FROM eda_table_fields WHERE Table_Name='%s';", name);
165 table = SQLiteTable { db = this, specialStatement = CopyString(command) };
167 field = { name = CopyString("Name"), type = class(String), num = -1, sqliteType = SQLITE_TEXT };
169 table.fields.Add(field);
170 field = { name = CopyString("Type"), type = class(Class), num = 0, sqliteType = SQLITE_TEXT };
172 table.fields.Add(field);
173 field = { name = CopyString("Length"), type = class(int), num = 1, sqliteType = SQLITE_INTEGER };
175 table.fields.Add(field);
177 else if(options.type == tableRows)
179 bool addFields = false;
181 sprintf(command, "SELECT Name FROM eda_table_fields WHERE Table_Name='%s';", name);
182 result = sqlite3_get_table(db, command, &t, &nRows, &nCols, null);
186 sqlite3_free_table(t);
188 sprintf(command, "SELECT sql FROM sqlite_master WHERE type='table' AND name='%s';", name);
189 nCols = 0, nRows = 0;
190 result = sqlite3_get_table(db, command, &t, &nRows, &nCols, null);
192 if((nCols || nRows) || options.create)
194 table = SQLiteTable { db = this, name = CopyString(name) };
197 table.mustCreate = true;
203 for(r = 1; r <= nRows; r++) // There should be only 1 row here
205 char * sql = t[nCols * r];
206 char * bracket = strchr(sql, '(');
219 Class type = class(int);
223 while((ch = bracket[c++]))
225 if(ch == ',' || ch == ')')
228 for(d = c-1; d >= 0 && bracket[d] != ' '; d--);
230 memcpy(fieldName, bracket + start, d - start);
231 fieldName[d - start] = 0;
233 memcpy(dataType, bracket + d + 1, c - d - 2);
234 dataType[c - d - 2] = 0;
236 while(ch && bracket[c] == ' ') c++;
238 if(!strcmp(dataType, "REAL")) { sqliteType = SQLITE_FLOAT; type = class(double); }
239 else if(!strcmp(dataType, "TEXT")) { sqliteType = SQLITE_TEXT; type = class(String); }
240 else if(!strcmp(dataType, "INTEGER")) { sqliteType = SQLITE_INTEGER; type = class(int); }
241 else if(!strcmp(dataType, "BLOB")) { sqliteType = SQLITE_BLOB; type = class(char *); } //class(byte *);
243 sprintf(command, "INSERT INTO eda_table_fields (Table_Name, Name, Type, Length) VALUES ('%s', '%s', '%s', %d);", name,
244 fieldName, type.name, 0);
245 result = sqlite3_exec(db, command, null, null, null);
248 SQLiteField field { name = CopyString(fieldName), type = type, num = table.fields.count, sqliteType = sqliteType };
250 table.fields.Add(field);
253 if(!ch || ch == ')') break;
260 sqlite3_stmt * statement;
262 sprintf(command, "SELECT Name, Type, Length FROM eda_table_fields WHERE Table_Name='%s';", name);
263 result = sqlite3_prepare_v2(db, command, -1, &statement, null);
265 while(sqlite3_step(statement) != SQLITE_DONE)
267 char * fieldName = sqlite3_column_text(statement, 0);
268 char * typeName = sqlite3_column_text(statement, 1);
269 int length = sqlite3_column_int(statement, 2);
273 ((Class)(&type)).OnGetDataFromString(typeName); // TODO: THIS REQUIRES A FIX SOMEWHERE ELSE
277 if(!strcmp(type.dataTypeString, "int") || !strcmp(type.dataTypeString, "unsigned int") ||
278 !strcmp(type.dataTypeString, "long") || !strcmp(type.dataTypeString, "long int") ||
279 !strcmp(type.dataTypeString, "uint") || !strcmp(type.dataTypeString, "uint32") ||
280 !strcmp(type.dataTypeString, "int64") || !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64") ||
281 !strcmp(type.dataTypeString, "short") || !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
282 !strcmp(type.dataTypeString, "char") || !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
283 sqliteType = SQLITE_INTEGER;
284 else if(!strcmp(type.dataTypeString, "double") || !strcmp(type.dataTypeString, "float"))
285 sqliteType = SQLITE_FLOAT;
286 else if(!strcmp(type.dataTypeString, "String") || !strcmp(type.dataTypeString, "char *"))
287 sqliteType = SQLITE_TEXT;
290 if(strcmp(type.fullName, "CIString") && !collations.Find(type.fullName))
292 collations.Add(type.fullName);
293 sqlite3_create_collation_v2(table.db.db, type.fullName, SQLITE_UTF8, type, CollationCompare, null);
295 sqliteType = SQLITE_BLOB;
300 SQLiteField field { name = CopyString(fieldName), type = type, length = length, num = table.fields.count, sqliteType = sqliteType };
302 table.fields.Add(field);
305 sqlite3_finalize(statement);
309 sqlite3_free_table(t);
318 sprintf(command, "BEGIN;");
319 result = sqlite3_exec(db, command, null, null, null);
321 PrintLn("BEGIN FAILED!");
322 return result == SQLITE_OK;
329 sprintf(command, "COMMIT;");
330 result = sqlite3_exec(db, command, null, null, null);
332 PrintLn("COMMIT FAILED!");
333 return result == SQLITE_OK;
336 bool CreateCustomFunction(char * name, SQLCustomFunction customFunction)
338 int result = sqlite3_create_function(db, name, 1, SQLITE_UTF8, customFunction, SQLiteFunctionProcessor, null, null);
339 return result == SQLITE_OK;
343 static void SQLiteFunctionProcessor(sqlite3_context* context, int n, sqlite3_value** value)
345 SQLCustomFunction sqlFunction = sqlite3_user_data(context);
346 char * text = sqlite3_value_text(*value);
347 sqlFunction.array.size = 1;
348 sqlFunction.array[0] = 0;
349 sqlFunction.Process(text);
350 sqlite3_result_text(context, sqlFunction.array.array, sqlFunction.array.count ? sqlFunction.array.count - 1 : 0, SQLITE_TRANSIENT);
353 class SQLiteTable : Table
358 LinkList<SQLiteField> fields { };
359 char * specialStatement;
360 SQLiteField primaryKey;
361 FieldIndex * indexFields;
362 int indexFieldsCount;
365 Field AddField(const String fieldName, Class type, int length)
372 Table refTable = null;
373 Field idField = null;
376 if(FindField(fieldName)) return null;
378 if(!strcmp(type.dataTypeString, "int") || !strcmp(type.dataTypeString, "unsigned int") ||
379 !strcmp(type.dataTypeString, "long") || !strcmp(type.dataTypeString, "long int") ||
380 !strcmp(type.dataTypeString, "uint") || !strcmp(type.dataTypeString, "uint32") ||
381 !strcmp(type.dataTypeString, "int64") || !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64") ||
382 !strcmp(type.dataTypeString, "short") || !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
383 !strcmp(type.dataTypeString, "char") || !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
385 strcpy(dataType, "INTEGER");
386 sqliteType = SQLITE_INTEGER;
388 else if(!strcmp(type.dataTypeString, "double") || !strcmp(type.dataTypeString, "float"))
390 strcpy(dataType, "REAL");
391 sqliteType = SQLITE_FLOAT;
393 else if(!strcmp(type.name, "CIString"))
395 strcpy(dataType, "TEXT");
396 sqliteType = SQLITE_BLOB;
398 else if(!strcmp(type.dataTypeString, "String") || !strcmp(type.dataTypeString, "char *"))
400 strcpy(dataType, "TEXT");
401 sqliteType = SQLITE_TEXT;
405 //strcpy(dataType, "BLOB");
406 strcpy(dataType, "TEXT");
407 sqliteType = SQLITE_BLOB;
409 if(!db.collations.Find(type.fullName))
411 db.collations.Add(type.fullName);
412 result = sqlite3_create_collation_v2(db.db, type.fullName, SQLITE_UTF8, type, CollationCompare, null);
415 if(sqliteType != SQLITE_BLOB && eClass_IsDerived(type, class(eda::Id)))
417 Table * table = (Table *)eClass_GetProperty(type, "table");
418 if(table) refTable = *table;
421 if(primaryKey || refTable != this)
423 for(idField = refTable.firstField; idField; idField = idField.next)
424 if(eClass_IsDerived(type, idField.type)) break;
427 PrintLn("WARNING: field not yet created for class ", (String)type.name);
430 idField = primaryKey;
434 PrintLn("WARNING: Table not yet created for class ", (String)type.name);
440 if(sqliteType == SQLITE_BLOB)
442 if(!strcmp(type.name, "CIString"))
443 sprintf(command, "CREATE TABLE `%s`(%s %s COLLATE NOCASE);", name, fieldName, dataType);
445 sprintf(command, "CREATE TABLE `%s`(%s %s COLLATE '%s');", name, fieldName, dataType, type.fullName);
449 if(!idField && refTable == this)
450 sprintf(command, "CREATE TABLE `%s`(`%s` %s PRIMARY KEY);", name, fieldName, dataType);
452 sprintf(command, "CREATE TABLE `%s`(`%s` %s REFERENCES `%s`(`%s`));", name, fieldName, dataType, refTable.name, idField.name);
455 sprintf(command, "CREATE TABLE `%s`(`%s` %s);", name, fieldName, dataType);
456 result = sqlite3_exec(db.db, command, null, null, null);
457 if(result) return null;
462 if(sqliteType == SQLITE_BLOB)
464 if(!strcmp(type.name, "CIString"))
465 sprintf(command, "ALTER TABLE `%s` ADD `%s` %s COLLATE NOCASE;", name, fieldName, dataType);
467 sprintf(command, "ALTER TABLE `%s` ADD `%s` %s COLLATE `%s`;", name, fieldName, dataType, type.fullName);
471 if(!idField && refTable == this)
473 PrintLn("WARNING: ALTER TABLE DOESN'T WORK WITH PRIMARY KEY FOR ", (String)name);
474 sprintf(command, "ALTER TABLE `%s` ADD `%s` %s PRIMARY KEY;", name, fieldName, dataType);
477 sprintf(command, "ALTER TABLE `%s` ADD `%s` %s REFERENCES `%s`(`%s`);", name, fieldName, dataType, refTable.name, idField.name);
480 sprintf(command, "ALTER TABLE `%s` ADD `%s` %s;", name, fieldName, dataType);
481 result = sqlite3_exec(db.db, command, null, null, null);
482 if(result) return null;
485 sprintf(command, "INSERT INTO eda_table_fields (Table_Name, Name, Type, Length) VALUES ('%s', '%s', '%s', %d);", name,
486 fieldName, type.name, length);
487 result = sqlite3_exec(db.db, command, null, null, null);
489 field = { name = CopyString(fieldName), type = type, num = fields.count, sqliteType = sqliteType };
492 if(!primaryKey && refTable == this)
497 Field FindField(const String name)
499 for(f : fields; !strcmp(f.name, name))
503 if(f.sqliteType != SQLITE_BLOB && eClass_IsDerived(f.type, class(eda::Id)))
506 Table * tablePtr = (Table *)eClass_GetProperty(f.type, "table");
507 if(tablePtr && *tablePtr == this)
516 bool GenerateIndex(int count, FieldIndex * fieldIndexes, bool init)
521 char indexName[4096];
524 indexFieldsCount = count;
525 indexFields = new FieldIndex[count];
526 memcpy(indexFields, fieldIndexes, count * sizeof(FieldIndex));
528 // TODO: USE CODED INDEX NAME INSTEAD?
529 strcpy(indexName, "index_");
530 strcat(indexName, name);
531 strcat(indexName, "_");
532 for(c = 0; c<count; c++)
534 if(fieldIndexes[c].field)
536 if(count == 1 && fieldIndexes[c].field == primaryKey)
538 strcat(indexName, fieldIndexes[c].field.name);
539 if(fieldIndexes[c].memberField)
541 strcat(indexName, ".");
542 strcat(indexName, fieldIndexes[c].memberField.name);
544 strcat(indexName, (fieldIndexes[c].order == ascending) ? "+" : "-");
550 sprintf(command, "CREATE INDEX IF NOT EXISTS `%s` ON `%s` (", indexName, name);
551 for(c = 0; c<count; c++)
553 char columnName[1024];
554 sprintf(columnName, "`%s` %s", fieldIndexes[c].field.name, (fieldIndexes[c].order == ascending) ? "ASC" : "DESC");
555 if(c > 0) strcat(command, ", ");
556 strcat(command, columnName);
558 strcat(command, ");");
559 result = sqlite3_exec(db.db, command, null, null, null);
561 return result == SQLITE_OK;
569 Field GetFirstField()
574 uint GetFieldsCount()
586 sprintf(command, "SELECT COUNT(*) FROM `%s`;", name);
587 result = sqlite3_get_table(db.db, command, &t, &nRows, &nCols, null);
588 if(result == SQLITE_OK)
590 rowCount = atoi(t[1]);
591 sqlite3_free_table(t);
596 DriverRow CreateRow()
599 sqlite3_stmt * statement;
600 sqlite3_stmt * sysIDStmt = null, * insertStmt = null, * deleteStmt = null, * selectRowIDsStmt = null, * setRowIDStmt = null;
603 strcpy(command, specialStatement);
606 /*sprintf(command, "SELECT ROWID, * FROM `%s` WHERE ? = ?;", name);
607 sqlite3_prepare_v2(db.db, command, -1, &findStmt, null);*/
608 sprintf(command, "SELECT ROWID, * FROM `%s` WHERE ROWID = ?;", name);
609 sqlite3_prepare_v2(db.db, command, -1, &sysIDStmt, null);
611 sprintf(command, "INSERT INTO `%s` DEFAULT VALUES;", name);
612 sqlite3_prepare_v2(db.db, command, -1, &insertStmt, null);
613 sprintf(command, "DELETE FROM `%s` WHERE ROWID = ?;", name);
614 sqlite3_prepare_v2(db.db, command, -1, &deleteStmt, null);
615 /*sprintf(command, "UPDATE `%s` SET ? = ? WHERE ROWID = ?;", name);
616 sqlite3_prepare_v2(db.db, command, -1, &updateStmt, null);*/
618 if(!indexFields || (indexFieldsCount == 1 && indexFields[0].field == primaryKey && indexFields[0].order == ascending))
619 sprintf(command, "SELECT ROWID, * FROM `%s`;", name);
623 sprintf(command, "SELECT ROWID, * FROM `%s` ORDER BY ", name);
624 for(c = 0; c < indexFieldsCount; c++)
627 FieldIndex * fIndex = &indexFields[c];
629 if(c) strcat(order, ", ");
631 strcat(order, fIndex->field.name);
633 if(fIndex->order == descending) strcat(command, " DESC");
634 strcat(command, order);
636 strcat(command, ";");
639 sqlite3_prepare_v2(db.db, command, -1, &statement, null);
641 sprintf(command, "SELECT ROWID FROM `%s` WHERE ROWID > ?", name);
642 sqlite3_prepare_v2(db.db, command, -1, &selectRowIDsStmt, null);
644 sprintf(command, "UPDATE `%s` SET ROWID = ? WHERE ROWID = ?", name);
645 sqlite3_prepare_v2(db.db, command, -1, &setRowIDStmt, null);
648 { tbl = this, defaultStatement = statement, curStatement = statement, sysIDStatement = sysIDStmt,
649 insertStatement = insertStmt, deleteStatement = deleteStmt, selectRowIDsStmt = selectRowIDsStmt, setRowIDStmt = setRowIDStmt };
655 delete specialStatement;
661 class SQLiteRow : DriverRow
664 sqlite3_stmt * curStatement;
666 sqlite3_stmt * defaultStatement;
667 sqlite3_stmt * findStatement;
668 sqlite3_stmt * sysIDStatement;
669 sqlite3_stmt * queryStatement;
670 sqlite3_stmt * findMultipleStatement;
671 sqlite3_stmt * selectRowIDsStmt;
672 sqlite3_stmt * setRowIDStmt;
674 sqlite3_stmt * insertStatement;
675 sqlite3_stmt * deleteStatement;
676 sqlite3_stmt * updateStatement;
688 if(defaultStatement) sqlite3_finalize(defaultStatement);
689 if(findStatement) sqlite3_finalize(findStatement);
690 if(findMultipleStatement) sqlite3_finalize(findMultipleStatement);
691 if(sysIDStatement) sqlite3_finalize(sysIDStatement);
692 if(insertStatement) sqlite3_finalize(insertStatement);
693 if(deleteStatement) sqlite3_finalize(deleteStatement);
694 if(updateStatement) sqlite3_finalize(updateStatement);
695 if(queryStatement) sqlite3_finalize(queryStatement);
696 if(selectRowIDsStmt) sqlite3_finalize(selectRowIDsStmt);
697 if(setRowIDStmt) sqlite3_finalize(setRowIDStmt);
700 bool Select(MoveOptions move)
704 curStatement = defaultStatement;
709 sqlite3_reset(curStatement);
710 result = sqlite3_step(curStatement);
711 done = result == SQLITE_DONE || (result && result != SQLITE_ROW);
712 if(done) { rowID = 0; sqlite3_reset(curStatement); return false; }
713 rowID = sqlite3_column_int64(curStatement, 0);
718 sqlite3_stmt * statement;
720 sprintf(command, "SELECT MAX(ROWID) FROM `%s`", tbl.name);
721 result = sqlite3_prepare_v2(tbl.db.db, command, -1, &statement, null);
722 result = sqlite3_step(statement);
723 rowID = sqlite3_column_int64(statement, 0);
724 sqlite3_finalize(statement);
731 result = sqlite3_step(curStatement);
732 done = result == SQLITE_DONE || (result && result != SQLITE_ROW);
733 if(done) { rowID = 0; sqlite3_reset(curStatement); return false; }
734 rowID = sqlite3_column_int64(curStatement, 0);
740 sqlite3_reset(curStatement);
750 bool Query(char * queryString)
756 sqlite3_reset(curStatement);
759 sqlite3_finalize(queryStatement);
760 queryStatement = null;
765 result = sqlite3_prepare_v2(tbl.db.db, queryString, -1, &queryStatement, null);
766 curStatement = queryStatement;
767 if(!strchr(queryString, '?'))
769 result = sqlite3_step(queryStatement);
771 done = result == SQLITE_DONE || (result && result != SQLITE_ROW);
772 if(done) { rowID = 0; sqlite3_reset(queryStatement); return false; }
774 rowID = sqlite3_column_int64(queryStatement, 0);
782 bool Find(Field fld, MoveOptions move, MatchOptions match, typed_object data)
786 SQLiteField sqlFld = (SQLiteField)fld;
787 Class dataType = sqlFld.type;
789 if(fld == tbl.primaryKey)
791 return GoToSysID(*(int *)data);
795 sqlite3_reset(curStatement);
797 sqlite3_finalize(findStatement);
799 sprintf(command, "SELECT ROWID, * FROM `%s` WHERE `%s` = ?;", tbl.name, fld.name);
800 result = sqlite3_prepare_v2(tbl.db.db, command, -1, &findStatement, null);
802 // result = sqlite3_bind_text(findStatement, 1, fld.name, strlen(fld.name), SQLITE_STATIC);
804 curStatement = findStatement;
805 switch(sqlFld.sqliteType)
809 switch(dataType.typeSize)
812 sqlite3_bind_int64(findStatement, 1, (sqlite3_int64)*(int64 *)data);
815 sqlite3_bind_int(findStatement, 1, *(int *)data);
821 value = (int)*(short *)data;
823 value = (int)*(uint16 *)data;
824 sqlite3_bind_int(findStatement, 1, value);
831 value = (int)*(char *)data;
833 value = (int)*(byte *)data;
834 sqlite3_bind_int(findStatement, 1, value);
842 if(dataType.typeSize == 8)
843 sqlite3_bind_double(findStatement, 1, *(double *)data);
845 sqlite3_bind_double(findStatement, 1, (double)*(float *)data);
851 sqlite3_bind_text(findStatement, 1, (char *)data, strlen((char *)data), SQLITE_STATIC);
853 sqlite3_bind_text(findStatement, 1, null, 0, SQLITE_STATIC);
859 SerialBuffer buffer { };
861 dataType._vTbl[__ecereVMethodID_class_OnSerialize](dataType, data, buffer);
862 //sqlite3_bind_blob(findStatement, 1, buffer._buffer, buffer.count, SQLITE_STATIC);
863 sqlite3_bind_text(findStatement, 1, buffer._buffer, buffer.count, SQLITE_STATIC);
864 result = sqlite3_step(findStatement);
866 done = result == SQLITE_DONE || (result && result != SQLITE_ROW);
867 if(done) { rowID = 0; sqlite3_reset(findStatement); delete buffer; return false; }
869 rowID = sqlite3_column_int64(findStatement, 0);
876 result = sqlite3_step(findStatement);
878 done = result == SQLITE_DONE || (result && result != SQLITE_ROW);
879 if(done) { rowID = 0; sqlite3_reset(findStatement); return false; }
881 rowID = sqlite3_column_int64(findStatement, 0);
885 bool FindMultiple(FieldFindData * findData, MoveOptions move, int numFields)
892 Array<SerialBuffer> serialBuffers { };
895 sqlite3_reset(curStatement);
896 if(findMultipleStatement)
897 sqlite3_finalize(findMultipleStatement);
899 sprintf(command, "SELECT ROWID, * FROM `%s` WHERE `", tbl.name);
900 for(c = 0; c < numFields; c++)
902 FieldFindData * fieldFind = &findData[c];
904 if(c) strcat(command, " AND `");
905 strcat(command, fieldFind->field.name);
906 strcat(command, "` = ?");
908 strcat(command, ";");
910 result = sqlite3_prepare_v2(tbl.db.db, command, -1, &findMultipleStatement, null);
911 curStatement = findMultipleStatement;
913 for(c = 0; c < numFields; c++)
915 FieldFindData * fieldFind = &findData[c];
916 SQLiteField sqlFld = (SQLiteField)fieldFind->field;
917 Class dataType = sqlFld.type;
919 switch(sqlFld.sqliteType)
923 switch(dataType.typeSize)
926 sqlite3_bind_int64(findMultipleStatement, 1 + c, (sqlite_int64)fieldFind->value.i64);
929 sqlite3_bind_int(findMultipleStatement, 1 + c, fieldFind->value.i);
935 value = (int)fieldFind->value.s;
937 value = (int)fieldFind->value.us;
938 sqlite3_bind_int(findMultipleStatement, 1 + c, value);
945 value = (int)fieldFind->value.c;
947 value = (int)fieldFind->value.uc;
948 sqlite3_bind_int(findMultipleStatement, 1 + c, value);
956 if(dataType.typeSize == 8)
957 sqlite3_bind_double(findMultipleStatement, 1 + c, fieldFind->value.d);
959 sqlite3_bind_double(findMultipleStatement, 1 + c, fieldFind->value.f);
964 if(fieldFind->value.p)
965 sqlite3_bind_text(findMultipleStatement, 1 + c, (char *)fieldFind->value.p, strlen(fieldFind->value.p), SQLITE_STATIC);
967 sqlite3_bind_text(findMultipleStatement, 1 + c, null, 0, SQLITE_STATIC);
973 SerialBuffer buffer { };
975 dataType._vTbl[__ecereVMethodID_class_OnSerialize](dataType, fieldFind->value.p, buffer);
976 //sqlite3_bind_blob(findMultipleStatement, 1 + c, buffer._buffer, buffer.count, SQLITE_STATIC);
977 sqlite3_bind_text(findMultipleStatement, 1 + c, buffer._buffer, buffer.count, SQLITE_STATIC);
979 serialBuffers.Add(buffer);
985 result = sqlite3_step(findMultipleStatement);
987 done = result == SQLITE_DONE || (result && result != SQLITE_ROW);
991 sqlite3_reset(findMultipleStatement);
993 serialBuffers.Free();
994 delete serialBuffers;
999 rowID = sqlite3_column_int64(findMultipleStatement, 0);
1001 serialBuffers.Free();
1002 delete serialBuffers;
1009 bool Synch(DriverRow to)
1017 //char command[1024];
1018 //sprintf(command, "INSERT INTO `%s` DEFAULT VALUES;", tbl.name);
1019 //result = sqlite3_exec(tbl.db.db, command, null, null, null);
1020 result = sqlite3_step(insertStatement);
1021 if(result == SQLITE_DONE) // if(result == SQLITE_OK)
1023 rowID = sqlite3_last_insert_rowid(tbl.db.db);
1024 if(rowID > MAXDWORD)
1026 int64 lastID = tbl.lastID;
1028 sqlite3_bind_int64(selectRowIDsStmt, 1, (sqlite3_int64)lastID);
1032 result = sqlite3_step(selectRowIDsStmt);
1033 if(result == SQLITE_DONE || result != SQLITE_ROW) break;
1034 id = sqlite3_column_int64(selectRowIDsStmt, 0);
1035 if(id - lastID > 1) break;
1038 sqlite3_reset(selectRowIDsStmt);
1040 sqlite3_bind_int64(setRowIDStmt, 2, (sqlite3_int64)rowID);
1043 sqlite3_bind_int64(setRowIDStmt, 1, (sqlite3_int64)rowID);
1044 result = sqlite3_step(setRowIDStmt);
1045 sqlite3_reset(setRowIDStmt);
1047 sqlite3_reset(insertStatement);
1048 curStatement = sysIDStatement;
1049 sqlite3_reset(curStatement);
1052 sqlite3_reset(insertStatement);
1059 //char command[1024];
1060 //sprintf(command, "DELETE FROM `%s` WHERE ROWID = %d;", tbl.name, rowID);
1061 //result = sqlite3_exec(tbl.db.db, command, null, null, null);
1062 sqlite3_bind_int64(deleteStatement, 1, (sqlite3_int64)rowID);
1063 result = sqlite3_step(deleteStatement);
1064 sqlite3_reset(deleteStatement);
1066 return result == SQLITE_OK || result == SQLITE_DONE;
1069 bool GetData(Field fld, typed_object &data)
1071 SQLiteField sqlFld = (SQLiteField)fld;
1072 int num = sqlFld.num + 1;
1073 Class dataType = sqlFld.type;
1074 switch(sqlFld.sqliteType)
1076 case SQLITE_INTEGER:
1078 switch(dataType.typeSize)
1081 if(fld == tbl.primaryKey)
1082 *(int64 *)data = rowID;
1084 *(int64 *)data = sqlite3_column_int64(curStatement, num);
1087 if(fld == tbl.primaryKey)
1088 *(int *)data = (int)(uint)rowID;
1090 *(int *)data = sqlite3_column_int(curStatement, num);
1095 if(fld == tbl.primaryKey)
1096 value = (int)(uint)rowID;
1098 value = sqlite3_column_int(curStatement, num);
1100 *(short *)data = (short)value;
1102 *(uint16 *)data = (uint16)value;
1108 if(fld == tbl.primaryKey)
1109 value = (int)(uint)rowID;
1111 value = sqlite3_column_int(curStatement, num);
1113 *(char *)data = (char)value;
1115 *(byte *)data = (byte)value;
1123 double d = sqlite3_column_double(curStatement, num);
1124 if(dataType.typeSize == 8)
1125 *(double *)data = d;
1127 *(float *)data = (float)d;
1132 int numBytes = sqlite3_column_bytes(curStatement, num);
1133 char * text = sqlite3_column_text(curStatement, num);
1134 *(char **)data = text ? new byte[numBytes+1] : null;
1136 memcpy(*(char **)data, text, numBytes+1);
1141 SerialBuffer buffer { };
1142 //buffer._buffer = sqlite3_column_blob(curStatement, num);
1143 buffer._size = sqlite3_column_bytes(curStatement, num);
1144 buffer._buffer = sqlite3_column_text(curStatement, num);
1145 buffer.count = buffer._size;
1147 dataType._vTbl[__ecereVMethodID_class_OnUnserialize](dataType, data, buffer);
1149 buffer._buffer = null;
1157 bool SetData(Field fld, typed_object data)
1159 SQLiteField sqlFld = (SQLiteField)fld;
1162 int num = sqlFld.num + 1;
1163 Class dataType = sqlFld.type;
1165 //sqlite3_stmt * setStatement;
1168 sqlite3_finalize(updateStatement);
1170 // sprintf(command, "UPDATE `%s` SET `%s` = ? WHERE ROWID = %d;", tbl.name, sqlFld.name, rowID);
1171 sprintf(command, "UPDATE `%s` SET `%s` = ? WHERE ROWID = ?;", tbl.name, sqlFld.name);
1173 result = sqlite3_prepare_v2(tbl.db.db, command, -1, &updateStatement, null);
1175 //sqlite3_bind_text(updateStatement, 1, sqlFld.name, strlen(sqlFld.name), SQLITE_STATIC);
1176 //sqlite3_bind_int64(updateStatement, 3, (sqlite3_int64)rowID);
1178 sqlite3_bind_int64(updateStatement, 2, (sqlite3_int64)rowID);
1179 switch(sqlFld.sqliteType)
1181 case SQLITE_INTEGER:
1183 switch(dataType.typeSize)
1186 sqlite3_bind_int64(updateStatement, 1, (sqlite3_int64)*(int64 *)data);
1189 sqlite3_bind_int(updateStatement, 1, *(int *)data);
1195 value = (int)*(short *)data;
1197 value = (int)*(uint16 *)data;
1198 sqlite3_bind_int(updateStatement, 1, value);
1205 value = (int)*(char *)data;
1207 value = (int)*(byte *)data;
1208 sqlite3_bind_int(updateStatement, 1, value);
1216 if(dataType.typeSize == 8)
1217 sqlite3_bind_double(updateStatement, 1, *(double *)data);
1219 sqlite3_bind_double(updateStatement, 1, (double)*(float *)data);
1224 // TOFIX: Checking a not casted typed_object for null should generate a compiler error (crashes!)
1226 sqlite3_bind_text(updateStatement, 1, (char *)data, strlen((char *)data), SQLITE_STATIC);
1228 sqlite3_bind_text(updateStatement, 1, null, 0, SQLITE_STATIC);
1234 SerialBuffer buffer { };
1236 dataType._vTbl[__ecereVMethodID_class_OnSerialize](dataType, data, buffer);
1237 //sqlite3_bind_blob(updateStatement, 1, buffer._buffer, buffer.count, SQLITE_STATIC);
1238 sqlite3_bind_text(updateStatement, 1, buffer._buffer, buffer.count, SQLITE_STATIC);
1239 sqlite3_step(updateStatement);
1240 sqlite3_reset(updateStatement);
1246 result = sqlite3_step(updateStatement);
1247 sqlite3_reset(updateStatement);
1248 if(fld == tbl.primaryKey)
1250 rowID = *(uint *)data;
1252 return result == SQLITE_DONE;
1257 return (int)(uint)rowID;
1260 bool GoToSysID(int id)
1262 //char command[1024];
1266 //sqlite3_finalize(statement);
1267 //sprintf(command, "SELECT ROWID, * FROM `%s` WHERE ROWID = ?;", tbl.name);
1268 //result = sqlite3_prepare_v2(tbl.db.db, command, -1, &statement, null);
1271 sqlite3_reset(curStatement);
1273 curStatement = sysIDStatement;
1274 sqlite3_reset(sysIDStatement);
1275 sqlite3_bind_int64(curStatement, 1, (sqlite_int64)rowID);
1276 result = sqlite3_step(curStatement);
1277 done = result == SQLITE_DONE || (result && result != SQLITE_ROW);
1278 if(done) { rowID = 0; sqlite3_reset(curStatement); return false; }
1282 bool SetQueryParam(int paramID, int value)
1285 if(curStatement != queryStatement)
1287 if(curStatement) sqlite3_reset(curStatement);
1288 curStatement = queryStatement;
1290 sqlite3_reset(queryStatement);
1291 result = sqlite3_bind_int(queryStatement, paramID, value);
1295 bool SetQueryParam64(int paramID, int64 value)
1298 if(curStatement != queryStatement)
1300 if(curStatement) sqlite3_reset(curStatement);
1301 curStatement = queryStatement;
1303 sqlite3_reset(queryStatement);
1304 result = sqlite3_bind_int64(queryStatement, paramID, (sqlite_int64)value);
1308 bool SetQueryParamText(int paramID, char * data)
1311 if(curStatement != queryStatement)
1313 if(curStatement) sqlite3_reset(curStatement);
1314 curStatement = queryStatement;
1316 sqlite3_reset(queryStatement);
1318 result = sqlite3_bind_text(queryStatement, paramID, (char *)data, strlen((char *)data), SQLITE_STATIC);
1320 result = sqlite3_bind_text(queryStatement, paramID, null, 0, SQLITE_STATIC);
1324 bool SetQueryParamObject(int paramID, void * data, Class type)
1327 if(curStatement != queryStatement)
1329 if(curStatement) sqlite3_reset(curStatement);
1330 curStatement = queryStatement;
1332 sqlite3_reset(queryStatement);
1334 SerialBuffer buffer { };
1335 type._vTbl[__ecereVMethodID_class_OnSerialize](type, data, buffer);
1336 result = sqlite3_bind_text(queryStatement, paramID, buffer._buffer, buffer.count, SQLITE_TRANSIENT);
1342 /*char * GetExtraColumn(int paramID)
1344 SQLiteField lastFld = tbl.fields.last;
1345 return sqlite3_column_text(curStatement, lastFld.num + 1 + paramID);
1347 char * GetColumn(int paramID)
1349 return sqlite3_column_text(curStatement, paramID);