PageRenderTime 51ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/gambas2-2.24.0/gb.db.sqlite3/src/dataset.cpp

#
C++ | 680 lines | 459 code | 125 blank | 96 comment | 90 complexity | 092f78feaab704625d088cabcef3beb9 MD5 | raw file
Possible License(s): GPL-2.0, JSON, LGPL-2.1
  1. /**********************************************************************
  2. * Copyright (c) 2002, Leo Seib, Hannover
  3. *
  4. * Project: C++ Dynamic Library
  5. * Module: Dataset abstraction later realisation file
  6. * Author: Leo Seib E-Mail: lev@almaty.pointstrike.net
  7. * Begin: 5/04/2002
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a copy
  10. * of this software and associated documentation files (the "Software"), to deal
  11. * in the Software without restriction, including without limitation the rights
  12. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. * copies of the Software, and to permit persons to whom the Software is
  14. * furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included in
  17. * all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. * THE SOFTWARE.
  26. *
  27. **********************************************************************/
  28. #include <stdio.h>
  29. #include <ctype.h>
  30. #include <stdarg.h>
  31. #include <time.h>
  32. #include <iostream>
  33. #include <string.h>
  34. #include "dataset.h"
  35. extern "C"
  36. {
  37. //************* Database implementation ***************
  38. Database::Database()
  39. {
  40. active = false; // No connection yet
  41. error = ""; //S_NO_CONNECTION;
  42. host = "";
  43. port = "";
  44. db = "";
  45. login = "";
  46. passwd = "";
  47. sequence_table = "db_sequence";
  48. }
  49. Database::~Database()
  50. {
  51. disconnect(); // Disconnect if connected to database
  52. }
  53. int Database::connectFull(const char *newHost, const char *newPort,
  54. const char *newDb, const char *newLogin,
  55. const char *newPasswd)
  56. {
  57. host = newHost;
  58. port = newPort;
  59. db = newDb;
  60. login = newLogin;
  61. passwd = newPasswd;
  62. return connect();
  63. }
  64. }
  65. //************* Dataset implementation ***************
  66. Dataset::Dataset()
  67. {
  68. db = NULL;
  69. haveError = active = false;
  70. frecno = 0;
  71. fbof = feof = true;
  72. autocommit = true;
  73. select_sql = "";
  74. fields_object = new Fields();
  75. edit_object = new Fields();
  76. }
  77. Dataset::Dataset(Database * newDb)
  78. {
  79. db = newDb;
  80. haveError = active = false;
  81. frecno = 0;
  82. fbof = feof = true;
  83. autocommit = true;
  84. select_sql = "";
  85. fields_object = new Fields();
  86. edit_object = new Fields();
  87. }
  88. Dataset::~Dataset()
  89. {
  90. update_sql.clear();
  91. insert_sql.clear();
  92. delete_sql.clear();
  93. delete fields_object;
  94. delete edit_object;
  95. }
  96. void Dataset::setSqlParams(const char *sqlFrmt, sqlType t, ...)
  97. {
  98. va_list ap;
  99. char sqlCmd[DB_BUFF_MAX + 1];
  100. va_start(ap, t);
  101. vsnprintf(sqlCmd, DB_BUFF_MAX - 1, sqlFrmt, ap);
  102. va_end(ap);
  103. switch (t)
  104. {
  105. case sqlSelect:
  106. set_select_sql(sqlCmd);
  107. break;
  108. case sqlUpdate:
  109. add_update_sql(sqlCmd);
  110. break;
  111. case sqlInsert:
  112. add_insert_sql(sqlCmd);
  113. break;
  114. case sqlDelete:
  115. add_delete_sql(sqlCmd);
  116. break;
  117. case sqlExec:
  118. sql = sqlCmd;
  119. break;
  120. }
  121. }
  122. void Dataset::set_select_sql(const char *sel_sql)
  123. {
  124. select_sql = sel_sql;
  125. }
  126. void Dataset::set_select_sql(const string & sel_sql)
  127. {
  128. select_sql = sel_sql;
  129. }
  130. void Dataset::parse_sql(string & sql)
  131. {
  132. string fpattern, by_what;
  133. pars.set_str(sql.c_str());
  134. for (uint i = 0; i < fields_object->size(); i++)
  135. {
  136. fpattern = ":OLD_" + (*fields_object)[i].props.name;
  137. by_what = "'" + (*fields_object)[i].val.get_asString() + "'";
  138. //cout << "parsing " << fpattern <<by_what<<"\n\n";
  139. sql = pars.replace(fpattern, by_what);
  140. }
  141. for (uint i = 0; i < edit_object->size(); i++)
  142. {
  143. fpattern = ":NEW_" + (*edit_object)[i].props.name;
  144. by_what = "'" + (*edit_object)[i].val.get_asString() + "'";
  145. sql = pars.replace(fpattern, by_what);
  146. }
  147. // StringList before_array, after_array;
  148. // int tag = 0;
  149. // bool eol_reached = false,
  150. // was_changed = false,
  151. // flag = false;
  152. // ExtString which_before, which_after;
  153. // ExtString bef, aft, prev_before, right_side, which_field, changed_field, f_value;
  154. // before_array.add(":NEW_", tag);
  155. // before_array.add(":OLD_", tag);
  156. // after_array.add(")", tag);
  157. // after_array.add(",", tag);
  158. // after_array.add(" ", tag);
  159. // sq.squish();
  160. // bef = sq.before_arr(before_array, which_before);
  161. // while (!(bef == prev_before)) {
  162. // right_side = sq.after(which_before, flag);
  163. // right_side.squish();
  164. // aft = right_side.after_arr(after_array, which_after);
  165. // aft.squish();
  166. // which_field = right_side.before(which_after);
  167. // // checking whather we reach end of line
  168. // if ((which_field == "\0") && (which_before != "\0")) {
  169. // which_field = right_side;
  170. // eol_reached = true;
  171. // }
  172. // // If new field and is in insert or edit mode - looks in edit_object
  173. // if ((which_before == ":NEW_") && (which_field != "\0")) {
  174. // which_field.squish();
  175. // f_value.assign(fv(which_field.getChars()));
  176. // f_value.addslashes();
  177. // changed_field.assign("'");
  178. // changed_field + f_value + "'";
  179. // }
  180. // else
  181. // // else looking old value in the current result set
  182. // if ((which_before == ":OLD_") && (which_field != "\0")) {
  183. // which_field.squish();
  184. // f_value.assign(f_old(which_field.getChars()));
  185. // f_value.addslashes();
  186. // changed_field.assign("'");
  187. // changed_field + f_value + "'";
  188. // }
  189. // if (!eol_reached) {
  190. // sq.assign(bef + changed_field + which_after + aft);
  191. // }
  192. // else {
  193. // if (!was_changed && (which_field != "\0")) {
  194. // sq.assign(bef + changed_field + which_after + aft);
  195. // was_changed = true;
  196. // }
  197. // }
  198. // prev_before = bef;
  199. // bef = sq.before_arr(before_array, which_before);
  200. // }
  201. }
  202. void Dataset::close(void)
  203. {
  204. haveError = false;
  205. frecno = 0;
  206. fbof = feof = true;
  207. active = false;
  208. }
  209. //bool Dataset::seek(int pos=0) {
  210. bool Dataset::seek(int pos)
  211. {
  212. frecno = (pos < num_rows() - 1) ? pos : num_rows() - 1;
  213. frecno = (frecno < 0) ? 0 : frecno;
  214. fbof = feof = (num_rows() == 0) ? true : false;
  215. return frecno;
  216. }
  217. void Dataset::refresh()
  218. {
  219. int row = frecno;
  220. if ((row != 0) && active)
  221. {
  222. close();
  223. open();
  224. seek(row);
  225. }
  226. else
  227. open();
  228. }
  229. void Dataset::first()
  230. {
  231. if (ds_state == dsSelect)
  232. {
  233. frecno = 0;
  234. feof = fbof = (num_rows() > 0) ? false : true;
  235. }
  236. }
  237. void Dataset::next()
  238. {
  239. if (ds_state == dsSelect)
  240. {
  241. fbof = false;
  242. if (frecno < num_rows() - 1)
  243. {
  244. frecno++;
  245. feof = false;
  246. }
  247. else
  248. feof = true;
  249. if (num_rows() <= 0)
  250. fbof = feof = true;
  251. }
  252. }
  253. void Dataset::prev()
  254. {
  255. if (ds_state == dsSelect)
  256. {
  257. feof = false;
  258. if (frecno)
  259. {
  260. frecno--;
  261. fbof = false;
  262. }
  263. else
  264. fbof = true;
  265. if (num_rows() <= 0)
  266. fbof = feof = true;
  267. }
  268. }
  269. void Dataset::last()
  270. {
  271. if (ds_state == dsSelect)
  272. {
  273. frecno = (num_rows() > 0) ? num_rows() - 1 : 0;
  274. feof = fbof = (num_rows() > 0) ? false : true;
  275. }
  276. }
  277. //bool Dataset::goto_rec(int pos=1) {
  278. bool Dataset::goto_rec(int pos)
  279. {
  280. if (ds_state == dsSelect)
  281. {
  282. return seek(pos - 1);
  283. }
  284. return false;
  285. }
  286. #if 0
  287. void Dataset::insert()
  288. {
  289. //cout << "insert\n\n";
  290. for (int i = 0; i < field_count(); i++)
  291. {
  292. (*fields_object)[i].val = "";
  293. (*edit_object)[i].val = "";
  294. //cout <<"Insert:"<<i<<"\n\n";
  295. }
  296. ds_state = dsInsert;
  297. }
  298. #endif
  299. void Dataset::edit()
  300. {
  301. if (ds_state != dsSelect)
  302. {
  303. cerr << "Editing is possible only when query exists!";
  304. return;
  305. }
  306. for (uint i = 0; i < fields_object->size(); i++)
  307. {
  308. (*edit_object)[i].val = (*fields_object)[i].val;
  309. }
  310. ds_state = dsEdit;
  311. }
  312. void Dataset::post()
  313. {
  314. if (ds_state == dsInsert)
  315. make_insert();
  316. else if (ds_state == dsEdit)
  317. make_edit();
  318. }
  319. void Dataset::deletion()
  320. {
  321. if (ds_state == dsSelect)
  322. make_deletion();
  323. }
  324. bool Dataset::set_field_value(const char *f_name, const field_value & value)
  325. {
  326. bool found = false;
  327. if ((ds_state == dsInsert) || (ds_state == dsEdit))
  328. {
  329. for (uint i = 0; i < fields_object->size(); i++)
  330. if ((*edit_object)[i].props.name == f_name)
  331. {
  332. (*edit_object)[i].val = value;
  333. found = true;
  334. }
  335. if (!found)
  336. {
  337. GB.Error("Field not found: &1", f_name);
  338. }
  339. return found;
  340. }
  341. GB.Error("Not in Insert or Edit state");
  342. return found;
  343. }
  344. const field_value & Dataset::get_field_value(const char *f_name)
  345. {
  346. static field_value fv;
  347. if (ds_state != dsInactive)
  348. {
  349. if (ds_state == dsEdit || ds_state == dsInsert)
  350. {
  351. for (uint i = 0; i < edit_object->size(); i++)
  352. if ((*edit_object)[i].props.name == f_name)
  353. return (*edit_object)[i].val;
  354. GB.Error("Field not found: %s", f_name);
  355. }
  356. else
  357. for (uint i = 0; i < fields_object->size(); i++)
  358. if ((*fields_object)[i].props.name == f_name)
  359. return (*fields_object)[i].val;
  360. GB.Error("Field not found: %s", f_name);
  361. }
  362. GB.Error("Dataset state is Inactive");
  363. return fv;
  364. }
  365. const field_value & Dataset::get_field_value(int index) //const char *f_name)
  366. {
  367. static field_value fv;
  368. if (ds_state != dsInactive)
  369. {
  370. if (ds_state == dsEdit || ds_state == dsInsert)
  371. return (*edit_object)[index].val;
  372. else
  373. return (*fields_object)[index].val;
  374. }
  375. GB.Error("Dataset state is Inactive");
  376. return fv;
  377. }
  378. const field_value Dataset::f_old(const char *f_name)
  379. {
  380. if (ds_state != dsInactive)
  381. for (uint i = 0; i < fields_object->size(); i++)
  382. if ((*fields_object)[i].props.name == f_name)
  383. return (*fields_object)[i].val;
  384. field_value fv;
  385. return fv;
  386. }
  387. void Dataset::setParamList(const ParamList & params)
  388. {
  389. plist = params;
  390. }
  391. bool Dataset::locate()
  392. {
  393. bool result;
  394. if (plist.empty())
  395. return false;
  396. std::map < string, field_value >::const_iterator i;
  397. first();
  398. while (!eof())
  399. {
  400. result = true;
  401. for (i = plist.begin(); i != plist.end(); ++i)
  402. if (fv(i->first.c_str()).get_asString() == i->second.get_asString())
  403. {
  404. continue;
  405. }
  406. else
  407. {
  408. result = false;
  409. break;
  410. }
  411. if (result)
  412. {
  413. return result;
  414. }
  415. next();
  416. }
  417. return false;
  418. }
  419. bool Dataset::locate(const ParamList & params)
  420. {
  421. plist = params;
  422. return locate();
  423. }
  424. bool Dataset::findNext(void)
  425. {
  426. bool result;
  427. if (plist.empty())
  428. return false;
  429. std::map < string, field_value >::const_iterator i;
  430. while (!eof())
  431. {
  432. result = true;
  433. for (i = plist.begin(); i != plist.end(); ++i)
  434. if (fv(i->first.c_str()).get_asString() == i->second.get_asString())
  435. {
  436. continue;
  437. }
  438. else
  439. {
  440. result = false;
  441. break;
  442. }
  443. if (result)
  444. {
  445. return result;
  446. }
  447. next();
  448. }
  449. return false;
  450. }
  451. void Dataset::add_update_sql(const char *upd_sql)
  452. {
  453. string s = upd_sql;
  454. update_sql.push_back(s);
  455. }
  456. void Dataset::add_update_sql(const string & upd_sql)
  457. {
  458. update_sql.push_back(upd_sql);
  459. }
  460. void Dataset::add_insert_sql(const char *ins_sql)
  461. {
  462. string s = ins_sql;
  463. insert_sql.push_back(s);
  464. }
  465. void Dataset::add_insert_sql(const string & ins_sql)
  466. {
  467. insert_sql.push_back(ins_sql);
  468. }
  469. void Dataset::add_delete_sql(const char *del_sql)
  470. {
  471. string s = del_sql;
  472. delete_sql.push_back(s);
  473. }
  474. void Dataset::add_delete_sql(const string & del_sql)
  475. {
  476. delete_sql.push_back(del_sql);
  477. }
  478. void Dataset::clear_update_sql()
  479. {
  480. update_sql.clear();
  481. }
  482. void Dataset::clear_insert_sql()
  483. {
  484. insert_sql.clear();
  485. }
  486. void Dataset::clear_delete_sql()
  487. {
  488. delete_sql.clear();
  489. }
  490. int Dataset::field_count()
  491. {
  492. return fields_object->size();
  493. }
  494. int Dataset::fieldCount()
  495. {
  496. return fields_object->size();
  497. }
  498. const char *Dataset::fieldName(int n)
  499. {
  500. if (n < field_count() && n >= 0)
  501. return (*fields_object)[n].props.name.c_str();
  502. else
  503. return NULL;
  504. }
  505. int Dataset::fieldSize(int n)
  506. {
  507. if (n < field_count() && n >= 0)
  508. return (*fields_object)[n].props.field_len;
  509. else
  510. return 0;
  511. }
  512. int Dataset::fieldIndex(const char *fn)
  513. {
  514. int index, length;
  515. if (strchr(fn, (int) '.'))
  516. {
  517. /* table name has been supplied */
  518. for (uint i = 0; i < fields_object->size(); i++)
  519. {
  520. //if ((*fields_object)[i].props.name == fn)
  521. if (strcmp((*fields_object)[i].props.name.c_str(), fn) == 0)
  522. return i;
  523. }
  524. }
  525. else
  526. {
  527. for (uint i = 0; i < fields_object->size(); i++)
  528. {
  529. index = (*fields_object)[i].props.name.find('.') + 1;
  530. length = (*fields_object)[i].props.name.length();
  531. /*printf("Field name [%s] find [%s] fn [%s]\n",
  532. (*fields_object)[i].props.name.c_str(),
  533. (*fields_object)[i].props.name.substr(index, length).c_str(), fn); */
  534. //if ((*fields_object)[i].props.name.substr(index, length) == fn){
  535. if (strcmp
  536. ((*fields_object)[i].props.name.substr(index, length).c_str(),
  537. fn) == 0)
  538. {
  539. return i;
  540. }
  541. }
  542. }
  543. return -1;
  544. }
  545. int Dataset::fieldType(int n)
  546. {
  547. if (n < field_count() && n >= 0)
  548. {
  549. //cout << (*fields_object)[n].val.gft();
  550. return (*fields_object)[n].val.get_fType();
  551. //return (*fields_object)[n].props.type;
  552. }
  553. else
  554. return 0;
  555. }