1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "sqlite_log_table_manager.h"
17 
18 namespace DistributedDB {
AddRelationalLogTableTrigger(sqlite3 * db,const TableInfo & table,const std::string & identity)19 int SqliteLogTableManager::AddRelationalLogTableTrigger(sqlite3 *db, const TableInfo &table,
20     const std::string &identity)
21 {
22     std::vector<std::string> sqls = GetDropTriggers(table);
23     std::string insertTrigger = GetInsertTrigger(table, identity);
24     if (!insertTrigger.empty()) {
25         sqls.emplace_back(insertTrigger);
26     }
27     std::string updateTrigger = GetUpdateTrigger(table, identity);
28     if (!updateTrigger.empty()) {
29         sqls.emplace_back(updateTrigger);
30     }
31     std::string deleteTrigger = GetDeleteTrigger(table, identity);
32     if (!deleteTrigger.empty()) {
33         sqls.emplace_back(deleteTrigger);
34     }
35     // add insert,update,delete trigger
36     for (const auto &sql : sqls) {
37         int errCode = SQLiteUtils::ExecuteRawSQL(db, sql);
38         if (errCode != E_OK) {
39             LOGE("[LogTableManager] execute create log trigger sql failed, errCode=%d", errCode);
40             return errCode;
41         }
42     }
43     return E_OK;
44 }
45 
CreateRelationalLogTable(sqlite3 * db,const TableInfo & table)46 int SqliteLogTableManager::CreateRelationalLogTable(sqlite3 *db, const TableInfo &table)
47 {
48     const std::string tableName = GetLogTableName(table);
49     std::string primaryKey = GetPrimaryKeySql(table);
50 
51     std::string createTableSql = "CREATE TABLE IF NOT EXISTS " + tableName + "(" \
52         "data_key    INT NOT NULL," \
53         "device      BLOB," \
54         "ori_device  BLOB," \
55         "timestamp   INT  NOT NULL," \
56         "wtimestamp  INT  NOT NULL," \
57         "flag        INT  NOT NULL," \
58         "hash_key    BLOB NOT NULL," \
59         "cloud_gid   TEXT," + \
60         "extend_field BLOB," + \
61         "cursor INT DEFAULT 0," + \
62         "version TEXT DEFAULT ''," + \
63         "sharing_resource TEXT DEFAULT ''," + \
64         "status INT DEFAULT 0," + \
65         primaryKey + ");";
66     std::vector<std::string> logTableSchema;
67     logTableSchema.emplace_back(createTableSql);
68     GetIndexSql(table, logTableSchema);
69 
70     for (const auto &sql : logTableSchema) {
71         int errCode = SQLiteUtils::ExecuteRawSQL(db, sql);
72         if (errCode != E_OK) {
73             LOGE("[LogTableManager] execute create log table schema failed, errCode=%d", errCode);
74             return errCode;
75         }
76     }
77     return E_OK;
78 }
79 
CreateKvSyncLogTable(sqlite3 * db)80 int SqliteLogTableManager::CreateKvSyncLogTable(sqlite3 *db)
81 {
82     const std::string tableName = "naturalbase_kv_aux_sync_data_log";
83     const std::string primaryKey = "PRIMARY KEY(userid, hash_key)";
84     std::string createTableSql = "CREATE TABLE IF NOT EXISTS " + tableName + "(" \
85         "userid    TEXT NOT NULL," + \
86         "hash_key  BLOB NOT NULL," + \
87         "cloud_gid TEXT," + \
88         "version   TEXT," + \
89         "cloud_flag INT DEFAULT 0," + \
90         primaryKey + ");";
91     int errCode = SQLiteUtils::ExecuteRawSQL(db, createTableSql);
92     if (errCode != E_OK) {
93         LOGE("[LogTableManager] execute create cloud log table schema failed, errCode=%d", errCode);
94         return errCode;
95     }
96     std::string createIndexSql = "CREATE INDEX IF NOT EXISTS gid_hash_key ON " + tableName + "(cloud_gid, hash_key)";
97     errCode = SQLiteUtils::ExecuteRawSQL(db, createIndexSql);
98     if (errCode != E_OK) {
99         LOGE("[LogTableManager] execute create gid index failed, errCode=%d", errCode);
100     }
101     return UpgradeKvSyncLogTable(tableName, db);
102 }
103 
GetIndexSql(const TableInfo & table,std::vector<std::string> & schema)104 void SqliteLogTableManager::GetIndexSql(const TableInfo &table, std::vector<std::string> &schema)
105 {
106     const std::string tableName = GetLogTableName(table);
107 
108     std::string indexTimestampFlag = "CREATE INDEX IF NOT EXISTS " + DBConstant::RELATIONAL_PREFIX +
109         "time_flag_index ON " + tableName + "(timestamp, flag);";
110     schema.emplace_back(indexTimestampFlag);
111 
112     std::string indexHashkey = "CREATE INDEX IF NOT EXISTS " + DBConstant::RELATIONAL_PREFIX +
113         "hashkey_index ON " + tableName + "(hash_key);";
114     schema.emplace_back(indexHashkey);
115 }
116 
GetLogTableName(const TableInfo & table) const117 std::string SqliteLogTableManager::GetLogTableName(const TableInfo &table) const
118 {
119     return DBConstant::RELATIONAL_PREFIX + table.GetTableName() + "_log";
120 }
121 
UpgradeKvSyncLogTable(const std::string & tableName,sqlite3 * db)122 int SqliteLogTableManager::UpgradeKvSyncLogTable(const std::string &tableName, sqlite3 *db)
123 {
124     TableInfo tableInfo;
125     int errCode = SQLiteUtils::AnalysisSchemaFieldDefine(db, tableName, tableInfo);
126     if (errCode != E_OK) {
127         return errCode;
128     }
129     auto fields = tableInfo.GetFields();
130     if (fields.find("cloud_flag") != fields.end()) {
131         return CreateKvCloudFlagIndex(tableName, db);
132     }
133     std::string addFlagSql = "ALTER TABLE " + tableName + " ADD COLUMN cloud_flag INT DEFAULT 0";
134     errCode = SQLiteUtils::ExecuteRawSQL(db, addFlagSql);
135     if (errCode != E_OK) {
136         LOGE("[LogTableManager] add cloud_flag failed, errCode=%d", errCode);
137         return errCode;
138     }
139     return CreateKvCloudFlagIndex(tableName, db);
140 }
141 
CreateKvCloudFlagIndex(const std::string & tableName,sqlite3 * db)142 int SqliteLogTableManager::CreateKvCloudFlagIndex(const std::string &tableName, sqlite3 *db)
143 {
144     std::string createIndexSql = "CREATE INDEX IF NOT EXISTS gid_hash_key_flag ON " + tableName +
145         "(cloud_gid, hash_key, cloud_flag)";
146     int errCode = SQLiteUtils::ExecuteRawSQL(db, createIndexSql);
147     if (errCode != E_OK) {
148         LOGE("[LogTableManager] add cloud_flag index failed, errCode=%d", errCode);
149     }
150     return errCode;
151 }
152 }