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