EDA Oracle Driver added
authorJuan Sanchez <aldeacity@gmail.com>
Mon, 6 Feb 2012 22:29:16 +0000 (23:29 +0100)
committerJuan Sanchez <aldeacity@gmail.com>
Mon, 6 Feb 2012 22:29:16 +0000 (23:29 +0100)
eda/drivers/oracle/EDAOracle.ec [new file with mode: 0644]
eda/drivers/oracle/EDAOracle.epj [new file with mode: 0644]
samples/db/EDATest/EDATest.ec
samples/db/MovieCollection/movieSchema.ec

diff --git a/eda/drivers/oracle/EDAOracle.ec b/eda/drivers/oracle/EDAOracle.ec
new file mode 100644 (file)
index 0000000..6786e7e
--- /dev/null
@@ -0,0 +1,1523 @@
+#ifdef ECERE_STATIC
+public import static "ecere"
+public import static "EDA"
+#else
+public import "ecere"
+public import "EDA"
+#endif
+
+#define property _property
+#define get _get
+#include <oci.h>
+#undef get
+#undef property
+
+define Oracle = "Oracle";
+
+static void UnusedFunction()
+{
+   int a;
+   a.OnGetString(0,0,0);
+   a.OnFree();
+   a.OnCopy(null);
+   a.OnCompare(null);
+   a.OnSaveEdit(null,0);
+   a.OnEdit(null,null,0,0,0,0,0);
+   a.OnDisplay(null,0,0,0,0,0,0);
+   a.OnGetDataFromString(null);
+   a.OnUnserialize(null);
+   a.OnSerialize(null);
+}
+
+default:
+extern int __ecereVMethodID_class_OnGetString;
+extern int __ecereVMethodID_class_OnGetDataFromString;
+extern int __ecereVMethodID_class_OnCompare;
+extern int __ecereVMethodID_class_OnSerialize;
+extern int __ecereVMethodID_class_OnUnserialize;
+extern int __ecereVMethodID_class_OnFree;
+
+public class OracleStaticLink { }   // Until .imp generation is fixed
+
+void ToUpperAndUnderscore(String stringValue)
+{
+   int i;
+
+   for (i = 0; stringValue[i]; i++)
+   {
+      stringValue[i] = toupper(stringValue[i]);  
+      if (stringValue[i] == 32)
+         stringValue[i] = '_';
+   }
+}
+
+int OracleExecuteNonQuery(OCIEnv* env, OCISvcCtx* svc, String command)
+{
+   OCIStmt* stmt; 
+   OCIError* err;
+   text errbuf[512];
+   ub4 buflen;
+   ub4 errcode;
+   int r;
+   
+   OCIHandleAlloc(env, (dvoid**)&err, OCI_HTYPE_ERROR,   0, 0);
+   OCIHandleAlloc(env, (dvoid**)&stmt, OCI_HTYPE_STMT, 0, 0);
+
+   r = OCIStmtPrepare(stmt, err, (OraText *)command,
+      (ub4)strlen((char *)command),
+      (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT);
+
+   r = OCIStmtExecute(svc, stmt, err, 1, 0,
+      (OCISnapshot *) 0, (OCISnapshot *) 0, OCI_COMMIT_ON_SUCCESS);
+   
+   if (err) OCIHandleFree(err, OCI_HTYPE_ERROR);
+   if (stmt) OCIHandleFree(stmt, OCI_HTYPE_STMT);
+
+   return r;
+}
+
+// Converts a hexadecimal string to integer
+int xtoi(const char* xs, unsigned int* result)
+{
+ size_t szlen = strlen(xs);
+ int i, xv, fact;
+
+ if (szlen > 0)
+ {
+  // Converting more than 32bit hexadecimal value?
+  if (szlen>8) return 2; // exit
+
+  // Begin conversion here
+  *result = 0;
+  fact = 1;
+
+  // Run until no more character to convert
+  for(i=szlen-1; i>=0 ;i--)
+  {
+   if (isxdigit(*(xs+i)))
+   {
+    if (*(xs+i)>=97)
+    {
+     xv = ( *(xs+i) - 97) + 10;
+    }
+    else if ( *(xs+i) >= 65)
+    {
+     xv = (*(xs+i) - 65) + 10;
+    }
+    else
+    {
+     xv = *(xs+i) - 48;
+    }
+    *result += (xv * fact);
+    fact *= 16;
+   }
+   else
+   {
+    // Conversion was abnormally terminated
+    // by non hexadecimal digit, hence
+    // returning only the converted with
+    // an error value 4 (illegal hex character)
+    return 4;
+   }
+  }
+ }
+
+ // Nothing to convert
+ return 1;
+}
+
+class OracleDataSource : DataSourceDriver
+{
+   class_property(name) = "Oracle";
+   uint databasesCount;
+   OCIEnv* env;
+   OCIError* err;
+   OCIServer* srv;
+   OCISvcCtx* svc;
+   OCISession* ses;
+
+   String BuildLocator(DataSource ds)
+   {
+      return null;
+   }
+
+   uint GetDatabasesCount()
+   {
+      return databasesCount;
+   }
+
+   ~OracleDataSource()
+   {
+      if (ses) OCIHandleFree(ses, OCI_HTYPE_SESSION);
+      if (svc) OCIHandleFree(svc, OCI_HTYPE_SVCCTX);
+      if (srv) OCIHandleFree(srv, OCI_HTYPE_SERVER);
+      if (err) OCIHandleFree(err, OCI_HTYPE_ERROR);
+      if (env) OCIHandleFree(env, OCI_HTYPE_ENV);
+
+      //OCITerminate(OCI_DEFAULT);
+   }
+
+   bool Connect(const String locator)
+   {
+      return true;
+   }
+
+   bool RenameDatabase(const String name, const String rename)
+   {
+      return false;
+   }
+
+   bool DeleteDatabase(const String name)
+   {
+      return false;
+   }
+
+   virtual String MakeDatabasePath(const String name)
+   {
+      return null;
+   }
+
+   Database OpenDatabase(const String name, CreateOptions createOptions, DataSource ds)
+   {
+      int r;
+      OracleDatabase result = null;
+
+      char s[MAX_F_STRING];
+      char t[MAX_LOCATION];
+      
+      s[0] = '\0';
+      strcat(s, "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(");
+      if(ds.host)
+         sprintf(t, "Host=%s", ds.host), strcat(s, t);
+      strcat(s, ")(");
+      if(ds.port)
+         sprintf(t, "Port=%s", ds.port), strcat(s, t);
+      strcat(s, "))(CONNECT_DATA=(");
+      if(name)
+         sprintf(t, "SID=%s", name), strcat(s, t);
+      strcat(s, ")))");
+      
+      if (ses) OCIHandleFree(ses, OCI_HTYPE_SESSION);
+      if (svc) OCIHandleFree(svc, OCI_HTYPE_SVCCTX);
+      if (srv) OCIHandleFree(srv, OCI_HTYPE_SERVER);
+      if (err) OCIHandleFree(err, OCI_HTYPE_ERROR);
+      if (env) OCIHandleFree(env, OCI_HTYPE_ENV);
+
+      r = OCIEnvCreate(&env, OCI_DEFAULT, 0, 0, 0, 0, 0, 0);                  
+
+      OCIHandleAlloc(env, (dvoid**)&err, OCI_HTYPE_ERROR,   0, 0);
+      OCIHandleAlloc(env, (dvoid**)&srv, OCI_HTYPE_SERVER,  0, 0);
+      OCIHandleAlloc(env, (dvoid**)&svc, OCI_HTYPE_SVCCTX,  0, 0);
+      OCIHandleAlloc(env, (dvoid**)&ses, OCI_HTYPE_SESSION, 0, 0);
+
+      r = OCIServerAttach(srv, err, name, strlen(name), (ub4) OCI_DEFAULT);
+
+      OCIAttrSet(svc, OCI_HTYPE_SVCCTX, srv, 0, OCI_ATTR_SERVER,  err);
+
+      OCIAttrSet(ses, OCI_HTYPE_SESSION, ds.user, strlen(ds.user), OCI_ATTR_USERNAME, err); 
+      OCIAttrSet(ses, OCI_HTYPE_SESSION, ds.pass, strlen(ds.pass), OCI_ATTR_PASSWORD, err);
+
+      r = OCISessionBegin(svc, err, ses, OCI_CRED_RDBMS, OCI_DEFAULT);
+
+      r = OCIAttrSet((dvoid *) svc, (ub4) OCI_HTYPE_SVCCTX, (dvoid *)ses, (ub4) 0, (ub4) OCI_ATTR_SESSION, err);
+
+      result = OracleDatabase {env = env; err = err; srv = srv; svc = svc; ses = ses};
+
+      return result;
+   }
+}
+
+class OracleField : Field
+{
+   char* name;
+   Class type;
+   int length;
+   public LinkElement<OracleField> link;
+   int num;
+   int oracleType;
+
+   OCIDefine* def;
+   OCIDefine* p_dfn;
+   char p_sli[1024];
+   int p_sliInt;
+   double p_sliFloat;
+   OCIDateTime *p_sliDateTime;
+
+   ~OracleField()
+   {
+      OCIDescriptorFree(p_sliDateTime, OCI_DTYPE_TIMESTAMP_LTZ);
+      delete name;
+   }
+
+   String GetName()
+   {
+      return name;
+   }
+   Class GetType()
+   {
+      return type;
+   }
+   int GetLength() { return length; }
+   Field GetPrev()
+   {
+      return link.prev;
+   }
+   Field GetNext()
+   {
+      return link.next;
+   }
+}
+
+class OracleDatabase : Database
+{
+   AVLTree<String> collations { };
+   OCIEnv* env;
+   OCIError* err;
+   OCIServer* srv;
+   OCISvcCtx* svc;
+   OCISession* ses;
+   
+   ~OracleDatabase()
+   {
+      //
+   }
+
+   uint ObjectsCount(ObjectType type)
+   {
+      // TODO
+      return 0;
+   }
+
+   bool RenameObject(ObjectType type, const String name, const String rename)
+   {
+      // TODO
+      return false;
+   }
+
+   bool DeleteObject(ObjectType type, const String name)
+   {
+      // TODO
+      return false;
+   }
+
+   Table OpenTable(const String name, OpenOptions options)
+   {
+      char command[1024];
+      int result;
+      int nRows = 0, nCols = 0;
+      char ** t;
+      OracleTable table = null;
+      int r;
+
+      text errbuf[512];
+      ub4 buflen;
+      ub4 errcode;
+
+      OCIDefine* p_dfn1;
+      OCIDefine* p_dfn2;
+      OCIDefine* p_dfn3;
+      char p_sli1[1024];
+      char p_sli2[1024];
+      int p_sli3; 
+
+      int oracleType;
+
+      if(options.type == tablesList)
+      {
+         OracleField field { name = CopyString("Name"), type = class(String), num = -1, oracleType = SQLT_STR };
+         strcpy(command, "SELECT DISTINCT(Table_Name) AS Name FROM EDA_TABLE_FIELDS");
+         table = OracleTable { db = this, specialStatement = CopyString(command) };
+         LinkTable(table);
+         incref field;
+         table.fields.Add(field);
+      }
+      else if(options.type == fieldsList)
+      {
+         OracleField field;
+
+         sprintf(command, "SELECT Name, Type, Length FROM EDA_TABLE_FIELDS WHERE UPPER(Table_Name)=UPPER('%s')", name);
+         table = OracleTable { db = this, specialStatement = CopyString(command) };
+         LinkTable(table);
+         field = { name = CopyString("Name"), type = class(String), num = -1, oracleType = SQLT_STR };
+         incref field;
+         table.fields.Add(field);
+         field = { name = CopyString("Type"), type = class(Class), num = 0, oracleType = SQLT_STR };
+         incref field;
+         table.fields.Add(field);
+         field = { name = CopyString("Lenght"), type = class(int), num = 1, oracleType = SQLT_INT };
+         incref field;
+         table.fields.Add(field);
+      }
+      else if(options.type == tableRows)
+      {
+         OracleField field;
+         int num;
+
+         OCIStmt* stmtRows; 
+
+         OCIHandleAlloc(env, (dvoid**)&stmtRows, OCI_HTYPE_STMT, 0, 0);
+
+         /* Check fields in internal table */
+         sprintf(command, "SELECT Name, Type, Length FROM EDA_TABLE_FIELDS WHERE UPPER(Table_Name)=UPPER('%s')", name);
+         r = OCIStmtPrepare(stmtRows, err, (OraText *)command,
+            (ub4)strlen((char *)command),
+            (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT);
+
+         table = OracleTable { db = this, name = CopyString(name) };
+         LinkTable(table);
+
+         /* Field definitions */
+         r = OCIDefineByPos(stmtRows, &p_dfn1, err, 1, (dvoid *) &p_sli1,
+            (sword) 30, SQLT_STR, (dvoid *) 0, (ub2 *)0,
+            (ub2 *)0, OCI_DEFAULT);
+
+         r = OCIDefineByPos(stmtRows, &p_dfn2, err, 2, (dvoid *) &p_sli2,
+            (sword) 30, SQLT_STR, (dvoid *) 0, (ub2 *)0,
+            (ub2 *)0, OCI_DEFAULT);
+
+         r = OCIDefineByPos(stmtRows, &p_dfn3, err, 3, (dvoid *) &p_sli3,
+            sizeof(int), SQLT_INT, (dvoid *) 0, (ub2 *)0,
+            (ub2 *)0, OCI_DEFAULT);
+         /* End of field definitions */
+
+         r = OCIStmtExecute(svc, stmtRows, err, 0, 0,
+            (OCISnapshot *) 0, (OCISnapshot *) 0, OCI_STMT_SCROLLABLE_READONLY);
+
+         while ((OCIStmtFetch2(stmtRows, err, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT)) != OCI_NO_DATA)
+         {
+            Class type = null;
+            oracleType = SQLT_BLOB;
+
+            ((Class)(&type)).OnGetDataFromString(p_sli2);    // TODO: THIS REQUIRES A FIX SOMEWHERE ELSE
+
+            if (type)
+            {
+               if(!strcmp(type.dataTypeString, "int") || !strcmp(type.dataTypeString, "unsigned int") || 
+                  !strcmp(type.dataTypeString, "long") || !strcmp(type.dataTypeString, "long int") || 
+                  !strcmp(type.dataTypeString, "uint") || !strcmp(type.dataTypeString, "uint32") || 
+                  !strcmp(type.dataTypeString, "int64") || !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64") || 
+                  !strcmp(type.dataTypeString, "short") || !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
+                  !strcmp(type.dataTypeString, "char") || !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
+                  oracleType = SQLT_INT;
+               else if(!strcmp(type.dataTypeString, "double") || !strcmp(type.dataTypeString, "float"))
+                  oracleType = SQLT_FLT;
+               else if(!strcmp(type.dataTypeString, "String") || !strcmp(type.dataTypeString, "char *"))
+                  oracleType = SQLT_STR;
+               else
+               {
+                  /* No basic datatype */
+                  if(strcmp(type.fullName, "CIString") && !collations.Find(type.fullName))
+                  {
+                     collations.Add(type.fullName);
+                  }
+                  oracleType = SQLT_BLOB;
+               }
+            }
+            else
+            {
+               type = class(String);
+               oracleType = SQLT_STR;
+            }
+
+            if (!strcmp(type.name, "Date"))
+            {
+               oracleType = SQLT_TIMESTAMP_TZ;
+            }
+            
+            field = { name = CopyString(p_sli1), type = type, length = p_sli3, num = table.fields.count, oracleType = oracleType };
+            incref field;
+            table.fields.Add(field);
+         }
+
+         if (stmtRows) OCIHandleFree(stmtRows, OCI_HTYPE_STMT);   
+      }
+
+      return (Table)table;
+   }
+
+   bool Begin()
+   {
+      return false;
+   }
+
+   bool Commit()
+   {
+      return false;
+   }
+
+   bool CreateCustomFunction(char * name, SQLCustomFunction customFunction)
+   {
+      printf("CreateCustomFunction\n");
+      return false;
+   }
+}
+
+class OracleTable : Table
+{
+   char * name;
+   bool mustCreate;
+   OracleDatabase db;
+   LinkList<OracleField> fields { };
+   char * specialStatement;
+   OracleField primaryKey;
+   FieldIndex * indexFields;
+   int indexFieldsCount;
+   int64 lastID;
+
+   text errbuf[512];
+   ub4 buflen;
+   ub4 errcode;
+
+   OCIStmt* stmt;
+   OCIDefine* def;
+   OCIDefine* p_dfn;
+   char p_sli[1024];  
+
+   void OracleReinitFieldsDataTimeDescriptors()
+   {
+      int r;
+      int i;
+
+      for (i = 0; i < fields.count; i++)
+      {
+         OracleField field = fields[i];
+
+         OCIDescriptorFree(field.p_sliDateTime, OCI_DTYPE_TIMESTAMP_LTZ);
+         r= OCIDescriptorAlloc(db.env,(dvoid **)&field.p_sliDateTime, OCI_DTYPE_TIMESTAMP,
+            0, (dvoid **)0);
+      }
+   }
+
+
+   Field AddField(const String fieldName, Class type, int length)
+   {
+      OracleField field;
+      char command[1024];
+      char dataType[256];
+      int result;
+      Table refTable = null;
+      Field idField = null;
+      int oracleType;
+
+      command[0] = 0;
+
+      if(FindField(fieldName)) return null;
+      
+      oracleType = SQLT_BLOB;
+
+      ((Class)(&type)).OnGetDataFromString(type);    // TODO: THIS REQUIRES A FIX SOMEWHERE ELSE
+
+      if (type)
+      {
+         if(!strcmp(type.dataTypeString, "int") || !strcmp(type.dataTypeString, "unsigned int") || 
+            !strcmp(type.dataTypeString, "long") || !strcmp(type.dataTypeString, "long int") || 
+            !strcmp(type.dataTypeString, "uint") || !strcmp(type.dataTypeString, "uint32") || 
+            !strcmp(type.dataTypeString, "int64") || !strcmp(type.dataTypeString, "unsigned int64") || !strcmp(type.dataTypeString, "uint64") || 
+            !strcmp(type.dataTypeString, "short") || !strcmp(type.dataTypeString, "unsigned short") || !strcmp(type.dataTypeString, "uint16") ||
+            !strcmp(type.dataTypeString, "char") || !strcmp(type.dataTypeString, "unsigned char") || !strcmp(type.dataTypeString, "byte"))
+            oracleType = SQLT_INT;
+         else if(!strcmp(type.dataTypeString, "double") || !strcmp(type.dataTypeString, "float"))
+            oracleType = SQLT_FLT;
+         else if(!strcmp(type.dataTypeString, "String") || !strcmp(type.dataTypeString, "char *"))
+            oracleType = SQLT_STR;
+         else
+         {
+            /* No basic datatype */
+            if(strcmp(type.fullName, "CIString") && !db.collations.Find(type.fullName))
+            {
+               db.collations.Add(type.fullName);
+            }
+            oracleType = SQLT_BLOB;
+         }
+      }
+      else
+      {
+         type = class(String);
+         oracleType = SQLT_STR;
+      }
+
+      if (!strcmp(type.name, "Date"))
+      {
+         oracleType = SQLT_TIMESTAMP_TZ;
+      }
+
+      field = { name = CopyString(fieldName), type = type, num = fields.count, oracleType = SQLT_STR };
+
+      incref field;
+      fields.Add(field);
+      return (Field)field;
+   }
+
+   Field FindField(const String name)
+   {
+      String upperName = CopyString(name);     
+      ToUpperAndUnderscore(upperName);
+
+      for(f : fields)
+      {
+         String upperFieldName = CopyString(f.name);
+         ToUpperAndUnderscore(upperFieldName);
+
+         if (!strcmp(upperFieldName, upperName))
+         {
+            if(!primaryKey)
+            {
+               if(eClass_IsDerived(f.type, class(eda::Id)))
+               {
+
+                  Table * tablePtr = (Table *)eClass_GetProperty(f.type, "table");
+                  if(tablePtr && *tablePtr == this)
+                     primaryKey = f;
+               }
+            }
+
+            delete upperFieldName;            
+            return (Field)f;  
+         }
+
+         delete upperFieldName;
+      }
+
+      delete upperName;
+      return null;
+   }
+
+   bool GenerateIndex(int count, FieldIndex * fieldIndexes, bool init)
+   {
+      return false;
+   }
+
+   String GetName()
+   {
+      return name;
+   }
+
+   Field GetFirstField()
+   {
+      return fields.first;
+   }
+
+   uint GetFieldsCount()
+   {
+      return fields.count;
+   }
+
+   uint GetRowsCount()
+   {
+      char command[1024];
+      char **t;
+      int nCols, nRows;
+      int result;
+      uint rowCount = 0;
+      
+      OCIStmt* stmtCount; 
+      OCIError* err;
+      text errbuf[512];
+      ub4 buflen;
+      ub4 errcode;
+      int r;
+
+      sprintf(command, "SELECT COUNT(*) FROM %s", name);
+
+      OCIHandleAlloc(db.env, (dvoid**)&err, OCI_HTYPE_ERROR,   0, 0);
+      OCIHandleAlloc(db.env, (dvoid**)&stmtCount, OCI_HTYPE_STMT, 0, 0);
+
+      r = OCIStmtPrepare(stmtCount, err, (OraText *)command,
+         (ub4)strlen((char *)command),
+         (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT);
+
+      r = OCIDefineByPos(stmtCount, &p_dfn, err, 1, (dvoid *) &rowCount,
+         (sword) sizeof(uint), SQLT_INT, (dvoid *) 0, (ub2 *)0,
+         (ub2 *)0, OCI_DEFAULT);
+
+      r = OCIStmtExecute(db.svc, stmtCount, err, 1, 0,
+         (OCISnapshot *) 0, (OCISnapshot *) 0, OCI_COMMIT_ON_SUCCESS);
+
+      if (err) OCIHandleFree(err, OCI_HTYPE_ERROR);
+      if (stmtCount) OCIHandleFree(stmtCount, OCI_HTYPE_STMT);
+
+      return rowCount;
+   }
+
+   // Returns true if not ordered by row ID
+   bool GetIndexOrder(char * fullOrder)
+   {
+      if(!indexFields || (indexFieldsCount == 1 && indexFields[0].field == primaryKey && indexFields[0].order == ascending))
+      {
+         OracleField field = GetFirstField();
+         strcpy(fullOrder, " ORDER BY ");
+         strcat(fullOrder, field.name);
+         strcat(fullOrder, "\0");
+         return false;
+      }
+      else
+      {
+         int c;
+         strcpy(fullOrder, " ORDER BY ");
+         for(c = 0; c < indexFieldsCount; c++)
+         {
+            char order[1024];
+            FieldIndex * fIndex = &indexFields[c];
+            order[0] = 0;
+            if(c) strcat(order, ", ");
+            strcat(order, "`");
+            strcat(order, fIndex->field.name);
+            strcat(order, "`");
+            if(fIndex->order == descending) strcat(order, " DESC");
+            strcat(fullOrder, order);
+         }
+         return true;
+      }
+
+      return false;
+   }
+
+   DriverRow CreateRow()
+   {
+      char command[1024];
+      int r;
+      int i;
+      String fieldList[1024];
+
+      if(specialStatement)
+         strcpy(command, specialStatement);
+      else
+      {
+         char order[1024];
+
+         GetIndexOrder(order);
+         sprintf(command, "SELECT * FROM %s %s", name, order);
+      }
+
+      if (stmt) OCIHandleFree(stmt, OCI_HTYPE_STMT);
+      OCIHandleAlloc(db.env, (dvoid**)&stmt, OCI_HTYPE_STMT, 0, 0); 
+
+      for (i = 0; i < fields.count; i++)
+      {
+         OracleField field = fields[i];
+         r= OCIDescriptorAlloc(db.env,(dvoid **)&field.p_sliDateTime, OCI_DTYPE_TIMESTAMP,
+            0, (dvoid **)0);
+      }
+
+      r = OCIStmtPrepare(stmt, db.err, (OraText *)command,
+         (ub4)strlen((char *)command),
+         (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT);
+      
+      for (i = 0; i < fields.count; i++)
+      {
+         OracleField field = fields[i];
+         switch(field.oracleType)
+         {
+            case SQLT_INT:
+            {
+               r = OCIDefineByPos(stmt, &field.p_dfn, db.err, i + 1, (dvoid *) &field.p_sliInt,
+                  sizeof(int), SQLT_INT, (dvoid *) 0, (ub2 *)0,
+                  (ub2 *)0, OCI_DEFAULT);
+               break;
+            }
+            case SQLT_FLT:
+            {
+               r = OCIDefineByPos(stmt, &field.p_dfn, db.err, i + 1, (dvoid *) &field.p_sliFloat,
+                  sizeof(double), SQLT_FLT, (dvoid *) 0, (ub2 *)0,
+                  (ub2 *)0, OCI_DEFAULT);
+               break;
+            }
+            case SQLT_TIMESTAMP_TZ:
+            {
+               r = OCIDefineByPos(stmt, &field.p_dfn, db.err, i + 1, (dvoid *) &field.p_sliDateTime,
+                  sizeof(field.p_sliDateTime), SQLT_TIMESTAMP_TZ, (dvoid *) 0, (ub2 *)0,
+                  (ub2 *)0, OCI_DEFAULT);
+               break;
+            }
+            case SQLT_STR:
+            case SQLT_BLOB: // No basic datatype
+            {
+               r = OCIDefineByPos(stmt, &field.p_dfn, db.err, i + 1, (dvoid *) &field.p_sli,
+                  (sword) 1024, SQLT_STR, (dvoid *) 0, (ub2 *)0,
+                  (ub2 *)0, OCI_DEFAULT);
+               break;
+            }
+         }
+      }
+
+      r = OCIStmtExecute(db.svc, stmt, db.err, 0, 0,
+         (OCISnapshot *) 0, (OCISnapshot *) 0, OCI_STMT_SCROLLABLE_READONLY);
+
+      return OracleRow { tbl = this, rowID = 0 };
+   }
+
+   ~OracleTable()
+   {
+      if (stmt) OCIHandleFree(stmt, OCI_HTYPE_STMT); 
+
+      delete name;
+      delete specialStatement;
+      delete indexFields;
+      fields.Free();
+   }
+}
+
+class OracleRow : DriverRow
+{
+   OracleTable tbl;
+
+   bool done;
+   done = true;
+   int64 rowID;
+   int numVal;
+   
+   bool Nil()
+   {
+      return done;
+   }
+
+   ~OracleRow()
+   {
+   }
+
+   bool Select(MoveOptions move)
+   {
+      int r;
+
+      text errbuf[512];
+      ub4 errcode;  
+      int i;
+
+      tbl.OracleReinitFieldsDataTimeDescriptors();
+
+      switch(move)
+      {
+         case first:
+         {
+            r = OCIStmtFetch2(tbl.stmt, tbl.db.err, 1, OCI_FETCH_FIRST, 0, OCI_DEFAULT);
+            if (r == OCI_NO_DATA)
+            {
+               return false;
+            }
+            rowID = 1;
+            return true;
+            break;
+         }
+         case last:
+         {
+            break;
+         }
+         case middle:
+         {
+            break;
+         }
+         case next:
+         {
+            r = OCIStmtFetch2(tbl.stmt, tbl.db.err, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
+            if (r == OCI_NO_DATA)
+            {
+               return false;
+            }
+            rowID += 1;
+            return true;
+            break;
+         }
+         case previous:
+         {           
+            break;
+         }
+         case nil:
+         {
+            break;
+         }
+         case here:
+         {
+            break;
+         }
+      }
+
+      return false;
+   }
+
+   bool Query(char * queryString)
+   {
+      return false;
+   }
+
+   void AddCursorWhereClauses(char * command, MoveOptions move, bool useIndex)
+   {
+      printf("%s\n", "AddCursorWhereClauses...");
+   }
+
+   bool Find(Field fld, MoveOptions move, MatchOptions match, typed_object data)
+   {
+      if(fld == tbl.primaryKey)
+      {
+         int id;
+         id = *(int *)data;
+         return GoToSysID(id);
+
+         //return done;
+      }
+      else
+      {
+         OracleField oracleField = (OracleField)fld;
+         Class dataType = oracleField.type;
+         int r;  
+
+         switch (oracleField.oracleType)
+         {
+
+            case SQLT_INT:
+            {
+               switch(dataType.typeSize)
+               {
+                  case 8:
+                  {
+                     int64 dataValue = *(int64 *)data;
+
+                     tbl.OracleReinitFieldsDataTimeDescriptors();
+
+                     rowID = 1;
+                     r = OCIStmtFetch2(tbl.stmt, tbl.db.err, 1, OCI_FETCH_FIRST, 0, OCI_DEFAULT);
+                     
+                     if (oracleField.p_sliInt == dataValue)
+                     {
+                        return true;
+                     }
+                     while (r != OCI_NO_DATA)
+                     {
+                        tbl.OracleReinitFieldsDataTimeDescriptors();
+
+                        r = OCIStmtFetch2(tbl.stmt, tbl.db.err, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
+                        rowID += 1;
+                        if (oracleField.p_sliInt == dataValue)
+                        {
+                           return true;
+                        }
+                     }
+                     break;
+                  }
+                  case 4:
+                  {
+                     int dataValue = *(int *)data;
+
+                     tbl.OracleReinitFieldsDataTimeDescriptors();
+
+                     rowID = 1;
+                     r = OCIStmtFetch2(tbl.stmt, tbl.db.err, 1, OCI_FETCH_FIRST, 0, OCI_DEFAULT);
+                     
+                     if (oracleField.p_sliInt == dataValue)
+                     {
+                        return true;
+                     }
+                     while (r != OCI_NO_DATA)
+                     {
+                        tbl.OracleReinitFieldsDataTimeDescriptors();
+
+                        r = OCIStmtFetch2(tbl.stmt, tbl.db.err, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
+                        rowID += 1;
+                        if (oracleField.p_sliInt == dataValue)
+                        {
+                           return true;
+                        }
+                     }
+                     break;
+                  }
+                  case 2:
+                  {
+                     uint16 dataValue = *(uint16 *)data;
+
+                     tbl.OracleReinitFieldsDataTimeDescriptors();
+
+                     rowID = 1;
+                     r = OCIStmtFetch2(tbl.stmt, tbl.db.err, 1, OCI_FETCH_FIRST, 0, OCI_DEFAULT);
+                     
+                     if (oracleField.p_sliInt == dataValue)
+                     {
+                        return true;
+                     }
+                     while (r != OCI_NO_DATA)
+                     {
+                        tbl.OracleReinitFieldsDataTimeDescriptors();
+
+                        r = OCIStmtFetch2(tbl.stmt, tbl.db.err, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
+                        rowID += 1;
+                        if (oracleField.p_sliInt == dataValue)
+                        {
+                           return true;
+                        }
+                     }
+                     break;
+                  }
+                  case 1:
+                  {
+                     if(dataType.typeSize == 8)
+                     {
+                        double dataValue = *(double *)data;
+
+                        tbl.OracleReinitFieldsDataTimeDescriptors();
+
+                        rowID = 1;
+                        r = OCIStmtFetch2(tbl.stmt, tbl.db.err, 1, OCI_FETCH_FIRST, 0, OCI_DEFAULT);
+                        
+                        if (oracleField.p_sliInt == dataValue)
+                        {
+                           return true;
+                        }
+                        while (r != OCI_NO_DATA)
+                        {
+                           tbl.OracleReinitFieldsDataTimeDescriptors();
+
+                           r = OCIStmtFetch2(tbl.stmt, tbl.db.err, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
+                           rowID += 1;
+                           if (oracleField.p_sliInt == dataValue)
+                           {
+                              return true;
+                           }
+                        }
+                     }
+                     else
+                     {
+                        float dataValue = *(float *)data;
+
+                        tbl.OracleReinitFieldsDataTimeDescriptors();
+
+                        rowID = 1;
+                        r = OCIStmtFetch2(tbl.stmt, tbl.db.err, 1, OCI_FETCH_FIRST, 0, OCI_DEFAULT);
+                        
+                        if (oracleField.p_sliInt == dataValue)
+                        {
+                           return true;
+                        }
+                        while (r != OCI_NO_DATA)
+                        {
+                           tbl.OracleReinitFieldsDataTimeDescriptors();
+
+                           r = OCIStmtFetch2(tbl.stmt, tbl.db.err, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
+                           rowID += 1;
+                           if (oracleField.p_sliInt == dataValue)
+                           {
+                              return true;
+                           }
+                        }
+                     }                     
+                     break;
+                  }
+               }
+               break;
+            }
+            case SQLT_FLT:
+            {
+               byte dataValue = *(byte *)data;
+
+               tbl.OracleReinitFieldsDataTimeDescriptors();
+
+               rowID = 1;
+               r = OCIStmtFetch2(tbl.stmt, tbl.db.err, 1, OCI_FETCH_FIRST, 0, OCI_DEFAULT);
+               
+               if (oracleField.p_sliInt == dataValue)
+               {
+                  return true;
+               }
+               while (r != OCI_NO_DATA)
+               {
+                  tbl.OracleReinitFieldsDataTimeDescriptors();
+
+                  r = OCIStmtFetch2(tbl.stmt, tbl.db.err, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
+                  rowID += 1;
+                  if (oracleField.p_sliInt == dataValue)
+                  {
+                     return true;
+                  }
+               }
+               break;
+            }
+            case SQLT_STR:
+            {
+               char *dataValue = *(char **)data;
+
+               tbl.OracleReinitFieldsDataTimeDescriptors();
+
+               rowID = 1;
+               r = OCIStmtFetch2(tbl.stmt, tbl.db.err, 1, OCI_FETCH_FIRST, 0, OCI_DEFAULT);
+               
+               if (!strcmp(oracleField.p_sli, dataValue))
+               {
+                  return true;
+               }
+               while (r != OCI_NO_DATA)
+               {
+                  tbl.OracleReinitFieldsDataTimeDescriptors();
+
+                  r = OCIStmtFetch2(tbl.stmt, tbl.db.err, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
+                  rowID += 1;
+                  if (!strcmp(oracleField.p_sli, dataValue))
+                  {
+                     return true;
+                  }
+               }
+               break;
+            }
+            case SQLT_TIMESTAMP_TZ:
+            {
+               sb2 year;
+               ub1 month;
+               ub1 day;
+               Date date = *(Date *)data;
+
+               tbl.OracleReinitFieldsDataTimeDescriptors();
+
+               rowID = 1;
+               r = OCIStmtFetch2(tbl.stmt, tbl.db.err, 1, OCI_FETCH_FIRST, 0, OCI_DEFAULT);
+               
+               OCIDateTimeGetDate(tbl.db.env, tbl.db.err, oracleField.p_sliDateTime,
+                  &year, &month, &day);  
+
+               if ((year == date.year) && (month == date.month) && (day == date.day))
+               {
+                  return true;
+               }
+               while (r != OCI_NO_DATA)
+               {
+                  tbl.OracleReinitFieldsDataTimeDescriptors();
+
+                  r = OCIStmtFetch2(tbl.stmt, tbl.db.err, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
+                  OCIDateTimeGetDate(tbl.db.env, tbl.db.err, oracleField.p_sliDateTime,
+                     &year, &month, &day);
+                  rowID += 1;
+                  if ((year == date.year) && (month == date.month) && (day == date.day))
+                  {
+                     return true;
+                  }
+               }
+               break;
+            }
+            case SQLT_BLOB: // No basic datatype
+            {
+               //TODO
+               break;
+            }
+         }
+      }
+      
+      return false;
+   }
+
+   bool FindMultiple(FieldFindData * findData, MoveOptions move, int numFields)
+   {
+      printf("%s\n", "FindMultiple...");
+      return false;
+   }
+
+   bool Synch(DriverRow to)
+   {
+      printf("%s\n", "Synch...");
+      return false;
+   }
+
+   bool Add(uint64 id)
+   {
+      /* We use primaryKey to new row. We increment primaryKey.
+         If we must do it without it, it has to be changed */
+
+      char command[1024];
+      String primaryKeyName;
+      String tableName;
+      int r;
+      int newID;
+
+      if (tbl.primaryKey)
+      {
+         primaryKeyName = CopyString(tbl.primaryKey.name);
+      }
+      else
+      {
+         primaryKeyName = CopyString(tbl.GetFirstField().name);
+      }
+
+      tableName = CopyString(tbl.name);
+
+      ToUpperAndUnderscore(primaryKeyName);
+      ToUpperAndUnderscore(tableName);
+
+      if (id)
+      {
+         /* New row with id as new value for primaryKey field */
+         sprintf(command, "INSERT INTO %s (%s) VALUES (%i)", tableName, primaryKeyName, id);
+      }
+      else
+      {
+         /* New row with id as max(id)+i*/
+         sprintf(command, "INSERT INTO %s (%s) SELECT MAX(CAST(%s AS INTEGER)) + 1 FROM %s",
+            tableName, primaryKeyName, primaryKeyName, tbl.name); 
+      }
+
+      OracleExecuteNonQuery(tbl.db.env, tbl.db.svc, command);
+      
+      r = OCIStmtExecute(tbl.db.svc, tbl.stmt, tbl.db.err, 0, 0,
+         (OCISnapshot *) 0, (OCISnapshot *) 0, OCI_STMT_SCROLLABLE_READONLY); 
+      r = OCIStmtFetch2(tbl.stmt, tbl.db.err, 1, OCI_FETCH_LAST, 0, OCI_DEFAULT);
+      
+      delete primaryKeyName;
+      delete tableName;
+
+      return true;
+   }
+
+   bool Delete()
+   {
+      String primaryKeyName;
+      String tableName;
+      OracleField primaryKeyField;
+      String primaryKeyValue;
+      String primaryKeyValueString[1024];
+      int primaryKeyValueInt;
+      bool deletePrimaryKeyValue = false;
+      char command[1024];
+      int r;
+
+      if (tbl.primaryKey)
+      {
+         primaryKeyName = CopyString(tbl.primaryKey.name);
+      }
+      else
+      {
+         primaryKeyName = CopyString(tbl.GetFirstField().name);
+      }
+      
+      primaryKeyField = tbl.FindField(primaryKeyName);
+
+      tableName = CopyString(tbl.name);
+
+      ToUpperAndUnderscore(primaryKeyName);
+      ToUpperAndUnderscore(tableName);
+
+      if (primaryKeyField.oracleType == SQLT_STR)
+      {
+         GetData(primaryKeyField, primaryKeyValue);
+         deletePrimaryKeyValue = true;
+      }
+      else
+      {
+         GetData(primaryKeyField, primaryKeyValueInt);
+         sprintf(primaryKeyValueString, "%i", primaryKeyValueInt);
+         primaryKeyValue = primaryKeyValueString;
+      }
+
+      sprintf(command, "DELETE %s WHERE %s = %s", tableName, primaryKeyName, primaryKeyValue);
+      r = OracleExecuteNonQuery(tbl.db.env, tbl.db.svc, command);
+
+      if (deletePrimaryKeyValue)
+         delete primaryKeyValue;
+
+      delete primaryKeyName;
+      delete tableName;
+
+      if ((r == OCI_SUCCESS) || (r == OCI_SUCCESS_WITH_INFO))
+         return true;
+
+      return false;
+   }
+
+   bool GetData(Field fld, typed_object &data)
+   {
+      OracleField sqlFld = (OracleField)fld;
+      Class dataType = sqlFld.type;
+
+      switch(sqlFld.oracleType)
+      {
+         case SQLT_INT:
+         {
+            switch(dataType.typeSize)
+            {
+               case 8:
+               {
+                  *(int64 *)data = sqlFld.p_sliInt;
+                  break;
+               }
+               case 4:
+               {
+                  *(int *)data = sqlFld.p_sliInt;
+                  break;
+               }
+               case 2:
+               {
+                  *(uint16 *)data = (uint16)sqlFld.p_sliInt;
+                  break;
+               }
+               case 1:
+               {
+                  if(dataType.typeSize == 8)
+                     *(double *)data = sqlFld.p_sliFloat;
+                  else
+                     *(float *)data = (float)sqlFld.p_sliFloat;
+                  break;
+               }
+            }
+            break;
+         }
+         case SQLT_FLT:
+         {
+            *(byte *)data = (byte)sqlFld.p_sliInt;
+            break;
+         }
+         case SQLT_STR:
+         {
+            int numBytes = strlen(sqlFld.p_sli);
+            *(char **)data = sqlFld.p_sli ? new byte[numBytes+1] : null;
+            if(sqlFld.p_sli)
+               memcpy(*(char **)data, sqlFld.p_sli, numBytes+1);
+            break;
+         }
+         case SQLT_TIMESTAMP_TZ:
+         {
+            sb2 year;
+            ub1 month;
+            ub1 day;
+
+            OCIDateTimeGetDate(tbl.db.env, tbl.db.err, sqlFld.p_sliDateTime,
+               &year, &month, &day);
+            if (day > 0)
+               *(Date *)data = Date { year = year, month = month - 1, day = day };
+            break;
+         }
+         case SQLT_BLOB: // No basic datatype
+         {
+            SerialBuffer buffer { };
+            char *dataBuffer;
+
+            buffer._size = strlen(sqlFld.p_sli) / 2;
+
+            if (buffer._size > 0)
+            {
+               int i;
+               int x = 0;
+               dataBuffer = new byte[buffer._size];
+               for(i = 0; i < strlen(sqlFld.p_sli); i+=2)
+               {
+                  int h;
+                  char c[3];
+
+                  c[0] = sqlFld.p_sli[i];
+                  c[1] = sqlFld.p_sli[i + 1];
+                  c[2] = '\0';
+
+                  xtoi(c, &h);
+                  dataBuffer[x] = h;
+
+                  x += 1;
+               }
+
+               buffer._buffer = dataBuffer;
+               buffer.count = buffer._size;
+
+               dataType._vTbl[__ecereVMethodID_class_OnUnserialize](dataType, data, buffer);
+
+               delete dataBuffer;
+               dataBuffer = null;
+            }
+
+            buffer._buffer = null;
+            delete buffer;
+            break;
+         }
+      }
+
+      return true;
+   }
+
+   bool SetData(Field fld, typed_object data)
+   {
+      OracleField sqlFld = (OracleField)fld;
+      Class dataType = sqlFld.type;
+      char command[1024];
+      String primaryKeyName;
+      String primaryKeyValue;
+      String primaryKeyValueString[1024];
+      int primaryKeyValueInt;
+      OracleField primaryKeyField;
+      bool deletePrimaryKeyValue = false;
+      String tableName = CopyString(tbl.name);
+      String fieldName = CopyString(sqlFld.name);
+      int r;
+      int actualRowID;
+
+      if (tbl.primaryKey)
+      {
+         primaryKeyName = CopyString(tbl.primaryKey.name);
+      }
+      else
+      {
+         primaryKeyName = CopyString(tbl.GetFirstField().name);
+      }
+      
+      primaryKeyField = tbl.FindField(primaryKeyName);
+      if (primaryKeyField.oracleType == SQLT_STR)
+      {
+         GetData(primaryKeyField, primaryKeyValue);
+         deletePrimaryKeyValue = true;
+      }
+      else
+      {
+         GetData(primaryKeyField, primaryKeyValueInt);
+         sprintf(primaryKeyValueString, "%i", primaryKeyValueInt);
+         primaryKeyValue = primaryKeyValueString;
+      }
+
+      ToUpperAndUnderscore(primaryKeyName);
+      ToUpperAndUnderscore(tableName);
+      ToUpperAndUnderscore(fieldName);
+
+      switch(sqlFld.oracleType)
+      {
+         case SQLT_INT:
+            switch(dataType.typeSize)
+            {
+               case 8:
+               {
+                  sprintf(command, "UPDATE %s SET %s = '%i' WHERE %s = %s", tableName, fieldName, (int64)data, primaryKeyName, primaryKeyValue);
+                  r = OracleExecuteNonQuery(tbl.db.env, tbl.db.svc, command);
+                  break;
+               }
+               case 4:
+               {
+                  sprintf(command, "UPDATE %s SET %s = '%i' WHERE %s = %s", tableName, fieldName, (int)data, primaryKeyName, primaryKeyValue);
+                  r = OracleExecuteNonQuery(tbl.db.env, tbl.db.svc, command);
+                  break;
+               }
+               case 2:
+               {
+                  sprintf(command, "UPDATE %s SET %s = '%i' WHERE %s = %s", tableName, fieldName, (uint16)data, primaryKeyName, primaryKeyValue);
+                  r = OracleExecuteNonQuery(tbl.db.env, tbl.db.svc, command);
+                  break;
+               }
+               case 1:
+               {
+                  if(dataType.typeSize == 8)
+                     sprintf(command, "UPDATE %s SET %s = '%d' WHERE %s = %s", tableName, fieldName, (double)data, primaryKeyName, primaryKeyValue);
+                  else
+                     sprintf(command, "UPDATE %s SET %s = '%d' WHERE %s = %s", tableName, fieldName, (float)data, primaryKeyName, primaryKeyValue);
+                  r = OracleExecuteNonQuery(tbl.db.env, tbl.db.svc, command);
+                  break;
+               }
+            }
+            break;
+         case SQLT_FLT:            
+            sprintf(command, "UPDATE %s SET %s = '%i' WHERE %s = %s", tableName, fieldName, (uint16)data, primaryKeyName, primaryKeyValue);
+            r = OracleExecuteNonQuery(tbl.db.env, tbl.db.svc, command);
+            break;
+         case SQLT_STR:
+         {
+            sprintf(command, "UPDATE %s SET %s = '%s' WHERE %s = %s", tableName, fieldName, (char *)data, primaryKeyName, primaryKeyValue);
+            r = OracleExecuteNonQuery(tbl.db.env, tbl.db.svc, command);
+            break;
+         }
+         case SQLT_TIMESTAMP_TZ:
+         {
+            sb2 year;
+            ub1 month;
+            ub1 day;
+            char date[11];
+
+            Date* ecDate = data;
+            year = ecDate->year;
+            month = ecDate->month;
+            day = ecDate->day;
+
+            sprintf(date, "%04i-%02i-%02i", year, month, day);
+            
+            sprintf(command, "UPDATE %s SET %s = TO_DATE('%s', 'YYYY-MM-DD') WHERE %s = %s", tableName, fieldName, date, primaryKeyName, primaryKeyValue);
+
+            if ((month > -1) && (month < 13))
+            {
+               r = OracleExecuteNonQuery(tbl.db.env, tbl.db.svc, command);
+            }
+            break;
+         }
+         case SQLT_BLOB: // No basic datatype
+         {           
+            break;
+         }
+      }
+
+      if (deletePrimaryKeyValue)
+         delete primaryKeyValue;
+
+      delete primaryKeyName;
+      delete tableName;
+      delete fieldName;
+
+      actualRowID = rowID;
+      OracleExecuteNonQuery(tbl.db.env, tbl.db.svc, command);
+      
+      r = OCIStmtExecute(tbl.db.svc, tbl.stmt, tbl.db.err, 0, 0,
+         (OCISnapshot *) 0, (OCISnapshot *) 0, OCI_STMT_SCROLLABLE_READONLY); 
+      r = OCIStmtFetch2(tbl.stmt, tbl.db.err, actualRowID, OCI_FETCH_ABSOLUTE, 0, OCI_DEFAULT);
+      
+      if ((r == OCI_SUCCESS) || (r == OCI_SUCCESS_WITH_INFO))
+         return true;
+      
+      return false;
+   }
+
+   int GetSysID()
+   {
+      return (int)(uint)rowID;
+   }
+
+   bool GoToSysID(uint id)
+   {
+      /* We need to find in primaryKey field the row matching primaryKey field value and id */    
+      char idValue[64];
+      int r;
+      int i;
+
+      tbl.OracleReinitFieldsDataTimeDescriptors();
+
+      rowID = 1;
+      r = OCIStmtFetch2(tbl.stmt, tbl.db.err, 1, OCI_FETCH_FIRST, 0, OCI_DEFAULT);
+      if (tbl.primaryKey.p_sliInt == id)
+      {
+         return true;
+      }
+      while (r != OCI_NO_DATA)
+      {
+         tbl.OracleReinitFieldsDataTimeDescriptors();
+
+         r = OCIStmtFetch2(tbl.stmt, tbl.db.err, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
+         rowID += 1;
+         if (tbl.primaryKey.p_sliInt == id)
+         {
+            return true;
+         }
+      }
+
+      return false;
+   }
+
+   bool SetQueryParam(int paramID, int value)
+   {
+      printf("%s\n", "SetQueryParam...");
+      return false;
+   }
+
+   bool SetQueryParam64(int paramID, int64 value)
+   {
+      printf("%s\n", "SetQueryParam634...");
+      return false;
+   }
+
+   bool SetQueryParamText(int paramID, char * data)
+   {
+      printf("%s\n", "SetQueryParamText...");
+      return false;
+   }
+
+   bool SetQueryParamObject(int paramID, void * data, Class type)
+   {
+      printf("%s\n", "SetQueryParamObject...");
+      return false;
+   }
+
+   char * GetColumn(int paramID)
+   {
+      printf("%s\n", "GetColumn...");
+      return null;
+   }
+}
\ No newline at end of file
diff --git a/eda/drivers/oracle/EDAOracle.epj b/eda/drivers/oracle/EDAOracle.epj
new file mode 100644 (file)
index 0000000..ca651dd
--- /dev/null
@@ -0,0 +1,51 @@
+{
+   "Version" : 0.2,
+   "ModuleName" : "EDAOracle",
+   "Options" : {
+      "Warnings" : "All",
+      "TargetType" : "SharedLibrary",
+      "TargetFileName" : "EDAOracle",
+      "Libraries" : [
+         "ecere"
+      ]
+   },
+   "Configurations" : [
+      {
+         "Name" : "Debug",
+         "Options" : {
+            "Debug" : true,
+            "Optimization" : "None",
+            "PreprocessorDefinitions" : [
+               "_DEBUG"
+            ],
+            "IncludeDirs" : [
+               "C:/oraclexe/app/oracle/product/11.2.0/server/oci/include"
+            ],
+            "Libraries" : [
+               "ecere",
+               "oci"
+            ],
+            "LinkerOptions" : [
+
+            ],
+            "LibraryDirs" : [
+               "C:/oraclexe/app/oracle/product/11.2.0/server/bin"
+            ]
+         }
+      },
+      {
+         "Name" : "Release",
+         "Options" : {
+            "Debug" : false,
+            "Optimization" : "Speed"
+         }
+      }
+   ],
+   "Files" : [
+      "EDAOracle.ec"
+   ],
+   "ResourcesPath" : "",
+   "Resources" : [
+
+   ]
+}
\ No newline at end of file
index 2539b09..5dc0b69 100644 (file)
@@ -69,6 +69,15 @@ class EDABetterTestForm : Window
             nameDb.contents = "mysql";
             groupDs.disabled = false;
          }
+         else if (!strcmp(select, "Oracle"))
+         {
+            host.contents = "localhost";
+            username.contents = "test";
+            password.contents = "test";
+            port.contents = "1521";
+            nameDb.contents = "xe";
+            groupDs.disabled = false;
+         }
          return true;
       }
 
@@ -82,8 +91,9 @@ class EDABetterTestForm : Window
          AddString("MemoryEDB");
          AddString("MySQL");
          AddString("PostgreSQL");
-         SelectRow(AddString("SQLite"));
+         AddString("SQLite");
          AddString("SQLiteCipher");
+         SelectRow(AddString("Oracle"));
 
          return true;
       }
index 99785ea..e21488f 100644 (file)
@@ -30,8 +30,10 @@ class MovieCollectionApp : GuiApplication
    {
       SetDefaultIdField("ID");
       SetDefaultNameField("Name");
-      ds = DataSource { driver = "SQLite" };
-      db = database_open(ds, "collection");
+      //ds = DataSource { driver = "SQLite" };
+      //db = database_open(ds, "collection");
+      ds = DataSource { driver = "Oracle", host = "localhost", port = "1521", user = "test", pass = "test" };
+      db = database_open(ds, "xe");
    }
    ~MovieCollectionApp()
    {