0
|
1 #include "gtest/gtest.h"
|
|
2
|
|
3 #include "../Core/Toolbox.h"
|
|
4 #include "../Core/SQLite/Connection.h"
|
|
5 #include "../Core/SQLite/Statement.h"
|
|
6
|
|
7 #include <sqlite3.h>
|
|
8
|
|
9 using namespace Palantir;
|
|
10
|
|
11
|
|
12 TEST(SQLite, Configuration)
|
|
13 {
|
|
14 ASSERT_EQ(1, sqlite3_threadsafe());
|
|
15 }
|
|
16
|
|
17
|
|
18 TEST(SQLite, Connection)
|
|
19 {
|
|
20 Toolbox::RemoveFile("coucou");
|
|
21 SQLite::Connection c;
|
|
22 c.Open("coucou");
|
|
23 c.Execute("CREATE TABLE c(k INTEGER PRIMARY KEY AUTOINCREMENT, v INTEGER)");
|
|
24 c.Execute("INSERT INTO c VALUES(NULL, 42);");
|
|
25 }
|
|
26
|
|
27
|
|
28 TEST(SQLite, StatementReferenceBasic)
|
|
29 {
|
|
30 sqlite3* db;
|
|
31 sqlite3_open(":memory:", &db);
|
|
32
|
|
33 {
|
|
34 SQLite::StatementReference r(db, "SELECT * FROM sqlite_master");
|
|
35 ASSERT_EQ(0u, r.GetReferenceCount());
|
|
36
|
|
37 {
|
|
38 SQLite::StatementReference r1(r);
|
|
39 ASSERT_EQ(1u, r.GetReferenceCount());
|
|
40 ASSERT_EQ(0u, r1.GetReferenceCount());
|
|
41
|
|
42 {
|
|
43 SQLite::StatementReference r2(r);
|
|
44 ASSERT_EQ(2u, r.GetReferenceCount());
|
|
45 ASSERT_EQ(0u, r1.GetReferenceCount());
|
|
46 ASSERT_EQ(0u, r2.GetReferenceCount());
|
|
47
|
|
48 SQLite::StatementReference r3(r2);
|
|
49 ASSERT_EQ(3u, r.GetReferenceCount());
|
|
50 ASSERT_EQ(0u, r1.GetReferenceCount());
|
|
51 ASSERT_EQ(0u, r2.GetReferenceCount());
|
|
52 ASSERT_EQ(0u, r3.GetReferenceCount());
|
|
53 }
|
|
54
|
|
55 ASSERT_EQ(1u, r.GetReferenceCount());
|
|
56 ASSERT_EQ(0u, r1.GetReferenceCount());
|
|
57
|
|
58 {
|
|
59 SQLite::StatementReference r2(r);
|
|
60 ASSERT_EQ(2u, r.GetReferenceCount());
|
|
61 ASSERT_EQ(0u, r1.GetReferenceCount());
|
|
62 ASSERT_EQ(0u, r2.GetReferenceCount());
|
|
63 }
|
|
64
|
|
65 ASSERT_EQ(1u, r.GetReferenceCount());
|
|
66 ASSERT_EQ(0u, r1.GetReferenceCount());
|
|
67 }
|
|
68
|
|
69 ASSERT_EQ(0u, r.GetReferenceCount());
|
|
70 }
|
|
71
|
|
72 sqlite3_close(db);
|
|
73 }
|
|
74
|
|
75 TEST(SQLite, StatementBasic)
|
|
76 {
|
|
77 SQLite::Connection c;
|
|
78 c.OpenInMemory();
|
|
79
|
|
80 SQLite::Statement s(c, "SELECT * from sqlite_master");
|
|
81 s.Run();
|
|
82
|
|
83 for (unsigned int i = 0; i < 5; i++)
|
|
84 {
|
|
85 SQLite::Statement cs(c, SQLITE_FROM_HERE, "SELECT * from sqlite_master");
|
|
86 cs.Step();
|
|
87 }
|
|
88 }
|
|
89
|
|
90
|
|
91 namespace
|
|
92 {
|
|
93 static bool destroyed;
|
|
94
|
|
95 class MyFunc : public SQLite::IScalarFunction
|
|
96 {
|
|
97 public:
|
|
98 MyFunc()
|
|
99 {
|
|
100 destroyed = false;
|
|
101 }
|
|
102
|
|
103 virtual ~MyFunc()
|
|
104 {
|
|
105 destroyed = true;
|
|
106 }
|
|
107
|
|
108 virtual const char* GetName() const
|
|
109 {
|
|
110 return "MYFUNC";
|
|
111 }
|
|
112
|
|
113 virtual unsigned int GetCardinality() const
|
|
114 {
|
|
115 return 2;
|
|
116 }
|
|
117
|
|
118 virtual void Compute(SQLite::FunctionContext& context)
|
|
119 {
|
|
120 context.SetIntResult(1000 + context.GetIntValue(0) * context.GetIntValue(1));
|
|
121 }
|
|
122 };
|
|
123
|
|
124 class MyDelete : public SQLite::IScalarFunction
|
|
125 {
|
|
126 public:
|
|
127 std::set<int> deleted_;
|
|
128
|
|
129 virtual const char* GetName() const
|
|
130 {
|
|
131 return "MYDELETE";
|
|
132 }
|
|
133
|
|
134 virtual unsigned int GetCardinality() const
|
|
135 {
|
|
136 return 1;
|
|
137 }
|
|
138
|
|
139 virtual void Compute(SQLite::FunctionContext& context)
|
|
140 {
|
|
141 deleted_.insert(context.GetIntValue(0));
|
|
142 context.SetNullResult();
|
|
143 }
|
|
144 };
|
|
145 }
|
|
146
|
|
147 TEST(SQLite, ScalarFunction)
|
|
148 {
|
|
149 {
|
|
150 SQLite::Connection c;
|
|
151 c.OpenInMemory();
|
|
152 c.Register(new MyFunc());
|
|
153 c.Execute("CREATE TABLE t(id INTEGER PRIMARY KEY, v1 INTEGER, v2 INTEGER);");
|
|
154 c.Execute("INSERT INTO t VALUES(NULL, 2, 3);");
|
|
155 c.Execute("INSERT INTO t VALUES(NULL, 4, 4);");
|
|
156 c.Execute("INSERT INTO t VALUES(NULL, 6, 5);");
|
|
157 SQLite::Statement t(c, "SELECT MYFUNC(v1, v2), v1, v2 FROM t");
|
|
158 int i = 0;
|
|
159 while (t.Step())
|
|
160 {
|
|
161 ASSERT_EQ(t.ColumnInt(0), 1000 + t.ColumnInt(1) * t.ColumnInt(2));
|
|
162 i++;
|
|
163 }
|
|
164 ASSERT_EQ(3, i);
|
|
165 ASSERT_FALSE(destroyed);
|
|
166 }
|
|
167 ASSERT_TRUE(destroyed);
|
|
168 }
|
|
169
|
|
170 TEST(SQLite, CascadedDeleteCallback)
|
|
171 {
|
|
172 SQLite::Connection c;
|
|
173 c.OpenInMemory();
|
|
174 MyDelete *func = new MyDelete();
|
|
175 c.Register(func);
|
|
176 c.Execute("CREATE TABLE parent(id INTEGER PRIMARY KEY, dummy INTEGER);");
|
|
177 c.Execute("CREATE TABLE child("
|
|
178 " id INTEGER PRIMARY KEY, "
|
|
179 " parent INTEGER REFERENCES parent(id) ON DELETE CASCADE, "
|
|
180 " value INTEGER);");
|
|
181 c.Execute("CREATE TRIGGER childRemoved "
|
|
182 "AFTER DELETE ON child "
|
|
183 "FOR EACH ROW BEGIN "
|
|
184 " SELECT MYDELETE(old.value); "
|
|
185 "END;");
|
|
186
|
|
187 c.Execute("INSERT INTO parent VALUES(42, 100);");
|
|
188 c.Execute("INSERT INTO parent VALUES(43, 101);");
|
|
189
|
|
190 c.Execute("INSERT INTO child VALUES(NULL, 42, 4200);");
|
|
191 c.Execute("INSERT INTO child VALUES(NULL, 42, 4201);");
|
|
192
|
|
193 c.Execute("INSERT INTO child VALUES(NULL, 43, 4300);");
|
|
194 c.Execute("INSERT INTO child VALUES(NULL, 43, 4301);");
|
|
195
|
|
196 // The following command deletes "parent(43, 101)", then in turns
|
|
197 // "child(NULL, 43, 4300/4301)", then calls the MyDelete on 4300 and
|
|
198 // 4301
|
|
199 c.Execute("DELETE FROM parent WHERE dummy=101");
|
|
200
|
|
201 ASSERT_EQ(2u, func->deleted_.size());
|
|
202 ASSERT_TRUE(func->deleted_.find(4300) != func->deleted_.end());
|
|
203 ASSERT_TRUE(func->deleted_.find(4301) != func->deleted_.end());
|
|
204 }
|