sqlite3_stmt * Connection::prepare( const string &query, const AttributeList ¶meters ) { if( db_ == NULL ) throw ActiveRecordException( "Database not connected", __FILE__, __LINE__ ); sqlite3_stmt *ppStmt = 0; int prepare_result = sqlite3_prepare_v2( db_, query.c_str(), query.size(), &ppStmt, 0 ); if( prepare_result != SQLITE_OK ) { stringstream error; error << "SQL error: \"" << sqlite_error( prepare_result ) << "\" "; error << "in \"" << query << "\""; bool added = false; for( AttributeList::const_iterator it = parameters.begin(); it != parameters.end(); ++it ) { error << ", "; if( ! added ) error << "["; error << *it; added = true; } if( added ) error << "]"; log( error.str() ); throw ActiveRecordException( error.str(), __FILE__, __LINE__ ); } bind_parameters( ppStmt, parameters ); return ppStmt; }
static int prepared_bind(sqlite3_drv_t *drv, char *buffer, int buffer_size) { int result; unsigned int prepared_index; long long_prepared_index; int index = 0, type, size; sqlite3_stmt *statement; #ifdef DEBUG fprintf(drv->log, "Finalizing prepared statement: %.*s\n", buffer_size, buffer); fflush(drv->log); #endif ei_decode_version(buffer, &index, NULL); ei_decode_tuple_header(buffer, &index, &size); // assert(size == 2); ei_decode_long(buffer, &index, &long_prepared_index); prepared_index = (unsigned int) long_prepared_index; if (prepared_index >= drv->prepared_count) { return output_error(drv, SQLITE_MISUSE, "Trying to bind non-existent prepared statement"); } statement = drv->prepared_stmts[prepared_index]; result = bind_parameters(drv, buffer, buffer_size, &index, statement, &type, &size); if (result == SQLITE_OK) { return output_ok(drv); } else { return result; // error has already been output } }
static int sql_bind_and_exec(sqlite3_drv_t *drv, char *buffer, int buffer_size) { int result; int index = 0; int type, size; const char *rest; sqlite3_stmt *statement; long bin_size; char *command; #ifdef DEBUG fprintf(drv->log, "Preexec: %.*s\n", buffer_size, buffer); fflush(drv->log); #endif ei_decode_version(buffer, &index, NULL); result = ei_decode_tuple_header(buffer, &index, &size); if (result || (size != 2)) { return output_error(drv, SQLITE_MISUSE, "Expected a tuple of SQL command and params"); } // decode SQL statement ei_get_type(buffer, &index, &type, &size); // TODO support any iolists if (type != ERL_BINARY_EXT) { return output_error(drv, SQLITE_MISUSE, "SQL should be sent as an Erlang binary"); } command = driver_alloc(size * sizeof(char)); ei_decode_binary(buffer, &index, command, &bin_size); // assert(bin_size == size) result = sqlite3_prepare_v2(drv->db, command, size, &statement, &rest); driver_free(command); if (result != SQLITE_OK) { return output_db_error(drv); } else if (statement == NULL) { return output_error(drv, SQLITE_MISUSE, "empty statement"); } result = bind_parameters(drv, buffer, buffer_size, &index, statement, &type, &size); if (result == SQLITE_OK) { return sql_exec_statement(drv, statement); } else { return result; // error has already been output } }