From 31fd2870497686667f20b2d43467a07482f8ab40 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 10 Sep 2013 14:10:45 +0200 Subject: Schema versioning support --- odb/sqlite/statement.cxx | 206 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 160 insertions(+), 46 deletions(-) (limited to 'odb/sqlite/statement.cxx') diff --git a/odb/sqlite/statement.cxx b/odb/sqlite/statement.cxx index de71e12..f20d8da 100644 --- a/odb/sqlite/statement.cxx +++ b/odb/sqlite/statement.cxx @@ -24,6 +24,9 @@ namespace odb statement:: ~statement () { + if (empty ()) + return; + { odb::tracer* t; if ((t = conn_.transaction_tracer ()) || @@ -39,8 +42,50 @@ namespace odb } void statement:: - init (const char* text, std::size_t text_size) + init (const char* text, + std::size_t text_size, + statement_kind sk, + const binding* proc, + bool optimize) { + string tmp; + if (proc != 0) + { + switch (sk) + { + case statement_select: + process_select (text, + &proc->bind->buffer, proc->count, sizeof (bind), + '"', '"', + optimize, + tmp); + break; + case statement_insert: + process_insert (text, + &proc->bind->buffer, proc->count, sizeof (bind), + '?', + tmp); + break; + case statement_update: + process_update (text, + &proc->bind->buffer, proc->count, sizeof (bind), + '?', + tmp); + break; + case statement_delete: + case statement_generic: + assert (false); + } + + text = tmp.c_str (); + text_size = tmp.size (); + } + + // Empty statement. + // + if (*text == '\0') + return; + int e; sqlite3_stmt* stmt (0); while ((e = sqlite3_prepare_v2 (conn_.handle (), @@ -83,15 +128,18 @@ namespace odb // SQLite parameters are counted from 1. // - n++; - for (size_t i (1); e == SQLITE_OK && i < n; ++i, ++p) + for (size_t i (0), j (1); e == SQLITE_OK && i < n; ++i) { - const bind& b (*p); - int j (static_cast (i)); + const bind& b (p[i]); + + if (b.buffer == 0) // Skip NULL entries. + continue; + + int c (static_cast (j++)); if (b.is_null != 0 && *b.is_null) { - e = sqlite3_bind_null (stmt_, j); + e = sqlite3_bind_null (stmt_, c); continue; } @@ -100,19 +148,19 @@ namespace odb case bind::integer: { long long v (*static_cast (b.buffer)); - e = sqlite3_bind_int64 (stmt_, j, static_cast (v)); + e = sqlite3_bind_int64 (stmt_, c, static_cast (v)); break; } case bind::real: { double v (*static_cast (b.buffer)); - e = sqlite3_bind_double (stmt_, j, v); + e = sqlite3_bind_double (stmt_, c, v); break; } case bind::text: { e = sqlite3_bind_text (stmt_, - j, + c, static_cast (b.buffer), static_cast (*b.size), SQLITE_STATIC); @@ -121,7 +169,7 @@ namespace odb case bind::text16: { e = sqlite3_bind_text16 (stmt_, - j, + c, b.buffer, static_cast (*b.size), SQLITE_STATIC); @@ -130,7 +178,7 @@ namespace odb case bind::blob: { e = sqlite3_bind_blob (stmt_, - j, + c, b.buffer, static_cast (*b.size), SQLITE_STATIC); @@ -144,21 +192,20 @@ namespace odb } bool statement:: - bind_result (const bind* p, size_t n, bool truncated) + bind_result (const bind* p, size_t count, bool truncated) { - // Make sure that the number of columns in the result returned by - // the database matches the number that we expect. A common cause - // of this assertion is a native view with a number of data members - // not matching the number of columns in the SELECT-list. - // - assert (static_cast (sqlite3_data_count (stmt_)) == n); - bool r (true); + int col_count (sqlite3_data_count (stmt_)); - for (size_t i (0); i < n; ++i) + int col (0); + for (size_t i (0); i != count && col != col_count; ++i) { const bind& b (p[i]); - int j (static_cast (i)); + + if (b.buffer == 0) // Skip NULL entries. + continue; + + int c (col++); if (truncated && (b.truncated == 0 || !*b.truncated)) continue; @@ -170,7 +217,7 @@ namespace odb // if (!truncated) { - *b.is_null = sqlite3_column_type (stmt_, j) == SQLITE_NULL; + *b.is_null = sqlite3_column_type (stmt_, c) == SQLITE_NULL; if (*b.is_null) continue; @@ -181,13 +228,13 @@ namespace odb case bind::integer: { *static_cast (b.buffer) = - static_cast (sqlite3_column_int64 (stmt_, j)); + static_cast (sqlite3_column_int64 (stmt_, c)); break; } case bind::real: { *static_cast (b.buffer) = - sqlite3_column_double (stmt_, j); + sqlite3_column_double (stmt_, c); break; } case bind::text: @@ -203,15 +250,15 @@ namespace odb if (b.type != bind::text16) { d = b.type == bind::text - ? sqlite3_column_text (stmt_, j) - : sqlite3_column_blob (stmt_, j); - *b.size = static_cast (sqlite3_column_bytes (stmt_, j)); + ? sqlite3_column_text (stmt_, c) + : sqlite3_column_blob (stmt_, c); + *b.size = static_cast (sqlite3_column_bytes (stmt_, c)); } else { - d = sqlite3_column_text16 (stmt_, j); + d = sqlite3_column_text16 (stmt_, c); *b.size = static_cast ( - sqlite3_column_bytes16 (stmt_, j)); + sqlite3_column_bytes16 (stmt_, c)); } if (*b.size > b.capacity) @@ -229,6 +276,13 @@ namespace odb } } + // Make sure that the number of columns in the result returned by + // the database matches the number that we expect. A common cause + // of this assertion is a native view with a number of data members + // not matching the number of columns in the SELECT-list. + // + assert (col == col_count); + return r; } @@ -237,14 +291,18 @@ namespace odb generic_statement:: generic_statement (connection_type& conn, const string& text) - : statement (conn, text), + : statement (conn, + text, statement_generic, + 0, false), result_set_ (stmt_ ? sqlite3_column_count (stmt_) != 0: false) { } generic_statement:: generic_statement (connection_type& conn, const char* text) - : statement (conn, text), + : statement (conn, + text, statement_generic, + 0, false), result_set_ (stmt_ ? sqlite3_column_count (stmt_) != 0: false) { } @@ -253,7 +311,9 @@ namespace odb generic_statement (connection_type& conn, const char* text, std::size_t text_size) - : statement (conn, text, text_size), + : statement (conn, + text, text_size, statement_generic, + 0, false), result_set_ (stmt_ ? sqlite3_column_count (stmt_) != 0: false) { } @@ -312,32 +372,58 @@ namespace odb select_statement:: select_statement (connection_type& conn, const string& text, + bool process, + bool optimize, binding& param, binding& result) - : statement (conn, text), param_ (¶m), result_ (result) + : statement (conn, + text, statement_select, + (process ? &result : 0), optimize), + param_ (¶m), + result_ (result) { } select_statement:: select_statement (connection_type& conn, const char* text, + bool process, + bool optimize, binding& param, binding& result) - : statement (conn, text), param_ (¶m), result_ (result) + : statement (conn, + text, statement_select, + (process ? &result : 0), optimize), + param_ (¶m), + result_ (result) { } select_statement:: select_statement (connection_type& conn, const string& text, + bool process, + bool optimize, binding& result) - : statement (conn, text), param_ (0), result_ (result) + : statement (conn, + text, statement_select, + (process ? &result : 0), optimize), + param_ (0), + result_ (result) { } select_statement:: - select_statement (connection_type& conn, const char* text, binding& result) - : statement (conn, text), param_ (0), result_ (result) + select_statement (connection_type& conn, + const char* text, + bool process, + bool optimize, + binding& result) + : statement (conn, + text, statement_select, + (process ? &result : 0), optimize), + param_ (0), + result_ (result) { } @@ -428,14 +514,24 @@ namespace odb insert_statement:: insert_statement (connection_type& conn, const string& text, + bool process, binding& param) - : statement (conn, text), param_ (param) + : statement (conn, + text, statement_insert, + (process ? ¶m : 0), false), + param_ (param) { } insert_statement:: - insert_statement (connection_type& conn, const char* text, binding& param) - : statement (conn, text), param_ (param) + insert_statement (connection_type& conn, + const char* text, + bool process, + binding& param) + : statement (conn, + text, statement_insert, + (process ? ¶m : 0), false), + param_ (param) { } @@ -499,14 +595,24 @@ namespace odb update_statement:: update_statement (connection_type& conn, const string& text, + bool process, binding& param) - : statement (conn, text), param_ (param) + : statement (conn, + text, statement_update, + (process ? ¶m : 0), false), + param_ (param) { } update_statement:: - update_statement (connection_type& conn, const char* text, binding& param) - : statement (conn, text), param_ (param) + update_statement (connection_type& conn, + const char* text, + bool process, + binding& param) + : statement (conn, + text, statement_update, + (process ? ¶m : 0), false), + param_ (param) { } @@ -554,13 +660,21 @@ namespace odb delete_statement (connection_type& conn, const string& text, binding& param) - : statement (conn, text), param_ (param) + : statement (conn, + text, statement_delete, + 0, false), + param_ (param) { } delete_statement:: - delete_statement (connection_type& conn, const char* text, binding& param) - : statement (conn, text), param_ (param) + delete_statement (connection_type& conn, + const char* text, + binding& param) + : statement (conn, + text, statement_delete, + 0, false), + param_ (param) { } -- cgit v1.1