lws-struct-sqlite.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2010 - 2020 Andy Green <[email protected]>
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to
  8. * deal in the Software without restriction, including without limitation the
  9. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  10. * sell copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  22. * IN THE SOFTWARE.
  23. */
  24. #include <libwebsockets.h>
  25. #include <private-lib-core.h>
  26. #include <sqlite3.h>
  27. /*
  28. * we get one of these per matching result from the query
  29. */
  30. static int
  31. lws_struct_sq3_deser_cb(void *priv, int cols, char **cv, char **cn)
  32. {
  33. lws_struct_args_t *a = (lws_struct_args_t *)priv;
  34. char *u = lwsac_use_zero(&a->ac, a->dest_len, a->ac_block_size);
  35. lws_dll2_owner_t *o = (lws_dll2_owner_t *)a->cb_arg;
  36. const lws_struct_map_t *map = a->map_st[0];
  37. int n, mems = a->map_entries_st[0];
  38. long long li;
  39. size_t lim;
  40. char **pp;
  41. char *s;
  42. if (!u) {
  43. lwsl_err("OOM\n");
  44. return 1;
  45. }
  46. lws_dll2_add_tail((lws_dll2_t *)((char *)u + a->toplevel_dll2_ofs), o);
  47. while (mems--) {
  48. for (n = 0; n < cols; n++) {
  49. if (!cv[n] || strcmp(cn[n], map->colname))
  50. continue;
  51. switch (map->type) {
  52. case LSMT_SIGNED:
  53. if (map->aux == sizeof(signed char)) {
  54. signed char *pc;
  55. pc = (signed char *)(u + map->ofs);
  56. *pc = atoi(cv[n]);
  57. break;
  58. }
  59. if (map->aux == sizeof(short)) {
  60. short *ps;
  61. ps = (short *)(u + map->ofs);
  62. *ps = atoi(cv[n]);
  63. break;
  64. }
  65. if (map->aux == sizeof(int)) {
  66. int *pi;
  67. pi = (int *)(u + map->ofs);
  68. *pi = atoi(cv[n]);
  69. break;
  70. }
  71. if (map->aux == sizeof(long)) {
  72. long *pl;
  73. pl = (long *)(u + map->ofs);
  74. *pl = atol(cv[n]);
  75. break;
  76. }
  77. {
  78. long long *pll;
  79. pll = (long long *)(u + map->ofs);
  80. *pll = atoll(cv[n]);
  81. }
  82. break;
  83. case LSMT_UNSIGNED:
  84. if (map->aux == sizeof(unsigned char)) {
  85. unsigned char *pc;
  86. pc = (unsigned char *)(u + map->ofs);
  87. *pc = atoi(cv[n]);
  88. break;
  89. }
  90. if (map->aux == sizeof(unsigned short)) {
  91. unsigned short *ps;
  92. ps = (unsigned short *)(u + map->ofs);
  93. *ps = atoi(cv[n]);
  94. break;
  95. }
  96. if (map->aux == sizeof(unsigned int)) {
  97. unsigned int *pi;
  98. pi = (unsigned int *)(u + map->ofs);
  99. *pi = atoi(cv[n]);
  100. break;
  101. }
  102. if (map->aux == sizeof(unsigned long)) {
  103. unsigned long *pl;
  104. pl = (unsigned long *)(u + map->ofs);
  105. *pl = atol(cv[n]);
  106. break;
  107. }
  108. {
  109. unsigned long long *pll;
  110. pll = (unsigned long long *)(u + map->ofs);
  111. *pll = atoll(cv[n]);
  112. }
  113. break;
  114. case LSMT_BOOLEAN:
  115. li = 0;
  116. if (!strcmp(cv[n], "true") ||
  117. !strcmp(cv[n], "TRUE") || cv[n][0] == '1')
  118. li = 1;
  119. if (map->aux == sizeof(char)) {
  120. char *pc;
  121. pc = (char *)(u + map->ofs);
  122. *pc = (char)li;
  123. break;
  124. }
  125. if (map->aux == sizeof(int)) {
  126. int *pi;
  127. pi = (int *)(u + map->ofs);
  128. *pi = (int)li;
  129. } else {
  130. uint64_t *p64;
  131. p64 = (uint64_t *)(u + map->ofs);
  132. *p64 = li;
  133. }
  134. break;
  135. case LSMT_STRING_CHAR_ARRAY:
  136. s = (char *)(u + map->ofs);
  137. lim = map->aux;
  138. lws_strncpy(s, cv[n], lim);
  139. break;
  140. case LSMT_STRING_PTR:
  141. pp = (char **)(u + map->ofs);
  142. lim = strlen(cv[n]);
  143. s = lwsac_use(&a->ac, lim + 1, a->ac_block_size);
  144. if (!s)
  145. return 1;
  146. *pp = s;
  147. memcpy(s, cv[n], lim);
  148. s[lim] = '\0';
  149. break;
  150. default:
  151. break;
  152. }
  153. }
  154. map++;
  155. }
  156. return 0;
  157. }
  158. /*
  159. * Call this with an LSM_SCHEMA map, its colname is the table name and its
  160. * type information describes the toplevel type. Schema is dereferenced and
  161. * put in args before the actual sq3 query, which is given the child map.
  162. */
  163. int
  164. lws_struct_sq3_deserialize(sqlite3 *pdb, const char *filter, const char *order,
  165. const lws_struct_map_t *schema, lws_dll2_owner_t *o,
  166. struct lwsac **ac, int start, int _limit)
  167. {
  168. int limit = _limit < 0 ? -_limit : _limit;
  169. char s[768], results[512], where[250];
  170. lws_struct_args_t a;
  171. int n, m;
  172. if (!order)
  173. order = "_lws_idx";
  174. memset(&a, 0, sizeof(a));
  175. a.cb_arg = o; /* lws_dll2_owner tracking query result objects */
  176. a.map_st[0] = schema->child_map;
  177. a.map_entries_st[0] = schema->child_map_size;
  178. a.dest_len = schema->aux; /* size of toplevel object to allocate */
  179. a.toplevel_dll2_ofs = schema->ofs;
  180. lws_dll2_owner_clear(o);
  181. /*
  182. * Explicitly list the columns instead of use *, so we can skip blobs
  183. */
  184. m = 0;
  185. for (n = 0; n < (int)schema->child_map_size; n++)
  186. m += lws_snprintf(&results[m], sizeof(results) - n - 1,
  187. "%s%c", schema->child_map[n].colname,
  188. n + 1 == (int)schema->child_map_size ? ' ' : ',');
  189. where[0] = '\0';
  190. lws_snprintf(where, sizeof(where), " where _lws_idx >= %llu %s",
  191. (unsigned long long)start, filter ? filter : "");
  192. lws_snprintf(s, sizeof(s) - 1, "select %s "
  193. "from %s %s order by %s %slimit %d;", results,
  194. schema->colname, where, order,
  195. _limit < 0 ? "desc " : "", limit);
  196. if (sqlite3_exec(pdb, s, lws_struct_sq3_deser_cb, &a, NULL) != SQLITE_OK) {
  197. lwsl_err("%s: %s: fail %s\n", __func__, sqlite3_errmsg(pdb), s);
  198. lwsac_free(&a.ac);
  199. return -1;
  200. }
  201. *ac = a.ac;
  202. return 0;
  203. }
  204. /*
  205. * This takes a struct and turns it into an sqlite3 UPDATE, using the given
  206. * schema... which has one LSM_SCHEMA_DLL2 entry wrapping the actual schema
  207. */
  208. static int
  209. _lws_struct_sq3_ser_one(sqlite3 *pdb, const lws_struct_map_t *schema,
  210. uint32_t idx, void *st)
  211. {
  212. const lws_struct_map_t *map = schema->child_map;
  213. int n, m, pk = 0, nentries = schema->child_map_size, nef = 0, did;
  214. size_t sql_est = 46 + strlen(schema->colname) + 1;
  215. /* "insert into (_lws_idx, ) values (00000001,);" ...
  216. * plus the table name */
  217. uint8_t *stb = (uint8_t *)st;
  218. const char *p;
  219. char *sql;
  220. /*
  221. * Figure out effective number of columns, exluding BLOB.
  222. *
  223. * The first UNSIGNED is a hidden index. Blobs are not handled by
  224. * lws_struct except to create the column in the schema.
  225. */
  226. pk = 0;
  227. nef = 0;
  228. for (n = 0; n < nentries; n++) {
  229. if (!pk && map[n].type == LSMT_UNSIGNED) {
  230. pk = 1;
  231. continue;
  232. }
  233. if (map[n].type == LSMT_BLOB_PTR)
  234. continue;
  235. nef++;
  236. }
  237. /*
  238. * Figure out an estimate for the length of the populated sqlite
  239. * command, and then malloc it up
  240. */
  241. for (n = 0; n < nentries; n++) {
  242. sql_est += strlen(map[n].colname) + 2;
  243. switch (map[n].type) {
  244. case LSMT_SIGNED:
  245. case LSMT_UNSIGNED:
  246. case LSMT_BOOLEAN:
  247. switch (map[n].aux) {
  248. case 1:
  249. sql_est += 3 + 2;
  250. break;
  251. case 2:
  252. sql_est += 5 + 2;
  253. break;
  254. case 4:
  255. sql_est += 10 + 2;
  256. break;
  257. case 8:
  258. sql_est += 20 + 2;
  259. break;
  260. }
  261. if (map[n].type == LSMT_SIGNED)
  262. sql_est++; /* minus sign */
  263. break;
  264. case LSMT_STRING_CHAR_ARRAY:
  265. sql_est += lws_sql_purify_len((const char *)st +
  266. map[n].ofs) + 2;
  267. break;
  268. case LSMT_STRING_PTR:
  269. p = *((const char * const *)&stb[map[n].ofs]);
  270. sql_est += (p ? lws_sql_purify_len(p) : 0) + 2;
  271. break;
  272. case LSMT_BLOB_PTR:
  273. /* we don't deal with blobs actually */
  274. sql_est -= strlen(map[n].colname) + 2;
  275. break;
  276. default:
  277. lwsl_err("%s: unsupported type\n", __func__);
  278. assert(0);
  279. break;
  280. }
  281. }
  282. sql = malloc(sql_est);
  283. if (!sql)
  284. return -1;
  285. m = lws_snprintf(sql, sql_est, "insert into %s(_lws_idx, ",
  286. schema->colname);
  287. /*
  288. * First explicit integer type is primary key autoincrement, should
  289. * not be specified
  290. */
  291. pk = 0;
  292. did = 0;
  293. for (n = 0; n < nentries; n++) {
  294. if (!pk && map[n].type == LSMT_UNSIGNED) {
  295. pk = 1;
  296. continue;
  297. }
  298. if (map[n].type == LSMT_BLOB_PTR)
  299. continue;
  300. did++;
  301. m += lws_snprintf(sql + m, sql_est - m,
  302. did == nef ? "%s" : "%s, ",
  303. map[n].colname);
  304. }
  305. m += lws_snprintf(sql + m, sql_est - m, ") values(%u, ", idx);
  306. pk = 0;
  307. did = 0;
  308. for (n = 0; n < nentries; n++) {
  309. uint64_t uu64;
  310. size_t q;
  311. if (!pk && map[n].type == LSMT_UNSIGNED) {
  312. pk = 1;
  313. continue;
  314. }
  315. switch (map[n].type) {
  316. case LSMT_SIGNED:
  317. case LSMT_UNSIGNED:
  318. case LSMT_BOOLEAN:
  319. uu64 = 0;
  320. for (q = 0; q < map[n].aux; q++)
  321. uu64 |= ((uint64_t)stb[map[n].ofs + q] <<
  322. (q << 3));
  323. if (map[n].type == LSMT_SIGNED)
  324. m += lws_snprintf(sql + m, sql_est - m, "%lld",
  325. (long long)(int64_t)uu64);
  326. else
  327. m += lws_snprintf(sql + m, sql_est - m, "%llu",
  328. (unsigned long long)uu64);
  329. break;
  330. case LSMT_STRING_CHAR_ARRAY:
  331. sql[m++] = '\'';
  332. lws_sql_purify(sql + m, (const char *)&stb[map[n].ofs],
  333. sql_est - m - 4);
  334. m += strlen(sql + m);
  335. sql[m++] = '\'';
  336. break;
  337. case LSMT_STRING_PTR:
  338. p = *((const char * const *)&stb[map[n].ofs]);
  339. sql[m++] = '\'';
  340. if (p) {
  341. lws_sql_purify(sql + m, p, sql_est - m - 4);
  342. m += strlen(sql + m);
  343. }
  344. sql[m++] = '\'';
  345. break;
  346. case LSMT_BLOB_PTR:
  347. continue;
  348. default:
  349. lwsl_err("%s: unsupported type\n", __func__);
  350. assert(0);
  351. break;
  352. }
  353. did++;
  354. if (did != nef) {
  355. if (sql_est - m < 6)
  356. return -1;
  357. sql[m++] = ',';
  358. sql[m++] = ' ';
  359. }
  360. }
  361. lws_snprintf(sql + m, sql_est - m, ");");
  362. n = sqlite3_exec(pdb, sql, NULL, NULL, NULL);
  363. if (n != SQLITE_OK) {
  364. lwsl_err("%s\n", sql);
  365. free(sql);
  366. lwsl_err("%s: %s: fail\n", __func__, sqlite3_errmsg(pdb));
  367. return -1;
  368. }
  369. free(sql);
  370. return 0;
  371. }
  372. int
  373. lws_struct_sq3_serialize(sqlite3 *pdb, const lws_struct_map_t *schema,
  374. lws_dll2_owner_t *owner, uint32_t manual_idx)
  375. {
  376. uint32_t idx = manual_idx;
  377. lws_start_foreach_dll(struct lws_dll2 *, p, owner->head) {
  378. void *item = (void *)((uint8_t *)p - schema->ofs_clist);
  379. if (_lws_struct_sq3_ser_one(pdb, schema, idx++, item))
  380. return 1;
  381. } lws_end_foreach_dll(p);
  382. return 0;
  383. }
  384. int
  385. lws_struct_sq3_create_table(sqlite3 *pdb, const lws_struct_map_t *schema)
  386. {
  387. const lws_struct_map_t *map = schema->child_map;
  388. int map_size = schema->child_map_size, subsequent = 0;
  389. char s[2048], *p = s, *end = &s[sizeof(s) - 1],
  390. *pri = " primary key autoincrement", *use;
  391. p += lws_snprintf(p, end - p,
  392. "create table if not exists %s (_lws_idx integer, ",
  393. schema->colname);
  394. while (map_size--) {
  395. if (map->type > LSMT_STRING_PTR && map->type != LSMT_BLOB_PTR) {
  396. map++;
  397. continue;
  398. }
  399. if (subsequent && (end - p) > 4) {
  400. *p++ = ',';
  401. *p++ = ' ';
  402. }
  403. subsequent = 1;
  404. if (map->type == LSMT_BLOB_PTR) {
  405. p += lws_snprintf(p, end - p, "%s blob", map->colname);
  406. } else {
  407. if (map->type < LSMT_STRING_CHAR_ARRAY) {
  408. use = "";
  409. if (map->colname[0] != '_') /* _lws_idx is not primary key */
  410. use = pri;
  411. p += lws_snprintf(p, end - p, "%s integer%s",
  412. map->colname, use);
  413. if (map->colname[0] != '_')
  414. pri = "";
  415. } else
  416. p += lws_snprintf(p, end - p, "%s varchar",
  417. map->colname);
  418. }
  419. map++;
  420. }
  421. p += lws_snprintf(p, end - p, ");");
  422. if (sqlite3_exec(pdb, s, NULL, NULL, NULL) != SQLITE_OK) {
  423. lwsl_err("%s: %s: fail\n", __func__, sqlite3_errmsg(pdb));
  424. return -1;
  425. }
  426. return 0;
  427. }
  428. int
  429. lws_struct_sq3_open(struct lws_context *context, const char *sqlite3_path,
  430. char create_if_missing, sqlite3 **pdb)
  431. {
  432. #if !defined(WIN32)
  433. int uid = 0, gid = 0;
  434. #endif
  435. if (sqlite3_open_v2(sqlite3_path, pdb,
  436. SQLITE_OPEN_READWRITE |
  437. (create_if_missing ? SQLITE_OPEN_CREATE : 0),
  438. NULL) != SQLITE_OK) {
  439. lwsl_info("%s: Unable to open db %s: %s\n",
  440. __func__, sqlite3_path, sqlite3_errmsg(*pdb));
  441. return 1;
  442. }
  443. #if !defined(WIN32)
  444. lws_get_effective_uid_gid(context, &uid, &gid);
  445. if (uid)
  446. if (chown(sqlite3_path, uid, gid))
  447. lwsl_err("%s: failed to chown %s\n", __func__, sqlite3_path);
  448. chmod(sqlite3_path, 0600);
  449. lwsl_debug("%s: created %s owned by %u:%u mode 0600\n", __func__,
  450. sqlite3_path, (unsigned int)uid, (unsigned int)gid);
  451. #else
  452. lwsl_debug("%s: created %s\n", __func__, sqlite3_path);
  453. #endif
  454. sqlite3_extended_result_codes(*pdb, 1);
  455. return 0;
  456. }
  457. int
  458. lws_struct_sq3_close(sqlite3 **pdb)
  459. {
  460. int n;
  461. if (!*pdb)
  462. return 0;
  463. n = sqlite3_close(*pdb);
  464. if (n != SQLITE_OK) {
  465. /*
  466. * trouble...
  467. */
  468. lwsl_err("%s: failed to close: %d\n", __func__, n);
  469. return 1;
  470. }
  471. *pdb = NULL;
  472. return 0;
  473. }