4 define MySQL = "MySQL";
6 #ifdef COMMENTED_OUT_MYSQL_NEED_MATCH_MODIFIED_DRIVER_STRUCTURE
11 #define DEFALT_SQL_STMT "SELECT * FROM db"
13 static MySqlLib mySqlLib;
15 static void LogMySqlError(MYSQL * mySql, String msg)
17 Logf("%s\n MySql Error: #%d %s\n", msg, mysql_errno(mySql), mysql_error(mySql));
20 static void LogMySqlErrorf(MYSQL * mySql, String format, ...)
22 char msg[MAX_F_STRING];
25 va_start(args, format);
26 vsprintf(msg, format, args);
29 Logf("%s\n MySql Error: #%d %s\n", msg, mysql_errno(mySql), mysql_error(mySql));
36 mysql_library_init(0, null, null);
45 static class MySqlDataSource : struct
51 static class MySqlDatabase : struct
59 static class MySqlTable : struct
73 static class MySqlField : struct
84 static class MySqlRow : struct
88 unsigned long *myLengths;
99 class MySqlDataDriver : DataDriver
103 class_property(name) = "MySql";
105 /* -------------------------------------------------------------------------------------------------- */
106 /* --- Driver --------------------------------------------------------------------------------------- */
108 uint ::DriverDefaultPort()
113 /* -------------------------------------------------------------------------------------------------- */
114 /* --- Data Source ---------------------------------------------------------------------------------- */
116 void ::SourceClose(DataSource ds)
118 MySqlDataSource src = (MySqlDataSource)ds.driverData;
121 if(src.mySql) mysql_close(src.mySql);
123 ds.driverData = null;
127 void ::SourceStatus(DataSource ds)
129 MySqlDataSource src = (MySqlDataSource)ds.driverData;
131 Log(" ********************************************* \n");
132 Log(" * MySql Status Info * \n");
133 Log(" ********************************************* \n");
134 pszT = mysql_get_client_info(); Logf(" Client info: %s\n", pszT);
135 pszT = mysql_get_host_info(src.mySql); Logf(" Host info: %s\n", pszT);
136 pszT = mysql_get_server_info(src.mySql); Logf(" Server info: %s\n", pszT);
137 Log(" _____________________________________\n\n");
139 Log(" ********************************************* \n");
140 Log(" * Stats * \n");
141 Log(" ********************************************* \n");
142 pszT = mysql_stat(src.mySql); Logf(" %s\n", pszT);
143 Log(" _____________________________________\n\n");
146 bool ::SourceConnect(DataSource ds, const String host, const String user, const String password, uint port)
148 bool success = false;
149 MySqlDataSource src {};
150 if(!mySqlLib) mySqlLib = { };
151 if(src.mySql) mysql_close(src.mySql);
152 if(src.mySql = mysql_init((MYSQL *) 0))
154 if(mysql_real_connect(src.mySql, host, user, password, null, port, null, 0))
156 src.mySql->reconnect = 1;
161 LogMySqlErrorf(src.mySql, "Can't connect to the mysql server on port %d !\n", port);
162 mysql_close(src.mySql);
167 LogMySqlError(src.mySql, "Can't initialize mysql socket");
168 mysql_close(src.mySql);
170 ds.driverData = (void *)src;
174 uint ::SourceDatabasesCount(DataSource ds)
176 MySqlDataSource src = (MySqlDataSource)ds.driverData;
177 Log("TODO: MySql - DataSourceDatabasesCount");
181 /* -------------------------------------------------------------------------------------------------- */
182 /* --- Database ------------------------------------------------------------------------------------- */
184 void ::DatabaseClose(Database db)
186 MySqlDatabase dDb = (MySqlDatabase)db.driverData;
187 Log("TODO: MySql - DatabaseClose");
190 uint ::DatabaseTablesCount(Database db)
192 MySqlDatabase dDb = (MySqlDatabase)db.driverData;
193 Log("TODO: MySql - DatabaseTablesCount");
197 uint ::DatabaseViewsCount(Database db)
199 MySqlDatabase dDb = (MySqlDatabase)db.driverData;
200 Log("TODO: MySql - DatabaseViewsCount");
204 String ::DatabaseNameGet(Database db)
206 MySqlDatabase dDb = (MySqlDatabase)db.driverData;
207 Log("TODO: MySql - DatabaseNameGet");
211 bool ::DatabaseNameSet(Database db, const String value)
213 MySqlDatabase dDb = (MySqlDatabase)db.driverData;
214 Log("TODO: MySql - DatabaseNameSet");
218 bool ::DatabaseOpen(Database db, DataSource ds, const String name, OpenOptions options)
220 MySqlDataSource src = (MySqlDataSource)ds.driverData;
221 MySqlDatabase dDb { mySql = src.mySql, src = src };
223 db.driver = ds.driver;
224 db.driverData = (void *)dDb;
226 databases = ds.OpenTable(null, { databasesList });
229 if(databases.row.field.Seek("SCHEMA_NAME", firstEqual))
231 if(!databases.row.Seek(name, firstEqual))
233 if(options.create == create)
235 char ddl[MAX_F_STRING];
236 sprintf(ddl, "CREATE DATABASE IF NOT EXISTS %s", name); // [[DEFAULT] CHARACTER SET, [[DEFAULT] COLLATE]]
237 if(mysql_query(src.mySql, ddl))
238 LogMySqlErrorf(src.mySql, "Couldn't execute DDL statement on the server!\n %s", ddl);
242 Logf("Database (%s) does not exist.\n", name);
248 Log("Unable to detect if database exists!\n");
252 Log("Unable to detect if database exists!\n");
254 if(mysql_select_db(dDb.mySql, name) < 0)
256 LogMySqlErrorf(src.mySql, "Can't open the %s database!\n", db);
262 bool ::DatabaseDelete(Database db, DataSource ds, const String name)
266 MySqlDatabase dDb = (MySqlDatabase)db.driverData;
270 MySqlDataSource src = (MySqlDataSource)ds.driverData;
272 Log("TODO: MySql - DatabaseDelete");
276 /* -------------------------------------------------------------------------------------------------- */
277 /* --- Table ---------------------------------------------------------------------------------------- */
279 void ::TableClose(Table tbl)
281 MySqlTable dTbl = (MySqlTable)tbl.driverData;
282 if(dTbl.myRes) mysql_free_result(dTbl.myRes);
285 uint ::TableFieldsCount(Table tbl)
287 MySqlTable dTbl = (MySqlTable)tbl.driverData;
288 return mysql_num_fields(dTbl.myRes);
291 uint ::TableRowsCount(Table tbl)
293 MySqlTable dTbl = (MySqlTable)tbl.driverData;
294 return (uint)mysql_num_rows(dTbl.myRes);
297 Field ::TableField(Table tbl)
299 MySqlTable dTbl = (MySqlTable)tbl.driverData;
302 dTbl.dFld = MySqlField { mysql_fetch_fields(dTbl.myRes), dTbl = dTbl, fldsCount = mysql_num_fields(dTbl.myRes), fldsPos = -1 };
303 dTbl.fld = Field { driver = tbl.driver, driverData = dTbl.dFld };
308 Row ::TableRow(Table tbl)
310 MySqlTable dTbl = (MySqlTable)tbl.driverData;
313 dTbl.dRow = MySqlRow { dTbl = dTbl, rowsCount = (uint)mysql_num_rows(dTbl.myRes), rowsPos = -1 };
314 dTbl.row = Row { driver = tbl.driver, driverData = dTbl.dRow };
319 String ::TableNameGet(Table tbl)
321 MySqlTable dTbl = (MySqlTable)tbl.driverData;
322 Log("TODO: MySql - TableNameGet");
326 bool ::TableNameSet(Table tbl, const String value)
328 MySqlTable dTbl = (MySqlTable)tbl.driverData;
329 Log("TODO: MySql - TableNameSet");
333 bool ::TableOpen(Table tbl, Database db, DataSource ds, const String query, OpenOptions options)
335 char sql[MAX_F_STRING];
340 tbl.driverData = (void *)dTbl;
343 dDb = (MySqlDatabase)db.driverData;
345 dTbl.mySql = dDb.mySql;
346 tbl.driver = db.driver;
347 if(options.type == tableRows)
348 tables = db.OpenTable(null, { tablesList });
349 else if(options.type == viewRows)
354 src = (MySqlDataSource)ds.driverData;
355 dTbl.mySql = src.mySql;
356 tbl.driver = ds.driver;
357 if(options.type == tableRows)
358 tables = ds.OpenTable(null, { tablesList });
359 else if(options.type == viewRows)
363 if(options.type == tableRows)
367 if(tables.row.field.Seek("TABLE_NAME", firstEqual))
369 if(!tables.row.Seek(query, firstEqual))
371 if(options.create == create)
373 char ddl[MAX_F_STRING];
374 sprintf(ddl, "CREATE TABLE IF NOT EXISTS %s (a INT);", query);
375 if(mysql_query(src.mySql, ddl))
376 LogMySqlErrorf(src.mySql, "Couldn't execute DDL statement on the server!\n %s", ddl);
380 Logf("Table (%s) does not exist.\n", query);
386 Log("Unable to detect if table exists!\n");
390 Log("Unable to detect if table exists!\n");
396 if(!mysql_query(dTbl.mySql, query))
398 if(options.access == integral)
399 dTbl.myRes = mysql_store_result(dTbl.mySql);
401 dTbl.myRes = mysql_use_result(dTbl.mySql);
404 LogMySqlErrorf(dTbl.mySql, "Couldn't execute %s on the server!", sql);
407 sprintf(sql, "SELECT * FROM %s", query);
408 if(!mysql_query(dTbl.mySql, sql))
410 if(options.access == integral)
411 dTbl.myRes = mysql_store_result(dTbl.mySql);
413 dTbl.myRes = mysql_use_result(dTbl.mySql);
416 LogMySqlErrorf(dTbl.mySql, "Couldn't execute %s on the server!", sql);
421 dTbl.myRes = mysql_list_processes(dTbl.mySql);
424 dTbl.myRes = mysql_list_dbs(dTbl.mySql, null);
427 dTbl.myRes = mysql_list_tables(dTbl.mySql, null);
430 sprintf(sql, "SHOW COLUMNS FROM %s", query);
431 if(!mysql_query(dTbl.mySql, sql))
432 dTbl.myRes = mysql_store_result(dTbl.mySql);
434 LogMySqlErrorf(dTbl.mySql, "Listing fields for table %s failed!", query);
440 //dTbl.fldsCount = mysql_num_fields(dTbl.myRes);
441 //dTbl.flds = mysql_fetch_fields(dTbl.myRes);
448 bool ::TableDelete(Table tbl, Database db, const String name)
452 MySqlTable dTbl = (MySqlTable)tbl.driverData;
456 MySqlDatabase dDb = (MySqlDatabase)db.driverData;
458 Log("TODO: MySql - TableDelete");
462 /* -------------------------------------------------------------------------------------------------- */
463 /* --- Field ---------------------------------------------------------------------------------------- */
465 bool FieldEnd(Field fld)
467 MySqlField dFld = (MySqlField)fld.driverData;
468 return dFld.fldsPos == dFld.fldsCount;
471 bool FieldNext(Field fld)
473 MySqlField dFld = (MySqlField)fld.driverData;
474 /*if(dFld.fldsPos == -1)
477 if(dFld.fldsPos == dFld.fldsCount)
483 bool FieldPrevious(Field fld)
485 MySqlField dFld = (MySqlField)fld.driverData;
486 if(dFld.fldsPos == -1)
487 dFld.fldsPos = dFld.fldsCount ? dFld.fldsCount + 1 : 0;
488 else if(dFld.fldsPos == 0)
490 dFld.fldsPos = dFld.fldsCount;
497 bool FieldSeek(Field fld, String value, SeekOptions options)
499 MySqlField dFld = (MySqlField)fld.driverData;
508 else if(options == first)
516 else if(options == firstEqual)
518 int len = strlen(value);
519 for(dFld.fldsPos = 0; dFld.fldsPos < dFld.fldsCount; dFld.fldsPos++)
520 if(dFld.myFlds[dFld.fldsPos].org_name_length == len && !strncmp(dFld.myFlds[dFld.fldsPos].org_name, value, len))
522 if(dFld.fldsPos == dFld.fldsCount)
529 else if(options == last)
533 dFld.fldsPos = dFld.fldsCount - 1;
537 else if(options == none)
545 String ::FieldNameGet(Field fld)
547 MySqlField dFld = (MySqlField)fld.driverData;
548 String name = new char [dFld.myFlds[dFld.fldsPos].org_name_length + 1];
549 strncpy(name, dFld.myFlds[dFld.fldsPos].org_name, dFld.myFlds[dFld.fldsPos].org_name_length);
550 name[dFld.myFlds[dFld.fldsPos].org_name_length] = '\0';
554 bool ::FieldNameSet(Field fld, const String value)
556 MySqlField dFld = (MySqlField)fld.driverData;
557 Log("TODO: MySql - FieldNameSet");
561 /* -------------------------------------------------------------------------------------------------- */
562 /* --- Row ------------------------------------------------------------------------------------------ */
564 Field ::RowField(Row row)
566 MySqlRow dRow = (MySqlRow)row.driverData;
567 MySqlTable dTbl = dRow.dTbl;
570 dRow.dFld = MySqlField { mysql_fetch_fields(dTbl.myRes), dTbl, mysql_num_fields(dTbl.myRes), -1 };
571 dRow.fld = Field { driver = row.driver, driverData = dRow.dFld };
576 bool ::RowEnd(Row row)
578 MySqlRow dRow = (MySqlRow)row.driverData;
579 return dRow.rowsPos == dRow.rowsCount;
582 bool ::RowNext(Row row)
584 MySqlRow dRow = (MySqlRow)row.driverData;
585 MySqlTable dTbl = dRow.dTbl;
586 if(dRow.rowsPos == -1)
588 if(dRow.rowsPos == dRow.rowsCount)
591 dRow.myRow = mysql_fetch_row(dTbl.myRes); // this won't work in all situations...
592 dRow.myLengths = mysql_fetch_lengths(dTbl.myRes);
596 bool ::RowPrevious(Row row)
598 MySqlRow dRow = (MySqlRow)row.driverData;
599 MySqlTable dTbl = dRow.dTbl;
600 if(dRow.rowsPos == -1)
601 dRow.rowsPos = dRow.rowsCount ? dRow.rowsCount + 1 : 0;
602 else if(dRow.rowsPos == 0)
604 dRow.rowsPos = dRow.rowsCount;
608 dRow.myRow = mysql_fetch_row(dTbl.myRes); // this won't work at all...
609 Log("TODO: MySql - FieldNameSet");
614 bool ::RowSeek(Row row, const String value, SeekOptions options)
616 MySqlRow dRow = (MySqlRow)row.driverData;
617 if(options == first || options == reset)
622 mysql_data_seek(dRow.dTbl.myRes, 0);
628 else if(options == firstEqual)
631 mysql_data_seek(dRow.dTbl.myRes, 0);
633 if(!strcmp(row.stringValue, value))
637 /*else if(options == Last)
641 dFld.fldsPos = dFld.fldsCount - 1;
645 /*else if(options == null)
650 //Log("TODO: MySql - RowSeek");
654 String ::RowStringValueGet(Row row)
657 MySqlRow dRow = (MySqlRow)row.driverData;
658 MySqlTable dTbl = dRow.dTbl;
659 MySqlField dFld = dRow.dFld;
661 switch(dFld.myFlds[dFld.fldsPos].type)
663 case FIELD_TYPE_TINY:
664 case FIELD_TYPE_SHORT:
665 case FIELD_TYPE_LONG:
666 case FIELD_TYPE_INT24:
667 case FIELD_TYPE_LONGLONG:
670 sprintf(temp, "%d", dRow.myRow[dFld.fldsPos]);
671 return CopyString(temp);
673 case FIELD_TYPE_DECIMAL:
674 return CopyString("FIELD_TYPE_DECIMAL");
675 case FIELD_TYPE_FLOAT:
676 return CopyString("FIELD_TYPE_FLOAT");
677 case FIELD_TYPE_DOUBLE:
678 return CopyString("FIELD_TYPE_DOUBLE");
679 case FIELD_TYPE_TIMESTAMP:
680 return CopyString("FIELD_TYPE_TIMESTAMP");
681 case FIELD_TYPE_DATE:
682 return CopyString("FIELD_TYPE_DATE");
683 case FIELD_TYPE_TIME:
684 return CopyString("FIELD_TYPE_TIME");
685 case FIELD_TYPE_DATETIME:
686 return CopyString("FIELD_TYPE_DATETIME");
687 case FIELD_TYPE_YEAR:
688 return CopyString("FIELD_TYPE_YEAR");
689 case FIELD_TYPE_STRING:
690 return dRow.myRow[dFld.fldsPos];
691 case FIELD_TYPE_VAR_STRING:
692 return dRow.myRow[dFld.fldsPos];
693 case FIELD_TYPE_BLOB:
694 return CopyString("FIELD_TYPE_BLOB");
696 return CopyString("FIELD_TYPE_SET");
697 case FIELD_TYPE_ENUM:
698 return CopyString("FIELD_TYPE_ENUM");
699 case FIELD_TYPE_NULL:
700 return CopyString("FIELD_TYPE_NULL");
701 //case FIELD_TYPE_CHAR:
702 // return CopyString("FIELD_TYPE_CHAR");
704 return CopyString("DEFAULT");
706 //sprintf(temp, "%.*s", (int)dRow.myLengths[dFld.fldsPos], dRow.myRow[dFld.fldsPos] ? dRow.myRow[dFld.fldsPos] : "null");
707 /*if(!dFld || dRow.myRow[dFld.fldsPos] == null || !strlen(dRow.myRow[dFld.fldsPos]))
709 return dRow.myRow[dFld.fldsPos];*/
710 //return CopyString(temp);
713 bool ::RowStringValueSet(Row row, const String value)
715 MySqlRow dRow = (MySqlRow)row.driverData;
716 Log("TODO: MySql - RowStringValueSet");