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 #include "sqlite_ext_funcs.h"
16 #include <cmath>
17 #include <functional>
18 #include <memory>
19 #include "log.h"
20 #include "sqlite3.h"
21 #include "../base/string_help.h"
22 namespace SysTuning {
23 namespace base {
24 /*
25 ** Return a stdev value
26 */
sqliteExtStdevFinalize(sqlite3_context * context)27 static void sqliteExtStdevFinalize(sqlite3_context* context)
28 {
29 StdevCtx* ptr = static_cast<StdevCtx*>(sqlite3_aggregate_context(context, 0));
30 if (ptr && ptr->cntValue > 1) {
31 sqlite3_result_double(context, sqrt(ptr->rSValue / (ptr->cntValue - 1)));
32 } else {
33 sqlite3_result_double(context, 0.0);
34 }
35 }
36 /*
37 ** called each value received during a calculation of stdev or variance
38 */
sqliteExtStdevNextStep(sqlite3_context * context,int argc,sqlite3_value ** argv)39 static void sqliteExtStdevNextStep(sqlite3_context* context, int argc, sqlite3_value** argv)
40 {
41 double deltaValue;
42 double x;
43
44 TS_ASSERT(argc == 1);
45 StdevCtx* ptr = static_cast<StdevCtx*>(sqlite3_aggregate_context(context, sizeof(StdevCtx)));
46 if (SQLITE_NULL != sqlite3_value_numeric_type(argv[0])) {
47 ptr->cntValue++;
48 x = sqlite3_value_double(argv[0]);
49 deltaValue = (x - ptr->rMValue);
50 ptr->rMValue += deltaValue / ptr->cntValue;
51 ptr->rSValue += deltaValue * (x - ptr->rMValue);
52 }
53 }
54
55 enum Type {
56 TS_NULL = 0,
57 TS_LONG,
58 TS_DOUBLE,
59 TS_STRING,
60 TS_BYTES,
61 };
62
63 struct TSSqlValue {
64 TSSqlValue() = default;
65
LongSysTuning::base::TSSqlValue66 static TSSqlValue Long(int64_t v)
67 {
68 TSSqlValue value;
69 value.longValue = v;
70 value.type = Type::TS_LONG;
71 return value;
72 }
73
DoubleSysTuning::base::TSSqlValue74 static TSSqlValue Double(double v)
75 {
76 TSSqlValue value;
77 value.doubleValue = v;
78 value.type = Type::TS_DOUBLE;
79 return value;
80 }
81
StringSysTuning::base::TSSqlValue82 static TSSqlValue String(const char* v)
83 {
84 TSSqlValue value;
85 value.stringValue = v;
86 value.type = Type::TS_STRING;
87 return value;
88 }
89
BytesSysTuning::base::TSSqlValue90 static TSSqlValue Bytes(const char* v, size_t size)
91 {
92 TSSqlValue value;
93 value.bytesValue = v;
94 value.bytesCount = size;
95 value.type = Type::TS_BYTES;
96 return value;
97 }
98
GetDoubleSysTuning::base::TSSqlValue99 double GetDouble() const
100 {
101 return doubleValue;
102 }
GetLongSysTuning::base::TSSqlValue103 int64_t GetLong() const
104 {
105 return longValue;
106 }
GetStringSysTuning::base::TSSqlValue107 const char* GetString() const
108 {
109 return stringValue;
110 }
GetBytesSysTuning::base::TSSqlValue111 const void* GetBytes() const
112 {
113 return bytesValue;
114 }
115
IsNullSysTuning::base::TSSqlValue116 bool IsNull() const
117 {
118 return type == Type::TS_NULL;
119 }
120
121 union {
122 const char* stringValue;
123 int64_t longValue;
124 double doubleValue;
125 const void* bytesValue;
126 };
127 size_t bytesCount = 0;
128 Type type = TS_NULL;
129 };
130
SqliteValueToTSSqlValue(sqlite3_value * value)131 TSSqlValue SqliteValueToTSSqlValue(sqlite3_value* value)
132 {
133 TSSqlValue sqlValue;
134 switch (sqlite3_value_type(value)) {
135 case SQLITE_INTEGER:
136 sqlValue.type = Type::TS_LONG;
137 sqlValue.longValue = sqlite3_value_int64(value);
138 break;
139 case SQLITE_FLOAT:
140 sqlValue.type = Type::TS_DOUBLE;
141 sqlValue.doubleValue = sqlite3_value_double(value);
142 break;
143 case SQLITE_TEXT:
144 sqlValue.type = Type::TS_STRING;
145 sqlValue.stringValue = reinterpret_cast<const char*>(sqlite3_value_text(value));
146 break;
147 case SQLITE_BLOB:
148 sqlValue.type = Type::TS_BYTES;
149 sqlValue.bytesValue = sqlite3_value_blob(value);
150 sqlValue.bytesCount = static_cast<size_t>(sqlite3_value_bytes(value));
151 break;
152 }
153 return sqlValue;
154 }
155 class JsonBuild {
156 public:
157 JsonBuild() = default;
AppendHead()158 void AppendHead()
159 {
160 body_ += "{";
161 }
AppendTail()162 void AppendTail()
163 {
164 body_ += "}";
165 }
AppendCommon()166 void AppendCommon()
167 {
168 body_ += ",";
169 }
AppendSqlValue(const std::string & field_name,const TSSqlValue & value)170 bool AppendSqlValue(const std::string& field_name, const TSSqlValue& value)
171 {
172 body_ += "\"" + field_name + "\":";
173 return AppendSqlValue(value);
174 }
AppendSqlValue(const TSSqlValue & value)175 bool AppendSqlValue(const TSSqlValue& value)
176 {
177 switch (value.type) {
178 case TS_LONG:
179 body_ += std::to_string(value.longValue) + ",";
180 break;
181 case TS_DOUBLE:
182 body_ += std::to_string(value.doubleValue) + ",";
183 break;
184 case TS_STRING:
185 body_ += "\"" + std::string(value.stringValue) + "\"" + ",";
186 break;
187 case TS_BYTES:
188 body_ += "\"" + std::string(static_cast<const char*>(value.bytesValue), value.bytesCount) + "\"" + ",";
189 break;
190 case TS_NULL:
191 body_ += std::to_string(0) + ",";
192 break;
193 }
194 return true;
195 }
196 std::string body_;
197 bool poped_ = false;
PopLast()198 void PopLast()
199 {
200 body_.pop_back();
201 }
Body()202 const std::string& Body()
203 {
204 return body_;
205 }
206 };
207
BuildJson(sqlite3_context * ctx,int argc,sqlite3_value ** argv)208 void BuildJson(sqlite3_context* ctx, int argc, sqlite3_value** argv)
209 {
210 const int PAIR_ARGS_SIZE = 2;
211 const auto* fn_ctx = static_cast<const JsonBuild*>(sqlite3_user_data(ctx));
212 if (argc % PAIR_ARGS_SIZE != 0) {
213 TS_LOGI("BuildJson arg number error");
214 sqlite3_result_error(ctx, "BuildJson arg number error", -1);
215 return;
216 }
217
218 JsonBuild builder;
219 builder.AppendHead();
220 for (int i = 0; i < argc; i += PAIR_ARGS_SIZE) {
221 if (sqlite3_value_type(argv[i]) != SQLITE_TEXT) {
222 TS_LOGI("BuildJson: Invalid args argc:%d, %d", argc, sqlite3_value_type(argv[i]));
223 sqlite3_result_error(ctx, "BuildJson: Invalid args", -1);
224 return;
225 }
226
227 auto* key = reinterpret_cast<const char*>(sqlite3_value_text(argv[i]));
228 auto value = SqliteValueToTSSqlValue(argv[i + 1]);
229 auto status = builder.AppendSqlValue(key, value);
230 if (!status) {
231 TS_LOGI("AppendSqlValueError");
232 sqlite3_result_error(ctx, "AppendSqlValueError", -1);
233 return;
234 }
235 }
236 builder.PopLast();
237 builder.AppendTail();
238 std::string raw = builder.Body();
239 if (raw.empty()) {
240 sqlite3_result_blob(ctx, "", 0, nullptr);
241 return;
242 }
243 std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t[]>(raw.size());
244 memcpy_s(data.get(), raw.size(), raw.data(), raw.size());
245 sqlite3_result_blob(ctx, data.release(), static_cast<int>(raw.size()), free);
246 }
247
RepeatedJsonStep(sqlite3_context * ctx,int argc,sqlite3_value ** argv)248 void RepeatedJsonStep(sqlite3_context* ctx, int argc, sqlite3_value** argv)
249 {
250 const int PAIR_ARGS_SIZE = 2;
251 auto** jsonBuild = static_cast<JsonBuild**>(sqlite3_aggregate_context(ctx, sizeof(JsonBuild*)));
252
253 if (*jsonBuild == nullptr) {
254 *jsonBuild = new JsonBuild();
255 }
256 JsonBuild* builder = *jsonBuild;
257 builder->AppendHead();
258 for (int i = 0; i < argc; i += PAIR_ARGS_SIZE) {
259 if (sqlite3_value_type(argv[i]) != SQLITE_TEXT) {
260 TS_LOGI("BuildJson: Invalid args argc:%d, %d", argc, sqlite3_value_type(argv[i]));
261 sqlite3_result_error(ctx, "BuildJson: Invalid args", -1);
262 return;
263 }
264
265 auto* key = reinterpret_cast<const char*>(sqlite3_value_text(argv[i]));
266 auto value = SqliteValueToTSSqlValue(argv[i + 1]);
267 auto status = builder->AppendSqlValue(key, value);
268 if (!status) {
269 TS_LOGI("AppendSqlValueError");
270 sqlite3_result_error(ctx, "AppendSqlValueError", -1);
271 return;
272 }
273 }
274 builder->PopLast();
275 builder->AppendTail();
276 builder->AppendCommon();
277 }
RepeatedFieldStep(sqlite3_context * ctx,int argc,sqlite3_value ** argv)278 void RepeatedFieldStep(sqlite3_context* ctx, int argc, sqlite3_value** argv)
279 {
280 if (argc != 1) {
281 TS_LOGE(
282 "RepeatedField only support one arg, you can use BuildJson or BuildRepeatedJson function for multi args");
283 return;
284 }
285 auto** jsonBuild = static_cast<JsonBuild**>(sqlite3_aggregate_context(ctx, sizeof(JsonBuild*)));
286
287 if (*jsonBuild == nullptr) {
288 *jsonBuild = new JsonBuild();
289 }
290 JsonBuild* builder = *jsonBuild;
291 for (int i = 0; i < argc; i++) {
292 auto value = SqliteValueToTSSqlValue(argv[i]);
293 auto status = builder->AppendSqlValue(value);
294 if (!status) {
295 sqlite3_result_error(ctx, "error", -1);
296 }
297 }
298 }
299
RepeatedFieldFinal(sqlite3_context * ctx)300 void RepeatedFieldFinal(sqlite3_context* ctx)
301 {
302 auto** jsonBuilder = static_cast<JsonBuild**>(sqlite3_aggregate_context(ctx, 0));
303
304 if (jsonBuilder == nullptr) {
305 sqlite3_result_null(ctx);
306 return;
307 }
308
309 std::unique_ptr<JsonBuild> builder(*jsonBuilder);
310 std::string raw = builder->Body();
311 raw.pop_back();
312 if (raw.empty()) {
313 sqlite3_result_null(ctx);
314 return;
315 }
316
317 std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t[]>(raw.size());
318 memcpy_s(data.get(), raw.size(), raw.data(), raw.size());
319 sqlite3_result_blob(ctx, data.release(), static_cast<int>(raw.size()), free);
320 }
321
RepeatedJsonFinal(sqlite3_context * ctx)322 void RepeatedJsonFinal(sqlite3_context* ctx)
323 {
324 auto** jsonBuilder = static_cast<JsonBuild**>(sqlite3_aggregate_context(ctx, 0));
325
326 if (jsonBuilder == nullptr) {
327 sqlite3_result_null(ctx);
328 return;
329 }
330
331 std::unique_ptr<JsonBuild> builder(*jsonBuilder);
332 builder->PopLast();
333 std::string raw = builder->Body();
334 if (raw.empty()) {
335 sqlite3_result_null(ctx);
336 return;
337 }
338
339 std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t[]>(raw.size());
340 memcpy_s(data.get(), raw.size(),raw.data(), raw.size());
341 sqlite3_result_blob(ctx, data.release(), static_cast<int>(raw.size()), free);
342 }
ts_create_extend_function(sqlite3 * db)343 void ts_create_extend_function(sqlite3* db)
344 {
345 sqlite3_create_function(db, "stdev", -1, SQLITE_UTF8, nullptr, 0, sqliteExtStdevNextStep, sqliteExtStdevFinalize);
346 auto ret = sqlite3_create_function_v2(db, "RepeatedField", 1, SQLITE_UTF8, nullptr, nullptr, RepeatedFieldStep,
347 RepeatedFieldFinal, nullptr);
348 if (ret) {
349 TS_LOGF("Error while initializing RepeatedField");
350 }
351 ret = sqlite3_create_function_v2(db, "BuildRepeatedJson", -1, SQLITE_UTF8, nullptr, nullptr, RepeatedJsonStep,
352 RepeatedJsonFinal, nullptr);
353 if (ret) {
354 TS_LOGF("Error while initializing BuildRepeatedJson");
355 }
356 std::unique_ptr<JsonBuild> ctx = std::make_unique<JsonBuild>();
357 ret = sqlite3_create_function_v2(db, "BuildJson", -1, SQLITE_UTF8, ctx.release(), BuildJson, nullptr, nullptr,
358 [](void* ptr) { delete static_cast<JsonBuild*>(ptr); });
359 if (ret != SQLITE_OK) {
360 TS_LOGF("Error while initializing BuildJson");
361 }
362 }
363 } // namespace base
364 } // namespace SysTuning