Sql.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /******************************************************************************
  2. Use 'SQL' class to access SQL database.
  3. SQL supports:
  4. -Microsoft SQL (MSSQL)
  5. -MySQL
  6. -PostgreSQL
  7. -SQLite
  8. MSSQL supports all SQL_DATA_TYPE enums
  9. MySQL supports all SQL_DATA_TYPE enums, however SDT_UID will be converted internally to BINARY(16)
  10. PostgreSQL supports all SQL_DATA_TYPE enums, however SDT_BYTE will be converted internally to SDT_SHORT
  11. SQLite supports all SQL_DATA_TYPE enums, however internally they will be converted to one of: SDT_LONG, SDT_DBL, SDT_STR, SDT_BINARY. SQLite also does not use 'str_len' or 'binary_size' for string and binary limits (all strings and binary values can be of unlimited length)
  12. /******************************************************************************/
  13. enum SQL_DATA_TYPE : Byte // possible type of an Column Data in a SQL Table
  14. {
  15. SDT_UNKNOWN ,
  16. SDT_BOOL , // bool
  17. SDT_BYTE , // 8-bit integer
  18. SDT_SHORT , // 16-bit integer
  19. SDT_INT , // 32-bit integer
  20. SDT_LONG , // 64-bit integer
  21. SDT_FLT , // 32-bit real
  22. SDT_DBL , // 64-bit real
  23. SDT_STR , // 16-bit string
  24. SDT_STR8 , // 8-bit string
  25. SDT_UID , // unique id
  26. SDT_DATE_TIME, // date time
  27. SDT_BINARY , // binary data
  28. };
  29. /******************************************************************************/
  30. struct SQLColumn // SQL Column definition, use this for creating new tables in a database
  31. {
  32. enum MODE : Byte
  33. {
  34. DEFAULT , // default mode for most of the columns
  35. UNIQUE , // requires that this column must have unique data, this can be set to custom number of columns
  36. PRIMARY , // requires that this column must have unique data, this can be set only up to 1 columns
  37. PRIMARY_AUTO, // requires that this column must have unique data, this can be set only up to 1 columns, this is a special type of PRIMARY mode, which automatically sets the value to a unique index, type of this column must be only of BYTE, SHORT, INT, LONG type
  38. };
  39. Str name ; // column name
  40. SQL_DATA_TYPE type ; // column type
  41. Bool allow_nulls; // if allow this column to have a null value
  42. MODE mode ; // column mode
  43. Str default_val; // default value (optional, can be left empty), this can be set to: string "abc..", number "5", binary data "0x00112233..", SQL function "GetDate()" - gets current DateTime, "NewID()" - generates random UID
  44. union
  45. {
  46. Int str_len ; // maximum number of characters allowed in a string type (STR,STR8), giving a value<=0 will make the length be as long as possible (but slower)
  47. Int binary_size; // maximum number of bytes allowed in a binary type (BINARY ), giving a value<=0 will make the size be as big as possible (but slower)
  48. };
  49. SQLColumn& set(C Str &name, SQL_DATA_TYPE type, Int str_len_bin_size=16) {T.name=name; T.type=type; T.str_len=T.binary_size=str_len_bin_size; return T;}
  50. SQLColumn() {type=SDT_UNKNOWN; allow_nulls=false; mode=DEFAULT; str_len=binary_size=16;}
  51. };
  52. /******************************************************************************/
  53. struct SQLValues // SQL Row values, use this for creating new rows in a table
  54. {
  55. SQLValues& New(C Str &name, Int value);
  56. SQLValues& New(C Str &name, Long value);
  57. SQLValues& New(C Str &name, Dbl value);
  58. SQLValues& New(C Str &name, C Str &value);
  59. SQLValues& New(C Str &name, C UID &value);
  60. SQLValues& New(C Str &name, C DateTime &value);
  61. SQLValues& New(C Str &name, CPtr value, Int size); // add new value from binary memory
  62. SQLValues& New(C Str &name, File &file ); // add new value from binary data of the file from its current position to the end of the file
  63. #if !EE_PRIVATE
  64. private:
  65. #endif
  66. struct Value {Byte type; Str name, value; Value() {type=0;} Value& set(C Str &name, C Str &value) {T.name=name; T.value=value; return T;}};
  67. Memc<Value> _values;
  68. };
  69. /******************************************************************************/
  70. struct SQL
  71. {
  72. // connect
  73. #if EE_PRIVATE
  74. Bool connectODBC(C Str &params, Str *messages, Int *error, Int sql_type);
  75. Bool connectODBC(C Str &server_name, C Str &database, C Str &user, C Str &password, Str *messages, Int *error, Int port, C Str &driver_name, Int sql_type);
  76. #endif
  77. Bool connectMSSQL (C Str &server_name, C Str &database, C Str &user=S, C Str &password=S, Str *messages=null, Int *error=null ); // connect to Microsoft SQL 'server_name' and 'database', 'messages'=optional pointer to custom string which will receive any messages, 'error'=optional pointer to error code, false on fail
  78. Bool connectMySQL (C Str &server_name, C Str &database, C Str &user=S, C Str &password=S, Str *messages=null, Int *error=null, C Str &mysql_driver_name="MySQL ODBC 5.3 Unicode Driver" ); // connect to MySQL 'server_name' and 'database', 'messages'=optional pointer to custom string which will receive any messages, 'error'=optional pointer to error code, false on fail
  79. Bool connectPgSQL (C Str &server_name, C Str &database, C Str &user=S, C Str &password=S, Str *messages=null, Int *error=null, Int port=5432, C Str &pgsql_driver_name="PostgreSQL ODBC Driver(UNICODE)"); // connect to PostgreSQL 'server_name' and 'database', 'messages'=optional pointer to custom string which will receive any messages, 'error'=optional pointer to error code, false on fail
  80. Bool connectSQLite(C Str &database_file_name, const_mem_addr Cipher *cipher=null ); // connect to a SQLite database, 'database_file_name'=path to the database file (SQLite stores database information in regular files), if the specified file does not exist, then it will be automatically created, 'cipher' must point to object in constant memory address (only pointer is stored through which the object can be later accessed), false on fail
  81. // connect using DSN, DSN is a name of the configuration containing all the required information, including 'server_name', 'database', 'user' and 'password', you can read more about it here - https://support.quadrahosting.com/kb-article-23-0,3,15.html
  82. Bool dsnConnectMSSQL(C Str &dsn, Str *messages=null, Int *error=null); // connect to Microsoft SQL using a 'dsn', 'messages'=optional pointer to custom string which will receive any messages, 'error'=optional pointer to error code, false on fail, please check here how to setup DSN - https://msdn.microsoft.com/en-us/library/windows/desktop/dn170503(v=vs.85).aspx
  83. Bool dsnConnectMySQL(C Str &dsn, Str *messages=null, Int *error=null); // connect to MySQL using a 'dsn', 'messages'=optional pointer to custom string which will receive any messages, 'error'=optional pointer to error code, false on fail, please check here how to setup DSN - http://dev.mysql.com/doc/connector-odbc/en/connector-odbc-configuration-dsn-windows.html
  84. Bool dsnConnectPgSQL(C Str &dsn, Str *messages=null, Int *error=null); // connect to PostgreSQL using a 'dsn', 'messages'=optional pointer to custom string which will receive any messages, 'error'=optional pointer to error code, false on fail
  85. // commands
  86. // tables
  87. Bool getTables(MemPtr<Str> table_names, Str *messages=null, Int *error=null); // get a list of all table names in the database, false on fail
  88. Bool delTable (C Str &table_name , Str *messages=null, Int *error=null); // delete a 'table_name' table from the database, false on fail
  89. Bool createTable (C Str &table_name , C MemPtr<SQLColumn> &columns, Str *messages=null, Int *error=null); // create a 'table_name' table in the database, false on fail
  90. Bool appendTable (C Str &table_name , C MemPtr<SQLColumn> &columns, Str *messages=null, Int *error=null); // append a 'table_name' table in the database, false on fail, this method works by adding new 'columns' to an existing table
  91. Bool existsTable (C Str &table_name , Str *messages=null, Int *error=null); // check if 'table_name' table exists in the database, false on fail
  92. // rows
  93. Bool delRow(C Str &table_name, C Str &condition, Str *messages=null, Int *error=null); // delete existing rows in 'table_name' table which meet the 'condition' , false on fail, 'condition' is a custom string specifying the condition, for example: "id=0" will delete all rows which have 'id' column equal to 0
  94. Bool newRow(C Str &table_name, C SQLValues &values, Str *messages=null, Int *error=null); // create a new row in 'table_name' table with given row 'values', false on fail
  95. Bool setRow(C Str &table_name, C Str &condition, C SQLValues &values, Str *messages=null, Int *error=null); // modify existing rows in 'table_name' table which meet the 'condition' by setting its 'values', false on fail, 'condition' is a custom string specifying the condition, for example: "id=0" will modify all rows which have 'id' column equal to 0
  96. Bool getAllRows (C Str &table_name, Str *messages=null, Int *error=null); // get all rows of a 'table_name' table , if the method succeeds you can access the rows using 'getNextRow' method, returned rows will have information about all their column data, false on fail
  97. Bool getRows (C Str &table_name, C Str &condition, Str *messages=null, Int *error=null); // get rows of a 'table_name' table which meet the 'condition', if the method succeeds you can access the rows using 'getNextRow' method, returned rows will have information about all their column data, false on fail, 'condition' is a custom string specifying the condition, for example: "id=0" will return all rows which have 'id' column equal to 0
  98. Bool getAllRowsCols(C Str &table_name, C MemPtr<Str> &columns, Str *messages=null, Int *error=null); // get all rows of a 'table_name' table , if the method succeeds you can access the rows using 'getNextRow' method, returned rows will have information only about selected column data, false on fail 'columns'=name of columns to return in the result, this method may be faster than 'getAllRows' because it returns only selected columns (unlike all columns in 'getAllRows')
  99. Bool getRowsCols (C Str &table_name, C Str &condition, C MemPtr<Str> &columns, Str *messages=null, Int *error=null); // get rows of a 'table_name' table which meet the 'condition', if the method succeeds you can access the rows using 'getNextRow' method, returned rows will have information only about selected column data, false on fail, 'condition' is a custom string specifying the condition, for example: "id=0" will return all rows which have 'id' column equal to 0, 'columns'=name of columns to return in the result, this method may be faster than 'getRows' because it returns only selected columns (unlike all columns in 'getRows')
  100. Int getAllRowsNum(C Str &table_name, Str *messages=null, Int *error=null); // get number of all rows of a 'table_name' table , -1 on fail
  101. Int getRowsNum (C Str &table_name, C Str &condition, Str *messages=null, Int *error=null); // get number of rows of a 'table_name' table which meet the 'condition', -1 on fail, 'condition' is a custom string specifying the condition, for example: "id=0" will return all rows which have 'id' column equal to 0
  102. Int getUniqueValuesNum(C Str &table_name, C Str &column_name, Str *messages=null, Int *error=null); // get number of unique values in 'column_name' column of 'table_name' table, -1 on fail
  103. // custom
  104. Bool command(C Str &command, Str *messages=null, Int *error=null); // 'command'=custom sql command to be executed, 'messages'=optional pointer to custom string which will receive any messages, 'error'=optional pointer to error code, false on fail
  105. // custom with parameters passed by method calls !! these methods are supported only on MSSQL, MySQL and PostgreSQL !!
  106. Bool commandPrepare(C Str &command, Str *messages=null, Int *error=null); // 'command'=custom sql command to be executed with parameters replaced with "?", 'messages'=optional pointer to custom string which will receive any messages, 'error'=optional pointer to error code, unlike the 'command' method above, this method only prepares execution of specified command, after calling this method you should call 'commandParam' for each parameter, and 'commandExecute' at the end. This method returns false on fail. For example: if(commandPrepare("insert into players(player_name, race, gender) values (?, ?, ?)"))commandParam(0, "John").commandParam(1, "Elf").commandParam(2, "Male").commandExecute(); Another example: if(commandPrepare("update players set player_name=? where player_id=?"))commandParam(0, "John").commandParam(1, "123").commandExecute();
  107. #if EE_PRIVATE
  108. Bool commandParamRaw (Int i, CPtr value, Int size, Int c_type, Int sql_type);
  109. Bool commandParamRaw2(Int i, CPtr value, Int size, Int c_type, Int sql_type);
  110. #endif
  111. SQL& commandParam(Int i, Bool value ); // set i-th parameter as 'value'
  112. SQL& commandParam(Int i, Int value ); // set i-th parameter as 'value'
  113. SQL& commandParam(Int i, UInt value ); // set i-th parameter as 'value'
  114. SQL& commandParam(Int i, Long value ); // set i-th parameter as 'value'
  115. SQL& commandParam(Int i, ULong value ); // set i-th parameter as 'value'
  116. SQL& commandParam(Int i, Flt value ); // set i-th parameter as 'value'
  117. SQL& commandParam(Int i, Dbl value ); // set i-th parameter as 'value'
  118. SQL& commandParam(Int i, CChar *value ); // set i-th parameter as 'value'
  119. SQL& commandParam(Int i, CChar8 *value ); // set i-th parameter as 'value'
  120. SQL& commandParam(Int i, C Str &value ); // set i-th parameter as 'value'
  121. SQL& commandParam(Int i, C Str8 &value ); // set i-th parameter as 'value'
  122. SQL& commandParam(Int i, C UID &value ); // set i-th parameter as 'value'
  123. SQL& commandParam(Int i, C DateTime &value ); // set i-th parameter as 'value'
  124. SQL& commandParam(Int i, C DateTimeMs &value ); // set i-th parameter as 'value'
  125. SQL& commandParam(Int i, C MemPtr<Byte> &value ); // set i-th parameter as 'value'
  126. SQL& commandParam(Int i, CPtr value, Int size); // get i-th parameter as 'value'
  127. Bool commandExecute(Str *messages=null, Int *error=null); // execute prepared command, 'messages'=optional pointer to custom string which will receive any messages, 'error'=optional pointer to error code, false on fail
  128. // get
  129. Str string(C Str &s)C; // return 's' string in SQL friendly format, this is needed for writing custom SQL conditions, this converts "John's" string into:
  130. // MSSQL : "N'John''s'"
  131. // MySQL : "'John\'s'"
  132. // PgSQL : "'John''s'"
  133. // SQLite : "'John''s'"
  134. Bool getNextRow(); // get next row, call this in a loop after calling sql command to process all returned rows, false on fail
  135. Int getCols(); // get number of columns in returned result, you can optionally call this after sql commands
  136. Bool getColDesc(Int i, Str &name, SQL_DATA_TYPE &type, Int &size); // get i-th column description, 'name'=column name, 'type'=column data type, 'size'=maximum column data size (in bytes)
  137. // reading column data must be done in sequential order !! (you can read data from column 0, 1, 2, ..; but NOT from 2, 0, 1, ..;)
  138. Bool getCol(Int i, Bool &value ); // get i-th column data as 'value', false on fail
  139. Bool getCol(Int i, Byte &value ); // get i-th column data as 'value', false on fail
  140. Bool getCol(Int i, Int &value ); // get i-th column data as 'value', false on fail
  141. Bool getCol(Int i, UInt &value ); // get i-th column data as 'value', false on fail
  142. Bool getCol(Int i, Long &value ); // get i-th column data as 'value', false on fail
  143. Bool getCol(Int i, ULong &value ); // get i-th column data as 'value', false on fail
  144. Bool getCol(Int i, Flt &value ); // get i-th column data as 'value', false on fail
  145. Bool getCol(Int i, Dbl &value ); // get i-th column data as 'value', false on fail
  146. Bool getCol(Int i, Str &value ); // get i-th column data as 'value', false on fail
  147. Bool getCol(Int i, Str8 &value ); // get i-th column data as 'value', false on fail
  148. Bool getCol(Int i, UID &value ); // get i-th column data as 'value', false on fail
  149. Bool getCol(Int i, DateTime &value ); // get i-th column data as 'value', false on fail
  150. Bool getCol(Int i, DateTimeMs &value ); // get i-th column data as 'value', false on fail
  151. Bool getCol(Int i, MemPtr<Byte> value ); // get i-th column data as 'value', false on fail
  152. Bool getCol(Int i, File &file ); // get i-th column data into file , false on fail, 'file'=file object which will have appended binary data from the column, 'file' should be already opened for writing, column binary data will be written into 'file' from the file's current position, during writing 'file' position will be adjusted by the size of written data
  153. Bool getCol(Int i, Char *value, Int max_length); // get i-th column data as array of 'max_length' characters, false on fail
  154. Bool getCol(Int i, Char8 *value, Int max_length); // get i-th column data as array of 'max_length' characters, false on fail
  155. Bool getCol(Int i, Ptr value, Int &size ); // get i-th column data as memory of 'size' size , before calling this method you should set 'size' to maximum capacity of the value buffer, after this method returns, 'size' will be equal to the actual amount of data written to the buffer, false on fail
  156. SQL& del(); // delete manually
  157. ~SQL() {del();}
  158. SQL();
  159. private:
  160. struct Row
  161. {
  162. struct Col
  163. {
  164. Long i;
  165. Dbl d;
  166. Str s;
  167. Mems<Byte> b;
  168. SQL_DATA_TYPE type;
  169. };
  170. Mems<Col> cols;
  171. };
  172. struct Col
  173. {
  174. Str name;
  175. SQL_DATA_TYPE type;
  176. };
  177. #if EE_PRIVATE
  178. enum SQL_TYPE : Byte
  179. {
  180. NONE ,
  181. MSSQL ,
  182. MYSQL ,
  183. PGSQL ,
  184. SQLITE,
  185. };
  186. #endif
  187. Byte _type;
  188. Ptr _env, _conn, _statement, _sqlite;
  189. Int _rows_pos;
  190. Memc<Row> _rows;
  191. Memc<Col> _cols;
  192. Memc< Memc<Byte> > _params;
  193. #if EE_PRIVATE
  194. Str value (C SQLValues::Value &value)C;
  195. Str token (C Str &token)C;
  196. Bool colDesc (C SQLColumn &col, Str &desc, Str *messages);
  197. void getStatus(Str *messages, Int *error, Bool statement=true);
  198. #endif
  199. NO_COPY_CONSTRUCTOR(SQL);
  200. };
  201. /******************************************************************************/