• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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