diff --git a/.gitignore b/.gitignore index 0335c15d..68c7968f 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ __pycache__/ build/ **/*.avf **/*.db +.cursor/ diff --git a/include/simdb/sqlite/DatabaseManager.hpp b/include/simdb/sqlite/DatabaseManager.hpp index 011c82ad..a70f9d47 100644 --- a/include/simdb/sqlite/DatabaseManager.hpp +++ b/include/simdb/sqlite/DatabaseManager.hpp @@ -155,6 +155,25 @@ class DatabaseManager return INSERT_(std::move(table), std::move(cols), std::move(vals)); } + /// \brief INSERT into a table with values for all columns, in schema order. + /// Equivalent to INSERT(table, SQL_COLUMNS(...), vals) with every + /// column of the table. The number and order of values must match + /// the table's columns. + std::unique_ptr INSERT(SqlTable&& table, SqlValues&& vals) + { + if (table.getName().find("internal$") == 0) + { + throw DBException("Cannot perform INSERT. This is an internal table."); + } + std::vector col_names; + for (const auto& col : schema_.getTable(table.getName()).getColumns()) + { + col_names.push_back(col->getName()); + } + SqlColumns cols(col_names); + return INSERT_(std::move(table), std::move(cols), std::move(vals)); + } + /// This INSERT() overload is to be used for tables that were defined with /// at least one default value for its column(s). std::unique_ptr INSERT(SqlTable&& table) @@ -177,6 +196,24 @@ class DatabaseManager return prepareINSERT_(std::move(table), std::move(cols)); } + /// \brief Create a prepared statement for inserting into all columns of a table. + /// Equivalent to prepareINSERT(table, SQL_COLUMNS(...)) with every column + /// of the table, in schema order. + std::unique_ptr prepareINSERT(SqlTable&& table) + { + if (table.getName().find("internal$") == 0) + { + throw DBException("Cannot perform INSERT. This is an internal table."); + } + std::vector col_names; + for (const auto& col : schema_.getTable(table.getName()).getColumns()) + { + col_names.push_back(col->getName()); + } + SqlColumns cols(col_names); + return prepareINSERT_(std::move(table), std::move(cols)); + } + /// \brief Execute an arbitrary SQL command on this database. void EXECUTE(const std::string& sql_cmd, bool in_transaction = true) { diff --git a/test/sqlite/Insert/main.cpp b/test/sqlite/Insert/main.cpp index f6b384c0..fbe2fe70 100644 --- a/test/sqlite/Insert/main.cpp +++ b/test/sqlite/Insert/main.cpp @@ -32,6 +32,15 @@ int main() record1->setPropertyInt64("SomeInt64", TEST_INT64 / 2); EXPECT_EQUAL(record1->getPropertyInt64("SomeInt64"), TEST_INT64 / 2); + // Verify INSERT(table, SQL_VALUES(...)) overload: all columns in schema order, no SQL_COLUMNS. + auto record_all_cols = db_mgr.INSERT( + SQL_TABLE("AllIntegerTypes"), + SQL_VALUES(TEST_INT32, TEST_INT64, static_cast(TEST_INT32), static_cast(TEST_INT64))); + EXPECT_EQUAL(record_all_cols->getPropertyInt32("SomeInt32"), TEST_INT32); + EXPECT_EQUAL(record_all_cols->getPropertyInt64("SomeInt64"), TEST_INT64); + EXPECT_EQUAL(record_all_cols->getPropertyUInt32("SomeUInt32"), static_cast(TEST_INT32)); + EXPECT_EQUAL(record_all_cols->getPropertyUInt64("SomeUInt64"), static_cast(TEST_INT64)); + // Verify INSERT for floating-point types auto record2 = db_mgr.INSERT( SQL_TABLE("FloatingPointTypes"), @@ -154,11 +163,26 @@ int main() EXPECT_EQUAL(high_volume_record2->getPropertyUInt32("EndTick"), UINT32_MAX); EXPECT_EQUAL(high_volume_record2->getPropertyBlob("DataBlob"), data_vec); + // Verify prepareINSERT(SqlTable) overload: all columns from schema, no SQL_COLUMNS. + auto all_cols_insert = db_mgr.prepareINSERT(SQL_TABLE("AllIntegerTypes")); + all_cols_insert->setColumnValue(0, TEST_INT32); + all_cols_insert->setColumnValue(1, TEST_INT64); + all_cols_insert->setColumnValue(2, static_cast(TEST_INT32)); + all_cols_insert->setColumnValue(3, static_cast(TEST_INT64)); + auto all_cols_id = all_cols_insert->createRecord(); + auto all_cols_record = db_mgr.findRecord("AllIntegerTypes", all_cols_id); + EXPECT_EQUAL(all_cols_record->getPropertyInt32("SomeInt32"), TEST_INT32); + EXPECT_EQUAL(all_cols_record->getPropertyInt64("SomeInt64"), TEST_INT64); + EXPECT_EQUAL(all_cols_record->getPropertyUInt32("SomeUInt32"), static_cast(TEST_INT32)); + EXPECT_EQUAL(all_cols_record->getPropertyUInt64("SomeUInt64"), static_cast(TEST_INT64)); + // Verify that we cannot write to an internal table. EXPECT_TRUE(db_mgr.getSchema().hasTable("internal$SchemaTables")); EXPECT_THROW(db_mgr.INSERT(SQL_TABLE("internal$SchemaTables"))); EXPECT_THROW(db_mgr.INSERT(SQL_TABLE("internal$SchemaTables"), SQL_COLUMNS("TableName"), SQL_VALUES("blah"))); + EXPECT_THROW(db_mgr.INSERT(SQL_TABLE("internal$SchemaTables"), SQL_VALUES("x", "y", "z"))); EXPECT_THROW(db_mgr.prepareINSERT(SQL_TABLE("internal$SchemaTables"), SQL_COLUMNS("TableName"))); + EXPECT_THROW(db_mgr.prepareINSERT(SQL_TABLE("internal$SchemaTables"))); EXPECT_THROW(db_mgr.EXECUTE("INSERT INTO internal$SchemaTables (TableName) VALUES (\"blah\")")); REPORT_ERROR;