summaryrefslogtreecommitdiffstats
path: root/xbmc/dbwrappers/dataset.h
blob: 5e420b14bed80fabd47087f280a0e9237824a0a9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
/*
 *  Copyright (C) 2002, Leo Seib, Hannover
 *
 *  Project:Dataset C++ Dynamic Library
 *  Module: Dataset abstraction layer header file
 *  Author: Leo Seib      E-Mail: leoseib@web.de
 *  Begin: 5/04/2002
 *
 *  SPDX-License-Identifier: MIT
 *  See LICENSES/README.md for more information.
 */

#pragma once

#include "qry_dat.h"

#include <cstdio>
#include <list>
#include <map>
#include <stdarg.h>
#include <string>
#include <unordered_map>

namespace dbiplus
{
class Dataset; // forward declaration of class Dataset

#define S_NO_CONNECTION "No active connection";

#define DB_BUFF_MAX 8 * 1024 // Maximum buffer's capacity

#define DB_CONNECTION_NONE 0
#define DB_CONNECTION_OK 1
#define DB_CONNECTION_BAD 2

#define DB_COMMAND_OK 0 // OK - command executed
#define DB_EMPTY_QUERY 1 // Query didn't return tuples
#define DB_TUPLES_OK 2 // Query returned tuples
#define DB_ERROR 5
#define DB_BAD_RESPONSE 6
#define DB_UNEXPECTED 7 // This shouldn't ever happen
#define DB_UNEXPECTED_RESULT -1 //For integer functions

/******************* Class Database definition ********************

   represents  connection with database server;

******************************************************************/
class Database
{
protected:
  bool active;
  bool compression;
  std::string error, // Error description
      host, port, db, login, passwd, //Login info
      sequence_table, //Sequence table for nextid
      default_charset, //Default character set
      key, cert, ca, capath, ciphers; //SSL - Encryption info

public:
  /* constructor */
  Database();
  /* destructor */
  virtual ~Database();
  virtual Dataset* CreateDataset() const = 0;
  /* sets a new host name */
  virtual void setHostName(const char* newHost) { host = newHost; }
  /* gets a host name */
  const char* getHostName(void) const { return host.c_str(); }
  /* sets a new port */
  void setPort(const char* newPort) { port = newPort; }
  /* gets a port */
  const char* getPort(void) const { return port.c_str(); }
  /* sets a new database name */
  virtual void setDatabase(const char* newDb) { db = newDb; }
  /* gets a database name */
  const char* getDatabase(void) const { return db.c_str(); }
  /* sets a new login to database */
  void setLogin(const char* newLogin) { login = newLogin; }
  /* gets a login */
  const char* getLogin(void) const { return login.c_str(); }
  /* sets a password */
  void setPasswd(const char* newPasswd) { passwd = newPasswd; }
  /* gets a password */
  const char* getPasswd(void) const { return passwd.c_str(); }
  /* active status is OK state */
  virtual bool isActive(void) const { return active; }
  /* Set new name of sequence table */
  void setSequenceTable(const char* new_seq_table) { sequence_table = new_seq_table; }
  /* Get name of sequence table */
  const char* getSequenceTable(void) { return sequence_table.c_str(); }
  /* Get the default character set */
  const char* getDefaultCharset(void) { return default_charset.c_str(); }
  /* Sets configuration */
  virtual void setConfig(const char* newKey,
                         const char* newCert,
                         const char* newCA,
                         const char* newCApath,
                         const char* newCiphers,
                         bool newCompression)
  {
    key = newKey;
    cert = newCert;
    ca = newCA;
    capath = newCApath;
    ciphers = newCiphers;
    compression = newCompression;
  }

  /* virtual methods that must be overloaded in derived classes */

  virtual int init(void) { return DB_COMMAND_OK; }
  virtual int status(void) { return DB_CONNECTION_NONE; }
  virtual int setErr(int err_code, const char* qry) = 0;
  virtual const char* getErrorMsg(void) { return error.c_str(); }

  virtual int connect(bool create) { return DB_COMMAND_OK; }
  virtual int connectFull(const char* newDb,
                          const char* newHost = NULL,
                          const char* newLogin = NULL,
                          const char* newPasswd = NULL,
                          const char* newPort = NULL,
                          const char* newKey = NULL,
                          const char* newCert = NULL,
                          const char* newCA = NULL,
                          const char* newCApath = NULL,
                          const char* newCiphers = NULL,
                          bool newCompression = false);
  virtual void disconnect(void) { active = false; }
  virtual int reset(void) { return DB_COMMAND_OK; }
  virtual int create(void) { return DB_COMMAND_OK; }
  virtual int drop(void) { return DB_COMMAND_OK; }
  virtual long nextid(const char* seq_name) = 0;

  /* \brief copy database */
  virtual int copy(const char* new_name) { return -1; }

  /* \brief drop all extra analytics from database */
  virtual int drop_analytics(void) { return -1; }

  virtual bool exists(void) { return false; }

  /* virtual methods for transaction */

  virtual void start_transaction() {}
  virtual void commit_transaction() {}
  virtual void rollback_transaction() {}

  /* virtual methods for formatting */

  /*! \brief Prepare a SQL statement for execution or querying using C printf nomenclature.
   \param format - C printf compliant format string
   \param ... - optional comma separated list of variables for substitution in format string placeholders.
   \return escaped and formatted string.
   */
  virtual std::string prepare(const char* format, ...);

  /*! \brief Prepare a SQL statement for execution or querying using C printf nomenclature
   \param format - C printf compliant format string
   \param args - va_list of variables for substitution in format string placeholders.
   \return escaped and formatted string.
   */
  virtual std::string vprepare(const char* format, va_list args) = 0;

  virtual bool in_transaction() { return false; }
};

/******************* Class Dataset definition *********************

  global abstraction for using Databases

******************************************************************/

// define Dataset States type
enum dsStates
{
  dsSelect,
  dsInsert,
  dsEdit,
  dsUpdate,
  dsDelete,
  dsInactive
};
enum sqlType
{
  sqlSelect,
  sqlUpdate,
  sqlInsert,
  sqlDelete,
  sqlExec
};

typedef std::list<std::string> StringList;
typedef std::map<std::string, field_value> ParamList;

class Dataset
{
protected:
  /*  char *Host     = ""; //WORK_HOST;
  char *Database = ""; //WORK_DATABASE;
  char *User     = ""; //WORK_USER;
  char *Password = ""; //WORK_PASSWORD;
*/

  Database* db; // info about db connection
  dsStates ds_state; // current state
  Fields *fields_object, *edit_object;
  std::unordered_map<std::string, unsigned int>
      name2indexMap; // Lower case field name -> database index

  /* query results*/
  result_set result;
  result_set exec_res;
  bool autorefresh;

  bool active; // Is Query Opened?
  bool haveError;
  int frecno; // number of current row bei bewegung
  std::string sql;

  ParamList plist; // Paramlist for locate
  bool fbof, feof;
  bool autocommit; // for transactions

  /* Variables to store SQL statements */
  std::string empty_sql; // Executed when result set is empty
  std::string select_sql; // May be only single string variable

  StringList update_sql; // May be an array in complex queries
  /* Field values for updating must has prefix :NEW_ and :OLD_ and field name
   Example:
   update  wt_story set idobject set idobject=:NEW_idobject,body=:NEW_body
   where idobject=:OLD_idobject
   Essentially fields idobject and body must present in the
   result set (select_sql statement) */

  StringList insert_sql; // May be an array in complex queries
  /* Field values for inserting must has prefix :NEW_ and field name
   Example:
   insert into wt_story (idobject, body) values (:NEW_idobject, :NEW_body)
   Essentially fields idobject and body must present in the
   result set (select_sql statement) */

  StringList delete_sql; // May be an array in complex queries
  /* Field values for deleing must has prefix :OLD_ and field name
   Example:
   delete from wt_story where idobject=:OLD_idobject
   Essentially field idobject must present in the
   result set (select_sql statement) */

  /* Arrays for searching */
  //  StringList names, values;

  /* Makes direct inserts into database via mysql_query function */
  virtual void make_insert() = 0;
  /* Edit SQL */
  virtual void make_edit() = 0;
  /* Delete SQL */
  virtual void make_deletion() = 0;

  /* This function works only with MySQL database
   Filling the fields information from select statement */
  virtual void fill_fields(void) = 0;

  /* Parse Sql - replacing fields with prefixes :OLD_ and :NEW_ with current values of OLD or NEW field. */
  void parse_sql(std::string& sql);

  /* Returns old field value (for :OLD) */
  virtual const field_value f_old(const char* f);

  /* fast string tolower helper */
  char* str_toLower(char* s);

public:
  /* constructor */
  Dataset();
  explicit Dataset(Database* newDb);

  /* destructor */
  virtual ~Dataset();

  /* sets a new value of connection to database */
  void setDatabase(Database* newDb) { db = newDb; }
  /* retrieves  a database which connected */
  Database* getDatabase(void) { return db; }

  /* sets a new query string to database server */
  void setExecSql(const char* newSql) { sql = newSql; }
  /* retrieves a query string */
  const char* getExecSql(void) { return sql.c_str(); }

  /* status active is OK query */
  virtual bool isActive(void) { return active; }

  virtual void setSqlParams(sqlType t, const char* sqlFrmt, ...);

  /* error handling */
  //  virtual void halt(const char *msg);

  /* last inserted id */
  virtual int64_t lastinsertid() = 0;
  /* sequence numbers */
  virtual long nextid(const char* seq_name) = 0;
  /* sequence numbers */
  virtual int num_rows() = 0;

  /* Open SQL query */
  virtual void open(const std::string& sql) = 0;
  virtual void open() = 0;
  /* func. executes a query without results to return */
  virtual int exec(const std::string& sql) = 0;
  virtual int exec() = 0;
  virtual const void* getExecRes() = 0;
  /* as open, but with our query exec Sql */
  virtual bool query(const std::string& sql) = 0;
  /* Close SQL Query*/
  virtual void close();
  /* This function looks for field Field_name with value equal Field_value
   Returns true if found (position of dataset is set to founded position)
   and false another way (position is not changed). */
  //  virtual bool lookup(char *field_name, char*field_value);
  /* Refresh dataset (reopen it and set the same cursor position) */
  virtual void refresh();

  /*! \brief Drop an index from the database table, provided it exists.
   \param table - name of the table the index to be dropped is associated with
   \param index - name of the index to be dropped
   \return true when the index is guaranteed to no longer exist in the database.
   */
  virtual bool dropIndex(const char* table, const char* index) { return false; }

  /* Go to record No (starting with 0) */
  virtual bool seek(int pos = 0);
  /* Go to record No (starting with 1) */
  virtual bool goto_rec(int pos = 1);
  /* Go to the first record in dataset */
  virtual void first();
  /* Go to next record in dataset */
  virtual void next();
  /* Go to previous record */
  virtual void prev();
  /* Go to last record in dataset */
  virtual void last();

  /* Check for Ending dataset */
  virtual bool eof(void) { return feof; }
  /* Check for Beginning dataset */
  virtual bool bof(void) { return fbof; }

  /* Start the insert mode */
  virtual void insert();
  /* Start the insert mode (alias for insert() function) */
  virtual void append() { insert(); }
  /* Start the edit mode */
  virtual void edit();
  /* Start the delete mode */
  virtual void del();

  /* Add changes, that were made during insert or edit states of dataset into the database */
  virtual void post();
  /* Delete statements from database */
  virtual void deletion();
  /* Cancel changes, made in insert or edit states of dataset */
  virtual void cancel() {}
  /* interrupt any pending database operation  */
  virtual void interrupt() {}

  virtual void setParamList(const ParamList& params);
  virtual bool locate();
  virtual bool locate(const ParamList& params);
  virtual bool findNext();

  /* func. retrieves a number of fields */
  /* Number of fields in a record */
  virtual int field_count();
  virtual int fieldCount();
  /* func. retrieves a field name with 'n' index */
  virtual const char* fieldName(int n);
  /* func. retrieves a field index with 'fn' field name,return -1 when field name not found */
  virtual int fieldIndex(const char* fn);

  /* Set field value */
  virtual bool set_field_value(const char* f_name, const field_value& value);
  /* alias for set_field_value */
  virtual bool sf(const char* f, const field_value& v) { return set_field_value(f, v); }

  /* Return field name by it index */
  //  virtual char *field_name(int f_index) { return field_by_index(f_index)->get_field_name(); }

  /* Getting value of field for current record */
  virtual const field_value get_field_value(const char* f_name);
  virtual const field_value get_field_value(int index);
  /* Alias to get_field_value */
  const field_value fv(const char* f) { return get_field_value(f); }
  const field_value fv(int index) { return get_field_value(index); }

  /* ------------ for transaction ------------------- */
  void set_autocommit(bool v) { autocommit = v; }
  bool get_autocommit() { return autocommit; }

  /* ----------------- for debug -------------------- */
  Fields* get_fields_object() { return fields_object; }
  Fields* get_edit_object() { return edit_object; }

  /* --------------- for fast access ---------------- */
  const result_set& get_result_set() { return result; }
  const sql_record* get_sql_record();

private:
  Dataset(const Dataset&) = delete;
  Dataset& operator=(const Dataset&) = delete;

  /* Get the column index from a string field_value request */
  bool get_index_map_entry(const char* f_name);

  void set_ds_state(dsStates new_state) { ds_state = new_state; }

public:
  /* return ds_state value */
  dsStates get_state() { return ds_state; }

  /*add a new value to select_sql*/
  void set_select_sql(const char* sel_sql);
  void set_select_sql(const std::string& select_sql);
  /*add a new value to update_sql*/
  void add_update_sql(const char* upd_sql);
  void add_update_sql(const std::string& upd_sql);
  /*add a new value to insert_sql*/
  void add_insert_sql(const char* ins_sql);
  void add_insert_sql(const std::string& ins_sql);
  /*add a new value to delete_sql*/
  void add_delete_sql(const char* del_sql);
  void add_delete_sql(const std::string& del_sql);

  /*clear update_sql*/
  void clear_update_sql();
  /*clear insert_sql*/
  void clear_insert_sql();
  /*clear delete_sql*/
  void clear_delete_sql();

  /* size of insert_sql*/
  size_t insert_sql_count();
  /* size of delete_sql*/
  size_t delete_sql_count();

  /*get value of select_sql*/
  const char* get_select_sql();
};

/******************** Class DbErrors definition *********************

			   error handling

******************************************************************/
class DbErrors
{

public:
  /* constructor */
  DbErrors();
  DbErrors(const char* msg, ...);

  const char* getMsg();

private:
  std::string msg_;
};

} // namespace dbiplus