1 /*
2 * Copyright (c) 2021 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 <gtest/gtest.h>
17
18 #include <string>
19
20 #include "common.h"
21 #include "rdb_errno.h"
22 #include "rdb_helper.h"
23 #include "rdb_open_callback.h"
24
25 using namespace testing::ext;
26 using namespace OHOS::NativeRdb;
27
28 class RdbAttachTest : public testing::Test {
29 public:
30 static void SetUpTestCase(void);
31 static void TearDownTestCase(void);
32 void SetUp();
33 void TearDown();
34 void QueryCheck1(std::shared_ptr<RdbStore> &store) const;
35 void QueryCheck2(std::shared_ptr<RdbStore> &store) const;
36
37 static const std::string MAIN_DATABASE_NAME;
38 static const std::string ATTACHED_DATABASE_NAME;
39 };
40
41 const std::string RdbAttachTest::MAIN_DATABASE_NAME = RDB_TEST_PATH + "main.db";
42
43 class MainOpenCallback : public RdbOpenCallback {
44 public:
45 int OnCreate(RdbStore &store) override;
46 int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override;
47 static const std::string CREATE_TABLE_TEST;
48 };
49
50 std::string const MainOpenCallback::CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test1(id INTEGER PRIMARY KEY "
51 "AUTOINCREMENT, name TEXT NOT NULL)";
52
OnCreate(RdbStore & store)53 int MainOpenCallback::OnCreate(RdbStore &store)
54 {
55 return store.ExecuteSql(CREATE_TABLE_TEST);
56 }
57
OnUpgrade(RdbStore & store,int oldVersion,int newVersion)58 int MainOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion)
59 {
60 return E_OK;
61 }
62
63 const std::string RdbAttachTest::ATTACHED_DATABASE_NAME = RDB_TEST_PATH + "attached.db";
64
65 class AttachedOpenCallback : public RdbOpenCallback {
66 public:
67 int OnCreate(RdbStore &store) override;
68 int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override;
69 static const std::string CREATE_TABLE_TEST;
70 };
71
72 std::string const AttachedOpenCallback::CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test2(id INTEGER PRIMARY KEY "
73 "AUTOINCREMENT, name TEXT NOT NULL)";
74
OnCreate(RdbStore & store)75 int AttachedOpenCallback::OnCreate(RdbStore &store)
76 {
77 return store.ExecuteSql(CREATE_TABLE_TEST);
78 }
79
OnUpgrade(RdbStore & store,int oldVersion,int newVersion)80 int AttachedOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion)
81 {
82 return E_OK;
83 }
84
SetUpTestCase(void)85 void RdbAttachTest::SetUpTestCase(void)
86 {
87 RdbStoreConfig attachedConfig(RdbAttachTest::ATTACHED_DATABASE_NAME);
88 AttachedOpenCallback attachedHelper;
89 int errCode = E_OK;
90 std::shared_ptr<RdbStore> attachedStore = RdbHelper::GetRdbStore(attachedConfig, 1, attachedHelper, errCode);
91 EXPECT_NE(attachedStore, nullptr);
92 }
93
TearDownTestCase(void)94 void RdbAttachTest::TearDownTestCase(void)
95 {
96 RdbHelper::DeleteRdbStore(MAIN_DATABASE_NAME);
97 RdbHelper::DeleteRdbStore(ATTACHED_DATABASE_NAME);
98 }
99
SetUp(void)100 void RdbAttachTest::SetUp(void)
101 {
102 }
103
TearDown(void)104 void RdbAttachTest::TearDown(void)
105 {
106 RdbHelper::ClearCache();
107 }
108
109 /**
110 * @tc.name: RdbStore_Attach_001
111 * @tc.desc: test attach, attach is not supported in wal mode
112 * @tc.type: FUNC
113 */
114 HWTEST_F(RdbAttachTest, RdbStore_Attach_001, TestSize.Level1)
115 {
116 RdbStoreConfig config(RdbAttachTest::MAIN_DATABASE_NAME);
117 MainOpenCallback helper;
118 int errCode = E_OK;
119 std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
120 EXPECT_NE(store, nullptr);
121
122 int ret = store->ExecuteSql("ATTACH '" + ATTACHED_DATABASE_NAME + "' as attached");
123 EXPECT_EQ(ret, E_NOT_SUPPORTED_ATTACH_IN_WAL_MODE);
124 }
125
126 /**
127 * @tc.name: RdbStore_Attach_002
128 * @tc.desc: test RdbStore attach
129 * @tc.type: FUNC
130 */
131 HWTEST_F(RdbAttachTest, RdbStore_Attach_002, TestSize.Level1)
132 {
133 RdbStoreConfig config(RdbAttachTest::MAIN_DATABASE_NAME);
134 config.SetJournalMode(JournalMode::MODE_TRUNCATE);
135 MainOpenCallback helper;
136 int errCode = E_OK;
137 std::shared_ptr<RdbStore> store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
138 EXPECT_NE(store, nullptr);
139
140 int ret = store->ExecuteSql("ATTACH DATABASE '" + ATTACHED_DATABASE_NAME + "' as 'attached'");
141 EXPECT_EQ(ret, E_OK);
142
143 int64_t id;
144 ValuesBucket values;
145 values.PutInt("id", 1);
146 values.PutString("name", std::string("zhangsan"));
147 ret = store->Insert(id, "test1", values);
148 EXPECT_EQ(ret, E_OK);
149 EXPECT_EQ(id, 1);
150
151 values.Clear();
152 values.PutInt("id", 1);
153 values.PutString("name", std::string("lisi"));
154 ret = store->Insert(id, "test2", values);
155 EXPECT_EQ(ret, E_OK);
156 EXPECT_EQ(id, 1);
157
158 QueryCheck1(store);
159
160 ret = store->ExecuteSql("DETACH DATABASE 'attached'");
161 EXPECT_EQ(ret, E_OK);
162
163 QueryCheck2(store);
164
165 ret = store->ExecuteSql("attach database '" + ATTACHED_DATABASE_NAME + "' as 'attached'");
166 EXPECT_EQ(ret, E_OK);
167
168 ret = store->ExecuteSql("detach database 'attached'");
169 EXPECT_EQ(ret, E_OK);
170 }
171
QueryCheck1(std::shared_ptr<RdbStore> & store) const172 void RdbAttachTest::QueryCheck1(std::shared_ptr<RdbStore> &store) const
173 {
174 std::shared_ptr<ResultSet> resultSet = store->QuerySql("SELECT * FROM test1");
175 EXPECT_NE(resultSet, nullptr);
176 int ret = resultSet->GoToNextRow();
177 EXPECT_EQ(ret, E_OK);
178 int columnIndex;
179 int intVal;
180 ret = resultSet->GetColumnIndex("id", columnIndex);
181 EXPECT_EQ(ret, E_OK);
182 ret = resultSet->GetInt(columnIndex, intVal);
183 EXPECT_EQ(ret, E_OK);
184 EXPECT_EQ(intVal, 1);
185 std::string strVal;
186 ret = resultSet->GetColumnIndex("name", columnIndex);
187 EXPECT_EQ(ret, E_OK);
188 ret = resultSet->GetString(columnIndex, strVal);
189 EXPECT_EQ(ret, E_OK);
190 EXPECT_EQ(strVal, "zhangsan");
191
192 resultSet = store->QuerySql("SELECT * FROM test2");
193 EXPECT_NE(resultSet, nullptr);
194 ret = resultSet->GoToNextRow();
195 EXPECT_EQ(ret, E_OK);
196 ret = resultSet->GetColumnIndex("id", columnIndex);
197 EXPECT_EQ(ret, E_OK);
198 ret = resultSet->GetInt(columnIndex, intVal);
199 EXPECT_EQ(ret, E_OK);
200 EXPECT_EQ(intVal, 1);
201 ret = resultSet->GetColumnIndex("name", columnIndex);
202 EXPECT_EQ(ret, E_OK);
203 ret = resultSet->GetString(columnIndex, strVal);
204 EXPECT_EQ(ret, E_OK);
205 EXPECT_EQ(strVal, "lisi");
206 }
207
QueryCheck2(std::shared_ptr<RdbStore> & store) const208 void RdbAttachTest::QueryCheck2(std::shared_ptr<RdbStore> &store) const
209 {
210 std::shared_ptr<ResultSet> resultSet = store->QuerySql("SELECT * FROM test1");
211 EXPECT_NE(resultSet, nullptr);
212 int ret = resultSet->GoToNextRow();
213 EXPECT_EQ(ret, E_OK);
214 int columnIndex;
215 int intVal;
216 ret = resultSet->GetColumnIndex("id", columnIndex);
217 EXPECT_EQ(ret, E_OK);
218 ret = resultSet->GetInt(columnIndex, intVal);
219 EXPECT_EQ(ret, E_OK);
220 EXPECT_EQ(intVal, 1);
221 std::string strVal;
222 ret = resultSet->GetColumnIndex("name", columnIndex);
223 EXPECT_EQ(ret, E_OK);
224 ret = resultSet->GetString(columnIndex, strVal);
225 EXPECT_EQ(ret, E_OK);
226 EXPECT_EQ(strVal, "zhangsan");
227
228 // detached, no table test2
229 resultSet = store->QuerySql("SELECT * FROM test2");
230 EXPECT_NE(resultSet, nullptr);
231 }