1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
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 "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,int32_t argc,sqlite3_value ** argv)39 static void sqliteExtStdevNextStep(sqlite3_context *context, int32_t argc, sqlite3_value **argv)
40 {
41 TS_ASSERT(argc == 1);
42 StdevCtx *ptr = static_cast<StdevCtx *>(sqlite3_aggregate_context(context, sizeof(StdevCtx)));
43 if (SQLITE_NULL != sqlite3_value_numeric_type(argv[0])) {
44 ptr->cntValue++;
45 double x = sqlite3_value_double(argv[0]);
46 double deltaValue = (x - ptr->rMValue);
47 ptr->rMValue += deltaValue / ptr->cntValue;
48 ptr->rSValue += deltaValue * (x - ptr->rMValue);
49 }
50 }
51
52 enum Type {
53 TS_NULL = 0,
54 TS_LONG,
55 TS_DOUBLE,
56 TS_STRING,
57 TS_BYTES,
58 };
59
60 struct TSSqlValue {
61 TSSqlValue() = default;
62
LongSysTuning::base::TSSqlValue63 static TSSqlValue Long(int64_t v)
64 {
65 TSSqlValue value;
66 value.longValue = v;
67 value.type = Type::TS_LONG;
68 return value;
69 }
70
DoubleSysTuning::base::TSSqlValue71 static TSSqlValue Double(double v)
72 {
73 TSSqlValue value;
74 value.doubleValue = v;
75 value.type = Type::TS_DOUBLE;
76 return value;
77 }
78
StringSysTuning::base::TSSqlValue79 static TSSqlValue String(const char *v)
80 {
81 TSSqlValue value;
82 value.stringValue = v;
83 value.type = Type::TS_STRING;
84 return value;
85 }
86
BytesSysTuning::base::TSSqlValue87 static TSSqlValue Bytes(const char *v, size_t size)
88 {
89 TSSqlValue value;
90 value.bytesValue = v;
91 value.bytesCount = size;
92 value.type = Type::TS_BYTES;
93 return value;
94 }
95
GetDoubleSysTuning::base::TSSqlValue96 double GetDouble() const
97 {
98 return doubleValue;
99 }
GetLongSysTuning::base::TSSqlValue100 int64_t GetLong() const
101 {
102 return longValue;
103 }
GetStringSysTuning::base::TSSqlValue104 const char *GetString() const
105 {
106 return stringValue;
107 }
GetBytesSysTuning::base::TSSqlValue108 const void *GetBytes() const
109 {
110 return bytesValue;
111 }
112
IsNullSysTuning::base::TSSqlValue113 bool IsNull() const
114 {
115 return type == Type::TS_NULL;
116 }
117
118 union {
119 const char *stringValue;
120 int64_t longValue;
121 double doubleValue;
122 const void *bytesValue;
123 };
124 size_t bytesCount = 0;
125 Type type = TS_NULL;
126 };
127
SqliteValueToTSSqlValue(sqlite3_value * value)128 TSSqlValue SqliteValueToTSSqlValue(sqlite3_value *value)
129 {
130 TSSqlValue sqlValue;
131 switch (sqlite3_value_type(value)) {
132 case SQLITE_INTEGER:
133 sqlValue.type = Type::TS_LONG;
134 sqlValue.longValue = sqlite3_value_int64(value);
135 break;
136 case SQLITE_FLOAT:
137 sqlValue.type = Type::TS_DOUBLE;
138 sqlValue.doubleValue = sqlite3_value_double(value);
139 break;
140 case SQLITE_TEXT:
141 sqlValue.type = Type::TS_STRING;
142 sqlValue.stringValue = reinterpret_cast<const char *>(sqlite3_value_text(value));
143 break;
144 case SQLITE_BLOB:
145 sqlValue.type = Type::TS_BYTES;
146 sqlValue.bytesValue = sqlite3_value_blob(value);
147 sqlValue.bytesCount = static_cast<size_t>(sqlite3_value_bytes(value));
148 break;
149 default:
150 TS_LOGE("type is not in scope");
151 }
152 return sqlValue;
153 }
154 struct JsonBuild {
155 JsonBuild() = default;
AppendHeadSysTuning::base::JsonBuild156 void AppendHead()
157 {
158 body += "{";
159 }
AppendTailSysTuning::base::JsonBuild160 void AppendTail()
161 {
162 body += "}";
163 }
AppendCommonSysTuning::base::JsonBuild164 void AppendCommon()
165 {
166 body += ",";
167 }
AppendSqlValueSysTuning::base::JsonBuild168 bool AppendSqlValue(const std::string &field_name, const TSSqlValue &value)
169 {
170 body += "\"" + field_name + "\":";
171 return AppendSqlValue(value);
172 }
AppendSqlValueSysTuning::base::JsonBuild173 bool AppendSqlValue(const TSSqlValue &value)
174 {
175 switch (value.type) {
176 case TS_LONG:
177 body += std::to_string(value.longValue) + ",";
178 break;
179 case TS_DOUBLE:
180 body += std::to_string(value.doubleValue) + ",";
181 break;
182 case TS_STRING:
183 body += "\"" + std::string(value.stringValue) + "\"" + ",";
184 break;
185 case TS_BYTES:
186 body += "\"" + std::string(static_cast<const char *>(value.bytesValue), value.bytesCount) + "\"" + ",";
187 break;
188 case TS_NULL:
189 body += std::to_string(0) + ",";
190 break;
191 }
192 return true;
193 }
194 std::string body;
195 bool poped = false;
PopLastSysTuning::base::JsonBuild196 void PopLast()
197 {
198 body.pop_back();
199 }
BodySysTuning::base::JsonBuild200 const std::string &Body() const
201 {
202 return body;
203 }
204 };
205
BuildJson(sqlite3_context * ctx,int32_t argc,sqlite3_value ** argv)206 void BuildJson(sqlite3_context *ctx, int32_t argc, sqlite3_value **argv)
207 {
208 const int32_t pairArgsSize = 2;
209 if (argc % pairArgsSize != 0) {
210 TS_LOGI("BuildJson arg number error");
211 sqlite3_result_error(ctx, "BuildJson arg number error", -1);
212 return;
213 }
214
215 JsonBuild builder;
216 builder.AppendHead();
217 for (int32_t i = 0; i < argc; i += pairArgsSize) {
218 if (sqlite3_value_type(argv[i]) != SQLITE_TEXT) {
219 TS_LOGI("BuildJson: Invalid args argc:%d, %d", argc, sqlite3_value_type(argv[i]));
220 sqlite3_result_error(ctx, "BuildJson: Invalid args", -1);
221 return;
222 }
223
224 auto *key = reinterpret_cast<const char *>(sqlite3_value_text(argv[i]));
225 auto value = SqliteValueToTSSqlValue(argv[i + 1]);
226 auto status = builder.AppendSqlValue(key, value);
227 if (!status) {
228 TS_LOGI("AppendSqlValueError");
229 sqlite3_result_error(ctx, "AppendSqlValueError", -1);
230 return;
231 }
232 }
233 builder.PopLast();
234 builder.AppendTail();
235 std::string raw = builder.Body();
236 if (raw.empty()) {
237 sqlite3_result_blob(ctx, "", 0, nullptr);
238 return;
239 }
240 std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t[]>(raw.size());
241 (void)memcpy_s(data.get(), raw.size(), raw.data(), raw.size());
242 sqlite3_result_blob(ctx, data.release(), static_cast<int32_t>(raw.size()), free);
243 }
244
RepeatedJsonStep(sqlite3_context * ctx,int32_t argc,sqlite3_value ** argv)245 void RepeatedJsonStep(sqlite3_context *ctx, int32_t argc, sqlite3_value **argv)
246 {
247 const int32_t pairArgsSize = 2;
248 auto **jsonBuild = static_cast<JsonBuild **>(sqlite3_aggregate_context(ctx, sizeof(JsonBuild *)));
249
250 if (*jsonBuild == nullptr) {
251 *jsonBuild = new JsonBuild();
252 }
253 JsonBuild *builder = *jsonBuild;
254 builder->AppendHead();
255 for (int32_t i = 0; i < argc; i += pairArgsSize) {
256 if (sqlite3_value_type(argv[i]) != SQLITE_TEXT) {
257 TS_LOGI("BuildJson: Invalid args argc:%d, %d", argc, sqlite3_value_type(argv[i]));
258 sqlite3_result_error(ctx, "BuildJson: Invalid args", -1);
259 return;
260 }
261
262 auto *key = reinterpret_cast<const char *>(sqlite3_value_text(argv[i]));
263 auto value = SqliteValueToTSSqlValue(argv[i + 1]);
264 auto status = builder->AppendSqlValue(key, value);
265 if (!status) {
266 TS_LOGI("AppendSqlValueError");
267 sqlite3_result_error(ctx, "AppendSqlValueError", -1);
268 return;
269 }
270 }
271 builder->PopLast();
272 builder->AppendTail();
273 builder->AppendCommon();
274 }
RepeatedFieldStep(sqlite3_context * ctx,int32_t argc,sqlite3_value ** argv)275 void RepeatedFieldStep(sqlite3_context *ctx, int32_t argc, sqlite3_value **argv)
276 {
277 if (argc != 1) {
278 TS_LOGE(
279 "RepeatedField only support one arg, you can use BuildJson or BuildRepeatedJson function for multi args");
280 return;
281 }
282 auto **jsonBuild = static_cast<JsonBuild **>(sqlite3_aggregate_context(ctx, sizeof(JsonBuild *)));
283
284 if (*jsonBuild == nullptr) {
285 *jsonBuild = new JsonBuild();
286 }
287 JsonBuild *builder = *jsonBuild;
288 for (int32_t i = 0; i < argc; i++) {
289 auto value = SqliteValueToTSSqlValue(argv[i]);
290 auto status = builder->AppendSqlValue(value);
291 if (!status) {
292 sqlite3_result_error(ctx, "error", -1);
293 }
294 }
295 }
296
RepeatedFieldFinal(sqlite3_context * ctx)297 void RepeatedFieldFinal(sqlite3_context *ctx)
298 {
299 auto **jsonBuilder = static_cast<JsonBuild **>(sqlite3_aggregate_context(ctx, 0));
300
301 if (jsonBuilder == nullptr) {
302 sqlite3_result_null(ctx);
303 return;
304 }
305
306 std::unique_ptr<JsonBuild> builder(*jsonBuilder);
307 std::string raw = builder->Body();
308 raw.pop_back();
309 if (raw.empty()) {
310 sqlite3_result_null(ctx);
311 return;
312 }
313
314 std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t[]>(raw.size());
315 (void)memcpy_s(data.get(), raw.size(), raw.data(), raw.size());
316 sqlite3_result_blob(ctx, data.release(), static_cast<int32_t>(raw.size()), free);
317 }
318
RepeatedJsonFinal(sqlite3_context * ctx)319 void RepeatedJsonFinal(sqlite3_context *ctx)
320 {
321 auto **jsonBuilder = static_cast<JsonBuild **>(sqlite3_aggregate_context(ctx, 0));
322
323 if (jsonBuilder == nullptr) {
324 sqlite3_result_null(ctx);
325 return;
326 }
327
328 std::unique_ptr<JsonBuild> builder(*jsonBuilder);
329 builder->PopLast();
330 std::string raw = builder->Body();
331 if (raw.empty()) {
332 sqlite3_result_null(ctx);
333 return;
334 }
335
336 std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t[]>(raw.size());
337 (void)memcpy_s(data.get(), raw.size(), raw.data(), raw.size());
338 sqlite3_result_blob(ctx, data.release(), static_cast<int32_t>(raw.size()), free);
339 }
ts_create_extend_function(sqlite3 * db)340 void ts_create_extend_function(sqlite3 *db)
341 {
342 sqlite3_create_function(db, "stdev", -1, SQLITE_UTF8, nullptr, 0, sqliteExtStdevNextStep, sqliteExtStdevFinalize);
343 auto ret = sqlite3_create_function_v2(db, "RepeatedField", 1, SQLITE_UTF8, nullptr, nullptr, RepeatedFieldStep,
344 RepeatedFieldFinal, nullptr);
345 if (ret) {
346 TS_LOGF("Error while initializing RepeatedField");
347 }
348 ret = sqlite3_create_function_v2(db, "BuildRepeatedJson", -1, SQLITE_UTF8, nullptr, nullptr, RepeatedJsonStep,
349 RepeatedJsonFinal, nullptr);
350 if (ret) {
351 TS_LOGF("Error while initializing BuildRepeatedJson");
352 }
353 std::unique_ptr<JsonBuild> ctx = std::make_unique<JsonBuild>();
354 ret = sqlite3_create_function_v2(db, "BuildJson", -1, SQLITE_UTF8, ctx.release(), BuildJson, nullptr, nullptr,
355 [](void *ptr) { delete static_cast<JsonBuild *>(ptr); });
356 if (ret != SQLITE_OK) {
357 TS_LOGF("Error while initializing BuildJson");
358 }
359 }
360 } // namespace base
361 } // namespace SysTuning