123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914 |
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sqlite3.h>
- #include "sql.h"
- #include "common.h"
- /**
- * NOTE: Remember to compile with linker flag
- * TODO: Implement more functions from SQLite3 lib.
- **/
- /**
- * Structure: sql_db
- * Typedef: sql_db_t
- * Author: Joachim M. Giæver
- *
- * Sections:
- * char *db_file: Path to the DB-file
- * sqlite3 *db_handle: SQLite3 handler
- * sql_stmt_t *stmts: SQL-statemnts
- * *lstmt: Last used SQL-statement (no function by now)
- * int db_flags: Flags
- * code: Status/error code
- *
- * Description:
- * Stores information about an SQL-handler and it relations.
- **/
- struct sql_db {
- char *db_file;
- sqlite3 *db_handle;
- sql_stmt_t *stmts,
- *lstmt;
- int db_flags,
- code;
- };
- /**
- * Structure: sql_stmt
- * Typedef: sql_stmt_t
- * Author: Joachim M. Giæver
- *
- * Sections:
- * sqlite3_stmt *db_stmt: SQL-statement
- * sql_db_t *sql: Related SQL-handler
- * const char *db_query: Query string
- * *tail: (Possibly) next query
- * int cols: #of colums in result
- * sql_stmt_t *next: Next statement
- *
- * Description:
- * Stores information about an SQL-statement and its relations.
- *
- **/
- struct sql_stmt {
- sqlite3_stmt *db_stmt;
- sql_db_t *sql;
- const char *db_query,
- *tail;
- int cols;
- sql_stmt_t *next;
- };
- /**
- * Function: sql_val_flags
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - int flags: Flags to check
- *
- * Description:
- * Validates the flag given, also between OR'd
- * values. Returns 0 (to trigger error) on failure.
- *
- * Returns: int, the flag
- **/
- static int sql_val_flags( int flags );
- /**
- * Function: sql_get_code
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - sql_db_t *sql: The SQL-handler to read code from
- *
- * Description:
- * Returns the status code stored in the SQL-handler
- *
- * Returns: int
- **/
- static int sql_get_code( sql_db_t *sql );
- /**
- * Function: sql_get_code_from_handle
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - sql_db_t *sql: The SQL-handler to read code from
- *
- * Description:
- * Read status code internal (sqlite) SQL-handler.
- *
- * Returns: int
- **/
- static int sql_get_code_from_handle( sql_db_t *sql );
- /**
- * Function: sql_set_code
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - sql_db_t *sql: The SQL-handler to set code for
- *
- * Description:
- * Sets an new errorcode, based on sqlite.
- *
- * Returns: int, current (newly set) error code
- **/
- static int sql_set_code( sql_db_t *sql );
- /**
- * Function: sql_set_internal_code
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - sql_db_t *sql: The SQL-handerl to set code for
- * - int code: Code to set
- *
- * Description:
- * Set internal (extended) error code.
- *
- * Returns: void
- **/
- static int sql_set_internal_code( sql_db_t *sql, int code );
- /**
- * Function: sql_errstr
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - int code: Error code
- *
- * Description:
- * Returns the error string related to the given errcode.
- *
- * Returns: const char *, the error string
- **/
- static const char *sql_errstr( int code );
- /**
- * Function: sql_add_stmt
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - sql_db_t *sql: Owner (SQL-handler.)
- *
- * Description:
- * Adds a stement to the SQL-handler, to keep
- * track of relation.
- *
- * Returns: sql_stmt_t *, added statement
- **/
- static sql_stmt_t *sql_add_stmt( sql_db_t *sql );
- /**
- * Function: sql_create
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - char *db_file: The DB-file to open
- * - int flags: The flags, doesnt support MUTEX and CACHE flags
- *
- * Description:
- * Creates an SQL-object; init the SQL
- *
- * Returns: sql_db_t *, db object
- **/
- sql_db_t *sql_create( char *db_file, int flags ) {
- sql_db_t *sql = ( sql_db_t *) malloc( sizeof( sql_db_t ) );
- if ( sql == NULL )
- errandend( "Unable to allocate memory for the database structure." );
- sql->db_file = strdup( db_file );
- sql->db_flags = sql_val_flags( flags );
- sql->stmts = NULL;
- sqlite3_open_v2( sql->db_file, &sql->db_handle, sql->db_flags, NULL );
- sql_set_code( sql );
- return sql;
- }
- /**
- * Function: sql_ok
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - sql_db_t *sql: The SQL-handler to check.
- *
- * Description:
- * Checks if last activity agains the DB (e.g a query)
- * was successfull.
- *
- * Returns: int, 1 on success, 0 on failure
- **/
- int sql_ok( sql_db_t *sql ) {
- return sql == NULL ? 0 : sql->code >= SQL_NOERR_LIMIT;
- }
- /**
- * Function: sql_done
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - sql_db_t *sql: The SQL-handler to check.
- *
- * Description:
- * Determines if the SQL-task is done.
- *
- * Returns: int, 1 on success, 0 on failure
- **/
- int sql_done( sql_db_t *sql ) {
- return sql == NULL ? 1 : sql->code == SQL_DONE;
- }
- /**
- * Function: sql_errmsg
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - sql_db_t *sql: The SQL-handler to look for errors in.
- *
- * Description:
- * Returns the corresponding SQL-error message.
- * If sql_ok() returns an error, there is an
- * error present.
- *
- * Returns: char *, the error message
- **/
- const char *sql_errmsg( sql_db_t *sql ) {
- int code = sql_get_code( sql );
- /*printf( // Debugging purposes!!
- "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",
- sql, sql->db_file, sql->db_flags, sql->code, code, sql->lstmt != NULL ? sql->lstmt->db_query : NULL
- );*/
- return code < SQL_ERR_LIMIT ? sql_errstr( code ) : sqlite3_errstr( code );
- }
- /**
- * Function: sql_close
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - sql_db_t *sql: The SQL-handler to close
- *
- * Description:
- * Close an SQL-handler. This will also free related
- * statements for the handler, which as unessacary.
- * Statements should be finalized by designer, but are
- * implemented as a "gb-collection".
- *
- * Returns: void
- **/
- void sql_close( sql_db_t *sql ) {
- sql_stmt_t *stmt;
- if ( sql == NULL )
- return;
- stmt = sql->stmts;
- while( stmt != NULL ) {
- sql_stmt_finalize( stmt );
- stmt = stmt->next;
- }
- sqlite3_close_v2( sql->db_handle );
- free( sql->db_file );
- free( sql );
- }
- /**
- * Function: sql_query
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - sql_db_t *sql: The SQL-handler to query agains
- * - const char *query: The SQL-statement/-query
- *
- * Description:
- * Creates an SQL-statement and queries the DB.
- *
- * Returns: sql_stmt_t *, the SQL-statement object.
- **/
- sql_stmt_t *sql_query( sql_db_t *sql, const char *query ) {
- sql_stmt_t *stmt;
- if ( sql == NULL )
- return NULL;
- stmt = sql_add_stmt( sql );
- if ( stmt == NULL ) {
- sql_set_internal_code( sql, SQL_OUTOFMEM );
- return NULL;
- }
- stmt->db_query = strdup( (char *)query );
- sqlite3_prepare_v2( sql->db_handle, stmt->db_query, strlen( query ), &stmt->db_stmt, &stmt->tail );
- sql_set_code( sql );
- sql->lstmt = stmt;
- stmt->cols = sqlite3_column_count( stmt->db_stmt );
- return stmt;
- }
- /**
- * Function: sql_column_count
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - sql_stmt_t *stmt: SQL-statement to check
- *
- * Description:
- * Returns the amount of colums returned from a query
- *
- * Returns: int, #colums returned
- **/
- int sql_column_count( sql_stmt_t *stmt ) {
- return stmt->cols;
- }
- /**
- * Function: sql_column_name
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - sql_stmt_t *stmt: SQL-statment to read from
- *
- * Description:
- * Returns the columname specified by the index.
- *
- * Returns: char *, colum name
- **/
- const char *sql_column_name( sql_stmt_t *stmt, int idx ) {
- return idx <= stmt->cols ? sqlite3_column_name( stmt->db_stmt, idx ) : NULL;
- }
- /**
- * Function: sql_column_text
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - sql_stmt_t *stmt: SQL-statement to read from
- *
- * Description:
- * Return the text stored in the column specified by the index.
- *
- * Returns: const unsigned char *, column text
- **/
- const unsigned char *sql_column_text( sql_stmt_t *stmt, int idx ) {
- return idx <= stmt->cols ? sqlite3_column_text( stmt->db_stmt, idx ) : NULL;
- }
- /**
- * Function: sql_stmt_step
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - sql_stmt_t *stmt: SQL-statement to read from
- *
- * Description:
- * Go to next entry in the retured query.
- *
- * Returns: int, 1 on success, 0 on failure.
- **/
- int sql_stmt_step( sql_stmt_t *stmt ) {
-
- if ( stmt == NULL )
- return SQL_DONE;
- sqlite3_step( stmt->db_stmt );
- return sql_set_code( sql_stmt_sql( stmt ) );
- }
- /**
- * Function: sql_stmt_sql
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - sql_stmt_t *stmt: SQL-statement to load handler from
- *
- * Description:
- * Returns the related SQL-handler for the SQL-statement.
- *
- * Returns: sql_db_t *, SQL-object
- **/
- sql_db_t *sql_stmt_sql( sql_stmt_t *stmt ) {
- return stmt == NULL ? NULL : stmt->sql;
- }
- /**
- * Function: sql_stmt_tail
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - sql_stmt_t *stmt: The parent statement
- *
- * Description:
- * Queries the SQL with the next tail-query.
- *
- * Note: This finalizes the parent statement.
- *
- * Returns: sql_stmt_t *, tail statement
- **/
- sql_stmt_t *sql_stmt_tail( sql_stmt_t *stmt ) {
- sql_stmt_t *new_stmt;
- if ( stmt == NULL || ( stmt != NULL && stmt->tail[0] == '\0' ) )
- return NULL;
- // Query tail
- new_stmt = sql_query( sql_stmt_sql( stmt ), stmt->tail );
- // End current.
- sql_stmt_finalize( stmt );
- return new_stmt;
- }
- /**
- * Function: sql_stmt_finalize
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - sql_stmt_t *stmt: SQL-statement to finalize
- *
- * Description:
- * Finalizes an SQL-statement AKA closing it.
- *
- * Returns: void
- **/
- void sql_stmt_finalize( sql_stmt_t *stmt ) {
- sql_db_t *sql;
- sql_stmt_t *tmp;
- if ( stmt == NULL )
- return;
- sql = sql_stmt_sql( stmt );
- tmp = sql->stmts;
- if ( tmp == stmt ) // if stmt is head of list; make next to head
- sql->stmts = tmp->next;
- else {
- // Find stmt in list
- while( tmp != NULL && tmp->next != stmt )
- tmp = tmp->next;
- // Merge prepending with append aka remove stmt
- if ( tmp != NULL )
- tmp->next = tmp->next == NULL ? NULL : tmp->next->next;
- }
- free( (char *)stmt->db_query );
- sqlite3_finalize( stmt->db_stmt );
- free( stmt );
- }
- /**
- * Function: sql_val_flags
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - int flags: Flags to check
- *
- * Description:
- * Validates the flag given, also between OR'd
- * values. Returns 0 (to trigger error) on failure.
- *
- * Returns: int, the flag
- **/
- static int sql_val_flags( int flags ) {
- if ( !(flags ^ (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE)) )
- return (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
- if ( !(flags ^ SQLITE_OPEN_READWRITE) )
- return SQLITE_OPEN_READWRITE;
- if ( !( flags ^ SQLITE_OPEN_READONLY ) )
- return SQLITE_OPEN_READONLY;
- return flags;
- }
- /**
- * Function: sql_get_code
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - sql_db_t *sql: The SQL-handler to read code from
- *
- * Description:
- * Returns the status code stored in the SQL-handler
- *
- * Returns: int
- **/
- static int sql_get_code( sql_db_t *sql ) {
- return sql->code >= SQL_NOERR_LIMIT ? sql->code - SQL_NOERR_LIMIT : ( sql->code < SQL_ERR_LIMIT ? sql->code : sql->code + -(SQL_ERR_LIMIT) );
- }
- /**
- * Function: sql_get_code_from_handle
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - sql_db_t *sql: The SQL-handler to read code from
- *
- * Description:
- * Read status code internal (sqlite) SQL-handler.
- *
- * Returns: int
- **/
- static int sql_get_code_from_handle( sql_db_t *sql ) {
- return sqlite3_errcode( sql->db_handle );
- }
- /**
- * Function: sql_set_code
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - sql_db_t *sql: The SQL-handler to set code for
- *
- * Description:
- * Sets an new errorcode, based on sqlite.
- *
- * Returns: int, current (newly set) error code
- **/
- static int sql_set_code( sql_db_t *sql ) {
- int res;
- res = sql_get_code_from_handle( sql );
- switch ( res ) {
- case SQLITE_OK: sql->code = SQL_OK; break;
- case SQLITE_ROW: sql->code = SQL_ROW; break;
- case SQLITE_DONE: sql->code = SQL_DONE; break;
- case SQLITE_ERROR: sql->code = SQL_ERROR; break;
- case SQLITE_INTERNAL: sql->code = SQL_INTERNAL; break;
- case SQLITE_PERM: sql->code = SQL_PERM; break;
- case SQLITE_ABORT: sql->code = SQL_ABORT; break;
- case SQLITE_BUSY: sql->code = SQL_BUSY; break;
- case SQLITE_LOCKED: sql->code = SQL_LOCKED; break;
- case SQLITE_NOMEM: sql->code = SQL_NOMEM; break;
- case SQLITE_READONLY: sql->code = SQL_READONLY; break;
- case SQLITE_INTERRUPT: sql->code = SQL_INTERRUPT; break;
- case SQLITE_IOERR: sql->code = SQL_IOERR; break;
- case SQLITE_CORRUPT: sql->code = SQL_CORRUPT; break;
- case SQLITE_NOTFOUND: sql->code = SQL_NOTFOUND; break;
- case SQLITE_FULL: sql->code = SQL_FULL; break;
- case SQLITE_CANTOPEN: sql->code = SQL_CANTOPEN; break;
- case SQLITE_PROTOCOL: sql->code = SQL_PROTOCOL; break;
- case SQLITE_EMPTY: sql->code = SQL_EMPTY; break;
- case SQLITE_SCHEMA: sql->code = SQL_SCHEMA; break;
- case SQLITE_TOOBIG: sql->code = SQL_TOOBIG; break;
- case SQLITE_CONSTRAINT: sql->code = SQL_CONSTRAINT; break;
- case SQLITE_MISMATCH: sql->code = SQL_MISMATCH; break;
- case SQLITE_MISUSE: sql->code = SQL_MISUSE; break;
- case SQLITE_NOLFS: sql->code = SQL_NOLFS; break;
- case SQLITE_AUTH: sql->code = SQL_AUTH; break;
- case SQLITE_FORMAT: sql->code = SQL_FORMAT; break;
- case SQLITE_RANGE: sql->code = SQL_RANGE; break;
- case SQLITE_NOTADB: sql->code = SQL_NOTADB; break;
- default:
- printf("OTHER CODE: %d\n", res );
- if ( res > 101 )
- sql->code = res + -(SQL_ERR_LIMIT);
- else
- errandend( "Undefined error-code specified.\n" );
- break;
- }
- return sql->code;
- }
- /**
- * Function: sql_set_internal_code
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - sql_db_t *sql: The SQL-handerl to set code for
- * - int code: Code to set
- *
- * Description:
- * Set internal (extended) error code.
- *
- * Returns: void
- **/
- static int sql_set_internal_code( sql_db_t *sql, int code ) {
- switch( code ) {
- case SQL_OUTOFMEM:
- case SQL_NULL_ABORTION:
- sql->code = code;
- break;
- default:
- errandend( "Implementation error: Code unknown." );
- }
- return sql->code;
- }
- /**
- * Function: sql_errstr
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - int code: Error code
- *
- * Description:
- * Returns the error string related to the given errcode.
- *
- * Returns: const char *, the error string
- **/
- static const char *sql_errstr( int code ) {
-
- char *errstr;
- switch( code ) {
- case SQL_OUTOFMEM:
- errstr = "Out of memory";
- break;
- case SQL_NULL_ABORTION:
- errstr = "Aborting: NULL pointer.";
- break;
- default:
- errstr = "Undefined error [SQL WRAPPER]";
- break;
- }
- return (const char *)errstr;
- }
- /**
- * Function: sql_add_stmt
- * Author: Joachim M. Giæver
- *
- * Parameters:
- * - sql_db_t *sql: Owner (SQL-handler.)
- *
- * Description:
- * Adds a stement to the SQL-handler, to keep
- * track of relation.
- *
- * Returns: sql_stmt_t *, added statement
- **/
- static sql_stmt_t *sql_add_stmt( sql_db_t *sql ) {
- sql_stmt_t *tmp, *stmt;
- tmp = sql->stmts;
- stmt = ( sql_stmt_t *) malloc( sizeof( sql_stmt_t ) );
- if ( stmt == NULL ) {
- sql_set_internal_code( sql, SQL_OUTOFMEM );
- return NULL;
- }
- // Put last in list.
- stmt->next = NULL;
- stmt->sql = sql;
- if ( tmp == NULL ) {
- sql->stmts = stmt;
- return stmt;
- }
- while( tmp != NULL && tmp->next != NULL )
- tmp = tmp->next;
- tmp->next = stmt;
- return stmt;
- }
- /***
- * THIS IS FOR DEBUGGING OF THE SQL WRAPPER;
- * To run this make project as:
- * $ make sql-test
- * and run by
- * $ ./sql-test
- **/
- #ifdef _DEBUG_SQL
- int main( int argc, char const *argv[] ) {
- int i;
- /* Query strings */
- char *iquery, *query1, *query2, *query3, *query4;
- /* DB statements */
- sql_stmt_t *istmt, *stmt1, *stmt2, *stmt3, *stmt4;
- /* DB Connection */
- sql_db_t *sql = sql_create( "./sql.sqlite3", SQLITE_OPEN_READONLY );
-
- if ( !sql_ok( sql ) ) {
- printf( "Error: %s\n", sql_errmsg( sql ) );
- goto end_test;
- }
- /** Various query strings, note query3 is multiple **/
- query1 = "SELECT orderNumber,orderDate from Orders where status = 'Cancelled'";
- query2 = "SELECT C.customerName AS Customer, SUM(OD.quantityOrdered) AS Total " \
- "FROM Orders O, Customers C, OrderDetails OD " \
- "WHERE O.customerNumber = C.customerNumber " \
- " AND O.orderNumber = OD.orderNumber " \
- "GROUP BY O.customerNumber " \
- "ORDER BY Total DESC;";
- query3 = "SELECT orderNumber,orderDate from Orders where status = 'Cancelled';"\
- "SELECT orderNumber,orderDate from Orders where status != 'Cancelled';"\
- "SELECT P.productName, T.totalQuantityOrdered " \
- "FROM Products P NATURAL JOIN " \
- " (SELECT productCode, SUM(quantityOrdered) AS totalQuantityOrdered " \
- " FROM OrderDetails GROUP BY productCode) AS T " \
- "WHERE T.totalQuantityOrdered >= 1000";
- query4 = "SELECT customerName FROM Customers";
- iquery = "INSERT INTO Customers (customerName, contactFirstName, contactLastName, phone, addressLine1, city, country) VALUES('Rotor klubben', 'Anna', 'Banana', 123456789, 'Flystripa', 'Tromsø', 'Noreg');";
- /**
- * Do insert
- **/
- puts("\nQUERY insert");
- istmt = sql_query( sql, (const char *)iquery);
- if ( !sql_ok( sql ) ) {
- printf("Error on insert: %s\n", sql_errmsg( sql ));
- goto query1_start;
- }
- // Just to prevent notice about unused...
- if ( istmt == NULL);
- /**
- * Do query 1:
- **/
- query1_start:
- puts("\nQUERY 1");
- stmt1 = sql_query( sql, (const char *)query1 );
- // Look for errors
- if ( !sql_ok( sql ) ) {
- printf("Error on query 1: %s\n", sql_errmsg( sql ) );
- goto query2_start; // Jumt over rest in query 1
- }
- // Loop through all columns
- for ( i = 0; i < sql_column_count( stmt1 ); i++ )
- printf( "Col: %s\n", sql_column_name( stmt1, i ) );
- // End statement
- sql_stmt_finalize( stmt1 );
- /**
- * Do query 2:
- **/
- query2_start:
- puts("\nQUERY 2");
- stmt2 = sql_query( sql, (const char *)query2 );
- // And do the same as query 1..
- if ( !sql_ok( sql ) ) {
- printf("Error on query 2: %s\n", sql_errmsg( sql ) );
- goto query3_start; // Jumt over rest in query 2
- }
- for ( i = 0; i < sql_column_count( stmt2 ); i++ )
- printf( "Col: %s\n", sql_column_name( stmt2, i ) );
- sql_stmt_finalize( stmt2 );
- /**
- * Do query 3: A multiple query string
- **/
- query3_start:
- puts("\nQUERY 3");
- stmt3 = sql_query( sql, (const char *)query3 );
- // Loop through all statement
- while( stmt3 != NULL ) {
- if ( !sql_ok( sql ) ) {
- printf("Error on query 3: %s\n", sql_errmsg( sql ) );
- goto query4_start;
- }
- /** Make some output **/
- for ( i = 0; i < sql_column_count( stmt3 ); i++ ) {
- printf( "%s:\n", sql_column_name( stmt3, i ) );
- sql_stmt_step( stmt3 );
- while( !sql_done( sql_stmt_sql( stmt3 ) ) ) {
- printf("%s", sql_column_text( stmt3, i ) );
-
- sql_stmt_step( stmt3 );
-
- if ( !sql_done( sql_stmt_sql( stmt3 ) ) )
- printf(", ");
-
- }
-
- if ( sql_done( sql_stmt_sql( stmt3 ) ) )
- printf("\n\n");
- }
- stmt3 = sql_stmt_tail( stmt3 );
- i++;
- }
- query4_start:
- puts("\nQUERY 4");
- stmt4 = sql_query( sql, (const char *)query4 );
- if ( !sql_ok( sql ) ) {
- printf("Error on query 4: %s\n", sql_errmsg( sql ) );
- goto end_test; // End test
- }
- /** Make some output **/
- for ( i = 0; i < sql_column_count( stmt4 ); i++ ) {
- printf( "%s:\n", sql_column_name( stmt4, i ) );
- sql_stmt_step( stmt4 );
- while( !sql_done( sql_stmt_sql( stmt4 ) ) ) {
- printf("%s", sql_column_text( stmt4, i ) );
-
- sql_stmt_step( stmt4 );
-
- if ( !sql_done( sql_stmt_sql( stmt4 ) ) )
- printf(", ");
-
- }
-
- if ( sql_done( sql_stmt_sql( stmt4 ) ) )
- printf("\n\n");
- }
- /*
- sql_stmt_finalize( stmt3 ):
- SQL-close finalizes stmt3
- */
- end_test:
- sql_close( sql );
- printf( "Exists. Test completed.\n" );
- return EXIT_SUCCESS;
- }
- #endif
|