Line data Source code
1 : /**
2 : Copyright (c) 2024 Stappler LLC <admin@stappler.dev>
3 :
4 : Permission is hereby granted, free of charge, to any person obtaining a copy
5 : of this software and associated documentation files (the "Software"), to deal
6 : in the Software without restriction, including without limitation the rights
7 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 : copies of the Software, and to permit persons to whom the Software is
9 : furnished to do so, subject to the following conditions:
10 :
11 : The above copyright notice and this permission notice shall be included in
12 : all copies or substantial portions of the Software.
13 :
14 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 : THE SOFTWARE.
21 : **/
22 :
23 : #include "SPSqliteDriver.h"
24 : #include "sqlite3.h"
25 :
26 : namespace STAPPLER_VERSIONIZED stappler::db::sqlite {
27 :
28 : static constexpr auto UNWRAP_VALUE = 0;
29 : static constexpr auto UNWRAP_INPUT = 0;
30 :
31 : struct UnwrapCursor {
32 : sqlite3_vtab_cursor base;
33 : BytesView origValue;
34 : BytesView currentValue;
35 : Value value;
36 : size_t current = 0;
37 : };
38 :
39 : static sqlite3_module s_UnwrapModule = {
40 : .iVersion = 4,
41 : .xCreate = nullptr, // [] (sqlite3*, void *pAux, int argc, const char *const* argv, sqlite3_vtab **ppVTab, char**) -> int { },
42 50 : .xConnect = [] (sqlite3 *db, void *pAux, int argc, const char * const* argv, sqlite3_vtab **ppVTab, char**) -> int {
43 : sqlite3_vtab *pNew;
44 : int rc;
45 :
46 50 : rc = sqlite3_declare_vtab(db, "CREATE TABLE x(__unwrap_value, input HIDDEN)");
47 50 : if (rc == SQLITE_OK) {
48 50 : pNew = *ppVTab = (sqlite3_vtab *)sqlite3_malloc(sizeof(*pNew));
49 50 : if (pNew == 0) {
50 0 : return SQLITE_NOMEM;
51 : }
52 50 : memset(pNew, 0, sizeof(*pNew));
53 : }
54 50 : return rc;
55 : },
56 350 : .xBestIndex = [] (sqlite3_vtab *pVTab, sqlite3_index_info *pIdxInfo) -> int {
57 350 : int unusableMask = 0;
58 350 : int inputIndex = -1;
59 350 : int idxMask = 0;
60 350 : auto pConstraint = pIdxInfo->aConstraint;
61 950 : for (int i = 0; i < pIdxInfo->nConstraint; i++, pConstraint++) {
62 : int iCol;
63 : int iMask;
64 600 : if (pConstraint->iColumn < UNWRAP_INPUT)
65 0 : continue;
66 600 : iCol = pConstraint->iColumn - UNWRAP_INPUT;
67 600 : iMask = 1 << iCol;
68 600 : if (pConstraint->usable == 0) {
69 175 : unusableMask |= iMask;
70 425 : } else if (pConstraint->op == SQLITE_INDEX_CONSTRAINT_EQ) {
71 425 : inputIndex = i;
72 425 : idxMask |= iMask;
73 : }
74 : }
75 :
76 350 : if (pIdxInfo->nOrderBy > 0 && pIdxInfo->aOrderBy[0].iColumn < 0 && pIdxInfo->aOrderBy[0].desc == 0) {
77 0 : pIdxInfo->orderByConsumed = 1;
78 : }
79 :
80 350 : if ((unusableMask & ~idxMask) != 0) {
81 : /* If there are any unusable constraints, then reject
82 : ** this entire plan */
83 175 : return SQLITE_CONSTRAINT;
84 : }
85 :
86 175 : if (inputIndex < 0) {
87 : /* No input */
88 0 : pIdxInfo->idxNum = 0;
89 : } else {
90 175 : pIdxInfo->estimatedCost = 1.0;
91 175 : pIdxInfo->aConstraintUsage[inputIndex].argvIndex = 1;
92 175 : pIdxInfo->aConstraintUsage[inputIndex].omit = 1;
93 175 : pIdxInfo->idxNum = 1; /* Only JSON supplied. Plan 1 */
94 : }
95 175 : return SQLITE_OK;
96 : },
97 50 : .xDisconnect = [] (sqlite3_vtab *pVTab) -> int {
98 50 : sqlite3_free(pVTab);
99 50 : return SQLITE_OK;
100 : },
101 : .xDestroy = nullptr, // [] (sqlite3_vtab *pVTab) -> int { },
102 175 : .xOpen = [] (sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor) -> int {
103 : UnwrapCursor *pCur;
104 175 : pCur = (UnwrapCursor *)sqlite3_malloc(sizeof(*pCur));
105 175 : if (pCur == 0) {
106 0 : return SQLITE_NOMEM;
107 : }
108 175 : memset(pCur, 0, sizeof(*pCur));
109 175 : *ppCursor = &pCur->base;
110 175 : return SQLITE_OK;
111 : },
112 175 : .xClose = [] (sqlite3_vtab_cursor *cur) -> int {
113 175 : UnwrapCursor *p = (UnwrapCursor*)cur;
114 175 : p->~UnwrapCursor();
115 175 : sqlite3_free(cur);
116 175 : return SQLITE_OK;
117 : },
118 225 : .xFilter = [] (sqlite3_vtab_cursor *cur, int idxNum, const char *idxStr, int argc, sqlite3_value **argv) -> int {
119 225 : UnwrapCursor *p = (UnwrapCursor*)cur;
120 225 : p->origValue = p->currentValue = BytesView((const uint8_t *)sqlite3_value_blob(argv[0]), sqlite3_value_bytes(argv[0]));
121 225 : p->value = data::read<Interface>(p->origValue);
122 225 : p->current = 0;
123 225 : if (p->value.isArray() || p->value.empty()) {
124 225 : return SQLITE_OK;
125 : }
126 0 : p->value = Value();
127 0 : return SQLITE_MISMATCH;
128 : },
129 400 : .xNext = [] (sqlite3_vtab_cursor *cur) -> int {
130 400 : UnwrapCursor *p = (UnwrapCursor*)cur;
131 400 : ++ p->current;
132 400 : return SQLITE_OK;
133 : },
134 625 : .xEof = [] (sqlite3_vtab_cursor *cur) -> int {
135 625 : UnwrapCursor *p = (UnwrapCursor*)cur;
136 625 : if (p->value.empty() || p->current == p->value.size()) {
137 200 : return 1;
138 : }
139 425 : return 0;
140 : },
141 500 : .xColumn = [] (sqlite3_vtab_cursor *cur, sqlite3_context *db, int col) -> int {
142 500 : UnwrapCursor *p = (UnwrapCursor*)cur;
143 :
144 500 : auto &val = p->value.getValue(p->current);
145 500 : switch (val.getType()) {
146 0 : case Value::Type::INTEGER:
147 0 : sqlite3_result_int64(db, val.getInteger());
148 0 : break;
149 0 : case Value::Type::DOUBLE:
150 0 : sqlite3_result_double(db, val.getDouble());
151 0 : break;
152 0 : case Value::Type::BOOLEAN:
153 0 : sqlite3_result_int(db, val.getBool() ? 1 : 0);
154 0 : break;
155 500 : case Value::Type::CHARSTRING:
156 500 : sqlite3_result_text64(db, val.getString().data(), val.getString().size(), nullptr, SQLITE_UTF8);
157 500 : break;
158 0 : case Value::Type::BYTESTRING:
159 0 : sqlite3_result_blob64(db, val.getBytes().data(), val.getBytes().size(), nullptr);
160 0 : break;
161 0 : default:
162 0 : sqlite3_result_null(db);
163 0 : break;
164 : }
165 500 : return SQLITE_OK;
166 : },
167 0 : .xRowid = [] (sqlite3_vtab_cursor *cur, sqlite3_int64 *pRowid) -> int {
168 0 : UnwrapCursor *p = (UnwrapCursor*) cur;
169 0 : *pRowid = p->current;
170 0 : return SQLITE_OK;
171 : },
172 : .xUpdate = nullptr, // [] (sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *) -> int { },
173 : .xBegin = nullptr, // [] (sqlite3_vtab *pVTab) -> int { },
174 : .xSync = nullptr, // [] (sqlite3_vtab *pVTab) -> int { },
175 : .xCommit = nullptr, // [] (sqlite3_vtab *pVTab) -> int { },
176 : .xRollback = nullptr, // [] (sqlite3_vtab *pVTab) -> int { },
177 : .xFindFunction = nullptr, // [] (sqlite3_vtab *pVtab, int nArg, const char *zName,
178 : // void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), void **ppArg) -> int { },
179 : .xRename = nullptr, // [] (sqlite3_vtab *pVtab, const char *zNew) -> int { },
180 : /* The methods above are in version 1 of the sqlite_module object. Those
181 : ** below are for version 2 and greater. */
182 : .xSavepoint = nullptr, // [] (sqlite3_vtab *pVTab, int) -> int { },
183 : .xRelease = nullptr, // [] (sqlite3_vtab *pVTab, int) -> int { },
184 : .xRollbackTo = nullptr, // [] (sqlite3_vtab *pVTab, int) -> int { },
185 : /* The methods above are in versions 1 and 2 of the sqlite_module object.
186 : ** Those below are for version 3 and greater. */
187 : .xShadowName = nullptr, // [] (const char*) -> int { }
188 : };
189 :
190 : }
|