sql.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <sqlite3.h>
  5. #include "sql.h"
  6. #include "common.h"
  7. /**
  8. * NOTE: Remember to compile with linker flag
  9. * TODO: Implement more functions from SQLite3 lib.
  10. **/
  11. /**
  12. * Structure: sql_db
  13. * Typedef: sql_db_t
  14. * Author: Joachim M. Giæver
  15. *
  16. * Sections:
  17. * char *db_file: Path to the DB-file
  18. * sqlite3 *db_handle: SQLite3 handler
  19. * sql_stmt_t *stmts: SQL-statemnts
  20. * *lstmt: Last used SQL-statement (no function by now)
  21. * int db_flags: Flags
  22. * code: Status/error code
  23. *
  24. * Description:
  25. * Stores information about an SQL-handler and it relations.
  26. **/
  27. struct sql_db {
  28. char *db_file;
  29. sqlite3 *db_handle;
  30. sql_stmt_t *stmts,
  31. *lstmt;
  32. int db_flags,
  33. code;
  34. };
  35. /**
  36. * Structure: sql_stmt
  37. * Typedef: sql_stmt_t
  38. * Author: Joachim M. Giæver
  39. *
  40. * Sections:
  41. * sqlite3_stmt *db_stmt: SQL-statement
  42. * sql_db_t *sql: Related SQL-handler
  43. * const char *db_query: Query string
  44. * *tail: (Possibly) next query
  45. * int cols: #of colums in result
  46. * sql_stmt_t *next: Next statement
  47. *
  48. * Description:
  49. * Stores information about an SQL-statement and its relations.
  50. *
  51. **/
  52. struct sql_stmt {
  53. sqlite3_stmt *db_stmt;
  54. sql_db_t *sql;
  55. const char *db_query,
  56. *tail;
  57. int cols;
  58. sql_stmt_t *next;
  59. };
  60. /**
  61. * Function: sql_val_flags
  62. * Author: Joachim M. Giæver
  63. *
  64. * Parameters:
  65. * - int flags: Flags to check
  66. *
  67. * Description:
  68. * Validates the flag given, also between OR'd
  69. * values. Returns 0 (to trigger error) on failure.
  70. *
  71. * Returns: int, the flag
  72. **/
  73. static int sql_val_flags( int flags );
  74. /**
  75. * Function: sql_get_code
  76. * Author: Joachim M. Giæver
  77. *
  78. * Parameters:
  79. * - sql_db_t *sql: The SQL-handler to read code from
  80. *
  81. * Description:
  82. * Returns the status code stored in the SQL-handler
  83. *
  84. * Returns: int
  85. **/
  86. static int sql_get_code( sql_db_t *sql );
  87. /**
  88. * Function: sql_get_code_from_handle
  89. * Author: Joachim M. Giæver
  90. *
  91. * Parameters:
  92. * - sql_db_t *sql: The SQL-handler to read code from
  93. *
  94. * Description:
  95. * Read status code internal (sqlite) SQL-handler.
  96. *
  97. * Returns: int
  98. **/
  99. static int sql_get_code_from_handle( sql_db_t *sql );
  100. /**
  101. * Function: sql_set_code
  102. * Author: Joachim M. Giæver
  103. *
  104. * Parameters:
  105. * - sql_db_t *sql: The SQL-handler to set code for
  106. *
  107. * Description:
  108. * Sets an new errorcode, based on sqlite.
  109. *
  110. * Returns: int, current (newly set) error code
  111. **/
  112. static int sql_set_code( sql_db_t *sql );
  113. /**
  114. * Function: sql_set_internal_code
  115. * Author: Joachim M. Giæver
  116. *
  117. * Parameters:
  118. * - sql_db_t *sql: The SQL-handerl to set code for
  119. * - int code: Code to set
  120. *
  121. * Description:
  122. * Set internal (extended) error code.
  123. *
  124. * Returns: void
  125. **/
  126. static int sql_set_internal_code( sql_db_t *sql, int code );
  127. /**
  128. * Function: sql_errstr
  129. * Author: Joachim M. Giæver
  130. *
  131. * Parameters:
  132. * - int code: Error code
  133. *
  134. * Description:
  135. * Returns the error string related to the given errcode.
  136. *
  137. * Returns: const char *, the error string
  138. **/
  139. static const char *sql_errstr( int code );
  140. /**
  141. * Function: sql_add_stmt
  142. * Author: Joachim M. Giæver
  143. *
  144. * Parameters:
  145. * - sql_db_t *sql: Owner (SQL-handler.)
  146. *
  147. * Description:
  148. * Adds a stement to the SQL-handler, to keep
  149. * track of relation.
  150. *
  151. * Returns: sql_stmt_t *, added statement
  152. **/
  153. static sql_stmt_t *sql_add_stmt( sql_db_t *sql );
  154. /**
  155. * Function: sql_create
  156. * Author: Joachim M. Giæver
  157. *
  158. * Parameters:
  159. * - char *db_file: The DB-file to open
  160. * - int flags: The flags, doesnt support MUTEX and CACHE flags
  161. *
  162. * Description:
  163. * Creates an SQL-object; init the SQL
  164. *
  165. * Returns: sql_db_t *, db object
  166. **/
  167. sql_db_t *sql_create( char *db_file, int flags ) {
  168. sql_db_t *sql = ( sql_db_t *) malloc( sizeof( sql_db_t ) );
  169. if ( sql == NULL )
  170. errandend( "Unable to allocate memory for the database structure." );
  171. sql->db_file = strdup( db_file );
  172. sql->db_flags = sql_val_flags( flags );
  173. sql->stmts = NULL;
  174. sqlite3_open_v2( sql->db_file, &sql->db_handle, sql->db_flags, NULL );
  175. sql_set_code( sql );
  176. return sql;
  177. }
  178. /**
  179. * Function: sql_ok
  180. * Author: Joachim M. Giæver
  181. *
  182. * Parameters:
  183. * - sql_db_t *sql: The SQL-handler to check.
  184. *
  185. * Description:
  186. * Checks if last activity agains the DB (e.g a query)
  187. * was successfull.
  188. *
  189. * Returns: int, 1 on success, 0 on failure
  190. **/
  191. int sql_ok( sql_db_t *sql ) {
  192. return sql == NULL ? 0 : sql->code >= SQL_NOERR_LIMIT;
  193. }
  194. /**
  195. * Function: sql_done
  196. * Author: Joachim M. Giæver
  197. *
  198. * Parameters:
  199. * - sql_db_t *sql: The SQL-handler to check.
  200. *
  201. * Description:
  202. * Determines if the SQL-task is done.
  203. *
  204. * Returns: int, 1 on success, 0 on failure
  205. **/
  206. int sql_done( sql_db_t *sql ) {
  207. return sql == NULL ? 1 : sql->code == SQL_DONE;
  208. }
  209. /**
  210. * Function: sql_errmsg
  211. * Author: Joachim M. Giæver
  212. *
  213. * Parameters:
  214. * - sql_db_t *sql: The SQL-handler to look for errors in.
  215. *
  216. * Description:
  217. * Returns the corresponding SQL-error message.
  218. * If sql_ok() returns an error, there is an
  219. * error present.
  220. *
  221. * Returns: char *, the error message
  222. **/
  223. const char *sql_errmsg( sql_db_t *sql ) {
  224. int code = sql_get_code( sql );
  225. /*printf( // Debugging purposes!!
  226. "DB OBJECT:\t\t%p\n- Filename\t:\t%s\n- Flags:\t\t%d\n- Internal code:\t%d\n- SQLITE code:\t\t%d\n- Query:\n\"%s\"\n",
  227. sql, sql->db_file, sql->db_flags, sql->code, code, sql->lstmt != NULL ? sql->lstmt->db_query : NULL
  228. );*/
  229. return code < SQL_ERR_LIMIT ? sql_errstr( code ) : sqlite3_errstr( code );
  230. }
  231. /**
  232. * Function: sql_close
  233. * Author: Joachim M. Giæver
  234. *
  235. * Parameters:
  236. * - sql_db_t *sql: The SQL-handler to close
  237. *
  238. * Description:
  239. * Close an SQL-handler. This will also free related
  240. * statements for the handler, which as unessacary.
  241. * Statements should be finalized by designer, but are
  242. * implemented as a "gb-collection".
  243. *
  244. * Returns: void
  245. **/
  246. void sql_close( sql_db_t *sql ) {
  247. sql_stmt_t *stmt;
  248. if ( sql == NULL )
  249. return;
  250. stmt = sql->stmts;
  251. while( stmt != NULL ) {
  252. sql_stmt_finalize( stmt );
  253. stmt = stmt->next;
  254. }
  255. sqlite3_close_v2( sql->db_handle );
  256. free( sql->db_file );
  257. free( sql );
  258. }
  259. /**
  260. * Function: sql_query
  261. * Author: Joachim M. Giæver
  262. *
  263. * Parameters:
  264. * - sql_db_t *sql: The SQL-handler to query agains
  265. * - const char *query: The SQL-statement/-query
  266. *
  267. * Description:
  268. * Creates an SQL-statement and queries the DB.
  269. *
  270. * Returns: sql_stmt_t *, the SQL-statement object.
  271. **/
  272. sql_stmt_t *sql_query( sql_db_t *sql, const char *query ) {
  273. sql_stmt_t *stmt;
  274. if ( sql == NULL )
  275. return NULL;
  276. stmt = sql_add_stmt( sql );
  277. if ( stmt == NULL ) {
  278. sql_set_internal_code( sql, SQL_OUTOFMEM );
  279. return NULL;
  280. }
  281. stmt->db_query = strdup( (char *)query );
  282. sqlite3_prepare_v2( sql->db_handle, stmt->db_query, strlen( query ), &stmt->db_stmt, &stmt->tail );
  283. sql_set_code( sql );
  284. sql->lstmt = stmt;
  285. stmt->cols = sqlite3_column_count( stmt->db_stmt );
  286. return stmt;
  287. }
  288. /**
  289. * Function: sql_column_count
  290. * Author: Joachim M. Giæver
  291. *
  292. * Parameters:
  293. * - sql_stmt_t *stmt: SQL-statement to check
  294. *
  295. * Description:
  296. * Returns the amount of colums returned from a query
  297. *
  298. * Returns: int, #colums returned
  299. **/
  300. int sql_column_count( sql_stmt_t *stmt ) {
  301. return stmt->cols;
  302. }
  303. /**
  304. * Function: sql_column_name
  305. * Author: Joachim M. Giæver
  306. *
  307. * Parameters:
  308. * - sql_stmt_t *stmt: SQL-statment to read from
  309. *
  310. * Description:
  311. * Returns the columname specified by the index.
  312. *
  313. * Returns: char *, colum name
  314. **/
  315. const char *sql_column_name( sql_stmt_t *stmt, int idx ) {
  316. return idx <= stmt->cols ? sqlite3_column_name( stmt->db_stmt, idx ) : NULL;
  317. }
  318. /**
  319. * Function: sql_column_text
  320. * Author: Joachim M. Giæver
  321. *
  322. * Parameters:
  323. * - sql_stmt_t *stmt: SQL-statement to read from
  324. *
  325. * Description:
  326. * Return the text stored in the column specified by the index.
  327. *
  328. * Returns: const unsigned char *, column text
  329. **/
  330. const unsigned char *sql_column_text( sql_stmt_t *stmt, int idx ) {
  331. return idx <= stmt->cols ? sqlite3_column_text( stmt->db_stmt, idx ) : NULL;
  332. }
  333. /**
  334. * Function: sql_stmt_step
  335. * Author: Joachim M. Giæver
  336. *
  337. * Parameters:
  338. * - sql_stmt_t *stmt: SQL-statement to read from
  339. *
  340. * Description:
  341. * Go to next entry in the retured query.
  342. *
  343. * Returns: int, 1 on success, 0 on failure.
  344. **/
  345. int sql_stmt_step( sql_stmt_t *stmt ) {
  346. if ( stmt == NULL )
  347. return SQL_DONE;
  348. sqlite3_step( stmt->db_stmt );
  349. return sql_set_code( sql_stmt_sql( stmt ) );
  350. }
  351. /**
  352. * Function: sql_stmt_sql
  353. * Author: Joachim M. Giæver
  354. *
  355. * Parameters:
  356. * - sql_stmt_t *stmt: SQL-statement to load handler from
  357. *
  358. * Description:
  359. * Returns the related SQL-handler for the SQL-statement.
  360. *
  361. * Returns: sql_db_t *, SQL-object
  362. **/
  363. sql_db_t *sql_stmt_sql( sql_stmt_t *stmt ) {
  364. return stmt == NULL ? NULL : stmt->sql;
  365. }
  366. /**
  367. * Function: sql_stmt_tail
  368. * Author: Joachim M. Giæver
  369. *
  370. * Parameters:
  371. * - sql_stmt_t *stmt: The parent statement
  372. *
  373. * Description:
  374. * Queries the SQL with the next tail-query.
  375. *
  376. * Note: This finalizes the parent statement.
  377. *
  378. * Returns: sql_stmt_t *, tail statement
  379. **/
  380. sql_stmt_t *sql_stmt_tail( sql_stmt_t *stmt ) {
  381. sql_stmt_t *new_stmt;
  382. if ( stmt == NULL || ( stmt != NULL && stmt->tail[0] == '\0' ) )
  383. return NULL;
  384. // Query tail
  385. new_stmt = sql_query( sql_stmt_sql( stmt ), stmt->tail );
  386. // End current.
  387. sql_stmt_finalize( stmt );
  388. return new_stmt;
  389. }
  390. /**
  391. * Function: sql_stmt_finalize
  392. * Author: Joachim M. Giæver
  393. *
  394. * Parameters:
  395. * - sql_stmt_t *stmt: SQL-statement to finalize
  396. *
  397. * Description:
  398. * Finalizes an SQL-statement AKA closing it.
  399. *
  400. * Returns: void
  401. **/
  402. void sql_stmt_finalize( sql_stmt_t *stmt ) {
  403. sql_db_t *sql;
  404. sql_stmt_t *tmp;
  405. if ( stmt == NULL )
  406. return;
  407. sql = sql_stmt_sql( stmt );
  408. tmp = sql->stmts;
  409. if ( tmp == stmt ) // if stmt is head of list; make next to head
  410. sql->stmts = tmp->next;
  411. else {
  412. // Find stmt in list
  413. while( tmp != NULL && tmp->next != stmt )
  414. tmp = tmp->next;
  415. // Merge prepending with append aka remove stmt
  416. if ( tmp != NULL )
  417. tmp->next = tmp->next == NULL ? NULL : tmp->next->next;
  418. }
  419. free( (char *)stmt->db_query );
  420. sqlite3_finalize( stmt->db_stmt );
  421. free( stmt );
  422. }
  423. /**
  424. * Function: sql_val_flags
  425. * Author: Joachim M. Giæver
  426. *
  427. * Parameters:
  428. * - int flags: Flags to check
  429. *
  430. * Description:
  431. * Validates the flag given, also between OR'd
  432. * values. Returns 0 (to trigger error) on failure.
  433. *
  434. * Returns: int, the flag
  435. **/
  436. static int sql_val_flags( int flags ) {
  437. if ( !(flags ^ (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE)) )
  438. return (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
  439. if ( !(flags ^ SQLITE_OPEN_READWRITE) )
  440. return SQLITE_OPEN_READWRITE;
  441. if ( !( flags ^ SQLITE_OPEN_READONLY ) )
  442. return SQLITE_OPEN_READONLY;
  443. return flags;
  444. }
  445. /**
  446. * Function: sql_get_code
  447. * Author: Joachim M. Giæver
  448. *
  449. * Parameters:
  450. * - sql_db_t *sql: The SQL-handler to read code from
  451. *
  452. * Description:
  453. * Returns the status code stored in the SQL-handler
  454. *
  455. * Returns: int
  456. **/
  457. static int sql_get_code( sql_db_t *sql ) {
  458. return sql->code >= SQL_NOERR_LIMIT ? sql->code - SQL_NOERR_LIMIT : ( sql->code < SQL_ERR_LIMIT ? sql->code : sql->code + -(SQL_ERR_LIMIT) );
  459. }
  460. /**
  461. * Function: sql_get_code_from_handle
  462. * Author: Joachim M. Giæver
  463. *
  464. * Parameters:
  465. * - sql_db_t *sql: The SQL-handler to read code from
  466. *
  467. * Description:
  468. * Read status code internal (sqlite) SQL-handler.
  469. *
  470. * Returns: int
  471. **/
  472. static int sql_get_code_from_handle( sql_db_t *sql ) {
  473. return sqlite3_errcode( sql->db_handle );
  474. }
  475. /**
  476. * Function: sql_set_code
  477. * Author: Joachim M. Giæver
  478. *
  479. * Parameters:
  480. * - sql_db_t *sql: The SQL-handler to set code for
  481. *
  482. * Description:
  483. * Sets an new errorcode, based on sqlite.
  484. *
  485. * Returns: int, current (newly set) error code
  486. **/
  487. static int sql_set_code( sql_db_t *sql ) {
  488. int res;
  489. res = sql_get_code_from_handle( sql );
  490. switch ( res ) {
  491. case SQLITE_OK: sql->code = SQL_OK; break;
  492. case SQLITE_ROW: sql->code = SQL_ROW; break;
  493. case SQLITE_DONE: sql->code = SQL_DONE; break;
  494. case SQLITE_ERROR: sql->code = SQL_ERROR; break;
  495. case SQLITE_INTERNAL: sql->code = SQL_INTERNAL; break;
  496. case SQLITE_PERM: sql->code = SQL_PERM; break;
  497. case SQLITE_ABORT: sql->code = SQL_ABORT; break;
  498. case SQLITE_BUSY: sql->code = SQL_BUSY; break;
  499. case SQLITE_LOCKED: sql->code = SQL_LOCKED; break;
  500. case SQLITE_NOMEM: sql->code = SQL_NOMEM; break;
  501. case SQLITE_READONLY: sql->code = SQL_READONLY; break;
  502. case SQLITE_INTERRUPT: sql->code = SQL_INTERRUPT; break;
  503. case SQLITE_IOERR: sql->code = SQL_IOERR; break;
  504. case SQLITE_CORRUPT: sql->code = SQL_CORRUPT; break;
  505. case SQLITE_NOTFOUND: sql->code = SQL_NOTFOUND; break;
  506. case SQLITE_FULL: sql->code = SQL_FULL; break;
  507. case SQLITE_CANTOPEN: sql->code = SQL_CANTOPEN; break;
  508. case SQLITE_PROTOCOL: sql->code = SQL_PROTOCOL; break;
  509. case SQLITE_EMPTY: sql->code = SQL_EMPTY; break;
  510. case SQLITE_SCHEMA: sql->code = SQL_SCHEMA; break;
  511. case SQLITE_TOOBIG: sql->code = SQL_TOOBIG; break;
  512. case SQLITE_CONSTRAINT: sql->code = SQL_CONSTRAINT; break;
  513. case SQLITE_MISMATCH: sql->code = SQL_MISMATCH; break;
  514. case SQLITE_MISUSE: sql->code = SQL_MISUSE; break;
  515. case SQLITE_NOLFS: sql->code = SQL_NOLFS; break;
  516. case SQLITE_AUTH: sql->code = SQL_AUTH; break;
  517. case SQLITE_FORMAT: sql->code = SQL_FORMAT; break;
  518. case SQLITE_RANGE: sql->code = SQL_RANGE; break;
  519. case SQLITE_NOTADB: sql->code = SQL_NOTADB; break;
  520. default:
  521. printf("OTHER CODE: %d\n", res );
  522. if ( res > 101 )
  523. sql->code = res + -(SQL_ERR_LIMIT);
  524. else
  525. errandend( "Undefined error-code specified.\n" );
  526. break;
  527. }
  528. return sql->code;
  529. }
  530. /**
  531. * Function: sql_set_internal_code
  532. * Author: Joachim M. Giæver
  533. *
  534. * Parameters:
  535. * - sql_db_t *sql: The SQL-handerl to set code for
  536. * - int code: Code to set
  537. *
  538. * Description:
  539. * Set internal (extended) error code.
  540. *
  541. * Returns: void
  542. **/
  543. static int sql_set_internal_code( sql_db_t *sql, int code ) {
  544. switch( code ) {
  545. case SQL_OUTOFMEM:
  546. case SQL_NULL_ABORTION:
  547. sql->code = code;
  548. break;
  549. default:
  550. errandend( "Implementation error: Code unknown." );
  551. }
  552. return sql->code;
  553. }
  554. /**
  555. * Function: sql_errstr
  556. * Author: Joachim M. Giæver
  557. *
  558. * Parameters:
  559. * - int code: Error code
  560. *
  561. * Description:
  562. * Returns the error string related to the given errcode.
  563. *
  564. * Returns: const char *, the error string
  565. **/
  566. static const char *sql_errstr( int code ) {
  567. char *errstr;
  568. switch( code ) {
  569. case SQL_OUTOFMEM:
  570. errstr = "Out of memory";
  571. break;
  572. case SQL_NULL_ABORTION:
  573. errstr = "Aborting: NULL pointer.";
  574. break;
  575. default:
  576. errstr = "Undefined error [SQL WRAPPER]";
  577. break;
  578. }
  579. return (const char *)errstr;
  580. }
  581. /**
  582. * Function: sql_add_stmt
  583. * Author: Joachim M. Giæver
  584. *
  585. * Parameters:
  586. * - sql_db_t *sql: Owner (SQL-handler.)
  587. *
  588. * Description:
  589. * Adds a stement to the SQL-handler, to keep
  590. * track of relation.
  591. *
  592. * Returns: sql_stmt_t *, added statement
  593. **/
  594. static sql_stmt_t *sql_add_stmt( sql_db_t *sql ) {
  595. sql_stmt_t *tmp, *stmt;
  596. tmp = sql->stmts;
  597. stmt = ( sql_stmt_t *) malloc( sizeof( sql_stmt_t ) );
  598. if ( stmt == NULL ) {
  599. sql_set_internal_code( sql, SQL_OUTOFMEM );
  600. return NULL;
  601. }
  602. // Put last in list.
  603. stmt->next = NULL;
  604. stmt->sql = sql;
  605. if ( tmp == NULL ) {
  606. sql->stmts = stmt;
  607. return stmt;
  608. }
  609. while( tmp != NULL && tmp->next != NULL )
  610. tmp = tmp->next;
  611. tmp->next = stmt;
  612. return stmt;
  613. }
  614. /***
  615. * THIS IS FOR DEBUGGING OF THE SQL WRAPPER;
  616. * To run this make project as:
  617. * $ make sql-test
  618. * and run by
  619. * $ ./sql-test
  620. **/
  621. #ifdef _DEBUG_SQL
  622. int main( int argc, char const *argv[] ) {
  623. int i;
  624. /* Query strings */
  625. char *iquery, *query1, *query2, *query3, *query4;
  626. /* DB statements */
  627. sql_stmt_t *istmt, *stmt1, *stmt2, *stmt3, *stmt4;
  628. /* DB Connection */
  629. sql_db_t *sql = sql_create( "./sql.sqlite3", SQLITE_OPEN_READONLY );
  630. if ( !sql_ok( sql ) ) {
  631. printf( "Error: %s\n", sql_errmsg( sql ) );
  632. goto end_test;
  633. }
  634. /** Various query strings, note query3 is multiple **/
  635. query1 = "SELECT orderNumber,orderDate from Orders where status = 'Cancelled'";
  636. query2 = "SELECT C.customerName AS Customer, SUM(OD.quantityOrdered) AS Total " \
  637. "FROM Orders O, Customers C, OrderDetails OD " \
  638. "WHERE O.customerNumber = C.customerNumber " \
  639. " AND O.orderNumber = OD.orderNumber " \
  640. "GROUP BY O.customerNumber " \
  641. "ORDER BY Total DESC;";
  642. query3 = "SELECT orderNumber,orderDate from Orders where status = 'Cancelled';"\
  643. "SELECT orderNumber,orderDate from Orders where status != 'Cancelled';"\
  644. "SELECT P.productName, T.totalQuantityOrdered " \
  645. "FROM Products P NATURAL JOIN " \
  646. " (SELECT productCode, SUM(quantityOrdered) AS totalQuantityOrdered " \
  647. " FROM OrderDetails GROUP BY productCode) AS T " \
  648. "WHERE T.totalQuantityOrdered >= 1000";
  649. query4 = "SELECT customerName FROM Customers";
  650. iquery = "INSERT INTO Customers (customerName, contactFirstName, contactLastName, phone, addressLine1, city, country) VALUES('Rotor klubben', 'Anna', 'Banana', 123456789, 'Flystripa', 'Tromsø', 'Noreg');";
  651. /**
  652. * Do insert
  653. **/
  654. puts("\nQUERY insert");
  655. istmt = sql_query( sql, (const char *)iquery);
  656. if ( !sql_ok( sql ) ) {
  657. printf("Error on insert: %s\n", sql_errmsg( sql ));
  658. goto query1_start;
  659. }
  660. // Just to prevent notice about unused...
  661. if ( istmt == NULL);
  662. /**
  663. * Do query 1:
  664. **/
  665. query1_start:
  666. puts("\nQUERY 1");
  667. stmt1 = sql_query( sql, (const char *)query1 );
  668. // Look for errors
  669. if ( !sql_ok( sql ) ) {
  670. printf("Error on query 1: %s\n", sql_errmsg( sql ) );
  671. goto query2_start; // Jumt over rest in query 1
  672. }
  673. // Loop through all columns
  674. for ( i = 0; i < sql_column_count( stmt1 ); i++ )
  675. printf( "Col: %s\n", sql_column_name( stmt1, i ) );
  676. // End statement
  677. sql_stmt_finalize( stmt1 );
  678. /**
  679. * Do query 2:
  680. **/
  681. query2_start:
  682. puts("\nQUERY 2");
  683. stmt2 = sql_query( sql, (const char *)query2 );
  684. // And do the same as query 1..
  685. if ( !sql_ok( sql ) ) {
  686. printf("Error on query 2: %s\n", sql_errmsg( sql ) );
  687. goto query3_start; // Jumt over rest in query 2
  688. }
  689. for ( i = 0; i < sql_column_count( stmt2 ); i++ )
  690. printf( "Col: %s\n", sql_column_name( stmt2, i ) );
  691. sql_stmt_finalize( stmt2 );
  692. /**
  693. * Do query 3: A multiple query string
  694. **/
  695. query3_start:
  696. puts("\nQUERY 3");
  697. stmt3 = sql_query( sql, (const char *)query3 );
  698. // Loop through all statement
  699. while( stmt3 != NULL ) {
  700. if ( !sql_ok( sql ) ) {
  701. printf("Error on query 3: %s\n", sql_errmsg( sql ) );
  702. goto query4_start;
  703. }
  704. /** Make some output **/
  705. for ( i = 0; i < sql_column_count( stmt3 ); i++ ) {
  706. printf( "%s:\n", sql_column_name( stmt3, i ) );
  707. sql_stmt_step( stmt3 );
  708. while( !sql_done( sql_stmt_sql( stmt3 ) ) ) {
  709. printf("%s", sql_column_text( stmt3, i ) );
  710. sql_stmt_step( stmt3 );
  711. if ( !sql_done( sql_stmt_sql( stmt3 ) ) )
  712. printf(", ");
  713. }
  714. if ( sql_done( sql_stmt_sql( stmt3 ) ) )
  715. printf("\n\n");
  716. }
  717. stmt3 = sql_stmt_tail( stmt3 );
  718. i++;
  719. }
  720. query4_start:
  721. puts("\nQUERY 4");
  722. stmt4 = sql_query( sql, (const char *)query4 );
  723. if ( !sql_ok( sql ) ) {
  724. printf("Error on query 4: %s\n", sql_errmsg( sql ) );
  725. goto end_test; // End test
  726. }
  727. /** Make some output **/
  728. for ( i = 0; i < sql_column_count( stmt4 ); i++ ) {
  729. printf( "%s:\n", sql_column_name( stmt4, i ) );
  730. sql_stmt_step( stmt4 );
  731. while( !sql_done( sql_stmt_sql( stmt4 ) ) ) {
  732. printf("%s", sql_column_text( stmt4, i ) );
  733. sql_stmt_step( stmt4 );
  734. if ( !sql_done( sql_stmt_sql( stmt4 ) ) )
  735. printf(", ");
  736. }
  737. if ( sql_done( sql_stmt_sql( stmt4 ) ) )
  738. printf("\n\n");
  739. }
  740. /*
  741. sql_stmt_finalize( stmt3 ):
  742. SQL-close finalizes stmt3
  743. */
  744. end_test:
  745. sql_close( sql );
  746. printf( "Exists. Test completed.\n" );
  747. return EXIT_SUCCESS;
  748. }
  749. #endif