1 /*
2 * Copyright (c) 2023 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 "cloud/cloud_storage_utils.h"
17 #include "simple_tracker_log_table_manager.h"
18
19 namespace DistributedDB {
20
CalcPrimaryKeyHash(const std::string & references,const TableInfo & table,const std::string & identity)21 std::string SimpleTrackerLogTableManager::CalcPrimaryKeyHash(const std::string &references, const TableInfo &table,
22 const std::string &identity)
23 {
24 (void)identity;
25 std::string sql;
26 if (table.GetPrimaryKey().size() == 1) {
27 sql = "calc_hash(" + references + "'" + table.GetPrimaryKey().at(0) + "', 0)";
28 } else {
29 sql = "calc_hash(";
30 for (const auto &it : table.GetPrimaryKey()) {
31 sql += "calc_hash(" + references + "'" + it.second + "', 0)||";
32 }
33 sql.pop_back();
34 sql.pop_back();
35 sql += ", 0)";
36 }
37 return sql;
38 }
39
GetIndexSql(const TableInfo & table,std::vector<std::string> & schema)40 void SimpleTrackerLogTableManager::GetIndexSql(const TableInfo &table, std::vector<std::string> &schema)
41 {
42 const std::string tableName = GetLogTableName(table);
43
44 std::string indexCursor = "CREATE INDEX IF NOT EXISTS " + tableName +
45 "_cursor_index ON " + tableName + "(cursor);";
46 std::string indexDataKey = "CREATE INDEX IF NOT EXISTS " + tableName +
47 "_data_key_index ON " + tableName + "(data_key);";
48 schema.emplace_back(indexCursor);
49 schema.emplace_back(indexDataKey);
50 }
51
GetPrimaryKeySql(const TableInfo & table)52 std::string SimpleTrackerLogTableManager::GetPrimaryKeySql(const TableInfo &table)
53 {
54 return "PRIMARY KEY(hash_key)";
55 }
56
57 // The parameter "identity" is a hash string that identifies a device. The same for the next two functions.
GetInsertTrigger(const TableInfo & table,const std::string & identity)58 std::string SimpleTrackerLogTableManager::GetInsertTrigger(const TableInfo &table, const std::string &identity)
59 {
60 if (table.GetTrackerTable().GetTrackerColNames().empty()) {
61 return "";
62 }
63 std::string logTblName = GetLogTableName(table);
64 std::string tableName = table.GetTableName();
65 std::string insertTrigger = "CREATE TRIGGER IF NOT EXISTS ";
66 insertTrigger += "naturalbase_rdb_" + tableName + "_ON_INSERT AFTER INSERT \n";
67 insertTrigger += "ON '" + tableName + "'\n";
68 insertTrigger += " FOR EACH ROW \n";
69 insertTrigger += "BEGIN\n";
70 insertTrigger += CloudStorageUtils::GetCursorIncSql(tableName) + "\n";
71 insertTrigger += "\t INSERT OR REPLACE INTO " + logTblName;
72 insertTrigger += " (data_key, device, ori_device, timestamp, wtimestamp, flag, hash_key, cloud_gid";
73 insertTrigger += ", extend_field, cursor, version, sharing_resource, status)";
74 insertTrigger += " VALUES (new." + std::string(DBConstant::SQLITE_INNER_ROWID) + ", '', '',";
75 insertTrigger += " get_raw_sys_time(), get_raw_sys_time(), 0x02, ";
76 insertTrigger += CalcPrimaryKeyHash("NEW.", table, identity) + ", '', ";
77 insertTrigger += table.GetTrackerTable().GetAssignValSql();
78 insertTrigger += ", " + CloudStorageUtils::GetSelectIncCursorSql(tableName) + ", '', '', 0);\n";
79 insertTrigger += "SELECT client_observer('" + tableName + "', NEW._rowid_, 0, ";
80 insertTrigger += table.GetTrackerTable().GetTrackerColNames().empty() ? "0" : "1";
81 insertTrigger += ");\n";
82 insertTrigger += "END;";
83 return insertTrigger;
84 }
85
GetUpdateTrigger(const TableInfo & table,const std::string & identity)86 std::string SimpleTrackerLogTableManager::GetUpdateTrigger(const TableInfo &table, const std::string &identity)
87 {
88 if (table.GetTrackerTable().GetTrackerColNames().empty()) {
89 return "";
90 }
91 (void)identity;
92 std::string logTblName = GetLogTableName(table);
93 std::string tableName = table.GetTableName();
94 std::string updateTrigger = "CREATE TRIGGER IF NOT EXISTS ";
95 updateTrigger += "naturalbase_rdb_" + tableName + "_ON_UPDATE AFTER UPDATE \n";
96 updateTrigger += "ON '" + tableName + "'\n";
97 updateTrigger += " FOR EACH ROW ";
98 updateTrigger += "BEGIN\n"; // if user change the primary key, we can still use gid to identify which one is updated
99 updateTrigger += CloudStorageUtils::GetCursorIncSql(tableName);
100 updateTrigger.pop_back();
101 updateTrigger += " AND " + table.GetTrackerTable().GetDiffTrackerValSql() + ";";
102 updateTrigger += "\t UPDATE " + logTblName;
103 updateTrigger += " SET timestamp=get_raw_sys_time(), device='', flag=0x02";
104 updateTrigger += table.GetTrackerTable().GetExtendAssignValSql();
105 updateTrigger += table.GetTrackerTable().GetDiffIncCursorSql(tableName);
106 updateTrigger += " WHERE data_key = OLD." + std::string(DBConstant::SQLITE_INNER_ROWID) + ";\n";
107 updateTrigger += "SELECT client_observer('" + tableName + "', OLD." + std::string(DBConstant::SQLITE_INNER_ROWID);
108 updateTrigger += ", 1, ";
109 updateTrigger += table.GetTrackerTable().GetDiffTrackerValSql();
110 updateTrigger += ");";
111 updateTrigger += "END;";
112 return updateTrigger;
113 }
114
GetDeleteTrigger(const TableInfo & table,const std::string & identity)115 std::string SimpleTrackerLogTableManager::GetDeleteTrigger(const TableInfo &table, const std::string &identity)
116 {
117 if (table.GetTrackerTable().GetTrackerColNames().empty()) {
118 return "";
119 }
120 (void)identity;
121 std::string tableName = table.GetTableName();
122 std::string deleteTrigger = "CREATE TRIGGER IF NOT EXISTS ";
123 deleteTrigger += "naturalbase_rdb_" + tableName + "_ON_DELETE BEFORE DELETE \n";
124 deleteTrigger += "ON '" + tableName + "'\n";
125 deleteTrigger += " FOR EACH ROW \n";
126 deleteTrigger += "BEGIN\n";
127 deleteTrigger += CloudStorageUtils::GetCursorIncSql(tableName) + "\n";
128 deleteTrigger += "\t UPDATE " + GetLogTableName(table);
129 deleteTrigger += " SET data_key=-1,flag=0x03,timestamp=get_raw_sys_time()";
130 deleteTrigger += table.GetTrackerTable().GetExtendAssignValSql(true);
131 deleteTrigger += ", cursor=" + CloudStorageUtils::GetSelectIncCursorSql(tableName) + "";
132 deleteTrigger += " WHERE data_key = OLD." + std::string(DBConstant::SQLITE_INNER_ROWID) + ";";
133 // -1 is rowid when data is deleted, 2 means change type is delete(ClientChangeType)
134 deleteTrigger += "SELECT client_observer('" + tableName + "', -1, 2, ";
135 deleteTrigger += table.GetTrackerTable().GetTrackerColNames().empty() ? "0" : "1";
136 deleteTrigger += ");\n";
137 deleteTrigger += "END;";
138 return deleteTrigger;
139 }
140
GetDropTriggers(const TableInfo & table)141 std::vector<std::string> SimpleTrackerLogTableManager::GetDropTriggers(const TableInfo &table)
142 {
143 std::vector<std::string> dropTriggers;
144 std::string tableName = table.GetTableName();
145 std::string insertTrigger = "DROP TRIGGER IF EXISTS naturalbase_rdb_" + tableName + "_ON_INSERT; ";
146 std::string updateTrigger = "DROP TRIGGER IF EXISTS naturalbase_rdb_" + tableName + "_ON_UPDATE; ";
147 std::string deleteTrigger = "DROP TRIGGER IF EXISTS naturalbase_rdb_" + tableName + "_ON_DELETE; ";
148 dropTriggers.emplace_back(insertTrigger);
149 dropTriggers.emplace_back(updateTrigger);
150 dropTriggers.emplace_back(deleteTrigger);
151 if (table.GetTrackerTable().GetTrackerColNames().empty()) {
152 std::string deleteLogTable = "DROP TABLE IF EXISTS " + GetLogTableName(table) + ";";
153 dropTriggers.emplace_back(deleteLogTable);
154 }
155 return dropTriggers;
156 }
157 }