2 * Copyright (C) 2002, Leo Seib, Hannover
4 * Project:Dataset C++ Dynamic Library
5 * Module: Dataset abstraction layer header file
6 * Author: Leo Seib E-Mail: leoseib@web.de
9 * SPDX-License-Identifier: MIT
10 * See LICENSES/README.md for more information.
22 #include <unordered_map>
26 class Dataset
; // forward declaration of class Dataset
28 #define S_NO_CONNECTION "No active connection";
30 #define DB_BUFF_MAX 8 * 1024 // Maximum buffer's capacity
32 #define DB_CONNECTION_NONE 0
33 #define DB_CONNECTION_OK 1
34 #define DB_CONNECTION_BAD 2
36 #define DB_COMMAND_OK 0 // OK - command executed
37 #define DB_EMPTY_QUERY 1 // Query didn't return tuples
38 #define DB_TUPLES_OK 2 // Query returned tuples
40 #define DB_BAD_RESPONSE 6
41 #define DB_UNEXPECTED 7 // This shouldn't ever happen
42 #define DB_UNEXPECTED_RESULT -1 //For integer functions
44 /******************* Class Database definition ********************
46 represents connection with database server;
48 ******************************************************************/
54 std::string error
, // Error description
55 host
, port
, db
, login
, passwd
, //Login info
56 sequence_table
, //Sequence table for nextid
57 default_charset
, //Default character set
58 key
, cert
, ca
, capath
, ciphers
; //SSL - Encryption info
65 virtual Dataset
* CreateDataset() const = 0;
66 /* sets a new host name */
67 virtual void setHostName(const char* newHost
) { host
= newHost
; }
68 /* gets a host name */
69 const char* getHostName(void) const { return host
.c_str(); }
71 void setPort(const char* newPort
) { port
= newPort
; }
73 const char* getPort(void) const { return port
.c_str(); }
74 /* sets a new database name */
75 virtual void setDatabase(const char* newDb
) { db
= newDb
; }
76 /* gets a database name */
77 const char* getDatabase(void) const { return db
.c_str(); }
78 /* sets a new login to database */
79 void setLogin(const char* newLogin
) { login
= newLogin
; }
81 const char* getLogin(void) const { return login
.c_str(); }
83 void setPasswd(const char* newPasswd
) { passwd
= newPasswd
; }
85 const char* getPasswd(void) const { return passwd
.c_str(); }
86 /* active status is OK state */
87 virtual bool isActive(void) const { return active
; }
88 /* Set new name of sequence table */
89 void setSequenceTable(const char* new_seq_table
) { sequence_table
= new_seq_table
; }
90 /* Get name of sequence table */
91 const char* getSequenceTable(void) { return sequence_table
.c_str(); }
92 /* Get the default character set */
93 const char* getDefaultCharset(void) { return default_charset
.c_str(); }
94 /* Sets configuration */
95 virtual void setConfig(const char* newKey
,
98 const char* newCApath
,
99 const char* newCiphers
,
106 ciphers
= newCiphers
;
107 compression
= newCompression
;
110 /* virtual methods that must be overloaded in derived classes */
112 virtual int init(void) { return DB_COMMAND_OK
; }
113 virtual int status(void) { return DB_CONNECTION_NONE
; }
114 virtual int setErr(int err_code
, const char* qry
) = 0;
115 virtual const char* getErrorMsg(void) { return error
.c_str(); }
117 virtual int connect(bool create
) { return DB_COMMAND_OK
; }
118 virtual int connectFull(const char* newDb
,
119 const char* newHost
= NULL
,
120 const char* newLogin
= NULL
,
121 const char* newPasswd
= NULL
,
122 const char* newPort
= NULL
,
123 const char* newKey
= NULL
,
124 const char* newCert
= NULL
,
125 const char* newCA
= NULL
,
126 const char* newCApath
= NULL
,
127 const char* newCiphers
= NULL
,
128 bool newCompression
= false);
129 virtual void disconnect(void) { active
= false; }
130 virtual int reset(void) { return DB_COMMAND_OK
; }
131 virtual int create(void) { return DB_COMMAND_OK
; }
132 virtual int drop(void) { return DB_COMMAND_OK
; }
133 virtual long nextid(const char* seq_name
) = 0;
135 /* \brief copy database */
136 virtual int copy(const char* new_name
) { return -1; }
138 /* \brief drop all extra analytics from database */
139 virtual int drop_analytics(void) { return -1; }
141 virtual bool exists(void) { return false; }
143 /* virtual methods for transaction */
145 virtual void start_transaction() {}
146 virtual void commit_transaction() {}
147 virtual void rollback_transaction() {}
149 /* virtual methods for formatting */
151 /*! \brief Prepare a SQL statement for execution or querying using C printf nomenclature.
152 \param format - C printf compliant format string
153 \param ... - optional comma separated list of variables for substitution in format string placeholders.
154 \return escaped and formatted string.
156 virtual std::string
prepare(const char* format
, ...);
158 /*! \brief Prepare a SQL statement for execution or querying using C printf nomenclature
159 \param format - C printf compliant format string
160 \param args - va_list of variables for substitution in format string placeholders.
161 \return escaped and formatted string.
163 virtual std::string
vprepare(const char* format
, va_list args
) = 0;
165 virtual bool in_transaction() { return false; }
168 /******************* Class Dataset definition *********************
170 global abstraction for using Databases
172 ******************************************************************/
174 // define Dataset States type
193 typedef std::list
<std::string
> StringList
;
194 typedef std::map
<std::string
, field_value
> ParamList
;
199 /* char *Host = ""; //WORK_HOST;
200 char *Database = ""; //WORK_DATABASE;
201 char *User = ""; //WORK_USER;
202 char *Password = ""; //WORK_PASSWORD;
205 Database
* db
; // info about db connection
206 dsStates ds_state
; // current state
207 Fields
*fields_object
, *edit_object
;
208 std::unordered_map
<std::string
, unsigned int>
209 name2indexMap
; // Lower case field name -> database index
216 bool active
; // Is Query Opened?
218 int frecno
; // number of current row bei bewegung
221 ParamList plist
; // Paramlist for locate
223 bool autocommit
; // for transactions
225 /* Variables to store SQL statements */
226 std::string empty_sql
; // Executed when result set is empty
227 std::string select_sql
; // May be only single string variable
229 StringList update_sql
; // May be an array in complex queries
230 /* Field values for updating must has prefix :NEW_ and :OLD_ and field name
232 update wt_story set idobject set idobject=:NEW_idobject,body=:NEW_body
233 where idobject=:OLD_idobject
234 Essentially fields idobject and body must present in the
235 result set (select_sql statement) */
237 StringList insert_sql
; // May be an array in complex queries
238 /* Field values for inserting must has prefix :NEW_ and field name
240 insert into wt_story (idobject, body) values (:NEW_idobject, :NEW_body)
241 Essentially fields idobject and body must present in the
242 result set (select_sql statement) */
244 StringList delete_sql
; // May be an array in complex queries
245 /* Field values for deleing must has prefix :OLD_ and field name
247 delete from wt_story where idobject=:OLD_idobject
248 Essentially field idobject must present in the
249 result set (select_sql statement) */
251 /* Arrays for searching */
252 // StringList names, values;
254 /* Makes direct inserts into database via mysql_query function */
255 virtual void make_insert() = 0;
257 virtual void make_edit() = 0;
259 virtual void make_deletion() = 0;
261 /* This function works only with MySQL database
262 Filling the fields information from select statement */
263 virtual void fill_fields(void) = 0;
265 /* Parse Sql - replacing fields with prefixes :OLD_ and :NEW_ with current values of OLD or NEW field. */
266 void parse_sql(std::string
& sql
);
268 /* Returns old field value (for :OLD) */
269 virtual field_value
f_old(const char* f
);
271 /* fast string tolower helper */
272 char* str_toLower(char* s
);
277 explicit Dataset(Database
* newDb
);
282 /* sets a new value of connection to database */
283 void setDatabase(Database
* newDb
) { db
= newDb
; }
284 /* retrieves a database which connected */
285 Database
* getDatabase(void) { return db
; }
287 /* sets a new query string to database server */
288 void setExecSql(const char* newSql
) { sql
= newSql
; }
289 /* retrieves a query string */
290 const char* getExecSql(void) { return sql
.c_str(); }
292 /* status active is OK query */
293 virtual bool isActive(void) { return active
; }
295 virtual void setSqlParams(sqlType t
, const char* sqlFrmt
, ...);
298 // virtual void halt(const char *msg);
300 /* last inserted id */
301 virtual int64_t lastinsertid() = 0;
302 /* sequence numbers */
303 virtual long nextid(const char* seq_name
) = 0;
304 /* sequence numbers */
305 virtual int num_rows() = 0;
308 virtual void open(const std::string
& sql
) = 0;
309 virtual void open() = 0;
310 /* func. executes a query without results to return */
311 virtual int exec(const std::string
& sql
) = 0;
312 virtual int exec() = 0;
313 virtual const void* getExecRes() = 0;
314 /* as open, but with our query exec Sql */
315 virtual bool query(const std::string
& sql
) = 0;
317 virtual void close();
318 /* This function looks for field Field_name with value equal Field_value
319 Returns true if found (position of dataset is set to founded position)
320 and false another way (position is not changed). */
321 // virtual bool lookup(char *field_name, char*field_value);
322 /* Refresh dataset (reopen it and set the same cursor position) */
323 virtual void refresh();
325 /*! \brief Drop an index from the database table, provided it exists.
326 \param table - name of the table the index to be dropped is associated with
327 \param index - name of the index to be dropped
328 \return true when the index is guaranteed to no longer exist in the database.
330 virtual bool dropIndex(const char* table
, const char* index
) { return false; }
332 /* Go to record No (starting with 0) */
333 virtual bool seek(int pos
= 0);
334 /* Go to record No (starting with 1) */
335 virtual bool goto_rec(int pos
= 1);
336 /* Go to the first record in dataset */
337 virtual void first();
338 /* Go to next record in dataset */
340 /* Go to previous record */
342 /* Go to last record in dataset */
345 /* Check for Ending dataset */
346 virtual bool eof(void) { return feof
; }
347 /* Check for Beginning dataset */
348 virtual bool bof(void) { return fbof
; }
350 /* Start the insert mode */
351 virtual void insert();
352 /* Start the insert mode (alias for insert() function) */
353 virtual void append() { insert(); }
354 /* Start the edit mode */
356 /* Start the delete mode */
359 /* Add changes, that were made during insert or edit states of dataset into the database */
361 /* Delete statements from database */
362 virtual void deletion();
363 /* Cancel changes, made in insert or edit states of dataset */
364 virtual void cancel() {}
365 /* interrupt any pending database operation */
366 virtual void interrupt() {}
368 virtual void setParamList(const ParamList
& params
);
369 virtual bool locate();
370 virtual bool locate(const ParamList
& params
);
371 virtual bool findNext();
373 /* func. retrieves a number of fields */
374 /* Number of fields in a record */
375 virtual int field_count();
376 virtual int fieldCount();
377 /* func. retrieves a field name with 'n' index */
378 virtual const char* fieldName(int n
);
379 /* func. retrieves a field index with 'fn' field name,return -1 when field name not found */
380 virtual int fieldIndex(const char* fn
);
382 /* Set field value */
383 virtual bool set_field_value(const char* f_name
, const field_value
& value
);
384 /* alias for set_field_value */
385 virtual bool sf(const char* f
, const field_value
& v
) { return set_field_value(f
, v
); }
387 /* Return field name by it index */
388 // virtual char *field_name(int f_index) { return field_by_index(f_index)->get_field_name(); }
390 /* Getting value of field for current record */
391 virtual const field_value
& get_field_value(const char* f_name
);
392 virtual const field_value
& get_field_value(int index
);
393 /* Alias to get_field_value */
394 const field_value
& fv(const char* f
) { return get_field_value(f
); }
395 const field_value
& fv(int index
) { return get_field_value(index
); }
397 /* ------------ for transaction ------------------- */
398 void set_autocommit(bool v
) { autocommit
= v
; }
399 bool get_autocommit() { return autocommit
; }
401 /* ----------------- for debug -------------------- */
402 Fields
* get_fields_object() { return fields_object
; }
403 Fields
* get_edit_object() { return edit_object
; }
405 /* --------------- for fast access ---------------- */
406 const result_set
& get_result_set() { return result
; }
407 const sql_record
* get_sql_record();
410 Dataset(const Dataset
&) = delete;
411 Dataset
& operator=(const Dataset
&) = delete;
413 /* Get the column index from a string field_value request */
414 bool get_index_map_entry(const char* f_name
);
416 void set_ds_state(dsStates new_state
) { ds_state
= new_state
; }
419 /* return ds_state value */
420 dsStates
get_state() { return ds_state
; }
422 /*add a new value to select_sql*/
423 void set_select_sql(const char* sel_sql
);
424 void set_select_sql(const std::string
& select_sql
);
425 /*add a new value to update_sql*/
426 void add_update_sql(const char* upd_sql
);
427 void add_update_sql(const std::string
& upd_sql
);
428 /*add a new value to insert_sql*/
429 void add_insert_sql(const char* ins_sql
);
430 void add_insert_sql(const std::string
& ins_sql
);
431 /*add a new value to delete_sql*/
432 void add_delete_sql(const char* del_sql
);
433 void add_delete_sql(const std::string
& del_sql
);
436 void clear_update_sql();
438 void clear_insert_sql();
440 void clear_delete_sql();
442 /* size of insert_sql*/
443 size_t insert_sql_count();
444 /* size of delete_sql*/
445 size_t delete_sql_count();
447 /*get value of select_sql*/
448 const char* get_select_sql();
451 /******************** Class DbErrors definition *********************
455 ******************************************************************/
462 DbErrors(const char* msg
, ...);
464 const char* getMsg();
470 } // namespace dbiplus