From 0884c09255bbd26504347570431f8e139670f5dd Mon Sep 17 00:00:00 2001 From: xukunrui Date: Fri, 28 Oct 2022 14:52:25 +0800 Subject: [PATCH] Fix sqlite execute sql with prepare-step Signed-off-by: xukunrui --- .../distributeddb/common/include/db_common.h | 2 + .../distributeddb/common/src/db_common.cpp | 8 ++ .../common/src/param_check_utils.cpp | 8 +- .../relational/relational_schema_object.cpp | 12 ++- .../sqlite/sqlite_multi_ver_data_storage.cpp | 10 +- .../sqlite/sqlite_multi_ver_transaction.cpp | 12 ++- .../src/sqlite/sqlite_multi_ver_transaction.h | 4 +- .../sqlite_single_ver_database_upgrader.cpp | 24 +++-- .../storage/src/sqlite/sqlite_utils.cpp | 91 +++++++++++-------- ...ibuteddb_relational_schema_object_test.cpp | 19 +++- ...stributeddb_interfaces_relational_test.cpp | 7 +- 11 files changed, 140 insertions(+), 57 deletions(-) diff --git a/services/distributeddataservice/libs/distributeddb/common/include/db_common.h b/services/distributeddataservice/libs/distributeddb/common/include/db_common.h index 338475c6..9b0347fe 100644 --- a/services/distributeddataservice/libs/distributeddb/common/include/db_common.h +++ b/services/distributeddataservice/libs/distributeddb/common/include/db_common.h @@ -60,6 +60,8 @@ public: static std::string GetDistributedTableName(const std::string &device, const std::string &tableName); static void GetDeviceFromName(const std::string &deviceTableName, std::string &deviceHash, std::string &tableName); + + static bool CheckIsAlnumAndUnderscore(const std::string &text); }; // Define short macro substitute for original long expression for convenience of using diff --git a/services/distributeddataservice/libs/distributeddb/common/src/db_common.cpp b/services/distributeddataservice/libs/distributeddb/common/src/db_common.cpp index 3e94f5ae..3444f86c 100644 --- a/services/distributeddataservice/libs/distributeddb/common/src/db_common.cpp +++ b/services/distributeddataservice/libs/distributeddb/common/src/db_common.cpp @@ -333,4 +333,12 @@ void DBCommon::GetDeviceFromName(const std::string &deviceTableName, std::string found - DBConstant::RELATIONAL_PREFIX.length()); } } + +bool DBCommon::CheckIsAlnumAndUnderscore(const std::string &text) +{ + auto iter = std::find_if_not(text.begin(), text.end(), [](char c) { + return (std::isalnum(c) || c == '_'); + }); + return iter == text.end(); +} } // namespace DistributedDB diff --git a/services/distributeddataservice/libs/distributeddb/common/src/param_check_utils.cpp b/services/distributeddataservice/libs/distributeddb/common/src/param_check_utils.cpp index 54c3b82f..07e34f37 100644 --- a/services/distributeddataservice/libs/distributeddb/common/src/param_check_utils.cpp +++ b/services/distributeddataservice/libs/distributeddb/common/src/param_check_utils.cpp @@ -15,6 +15,7 @@ #include "param_check_utils.h" +#include "db_common.h" #include "db_errno.h" #include "platform_specific.h" #include "log_print.h" @@ -202,12 +203,9 @@ uint8_t ParamCheckUtils::GetValidCompressionRate(uint8_t compressionRate) bool ParamCheckUtils::CheckRelationalTableName(const std::string &tableName) { - auto iter = std::find_if_not(tableName.begin(), tableName.end(), [](char c) { - return (std::isalnum(c) || c == '_'); - }); - if (iter != tableName.end()) { + if (!DBCommon::CheckIsAlnumAndUnderscore(tableName)) { return false; } return tableName.compare(0, DBConstant::SYSTEM_TABLE_PREFIX.size(), DBConstant::SYSTEM_TABLE_PREFIX) != 0; } -} // namespace DistributedDB \ No newline at end of file +} // namespace DistributedDB diff --git a/services/distributeddataservice/libs/distributeddb/common/src/relational/relational_schema_object.cpp b/services/distributeddataservice/libs/distributeddb/common/src/relational/relational_schema_object.cpp index c087a3a5..d10a499e 100644 --- a/services/distributeddataservice/libs/distributeddb/common/src/relational/relational_schema_object.cpp +++ b/services/distributeddataservice/libs/distributeddb/common/src/relational/relational_schema_object.cpp @@ -17,6 +17,7 @@ #include +#include "db_common.h" #include "json_object.h" #include "schema_constant.h" #include "schema_utils.h" @@ -632,6 +633,10 @@ int RelationalSchemaObject::ParseCheckTableName(const JsonObject &inJsonObject, int errCode = GetMemberFromJsonObject(inJsonObject, "NAME", FieldType::LEAF_FIELD_STRING, true, fieldValue); if (errCode == E_OK) { + if (!DBCommon::CheckIsAlnumAndUnderscore(fieldValue.stringValue)) { + LOGE("[RelationalSchema][Parse] Invalid characters in table name, err=%d.", errCode); + return -E_SCHEMA_PARSE_FAIL; + } resultTable.SetTableName(fieldValue.stringValue); } return errCode; @@ -660,6 +665,11 @@ int RelationalSchemaObject::ParseCheckTableDefine(const JsonObject &inJsonObject return errCode; } + if (!DBCommon::CheckIsAlnumAndUnderscore(field.first[1])) { + LOGE("[RelationalSchema][Parse] Invalid characters in field name, err=%d.", errCode); + return -E_SCHEMA_PARSE_FAIL; + } + FieldInfo fieldInfo; fieldInfo.SetFieldName(field.first[1]); // 1 : table name element in path errCode = ParseCheckTableFieldInfo(fieldObj, field.first, fieldInfo); @@ -755,4 +765,4 @@ int RelationalSchemaObject::ParseCheckTableIndex(const JsonObject &inJsonObject, return E_OK; } } -#endif \ No newline at end of file +#endif diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_multi_ver_data_storage.cpp b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_multi_ver_data_storage.cpp index 568ea7a6..de29a3ac 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_multi_ver_data_storage.cpp +++ b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_multi_ver_data_storage.cpp @@ -37,8 +37,10 @@ namespace { const std::string CREATE_TABLE_SQL = "CREATE TABLE IF NOT EXISTS version_data(key BLOB, value BLOB, oper_flag INTEGER, version INTEGER, " \ "timestamp INTEGER, ori_timestamp INTEGER, hash_key BLOB, " \ - "PRIMARY key(hash_key, version));" \ - "CREATE INDEX IF NOT EXISTS version_index ON version_data (version);" \ + "PRIMARY key(hash_key, version));"; + const std::string CREATE_TABLE_VERSION_INDEX_SQL = + "CREATE INDEX IF NOT EXISTS version_index ON version_data (version);"; + const std::string CREATE_TABLE_FLAG_INDEX_SQL = "CREATE INDEX IF NOT EXISTS flag_index ON version_data (oper_flag);"; const std::size_t MAX_READ_CONNECT_NUM = 16; @@ -95,6 +97,8 @@ int SQLiteMultiVerDataStorage::Open(const Property &property) DBConstant::MULTI_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; std::vector tableVect; tableVect.push_back(CREATE_TABLE_SQL); + tableVect.push_back(CREATE_TABLE_VERSION_INDEX_SQL); + tableVect.push_back(CREATE_TABLE_FLAG_INDEX_SQL); OpenDbProperties option = {uri_, property.isNeedCreate, false, tableVect, property.cipherType, property.passwd}; sqlite3 *db = nullptr; @@ -394,4 +398,4 @@ int SQLiteMultiVerDataStorage::ImportDatabase(const Property &property, const st return E_OK; } } // namespace DistributedDB -#endif \ No newline at end of file +#endif diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_multi_ver_transaction.cpp b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_multi_ver_transaction.cpp index 53712b1e..53848f6b 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_multi_ver_transaction.cpp +++ b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_multi_ver_transaction.cpp @@ -37,8 +37,12 @@ namespace DistributedDB { const std::string SQLiteMultiVerTransaction::CREATE_TABLE_SQL = "CREATE TABLE IF NOT EXISTS version_data(key BLOB, value BLOB, oper_flag INTEGER, version INTEGER, " \ "timestamp INTEGER, ori_timestamp INTEGER, hash_key BLOB, " \ - "PRIMARY key(hash_key, version));" \ - "CREATE INDEX IF NOT EXISTS version_index ON version_data (version);" \ + "PRIMARY key(hash_key, version));"; + +const std::string SQLiteMultiVerTransaction::CREATE_TABLE_VERSION_INDEX_SQL = + "CREATE INDEX IF NOT EXISTS version_index ON version_data (version);"; + +const std::string SQLiteMultiVerTransaction::CREATE_TABLE_FLAG_INDEX_SQL = "CREATE INDEX IF NOT EXISTS flag_index ON version_data (oper_flag);"; const std::string SQLiteMultiVerTransaction::SELECT_ONE_SQL = @@ -138,6 +142,8 @@ int SQLiteMultiVerTransaction::Initialize(const std::string &uri, { std::vector tableVect; tableVect.push_back(CREATE_TABLE_SQL); + tableVect.push_back(CREATE_TABLE_VERSION_INDEX_SQL); + tableVect.push_back(CREATE_TABLE_FLAG_INDEX_SQL); OpenDbProperties option = {uri, true, false, tableVect, type, passwd}; int errCode = SQLiteUtils::OpenDatabase(option, db_); if (errCode != E_OK) { @@ -1521,4 +1527,4 @@ END: return errCode; } } // namespace DistributedDB -#endif \ No newline at end of file +#endif diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_multi_ver_transaction.h b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_multi_ver_transaction.h index 72c03751..ebbc29ad 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_multi_ver_transaction.h +++ b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_multi_ver_transaction.h @@ -165,6 +165,8 @@ private: int GetPrePutValues(const Version &versionInfo, TimeStamp timestamp, std::vector &values) const; static const std::string CREATE_TABLE_SQL; + static const std::string CREATE_TABLE_VERSION_INDEX_SQL; + static const std::string CREATE_TABLE_FLAG_INDEX_SQL; static const std::string SELECT_ONE_SQL; // select the rowid static const std::string SELECT_BATCH_SQL; // select the rowid and the key static const std::string SELECT_HASH_ENTRY_SQL; // select the data according the hash key @@ -210,4 +212,4 @@ private: } // namespace DistributedDB #endif // SQLITE_MULTI_VER_TRANSACTION_H -#endif \ No newline at end of file +#endif diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_database_upgrader.cpp b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_database_upgrader.cpp index f0ff27ee..3dd7bc99 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_database_upgrader.cpp +++ b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_database_upgrader.cpp @@ -52,10 +52,16 @@ namespace { "key BLOB PRIMARY KEY NOT NULL," \ "value BLOB);"; - const std::string CREATE_SYNC_TABLE_INDEX_SQL = - "CREATE INDEX IF NOT EXISTS key_index ON sync_data (key, flag);" \ - "CREATE INDEX IF NOT EXISTS time_index ON sync_data (timestamp);" \ - "CREATE INDEX IF NOT EXISTS dev_index ON sync_data (device);" \ + const std::string CREATE_SYNC_TABLE_INDEX_SQL_KEY_INDEX = + "CREATE INDEX IF NOT EXISTS key_index ON sync_data (key, flag);"; + + const std::string CREATE_SYNC_TABLE_INDEX_SQL_TIME_INDEX = + "CREATE INDEX IF NOT EXISTS time_index ON sync_data (timestamp);"; + + const std::string CREATE_SYNC_TABLE_INDEX_SQL_DEV_INDEX = + "CREATE INDEX IF NOT EXISTS dev_index ON sync_data (device);"; + + const std::string CREATE_SYNC_TABLE_INDEX_SQL_LOCAL_HASHKEY_INDEX = "CREATE INDEX IF NOT EXISTS local_hashkey_index ON local_data (hash_key);"; const std::string DROP_META_TABLE_SQL = "DROP TABLE IF EXISTS main.meta_data;"; @@ -151,14 +157,20 @@ void SQLiteSingleVerDatabaseUpgrader::SetUpgradeSqls(int version, std::vector logTableSchema; + logTableSchema.emplace_back(createTableSql); + logTableSchema.emplace_back(timeFlagIndexSql); + logTableSchema.emplace_back(hashKeyIndexSql); + + for (const auto &sql : logTableSchema) { + int errCode = SQLiteUtils::ExecuteRawSQL(db, sql); + if (errCode != E_OK) { + LOGE("[SQLite] execute create table sql failed"); + return errCode; + } } - return errCode; + return E_OK; } namespace { @@ -1456,13 +1472,13 @@ int SQLiteUtils::CloneIndexes(sqlite3 *db, const std::string &oriTableName, cons return errCode; } - sql.clear(); + std::vector indexes; while (true) { errCode = SQLiteUtils::StepWithRetry(stmt, false); if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { std::string indexSql; (void)GetColumnTextValue(stmt, 0, indexSql); - sql += indexSql; + indexes.emplace_back(indexSql); continue; } if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { @@ -1475,9 +1491,12 @@ int SQLiteUtils::CloneIndexes(sqlite3 *db, const std::string &oriTableName, cons if (errCode != E_OK) { return errCode; } - errCode = SQLiteUtils::ExecuteRawSQL(db, sql); - if (errCode != E_OK) { - LOGE("[SQLite] execute create table sql failed"); + + for (const auto &it : indexes) { + errCode = SQLiteUtils::ExecuteRawSQL(db, it); + if (errCode != E_OK) { + LOGE("[SQLite] execute clone index sql failed"); + } } return errCode; } @@ -2127,4 +2146,4 @@ int64_t SQLiteUtils::GetLastRowId(sqlite3 *db) } return sqlite3_last_insert_rowid(db); } -} // namespace DistributedDB \ No newline at end of file +} // namespace DistributedDB diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_relational_schema_object_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_relational_schema_object_test.cpp index c26c2943..ed9a43ee 100644 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_relational_schema_object_test.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_relational_schema_object_test.cpp @@ -158,6 +158,7 @@ namespace { const std::string TABLE_DEFINE_STR_NAME = R""("NAME": "FIRST",)""; const std::string TABLE_DEFINE_STR_NAME_INVALID = R"("NAME": 123,)"; + const std::string TABLE_DEFINE_STR_NAME_INVALID_CHARACTER = R"("NAME": "t1; --",)"; const std::string TABLE_DEFINE_STR_FIELDS = R""("DEFINE": { "field_name1": { "COLUMN_ID":1, @@ -178,6 +179,12 @@ namespace { "NOT_NULL": true, "DEFAULT": "abcd" }},)""; + const std::string TABLE_DEFINE_STR_FIELDS_INVALID_CHARACTER = R""("DEFINE": { + "1 = 1; --": { + "COLUMN_ID":1, + "NOT_NULL": true, + "DEFAULT": "abcd" + }},)""; const std::string TABLE_DEFINE_STR_KEY = R""("PRIMARY_KEY": "field_name1")""; const std::string TABLE_DEFINE_STR_KEY_INVALID = R""("PRIMARY_KEY": false)""; } @@ -314,6 +321,16 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaParseTest003, errCode = schemaObj.ParseFromSchemaString(GenerateFromTableStr("[" + invalidTableStr05 + "]")); EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL); + std::string invalidTableStr07 = "{" + TABLE_DEFINE_STR_NAME_INVALID_CHARACTER + TABLE_DEFINE_STR_FIELDS + + TABLE_DEFINE_STR_KEY + "}"; + errCode = schemaObj.ParseFromSchemaString(GenerateFromTableStr("[" + invalidTableStr07 + "]")); + EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL); + + std::string invalidTableStr08 = "{" + TABLE_DEFINE_STR_NAME + TABLE_DEFINE_STR_FIELDS_INVALID_CHARACTER + + TABLE_DEFINE_STR_KEY + "}"; + errCode = schemaObj.ParseFromSchemaString(GenerateFromTableStr("[" + invalidTableStr08 + "]")); + EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL); + errCode = schemaObj.ParseFromSchemaString(""); EXPECT_EQ(errCode, -E_INVALID_ARGS); } @@ -466,4 +483,4 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, TableCompareTest001, TestSize. inTable3.AddField(field2); EXPECT_EQ(table.CompareWithTable(inTable3), -E_RELATIONAL_TABLE_EQUAL); } -#endif \ No newline at end of file +#endif diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp index 824f9be1..fb6bbb0e 100644 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp @@ -73,6 +73,8 @@ namespace { const std::string INSERT_SYNC_DATA_SQL = "INSERT OR REPLACE INTO sync_data (key, timestamp, flag, hash_key) " "VALUES('KEY', 123456789, 1, 'HASH_KEY');"; + + const std::string INVALID_TABLE_FIELD_SQL = "create table if not exists t1 ('1 = 1; --' int primary key, b blob)"; } class DistributedDBInterfacesRelationalTest : public testing::Test { @@ -314,7 +316,6 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest005, TestSize ASSERT_NE(db, nullptr); EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); EXPECT_EQ(RelationalTestUtils::ExecSql(db, NORMAL_CREATE_TABLE_SQL), SQLITE_OK); - EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); /** * @tc.steps:step2. Open store @@ -333,12 +334,16 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest005, TestSize EXPECT_EQ(delegate->CreateDistributedTable("Handle-J@^."), INVALID_ARGS); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, INVALID_TABLE_FIELD_SQL), SQLITE_OK); + EXPECT_EQ(delegate->CreateDistributedTable("t1"), NOT_SUPPORT); + /** * @tc.steps:step4. Close store * @tc.expected: step4. Return OK. */ status = g_mgr.CloseStore(delegate); EXPECT_EQ(status, OK); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); } /** -- Gitee