2 public import static "ecere"
17 public enum OpenType { queryRows, tableRows, viewRows, processesList, databasesList, tablesList, fieldsList };
18 public enum CreateOptions { no, create, readOnly };
19 public enum AccessOptions { integral, random };
20 public enum SeekOptions { none, reset, first, last, firstEqual, lastEqual };
21 public enum MoveOptions { nil, first, last, next, previous, middle, here };
22 public enum MatchOptions { nil };
23 public enum ObjectType { table, view };
24 public enum State { none, driver, connected, opened, closed, errorDriver };
27 #define AUTO_DELETE_TABLES
29 public class OpenOptions : uint
33 CreateOptions create:2;
34 AccessOptions access:2;
37 public class DataSourceDriver
39 OldList listDB { offset = (uint)(uintptr)&((Database)0).prev };
40 class_data const char * name;
42 class_property const char * name
44 set { class_data(name) = value; }
45 get { return class_data(name); }
48 class_data const char * databaseFileExtension;
49 class_property const char * databaseFileExtension { set { class_data(databaseFileExtension) = value; } get { return class_data(databaseFileExtension); } }
50 class_data const char * tableFileExtension;
51 class_property const char * tableFileExtension { set { class_data(tableFileExtension) = value; } get { return class_data(tableFileExtension); } }
54 virtual String BuildLocator(DataSource ds);
55 virtual uint GetDatabasesCount();
56 virtual bool Connect(const String locator);
57 virtual void Status();
58 virtual bool RenameDatabase(const String name, const String rename);
59 virtual bool DeleteDatabase(const String name);
60 virtual Database OpenDatabase(const String name, CreateOptions create, DataSource ds);
61 virtual Array<const String> GetDatabases() { return null; } // TODO: make this Container<Database> GetDatabases(); // if supported, filled with ready to open Databases
66 while((db = listDB.first))
75 static subclass(DataSourceDriver) GetDataDriver(const char * driverName)
77 subclass(DataSourceDriver) driver = null;
78 driver = FindDataDriverDerivative(class(DataSourceDriver), driverName);
82 char moduleName[MAX_LOCATION];
83 sprintf(moduleName, "EDA%s", driverName);
84 if((module = eModule_Load(__thisModule.application, moduleName, publicAccess)))
85 driver = FindDataDriverDerivative(eSystem_FindClass(module /*__thisModule.application*/, "DataSourceDriver"), driverName);
90 static subclass(DataSourceDriver) FindDataDriverDerivative(Class dataSourceDriverClass, const char * driverName)
93 subclass(DataSourceDriver) derivative = null;
94 for(link = dataSourceDriverClass.derivatives.first; link; link = link.next)
96 subclass(DataSourceDriver) dataDriver = link.data;
97 Class driverClass = link.data;
98 if(dataDriver.name && !strcmp(dataDriver.name, driverName))
100 derivative = dataDriver;
103 if(driverClass.derivatives.first && (derivative = FindDataDriverDerivative(driverClass, driverName)))
109 public class DataSource
129 property const String driver
131 get { return ds ? ((subclass(DataSourceDriver))(ds._class)).name : null; }
135 if(value && value[0])
137 subclass(DataSourceDriver) driver = GetDataDriver(value);
139 ds = eInstance_New(driver);
141 PrintLn("EDA: Unable to find a driver named ", value);
145 property const String host
147 set { delete host; host = CopyString(value); }
150 property const String port
152 set { delete port; port = CopyString(value); }
155 property const String user
157 set { delete user; user = CopyString(value); }
160 property const String pass
162 set { delete pass; pass = CopyString(value); }
165 property const String locator
174 locator = CopyString(value);
176 get { return locator; }
179 property uint databasesCount { get { return ds.GetDatabasesCount(); } }
180 property Array<const String> databases { get { return ds.GetDatabases(); } } // TODO: make this Container<Database> databases { ... }
185 if(host || port || user || pass)
188 locator = ds.BuildLocator(this);
191 return ds ? ds.Connect(locator) : false;
193 void Status() { ds.Status(); }
194 bool RenameDatabase(const String name, const String rename) { return ds.RenameDatabase(name, rename); }
195 bool DeleteDatabase(const String name) { return ds.DeleteDatabase(name); }
196 Database OpenDatabase(const String name, CreateOptions create)
198 Database db = ds.OpenDatabase(name, create, this);
208 public class Database
212 OldList listTbl { offset = (uint)(uintptr)&((Table)0).prev };
213 public virtual String GetName();
214 public virtual Array<String> GetTables(); // TODO: make this Container<Table> GetTables(); // if supported, filled with ready to open Tables
220 ds.listDB.Remove(this);
221 while((tbl = listTbl.first))
228 public void LinkTable(Table tbl)
230 #ifdef AUTO_DELETE_TABLES
237 property String name { get { return GetName(); } }
238 property uint tablesCount { get { return ObjectsCount(table); } }
239 property uint viewsCount { get { return ObjectsCount(view); } }
240 property Array<String> tables { get { return GetTables(); } }
242 virtual uint ObjectsCount(ObjectType type);
243 virtual bool RenameObject(ObjectType type, const String name, const String rename);
244 virtual bool DeleteObject(ObjectType type, const String name);
245 virtual Table OpenTable(const String name, OpenOptions open);
246 virtual bool Begin();
247 virtual bool Commit();
248 virtual bool CreateCustomFunction(const char * name, SQLCustomFunction customFunction);
251 public enum IndexOrder { ascending, descending };
253 public struct FieldIndex
262 Mutex idRowCacheMutex { };
269 OldList listRows { offset = (uint)(uintptr)&((Row)0).prev };
272 virtual const String GetName();
273 virtual Field GetFirstField();
274 virtual Field GetPrimaryKey();
275 virtual uint GetFieldsCount();
276 virtual uint GetRowsCount();
277 virtual DriverRow CreateRow();
283 // Delete cached Id row
284 idRowCacheMutex.Wait();
286 idRowCacheMutex.Release();
288 #ifdef AUTO_DELETE_TABLES
290 db.listTbl.Remove(this);
292 while((row = listRows.first))
296 property const String name { get { return GetName(); } }
297 property Field firstField { get { return GetFirstField(); } }
298 property Field primaryKey { get { return GetPrimaryKey(); } }
299 property uint fieldsCount { get { return GetFieldsCount(); } }
300 property uint rowsCount { get { return GetRowsCount(); } }
301 property Container<Field> fields { get { return GetFields(); } }
303 virtual Field AddField(const String name, Class type, int length);
304 virtual Field FindField(const String name);
305 virtual bool GenerateIndex(int count, FieldIndex * fieldIndexes, bool init);
306 virtual Container<Field> GetFields();
308 bool Index(int count, FieldIndex * fieldIndexes)
310 return GenerateIndex(count, fieldIndexes, true);
313 void GUIListBoxAddRowsField(ListBox list, const String fieldName)
317 fld = FindField(fieldName);
325 list.AddRow().SetData(null, s);
332 void GUIListBoxAddFields(ListBox list)
337 for(fld = firstField; fld; fld = fld.next)
351 void GUIListBoxAddRows(ListBox list)
362 Field fld = firstField;
363 for(df = list.firstField; df; df = df.next, fld = fld.next)
366 Class type = fld.type;
367 if(type.type == unitClass && !type.typeSize)
369 Class dataType = eSystem_FindClass(type.module, type.dataTypeString);
373 if(type.type == structClass)
374 data = (int64)(intptr)new0 byte[type.structSize];
380 ((bool (*)())(void *)r.GetData)(r, fld, type, (type.type == structClass) ? (void *)(intptr)data : &data);
381 if(type.type == systemClass || type.type == unitClass || type.type == bitClass || type.type == enumClass)
382 dr.SetData(df, (void *)&data);
384 dr.SetData(df, (void *)(intptr)data);
386 // Is this missing some frees here? strings? Probably not: freeData = true?
387 // ((void (*)(void *, void *))(void *)type._vTbl[__ecereVMethodID_class_OnFree])(type, data);
388 if(type.type == structClass)
390 delete (void *)(intptr)data;
392 else if(!strcmp(type.dataTypeString, "char *"))
394 // Strings are handled as a special case in ListBox -- normalClass, but copied when freeData = true
395 delete (char *)(intptr)data;
409 virtual const String GetName();
410 virtual Class GetType();
411 virtual int GetLength();
412 virtual Field GetPrev();
413 virtual Field GetNext();
414 virtual Table GetTable();
416 property const String name { get { return GetName(); } }
417 property Class type { get { return GetType(); } }
418 property int length { get { return GetLength(); } }
419 property Field prev { get { return GetPrev(); } }
420 property Field next { get { return GetNext(); } }
421 property Table table { get { return GetTable(); } }
423 bool GetData(Row row, typed_object & data)
425 return row.GetData(this, data);
428 bool SetData(Row row, typed_object & data)
430 return row.SetData(this, data);
446 tbl.listRows.Remove(this);
458 row = value ? value.CreateRow() : null;
462 tbl.listRows.Remove(this);
479 tbl.listRows.Add(this);
486 property bool nil { get { return row ? row.Nil() : true; } }
488 property const char * query
492 // So we can do row.query = row.query
493 if(query != value) { delete query; query = CopyString(value); }
494 if(row) row.Query(value);
496 get { return query; }
498 property uint rowsCount
504 // NOTE: This does not work if the query relies on bound data...
505 String from = SearchString(query, 0, "FROM", false, true);
508 uint len = strlen(query);
509 String countQuery = new char[len+40];
513 strcpy(countQuery, "SELECT COUNT(*) ");
514 strcat(countQuery, from);
515 r.query = countQuery;
516 result = r.GetColumn(0);
517 count = result ? strtol(result, null, 0) : 0;
523 return tbl.rowsCount;
528 public bool Query(const char * query) // Add printf format support
531 return row.Query(query);
534 bool Select(MoveOptions move) { return row ? row.Select(move) : false; }
535 bool First() { return row ? row.Select(first) : false; }
536 bool Last() { return row ? row.Select(last) : false; }
537 bool Next() { return row ? row.Select(next) : false; }
538 bool Previous() { return row ? row.Select(previous) : false; }
540 bool Find(Field field, MoveOptions move, MatchOptions match, typed_object data) { return (row && field) ? row.Find(field, move, match, data) : false; }
541 bool FindMultiple(FieldFindData * findData, MoveOptions move, int numFields) { return row ? row.FindMultiple(findData, move, numFields) : false; }
543 bool Synch(Row to) { return row && to && row._class == to.row._class ? row.Synch(to.row) : false; }
545 bool Add() { return row ? row.Add(0) : false; }
546 bool AddID(uint64 id) { return row ? row.Add(id) : false; }
547 bool GetData(Field field, typed_object & data) { return (row && field) ? row.GetData(field, data) : false; }
548 bool SetData(Field field, typed_object data) { return (row && field) ? row.SetData(field, data) : false; }
549 bool Delete() { return row ? row.Delete() : false; }
550 bool SetQueryParam(int paramID, int value) { return row ? row.SetQueryParam(paramID, value) : false; }
551 bool SetQueryParam64(int paramID, int64 value) { return row ? row.SetQueryParam64(paramID, value) : false; }
552 bool SetQueryParamText(int paramID, const char * value) { return row ? row.SetQueryParamText(paramID, value) : false; }
553 bool SetQueryParamObject(int paramID, void * value, Class type) { return row ? row.SetQueryParamObject(paramID, value, type) : false; }
554 // TOCHECK: Field is passed here to have sqlite type handy. The API might be nicer without
555 bool BindQueryData(int paramID, Field fld, typed_object value) { return row ? row.BindQueryData(paramID, fld, value) : false; }
556 const char * GetColumn(int paramID) { return row ? row.GetColumn(paramID) : null; }
558 bool GUIDataRowSetData(DataRow dr, DataField df, Field fld)
561 Class type = fld.type;
562 if(type.type == unitClass && !type.typeSize)
564 Class dataType = eSystem_FindClass(type.module, type.dataTypeString);
568 if(type.type == structClass)
569 data = (int64)(intptr)new0 byte[type.structSize];
570 ((bool (*)())(void *)GetData)(this, fld, type, (type.type == structClass) ? (void *)(intptr)data : &data);
572 if((type.type == systemClass || type.type == unitClass || type.type == bitClass || type.type == enumClass))
573 dr.SetData(df, (void *)&data);
575 dr.SetData(df, (void *)(intptr)data);
576 if(type.type == structClass)
578 void * dataPtr = (void *)(intptr)data;
581 else if(!strcmp(type.dataTypeString, "char *"))
583 // Strings are handled as a special case in ListBox -- normalClass, but copied when freeData = true
584 delete (char *)(intptr)data;
589 property uint sysID { get { return row ? row.GetSysID() : 0; } set { if(row) row.GoToSysID(value); } }
592 public class DriverRow
596 virtual bool Select(MoveOptions move);
597 virtual bool Find(Field fld, MoveOptions move, MatchOptions match, typed_object data);
598 virtual bool FindMultiple(FieldFindData * findData, MoveOptions move, int numFields);
599 virtual bool Synch(DriverRow to);
600 virtual bool Add(uint64 id);
601 virtual bool Delete();
603 virtual bool GetData(Field fld, typed_object &data);
604 virtual bool SetData(Field fld, typed_object data);
605 virtual uint GetSysID();
606 virtual bool GoToSysID(uint id);
607 virtual bool Query(const char * queryString);
608 virtual bool SetQueryParam(int paramID, int value);
609 virtual bool SetQueryParam64(int paramID, int64 value);
610 virtual bool SetQueryParamText(int paramID, const char * value);
611 virtual bool SetQueryParamObject(int paramID, const void * data, Class type);
612 virtual const char * GetColumn(int paramID);
613 virtual bool BindQueryData(int paramID, Field fld, typed_object value);
616 public class SQLCustomFunction
621 Array<Class> args { };
623 // Array<void *> does not work right now :(
624 Array</*ffi_type*/ String> argTypes { };
628 public struct FieldFindData
634 static inline void DebugLn(typed_object object, ...)
636 #if defined(_DEBUG_LINE)
639 va_start(args, object);
640 PrintStdArgsToBuffer(buffer, sizeof(buffer), object, args);