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 static class SQLiteDataSource : DataSourceDriver
118 class_property(name) = "SQLite";
120 OldList listDatabases;
123 String BuildLocator(DataSource ds)
125 return CopyString(ds.host);
128 uint GetDatabasesCount()
130 return databasesCount;
138 bool Connect(const String locator)
141 path = CopyString(locator);
142 // TODO, use user name and password for local security?
143 // TODO, open ds in read or write mode
147 FileListing listing { path, "sqlite" };
149 while(listing.Find())
156 bool RenameDatabase(const String name, const String rename)
158 if(name && rename && path && FileExists(path))
161 path = MakeDatabasePath(name);
166 repath = MakeDatabasePath(rename);
167 renamed = RenameFile(path, repath);
177 bool DeleteDatabase(const String name)
179 if(path && FileExists(path))
182 String path = MakeDatabasePath(name);
183 deleted = DeleteFile(path); // delete file seems to return true even if the file does not exist
191 String MakeDatabasePath(const String name)
195 char build[MAX_LOCATION];
196 strcpy(build, path ? path : "");
197 PathCat(build, name);
198 ChangeExtension(build, "sqlite", build);
199 return CopyString(build);
204 Database OpenDatabase(const String name, CreateOptions createOptions, DataSource ds)
206 Database result = null;
209 String path = MakeDatabasePath(name);
212 // sqlite3_open(path, &db);
213 // sqlite3_open_v2(path, &db, SQLITE_OPEN_READONLY /*SQLITE_OPEN_READWRITE*/ /*SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE*/, null );
215 if(sqlite3_open_v2(path, &db, (createOptions == readOnly) ? SQLITE_OPEN_READONLY :
216 (SQLITE_OPEN_READWRITE | ((createOptions == create) ? SQLITE_OPEN_CREATE : 0)), null))
218 // fprintf(stderr, "%s\n", s); // interesting
219 printf("Can't open database (%s): %s\n", path, sqlite3_errmsg(db));
225 sprintf(command, "CREATE TABLE eda_table_fields(Table_Name TEXT, Name TEXT, Type TEXT, Length INT);");
226 sqlite3_exec(db, command, null, null, null);
228 result = SQLiteDatabase { db = db };
236 class SQLiteDatabase : Database
239 AVLTree<String> collations { };
246 uint ObjectsCount(ObjectType type)
252 bool RenameObject(ObjectType type, const String name, const String rename)
258 bool DeleteObject(ObjectType type, const String name)
264 Table OpenTable(const String name, OpenOptions options)
268 int nRows = 0, nCols = 0;
270 SQLiteTable table = null;
271 if(options.type == tablesList)
273 SQLiteField field { name = CopyString("Name"), type = class(String), num = -1, sqliteType = SQLITE_TEXT };
274 strcpy(command, "SELECT name FROM sqlite_master WHERE type='table' AND name!='eda_table_fields';");
275 table = SQLiteTable { db = this, specialStatement = CopyString(command) };
278 table.fields.Add(field);
280 else if(options.type == fieldsList)
284 sprintf(command, "SELECT Name, Type, Length FROM eda_table_fields WHERE Table_Name='%s';", name);
285 table = SQLiteTable { db = this, specialStatement = CopyString(command) };
287 field = { name = CopyString("Name"), type = class(String), num = -1, sqliteType = SQLITE_TEXT };
289 table.fields.Add(field);
290 field = { name = CopyString("Type"), type = class(Class), num = 0, sqliteType = SQLITE_TEXT };
292 table.fields.Add(field);
293 field = { name = CopyString("Length"), type = class(int), num = 1, sqliteType = SQLITE_INTEGER };
295 table.fields.Add(field);
297 else if(options.type == tableRows)
299 bool addFields = false;
301 sprintf(command, "SELECT Name FROM eda_table_fields WHERE Table_Name='%s';", name);
302 result = sqlite3_get_table(db, command, &t, &nRows, &nCols, null);
306 sqlite3_free_table(t);
308 sprintf(command, "SELECT sql FROM sqlite_master WHERE type='table' AND name='%s';", name);
309 nCols = 0, nRows = 0;
310 result = sqlite3_get_table(db, command, &t, &nRows, &nCols, null);
312 if((nCols || nRows) || options.create)
314 table = SQLiteTable { db = this, name = CopyString(name) };
317 table.mustCreate = true;
323 for(r = 1; r <= nRows; r++) // There should be only 1 row here
325 char * sql = t[nCols * r];
326 char * bracket = strchr(sql, '(');
339 Class type = class(int);
343 while((ch = bracket[c++]))
345 if(ch == ',' || ch == ')')
348 for(d = c-1; d >= 0 && bracket[d] != ' '; d--);
350 memcpy(fieldName, bracket + start, d - start);
351 fieldName[d - start] = 0;
353 memcpy(dataType, bracket + d + 1, c - d - 2);
354 dataType[c - d - 2] = 0;
356 while(ch && bracket[c] == ' ') c++;
358 if(!strcmp(dataType, "REAL")) { sqliteType = SQLITE_FLOAT; type = class(double); }
359 else if(!strcmp(dataType, "TEXT")) { sqliteType = SQLITE_TEXT; type = class(String); }
360 else if(!strcmp(dataType, "INTEGER")) { sqliteType = SQLITE_INTEGER; type = class(int); }
361 else if(!strcmp(dataType, "BLOB")) { sqliteType = SQLITE_BLOB; type = class(char *); } //class(byte *);
363 sprintf(command, "INSERT INTO eda_table_fields (Table_Name, Name, Type, Length) VALUES ('%s', '%s', '%s', %d);", name,
364 fieldName, type.name, 0);
365 result = sqlite3_exec(db, command, null, null, null);
368 SQLiteField field { name = CopyString(fieldName), type = type, num = table.fields.count, sqliteType = sqliteType };
370 table.fields.Add(field);
373 if(!ch || ch == ')') break;
380 sqlite3_stmt * statement;
382 sprintf(command, "SELECT Name, Type, Length FROM eda_table_fields WHERE Table_Name='%s';", name);
383 result = sqlite3_prepare_v2(db, command, -1, &statement, null);
385 while(sqlite3_step(statement) != SQLITE_DONE)
387 char * fieldName = sqlite3_column_text(statement, 0);
388 char * typeName = sqlite3_column_text(statement, 1);
389 int length = sqlite3_column_int(statement, 2);
393 ((Class)(&type)).OnGetDataFromString(typeName); // TODO: THIS REQUIRES A FIX SOMEWHERE ELSE
397 if(!strcmp(type.dataTypeString, "int") || !strcmp(type.dataTypeString, "unsigned int") ||
398 !strcmp(type.dataTypeString, "long") || !strcmp(type.dataTypeString, "long int") ||
399 !strcmp(type.dataTypeString, "uint") || !strcmp(type.dataTypeString, "uint32") ||
400 !strcmp(type.dataTypeString, "int64") || !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64") ||
401 !strcmp(type.dataTypeString, "short") || !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
402 !strcmp(type.dataTypeString, "char") || !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
403 sqliteType = SQLITE_INTEGER;
404 else if(!strcmp(type.dataTypeString, "double") || !strcmp(type.dataTypeString, "float"))
405 sqliteType = SQLITE_FLOAT;
406 else if(!strcmp(type.dataTypeString, "String") || !strcmp(type.dataTypeString, "char *"))
407 sqliteType = SQLITE_TEXT;
410 if(strcmp(type.fullName, "CIString") && !collations.Find(type.fullName))
412 collations.Add(type.fullName);
413 sqlite3_create_collation_v2(table.db.db, type.fullName, SQLITE_UTF8, type, CollationCompare, null);
415 sqliteType = SQLITE_BLOB;
420 SQLiteField field { name = CopyString(fieldName), type = type, length = length, num = table.fields.count, sqliteType = sqliteType };
422 table.fields.Add(field);
425 sqlite3_finalize(statement);
429 sqlite3_free_table(t);
438 sprintf(command, "BEGIN;");
439 result = sqlite3_exec(db, command, null, null, null);
441 PrintLn("BEGIN FAILED!");
442 return result == SQLITE_OK;
449 sprintf(command, "COMMIT;");
450 result = sqlite3_exec(db, command, null, null, null);
452 PrintLn("COMMIT FAILED!");
453 return result == SQLITE_OK;
456 bool CreateCustomFunction(char * name, SQLCustomFunction customFunction)
458 int result = sqlite3_create_function(db, name, 1, SQLITE_UTF8, customFunction, SQLiteFunctionProcessor, null, null);
459 return result == SQLITE_OK;
463 static void SQLiteFunctionProcessor(sqlite3_context* context, int n, sqlite3_value** value)
465 SQLCustomFunction sqlFunction = sqlite3_user_data(context);
466 char * text = sqlite3_value_text(*value);
467 sqlFunction.array.size = 1;
468 sqlFunction.array[0] = 0;
469 sqlFunction.Process(text);
470 sqlite3_result_text(context, sqlFunction.array.array, sqlFunction.array.count ? sqlFunction.array.count - 1 : 0, SQLITE_TRANSIENT);
473 class SQLiteTable : Table
478 LinkList<SQLiteField> fields { };
479 char * specialStatement;
480 SQLiteField primaryKey;
481 FieldIndex * indexFields;
482 int indexFieldsCount;
485 Field AddField(const String fieldName, Class type, int length)
492 Table refTable = null;
493 Field idField = null;
496 if(FindField(fieldName)) return null;
498 if(!strcmp(type.dataTypeString, "int") || !strcmp(type.dataTypeString, "unsigned int") ||
499 !strcmp(type.dataTypeString, "long") || !strcmp(type.dataTypeString, "long int") ||
500 !strcmp(type.dataTypeString, "uint") || !strcmp(type.dataTypeString, "uint32") ||
501 !strcmp(type.dataTypeString, "int64") || !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64") ||
502 !strcmp(type.dataTypeString, "short") || !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
503 !strcmp(type.dataTypeString, "char") || !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
505 strcpy(dataType, "INTEGER");
506 sqliteType = SQLITE_INTEGER;
508 else if(!strcmp(type.dataTypeString, "double") || !strcmp(type.dataTypeString, "float"))
510 strcpy(dataType, "REAL");
511 sqliteType = SQLITE_FLOAT;
513 else if(!strcmp(type.name, "CIString"))
515 strcpy(dataType, "TEXT");
516 sqliteType = SQLITE_BLOB;
518 else if(!strcmp(type.dataTypeString, "String") || !strcmp(type.dataTypeString, "char *"))
520 strcpy(dataType, "TEXT");
521 sqliteType = SQLITE_TEXT;
525 //strcpy(dataType, "BLOB");
526 strcpy(dataType, "TEXT");
527 sqliteType = SQLITE_BLOB;
529 if(!db.collations.Find(type.fullName))
531 db.collations.Add(type.fullName);
532 result = sqlite3_create_collation_v2(db.db, type.fullName, SQLITE_UTF8, type, CollationCompare, null);
535 if(sqliteType != SQLITE_BLOB && eClass_IsDerived(type, class(eda::Id)))
537 Table * table = (Table *)eClass_GetProperty(type, "table");
538 if(table) refTable = *table;
541 if(primaryKey || refTable != this)
543 for(idField = refTable.firstField; idField; idField = idField.next)
544 if(eClass_IsDerived(type, idField.type)) break;
547 PrintLn("WARNING: field not yet created for class ", (String)type.name);
550 idField = primaryKey;
554 PrintLn("WARNING: Table not yet created for class ", (String)type.name);
560 if(sqliteType == SQLITE_BLOB)
562 if(!strcmp(type.name, "CIString"))
563 sprintf(command, "CREATE TABLE `%s`(%s %s COLLATE NOCASE);", name, fieldName, dataType);
565 sprintf(command, "CREATE TABLE `%s`(%s %s COLLATE '%s');", name, fieldName, dataType, type.fullName);
569 if(!idField && refTable == this)
570 sprintf(command, "CREATE TABLE `%s`(`%s` %s PRIMARY KEY);", name, fieldName, dataType);
572 sprintf(command, "CREATE TABLE `%s`(`%s` %s REFERENCES `%s`(`%s`));", name, fieldName, dataType, refTable.name, idField.name);
575 sprintf(command, "CREATE TABLE `%s`(`%s` %s);", name, fieldName, dataType);
576 result = sqlite3_exec(db.db, command, null, null, null);
577 if(result) return null;
582 if(sqliteType == SQLITE_BLOB)
584 if(!strcmp(type.name, "CIString"))
585 sprintf(command, "ALTER TABLE `%s` ADD `%s` %s COLLATE NOCASE;", name, fieldName, dataType);
587 sprintf(command, "ALTER TABLE `%s` ADD `%s` %s COLLATE `%s`;", name, fieldName, dataType, type.fullName);
591 if(!idField && refTable == this)
593 PrintLn("WARNING: ALTER TABLE DOESN'T WORK WITH PRIMARY KEY FOR ", (String)name);
594 sprintf(command, "ALTER TABLE `%s` ADD `%s` %s PRIMARY KEY;", name, fieldName, dataType);
597 sprintf(command, "ALTER TABLE `%s` ADD `%s` %s REFERENCES `%s`(`%s`);", name, fieldName, dataType, refTable.name, idField.name);
600 sprintf(command, "ALTER TABLE `%s` ADD `%s` %s;", name, fieldName, dataType);
601 result = sqlite3_exec(db.db, command, null, null, null);
602 if(result) return null;
605 sprintf(command, "INSERT INTO eda_table_fields (Table_Name, Name, Type, Length) VALUES ('%s', '%s', '%s', %d);", name,
606 fieldName, type.name, length);
607 result = sqlite3_exec(db.db, command, null, null, null);
609 field = { name = CopyString(fieldName), type = type, num = fields.count, sqliteType = sqliteType };
612 if(!primaryKey && refTable == this)
617 Field FindField(const String name)
619 for(f : fields; !strcmp(f.name, name))
623 if(f.sqliteType != SQLITE_BLOB && eClass_IsDerived(f.type, class(eda::Id)))
626 Table * tablePtr = (Table *)eClass_GetProperty(f.type, "table");
627 if(tablePtr && *tablePtr == this)
636 bool GenerateIndex(int count, FieldIndex * fieldIndexes, bool init)
641 char indexName[4096];
644 indexFieldsCount = count;
645 indexFields = new FieldIndex[count];
646 memcpy(indexFields, fieldIndexes, count * sizeof(FieldIndex));
648 // TODO: USE CODED INDEX NAME INSTEAD?
649 strcpy(indexName, "index_");
650 strcat(indexName, name);
651 strcat(indexName, "_");
652 for(c = 0; c<count; c++)
654 if(fieldIndexes[c].field)
656 if(count == 1 && fieldIndexes[c].field == primaryKey)
658 strcat(indexName, fieldIndexes[c].field.name);
659 if(fieldIndexes[c].memberField)
661 strcat(indexName, ".");
662 strcat(indexName, fieldIndexes[c].memberField.name);
664 strcat(indexName, (fieldIndexes[c].order == ascending) ? "+" : "-");
670 sprintf(command, "CREATE INDEX IF NOT EXISTS `%s` ON `%s` (", indexName, name);
671 for(c = 0; c<count; c++)
673 char columnName[1024];
674 sprintf(columnName, "`%s` %s", fieldIndexes[c].field.name, (fieldIndexes[c].order == ascending) ? "ASC" : "DESC");
675 if(c > 0) strcat(command, ", ");
676 strcat(command, columnName);
678 strcat(command, ");");
679 result = sqlite3_exec(db.db, command, null, null, null);
681 return result == SQLITE_OK;
689 Field GetFirstField()
694 uint GetFieldsCount()
706 sprintf(command, "SELECT COUNT(*) FROM `%s`;", name);
707 result = sqlite3_get_table(db.db, command, &t, &nRows, &nCols, null);
708 if(result == SQLITE_OK)
710 rowCount = atoi(t[1]);
711 sqlite3_free_table(t);
716 DriverRow CreateRow()
719 sqlite3_stmt * statement;
720 sqlite3_stmt * sysIDStmt = null, * insertStmt = null, * deleteStmt = null, * selectRowIDsStmt = null, * setRowIDStmt = null;
723 strcpy(command, specialStatement);
726 /*sprintf(command, "SELECT ROWID, * FROM `%s` WHERE ? = ?;", name);
727 sqlite3_prepare_v2(db.db, command, -1, &findStmt, null);*/
728 sprintf(command, "SELECT ROWID, * FROM `%s` WHERE ROWID = ?;", name);
729 sqlite3_prepare_v2(db.db, command, -1, &sysIDStmt, null);
731 sprintf(command, "INSERT INTO `%s` DEFAULT VALUES;", name);
732 sqlite3_prepare_v2(db.db, command, -1, &insertStmt, null);
733 sprintf(command, "DELETE FROM `%s` WHERE ROWID = ?;", name);
734 sqlite3_prepare_v2(db.db, command, -1, &deleteStmt, null);
735 /*sprintf(command, "UPDATE `%s` SET ? = ? WHERE ROWID = ?;", name);
736 sqlite3_prepare_v2(db.db, command, -1, &updateStmt, null);*/
738 if(!indexFields || (indexFieldsCount == 1 && indexFields[0].field == primaryKey && indexFields[0].order == ascending))
739 sprintf(command, "SELECT ROWID, * FROM `%s`;", name);
743 sprintf(command, "SELECT ROWID, * FROM `%s` ORDER BY ", name);
744 for(c = 0; c < indexFieldsCount; c++)
747 FieldIndex * fIndex = &indexFields[c];
749 if(c) strcat(order, ", ");
751 strcat(order, fIndex->field.name);
753 if(fIndex->order == descending) strcat(command, " DESC");
754 strcat(command, order);
756 strcat(command, ";");
759 sqlite3_prepare_v2(db.db, command, -1, &statement, null);
761 sprintf(command, "SELECT ROWID FROM `%s` WHERE ROWID > ?", name);
762 sqlite3_prepare_v2(db.db, command, -1, &selectRowIDsStmt, null);
764 sprintf(command, "UPDATE `%s` SET ROWID = ? WHERE ROWID = ?", name);
765 sqlite3_prepare_v2(db.db, command, -1, &setRowIDStmt, null);
768 { tbl = this, defaultStatement = statement, curStatement = statement, sysIDStatement = sysIDStmt,
769 insertStatement = insertStmt, deleteStatement = deleteStmt, selectRowIDsStmt = selectRowIDsStmt, setRowIDStmt = setRowIDStmt };
775 delete specialStatement;
781 class SQLiteRow : DriverRow
784 sqlite3_stmt * curStatement;
786 sqlite3_stmt * defaultStatement;
787 sqlite3_stmt * findStatement;
788 sqlite3_stmt * sysIDStatement;
789 sqlite3_stmt * queryStatement;
790 sqlite3_stmt * findMultipleStatement;
791 sqlite3_stmt * selectRowIDsStmt;
792 sqlite3_stmt * setRowIDStmt;
794 sqlite3_stmt * insertStatement;
795 sqlite3_stmt * deleteStatement;
796 sqlite3_stmt * updateStatement;
808 if(defaultStatement) sqlite3_finalize(defaultStatement);
809 if(findStatement) sqlite3_finalize(findStatement);
810 if(findMultipleStatement) sqlite3_finalize(findMultipleStatement);
811 if(sysIDStatement) sqlite3_finalize(sysIDStatement);
812 if(insertStatement) sqlite3_finalize(insertStatement);
813 if(deleteStatement) sqlite3_finalize(deleteStatement);
814 if(updateStatement) sqlite3_finalize(updateStatement);
815 if(queryStatement) sqlite3_finalize(queryStatement);
816 if(selectRowIDsStmt) sqlite3_finalize(selectRowIDsStmt);
817 if(setRowIDStmt) sqlite3_finalize(setRowIDStmt);
820 bool Select(MoveOptions move)
824 curStatement = defaultStatement;
829 sqlite3_reset(curStatement);
830 result = sqlite3_step(curStatement);
831 done = result == SQLITE_DONE || (result && result != SQLITE_ROW);
832 if(done) { rowID = 0; sqlite3_reset(curStatement); return false; }
833 rowID = sqlite3_column_int64(curStatement, 0);
838 sqlite3_stmt * statement;
840 sprintf(command, "SELECT MAX(ROWID) FROM `%s`", tbl.name);
841 result = sqlite3_prepare_v2(tbl.db.db, command, -1, &statement, null);
842 result = sqlite3_step(statement);
843 rowID = sqlite3_column_int64(statement, 0);
844 sqlite3_finalize(statement);
851 result = sqlite3_step(curStatement);
852 done = result == SQLITE_DONE || (result && result != SQLITE_ROW);
853 if(done) { rowID = 0; sqlite3_reset(curStatement); return false; }
854 rowID = sqlite3_column_int64(curStatement, 0);
860 sqlite3_reset(curStatement);
870 bool Query(char * queryString)
876 sqlite3_reset(curStatement);
879 sqlite3_finalize(queryStatement);
880 queryStatement = null;
885 result = sqlite3_prepare_v2(tbl.db.db, queryString, -1, &queryStatement, null);
886 curStatement = queryStatement;
887 if(!strchr(queryString, '?'))
889 result = sqlite3_step(queryStatement);
891 done = result == SQLITE_DONE || (result && result != SQLITE_ROW);
892 if(done) { rowID = 0; sqlite3_reset(queryStatement); return false; }
894 rowID = sqlite3_column_int64(queryStatement, 0);
902 bool Find(Field fld, MoveOptions move, MatchOptions match, typed_object data)
906 SQLiteField sqlFld = (SQLiteField)fld;
907 Class dataType = sqlFld.type;
909 if(fld == tbl.primaryKey)
911 return GoToSysID(*(int *)data);
915 sqlite3_reset(curStatement);
917 sqlite3_finalize(findStatement);
919 sprintf(command, "SELECT ROWID, * FROM `%s` WHERE `%s` = ?;", tbl.name, fld.name);
920 result = sqlite3_prepare_v2(tbl.db.db, command, -1, &findStatement, null);
922 // result = sqlite3_bind_text(findStatement, 1, fld.name, strlen(fld.name), SQLITE_STATIC);
924 curStatement = findStatement;
925 switch(sqlFld.sqliteType)
929 switch(dataType.typeSize)
932 sqlite3_bind_int64(findStatement, 1, (sqlite3_int64)*(int64 *)data);
935 sqlite3_bind_int(findStatement, 1, *(int *)data);
941 value = (int)*(short *)data;
943 value = (int)*(uint16 *)data;
944 sqlite3_bind_int(findStatement, 1, value);
951 value = (int)*(char *)data;
953 value = (int)*(byte *)data;
954 sqlite3_bind_int(findStatement, 1, value);
962 if(dataType.typeSize == 8)
963 sqlite3_bind_double(findStatement, 1, *(double *)data);
965 sqlite3_bind_double(findStatement, 1, (double)*(float *)data);
971 sqlite3_bind_text(findStatement, 1, (char *)data, strlen((char *)data), SQLITE_STATIC);
973 sqlite3_bind_text(findStatement, 1, null, 0, SQLITE_STATIC);
979 SerialBuffer buffer { };
981 dataType._vTbl[__ecereVMethodID_class_OnSerialize](dataType, data, buffer);
982 //sqlite3_bind_blob(findStatement, 1, buffer._buffer, buffer.count, SQLITE_STATIC);
983 sqlite3_bind_text(findStatement, 1, buffer._buffer, buffer.count, SQLITE_STATIC);
984 result = sqlite3_step(findStatement);
986 done = result == SQLITE_DONE || (result && result != SQLITE_ROW);
987 if(done) { rowID = 0; sqlite3_reset(findStatement); delete buffer; return false; }
989 rowID = sqlite3_column_int64(findStatement, 0);
996 result = sqlite3_step(findStatement);
998 done = result == SQLITE_DONE || (result && result != SQLITE_ROW);
999 if(done) { rowID = 0; sqlite3_reset(findStatement); return false; }
1001 rowID = sqlite3_column_int64(findStatement, 0);
1005 bool FindMultiple(FieldFindData * findData, MoveOptions move, int numFields)
1012 Array<SerialBuffer> serialBuffers { };
1015 sqlite3_reset(curStatement);
1016 if(findMultipleStatement)
1017 sqlite3_finalize(findMultipleStatement);
1019 sprintf(command, "SELECT ROWID, * FROM `%s` WHERE `", tbl.name);
1020 for(c = 0; c < numFields; c++)
1022 FieldFindData * fieldFind = &findData[c];
1024 if(c) strcat(command, " AND `");
1025 strcat(command, fieldFind->field.name);
1026 strcat(command, "` = ?");
1028 strcat(command, ";");
1030 result = sqlite3_prepare_v2(tbl.db.db, command, -1, &findMultipleStatement, null);
1031 curStatement = findMultipleStatement;
1033 for(c = 0; c < numFields; c++)
1035 FieldFindData * fieldFind = &findData[c];
1036 SQLiteField sqlFld = (SQLiteField)fieldFind->field;
1037 Class dataType = sqlFld.type;
1039 switch(sqlFld.sqliteType)
1041 case SQLITE_INTEGER:
1043 switch(dataType.typeSize)
1046 sqlite3_bind_int64(findMultipleStatement, 1 + c, (sqlite_int64)fieldFind->value.i64);
1049 sqlite3_bind_int(findMultipleStatement, 1 + c, fieldFind->value.i);
1055 value = (int)fieldFind->value.s;
1057 value = (int)fieldFind->value.us;
1058 sqlite3_bind_int(findMultipleStatement, 1 + c, value);
1065 value = (int)fieldFind->value.c;
1067 value = (int)fieldFind->value.uc;
1068 sqlite3_bind_int(findMultipleStatement, 1 + c, value);
1076 if(dataType.typeSize == 8)
1077 sqlite3_bind_double(findMultipleStatement, 1 + c, fieldFind->value.d);
1079 sqlite3_bind_double(findMultipleStatement, 1 + c, fieldFind->value.f);
1084 if(fieldFind->value.p)
1085 sqlite3_bind_text(findMultipleStatement, 1 + c, (char *)fieldFind->value.p, strlen(fieldFind->value.p), SQLITE_STATIC);
1087 sqlite3_bind_text(findMultipleStatement, 1 + c, null, 0, SQLITE_STATIC);
1093 SerialBuffer buffer { };
1095 dataType._vTbl[__ecereVMethodID_class_OnSerialize](dataType, fieldFind->value.p, buffer);
1096 //sqlite3_bind_blob(findMultipleStatement, 1 + c, buffer._buffer, buffer.count, SQLITE_STATIC);
1097 sqlite3_bind_text(findMultipleStatement, 1 + c, buffer._buffer, buffer.count, SQLITE_STATIC);
1099 serialBuffers.Add(buffer);
1105 result = sqlite3_step(findMultipleStatement);
1107 done = result == SQLITE_DONE || (result && result != SQLITE_ROW);
1111 sqlite3_reset(findMultipleStatement);
1113 serialBuffers.Free();
1114 delete serialBuffers;
1119 rowID = sqlite3_column_int64(findMultipleStatement, 0);
1121 serialBuffers.Free();
1122 delete serialBuffers;
1129 bool Synch(DriverRow to)
1137 //char command[1024];
1138 //sprintf(command, "INSERT INTO `%s` DEFAULT VALUES;", tbl.name);
1139 //result = sqlite3_exec(tbl.db.db, command, null, null, null);
1140 result = sqlite3_step(insertStatement);
1141 if(result == SQLITE_DONE) // if(result == SQLITE_OK)
1143 rowID = sqlite3_last_insert_rowid(tbl.db.db);
1144 if(rowID > MAXDWORD)
1146 int64 lastID = tbl.lastID;
1148 sqlite3_bind_int64(selectRowIDsStmt, 1, (sqlite3_int64)lastID);
1152 result = sqlite3_step(selectRowIDsStmt);
1153 if(result == SQLITE_DONE || result != SQLITE_ROW) break;
1154 id = sqlite3_column_int64(selectRowIDsStmt, 0);
1155 if(id - lastID > 1) break;
1158 sqlite3_reset(selectRowIDsStmt);
1160 sqlite3_bind_int64(setRowIDStmt, 2, (sqlite3_int64)rowID);
1163 sqlite3_bind_int64(setRowIDStmt, 1, (sqlite3_int64)rowID);
1164 result = sqlite3_step(setRowIDStmt);
1165 sqlite3_reset(setRowIDStmt);
1167 sqlite3_reset(insertStatement);
1168 curStatement = sysIDStatement;
1169 sqlite3_reset(curStatement);
1172 sqlite3_reset(insertStatement);
1179 //char command[1024];
1180 //sprintf(command, "DELETE FROM `%s` WHERE ROWID = %d;", tbl.name, rowID);
1181 //result = sqlite3_exec(tbl.db.db, command, null, null, null);
1182 sqlite3_bind_int64(deleteStatement, 1, (sqlite3_int64)rowID);
1183 result = sqlite3_step(deleteStatement);
1184 sqlite3_reset(deleteStatement);
1186 return result == SQLITE_OK || result == SQLITE_DONE;
1189 bool GetData(Field fld, typed_object &data)
1191 SQLiteField sqlFld = (SQLiteField)fld;
1192 int num = sqlFld.num + 1;
1193 Class dataType = sqlFld.type;
1194 switch(sqlFld.sqliteType)
1196 case SQLITE_INTEGER:
1198 switch(dataType.typeSize)
1201 if(fld == tbl.primaryKey)
1202 *(int64 *)data = rowID;
1204 *(int64 *)data = sqlite3_column_int64(curStatement, num);
1207 if(fld == tbl.primaryKey)
1208 *(int *)data = (int)(uint)rowID;
1210 *(int *)data = sqlite3_column_int(curStatement, num);
1215 if(fld == tbl.primaryKey)
1216 value = (int)(uint)rowID;
1218 value = sqlite3_column_int(curStatement, num);
1220 *(short *)data = (short)value;
1222 *(uint16 *)data = (uint16)value;
1228 if(fld == tbl.primaryKey)
1229 value = (int)(uint)rowID;
1231 value = sqlite3_column_int(curStatement, num);
1233 *(char *)data = (char)value;
1235 *(byte *)data = (byte)value;
1243 double d = sqlite3_column_double(curStatement, num);
1244 if(dataType.typeSize == 8)
1245 *(double *)data = d;
1247 *(float *)data = (float)d;
1252 int numBytes = sqlite3_column_bytes(curStatement, num);
1253 char * text = sqlite3_column_text(curStatement, num);
1254 *(char **)data = text ? new byte[numBytes+1] : null;
1256 memcpy(*(char **)data, text, numBytes+1);
1261 SerialBuffer buffer { };
1262 //buffer._buffer = sqlite3_column_blob(curStatement, num);
1263 buffer._size = sqlite3_column_bytes(curStatement, num);
1264 buffer._buffer = sqlite3_column_text(curStatement, num);
1265 buffer.count = buffer._size;
1267 dataType._vTbl[__ecereVMethodID_class_OnUnserialize](dataType, data, buffer);
1269 buffer._buffer = null;
1277 bool SetData(Field fld, typed_object data)
1279 SQLiteField sqlFld = (SQLiteField)fld;
1282 int num = sqlFld.num + 1;
1283 Class dataType = sqlFld.type;
1285 //sqlite3_stmt * setStatement;
1288 sqlite3_finalize(updateStatement);
1290 // sprintf(command, "UPDATE `%s` SET `%s` = ? WHERE ROWID = %d;", tbl.name, sqlFld.name, rowID);
1291 sprintf(command, "UPDATE `%s` SET `%s` = ? WHERE ROWID = ?;", tbl.name, sqlFld.name);
1293 result = sqlite3_prepare_v2(tbl.db.db, command, -1, &updateStatement, null);
1295 //sqlite3_bind_text(updateStatement, 1, sqlFld.name, strlen(sqlFld.name), SQLITE_STATIC);
1296 //sqlite3_bind_int64(updateStatement, 3, (sqlite3_int64)rowID);
1298 sqlite3_bind_int64(updateStatement, 2, (sqlite3_int64)rowID);
1299 switch(sqlFld.sqliteType)
1301 case SQLITE_INTEGER:
1303 switch(dataType.typeSize)
1306 sqlite3_bind_int64(updateStatement, 1, (sqlite3_int64)*(int64 *)data);
1309 sqlite3_bind_int(updateStatement, 1, *(int *)data);
1315 value = (int)*(short *)data;
1317 value = (int)*(uint16 *)data;
1318 sqlite3_bind_int(updateStatement, 1, value);
1325 value = (int)*(char *)data;
1327 value = (int)*(byte *)data;
1328 sqlite3_bind_int(updateStatement, 1, value);
1336 if(dataType.typeSize == 8)
1337 sqlite3_bind_double(updateStatement, 1, *(double *)data);
1339 sqlite3_bind_double(updateStatement, 1, (double)*(float *)data);
1345 sqlite3_bind_text(updateStatement, 1, (char *)data, strlen((char *)data), SQLITE_STATIC);
1347 sqlite3_bind_text(updateStatement, 1, null, 0, SQLITE_STATIC);
1353 SerialBuffer buffer { };
1355 dataType._vTbl[__ecereVMethodID_class_OnSerialize](dataType, data, buffer);
1356 //sqlite3_bind_blob(updateStatement, 1, buffer._buffer, buffer.count, SQLITE_STATIC);
1357 sqlite3_bind_text(updateStatement, 1, buffer._buffer, buffer.count, SQLITE_STATIC);
1358 sqlite3_step(updateStatement);
1359 sqlite3_reset(updateStatement);
1365 result = sqlite3_step(updateStatement);
1366 sqlite3_reset(updateStatement);
1367 if(fld == tbl.primaryKey)
1369 rowID = *(uint *)data;
1371 return result == SQLITE_DONE;
1376 return (int)(uint)rowID;
1379 bool GoToSysID(int id)
1381 //char command[1024];
1385 //sqlite3_finalize(statement);
1386 //sprintf(command, "SELECT ROWID, * FROM `%s` WHERE ROWID = ?;", tbl.name);
1387 //result = sqlite3_prepare_v2(tbl.db.db, command, -1, &statement, null);
1390 sqlite3_reset(curStatement);
1392 curStatement = sysIDStatement;
1393 sqlite3_reset(sysIDStatement);
1394 sqlite3_bind_int64(curStatement, 1, (sqlite_int64)rowID);
1395 result = sqlite3_step(curStatement);
1396 done = result == SQLITE_DONE || (result && result != SQLITE_ROW);
1397 if(done) { rowID = 0; sqlite3_reset(curStatement); return false; }
1401 bool SetQueryParam(int paramID, int value)
1404 if(curStatement != queryStatement)
1406 if(curStatement) sqlite3_reset(curStatement);
1407 curStatement = queryStatement;
1409 sqlite3_reset(queryStatement);
1410 result = sqlite3_bind_int(queryStatement, paramID, value);
1414 bool SetQueryParam64(int paramID, int64 value)
1417 if(curStatement != queryStatement)
1419 if(curStatement) sqlite3_reset(curStatement);
1420 curStatement = queryStatement;
1422 sqlite3_reset(queryStatement);
1423 result = sqlite3_bind_int64(queryStatement, paramID, (sqlite_int64)value);
1427 bool SetQueryParamText(int paramID, char * data)
1430 if(curStatement != queryStatement)
1432 if(curStatement) sqlite3_reset(curStatement);
1433 curStatement = queryStatement;
1435 sqlite3_reset(queryStatement);
1437 result = sqlite3_bind_text(queryStatement, paramID, (char *)data, strlen((char *)data), SQLITE_STATIC);
1439 result = sqlite3_bind_text(queryStatement, paramID, null, 0, SQLITE_STATIC);
1443 bool SetQueryParamObject(int paramID, void * data, Class type)
1446 if(curStatement != queryStatement)
1448 if(curStatement) sqlite3_reset(curStatement);
1449 curStatement = queryStatement;
1451 sqlite3_reset(queryStatement);
1453 SerialBuffer buffer { };
1454 type._vTbl[__ecereVMethodID_class_OnSerialize](type, data, buffer);
1455 result = sqlite3_bind_text(queryStatement, paramID, buffer._buffer, buffer.count, SQLITE_TRANSIENT);
1461 /*char * GetExtraColumn(int paramID)
1463 SQLiteField lastFld = tbl.fields.last;
1464 return sqlite3_column_text(curStatement, lastFld.num + 1 + paramID);
1466 char * GetColumn(int paramID)
1468 return sqlite3_column_text(curStatement, paramID);