sqlite3.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems®.
  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. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include "platform.h"
  14. #include "sqlite3.h"
  15. #include "jexcept.hpp"
  16. #include "jthread.hpp"
  17. #include "hqlplugins.hpp"
  18. #include "deftype.hpp"
  19. #include "eclhelper.hpp"
  20. #include "eclrtl.hpp"
  21. #include "eclrtl_imp.hpp"
  22. #include "rtlds_imp.hpp"
  23. #include "rtlfield_imp.hpp"
  24. #include "rtlembed.hpp"
  25. #include "nbcd.hpp"
  26. #ifdef _WIN32
  27. #define EXPORT __declspec(dllexport)
  28. #else
  29. #define EXPORT
  30. #endif
  31. __declspec(noreturn) static void UNSUPPORTED(const char *feature) __attribute__((noreturn));
  32. static void UNSUPPORTED(const char *feature)
  33. {
  34. throw MakeStringException(-1, "UNSUPPORTED feature: %s not supported in sqlite3 plugin", feature);
  35. }
  36. static const char * compatibleVersions[] = {
  37. "SqLite3 Embed Helper 1.0.0",
  38. NULL };
  39. static const char *version = "SqLite3 Embed Helper 1.0.0";
  40. extern "C" EXPORT bool getECLPluginDefinition(ECLPluginDefinitionBlock *pb)
  41. {
  42. if (pb->size == sizeof(ECLPluginDefinitionBlockEx))
  43. {
  44. ECLPluginDefinitionBlockEx * pbx = (ECLPluginDefinitionBlockEx *) pb;
  45. pbx->compatibleVersions = compatibleVersions;
  46. }
  47. else if (pb->size != sizeof(ECLPluginDefinitionBlock))
  48. return false;
  49. pb->magicVersion = PLUGIN_VERSION;
  50. pb->version = version;
  51. pb->moduleName = "sqlite3";
  52. pb->ECL = NULL;
  53. pb->flags = PLUGIN_MULTIPLE_VERSIONS;
  54. pb->description = "SqLite3 Embed Helper";
  55. return true;
  56. }
  57. namespace sqlite3embed {
  58. // Use class OwnedStatement for a sqlite3 stmt object that needs to be released cleanly
  59. class OwnedStatement
  60. {
  61. sqlite3_stmt *ptr;
  62. public:
  63. inline OwnedStatement() : ptr(NULL) {}
  64. inline OwnedStatement(sqlite3_stmt *_ptr) : ptr(_ptr) {}
  65. inline ~OwnedStatement() { clear(); }
  66. inline sqlite3_stmt * get() const { return ptr; }
  67. inline sqlite3_stmt * getClear() { sqlite3_stmt *ret = ptr; ptr = NULL; return ret; }
  68. inline sqlite3_stmt * operator -> () const { return ptr; }
  69. inline operator sqlite3_stmt *() const { return ptr; }
  70. inline void clear() { sqlite3_finalize(ptr); ptr = NULL; }
  71. inline void setown(sqlite3_stmt *_ptr) { clear(); ptr = _ptr; }
  72. inline sqlite3_stmt **ref() { return &ptr; }
  73. };
  74. // Conversions from SqLite3 values to ECL data
  75. __declspec(noreturn) static void typeError(const char *expected, const RtlFieldInfo *field) __attribute__((noreturn));
  76. static void typeError(const char *expected, const RtlFieldInfo *field)
  77. {
  78. VStringBuffer msg("sqlite3: type mismatch - %s expected", expected);
  79. if (field)
  80. msg.appendf(" for field %s", str(field->name));
  81. rtlFail(0, msg.str());
  82. }
  83. static inline bool isNull(sqlite3_value *val)
  84. {
  85. return sqlite3_value_type(val) == SQLITE_NULL;
  86. }
  87. static bool getBooleanResult(const RtlFieldInfo *field, sqlite3_value *val)
  88. {
  89. assertex(val);
  90. if (isNull(val))
  91. {
  92. NullFieldProcessor p(field);
  93. return p.boolResult;
  94. }
  95. if (sqlite3_value_type(val) != SQLITE_INTEGER)
  96. typeError("boolean", field);
  97. return sqlite3_value_int64(val) != 0;
  98. }
  99. static void getDataResult(const RtlFieldInfo *field, sqlite3_value *val, size32_t &chars, void * &result)
  100. {
  101. assertex(val);
  102. if (isNull(val))
  103. {
  104. NullFieldProcessor p(field);
  105. rtlStrToDataX(chars, result, p.resultChars, p.stringResult);
  106. return;
  107. }
  108. if (sqlite3_value_type(val) != SQLITE_BLOB && sqlite3_value_type(val) != SQLITE_TEXT)
  109. typeError("blob", field);
  110. const void *blob = sqlite3_value_blob(val);
  111. int bytes = sqlite3_value_bytes(val);
  112. rtlStrToDataX(chars, result, bytes, blob);
  113. }
  114. static double getRealResult(const RtlFieldInfo *field, sqlite3_value *val)
  115. {
  116. assertex(val);
  117. if (isNull(val))
  118. {
  119. NullFieldProcessor p(field);
  120. return p.doubleResult;
  121. }
  122. if (sqlite3_value_type(val) != SQLITE_FLOAT)
  123. typeError("real", field);
  124. return sqlite3_value_double(val);
  125. }
  126. static __int64 getSignedResult(const RtlFieldInfo *field, sqlite3_value *val)
  127. {
  128. assertex(val);
  129. if (isNull(val))
  130. {
  131. NullFieldProcessor p(field);
  132. return p.intResult;
  133. }
  134. if (sqlite3_value_type(val) != SQLITE_INTEGER)
  135. typeError("integer", field);
  136. return sqlite3_value_int64(val);
  137. }
  138. static unsigned __int64 getUnsignedResult(const RtlFieldInfo *field, sqlite3_value *val)
  139. {
  140. assertex(val);
  141. if (isNull(val))
  142. {
  143. NullFieldProcessor p(field);
  144. return p.uintResult;
  145. }
  146. if (sqlite3_value_type(val) != SQLITE_INTEGER)
  147. typeError("integer", field);
  148. return (unsigned __int64) sqlite3_value_int64(val);
  149. }
  150. static void getStringResult(const RtlFieldInfo *field, sqlite3_value *val, size32_t &chars, char * &result)
  151. {
  152. assertex(val);
  153. if (isNull(val))
  154. {
  155. NullFieldProcessor p(field);
  156. rtlStrToStrX(chars, result, p.resultChars, p.stringResult);
  157. return;
  158. }
  159. if (sqlite3_value_type(val) != SQLITE_TEXT)
  160. typeError("string", field);
  161. const char *text = (const char *) sqlite3_value_text(val);
  162. int bytes = sqlite3_value_bytes(val);
  163. unsigned numchars = rtlUtf8Length(bytes, text);
  164. rtlUtf8ToStrX(chars, result, numchars, text);
  165. }
  166. static void getUTF8Result(const RtlFieldInfo *field, sqlite3_value *val, size32_t &chars, char * &result)
  167. {
  168. assertex(val);
  169. if (isNull(val))
  170. {
  171. NullFieldProcessor p(field);
  172. rtlUtf8ToUtf8X(chars, result, p.resultChars, p.stringResult);
  173. return;
  174. }
  175. if (sqlite3_value_type(val) != SQLITE_TEXT)
  176. typeError("string", field);
  177. const char *text = (const char *) sqlite3_value_text(val);
  178. int bytes = sqlite3_value_bytes(val);
  179. unsigned numchars = rtlUtf8Length(bytes, text);
  180. rtlUtf8ToUtf8X(chars, result, numchars, text);
  181. }
  182. static void getUnicodeResult(const RtlFieldInfo *field, sqlite3_value *val, size32_t &chars, UChar * &result)
  183. {
  184. assertex(val);
  185. if (isNull(val))
  186. {
  187. NullFieldProcessor p(field);
  188. rtlUnicodeToUnicodeX(chars, result, p.resultChars, p.unicodeResult);
  189. return;
  190. }
  191. if (sqlite3_value_type(val) != SQLITE_TEXT)
  192. typeError("string", field);
  193. const UChar *text = (const UChar *) sqlite3_value_text16(val);
  194. int bytes = sqlite3_value_bytes16(val);
  195. unsigned numchars = bytes / sizeof(UChar);
  196. rtlUnicodeToUnicodeX(chars, result, numchars, text);
  197. }
  198. // A SqLite3RowBuilder object is used to construct an ECL row from a sqlite result
  199. class SqLite3RowBuilder : public CInterfaceOf<IFieldSource>
  200. {
  201. public:
  202. SqLite3RowBuilder(sqlite3_stmt *_stmt)
  203. : stmt(_stmt), val(NULL), colIdx(0)
  204. {
  205. }
  206. virtual bool getBooleanResult(const RtlFieldInfo *field)
  207. {
  208. nextField(field);
  209. return sqlite3embed::getBooleanResult(field, val);
  210. }
  211. virtual void getDataResult(const RtlFieldInfo *field, size32_t &len, void * &result)
  212. {
  213. nextField(field);
  214. sqlite3embed::getDataResult(field, val, len, result);
  215. }
  216. virtual double getRealResult(const RtlFieldInfo *field)
  217. {
  218. nextField(field);
  219. return sqlite3embed::getRealResult(field, val);
  220. }
  221. virtual __int64 getSignedResult(const RtlFieldInfo *field)
  222. {
  223. nextField(field);
  224. return sqlite3embed::getSignedResult(field, val);
  225. }
  226. virtual unsigned __int64 getUnsignedResult(const RtlFieldInfo *field)
  227. {
  228. nextField(field);
  229. return sqlite3embed::getUnsignedResult(field, val);
  230. }
  231. virtual void getStringResult(const RtlFieldInfo *field, size32_t &chars, char * &result)
  232. {
  233. nextField(field);
  234. sqlite3embed::getStringResult(field, val, chars, result);
  235. }
  236. virtual void getUTF8Result(const RtlFieldInfo *field, size32_t &chars, char * &result)
  237. {
  238. nextField(field);
  239. sqlite3embed::getUTF8Result(field, val, chars, result);
  240. }
  241. virtual void getUnicodeResult(const RtlFieldInfo *field, size32_t &chars, UChar * &result)
  242. {
  243. nextField(field);
  244. sqlite3embed::getUnicodeResult(field, val, chars, result);
  245. }
  246. virtual void getDecimalResult(const RtlFieldInfo *field, Decimal &value)
  247. {
  248. nextField(field);
  249. double ret = sqlite3embed::getRealResult(field, val);
  250. value.setReal(ret);
  251. }
  252. virtual void processBeginSet(const RtlFieldInfo * field, bool &isAll)
  253. {
  254. UNSUPPORTED("SET fields");
  255. }
  256. virtual bool processNextSet(const RtlFieldInfo * field)
  257. {
  258. throwUnexpected();
  259. }
  260. virtual void processBeginDataset(const RtlFieldInfo * field)
  261. {
  262. UNSUPPORTED("Nested datasets");
  263. }
  264. virtual void processBeginRow(const RtlFieldInfo * field)
  265. {
  266. }
  267. virtual bool processNextRow(const RtlFieldInfo * field)
  268. {
  269. throwUnexpected();
  270. }
  271. virtual void processEndSet(const RtlFieldInfo * field)
  272. {
  273. throwUnexpected();
  274. }
  275. virtual void processEndDataset(const RtlFieldInfo * field)
  276. {
  277. throwUnexpected();
  278. }
  279. virtual void processEndRow(const RtlFieldInfo * field)
  280. {
  281. }
  282. protected:
  283. void nextField(const RtlFieldInfo * field)
  284. {
  285. val = sqlite3_column_value(stmt, colIdx++);
  286. }
  287. sqlite3_value *val;
  288. sqlite3_stmt *stmt;
  289. unsigned colIdx;
  290. };
  291. // A SqLite3 function that returns a dataset will return a SqLite3RowStream object that can be
  292. // interrogated to return each row of the result in turn
  293. class SqLite3RowStream : public CInterfaceOf<IRowStream>
  294. {
  295. public:
  296. SqLite3RowStream(sqlite3_stmt *_stmt, IEngineRowAllocator *_resultAllocator)
  297. : stmt(_stmt), resultAllocator(_resultAllocator)
  298. {
  299. assertex(stmt);
  300. }
  301. virtual const void *nextRow()
  302. {
  303. if (!stmt)
  304. return NULL;
  305. int rc = sqlite3_step(stmt);
  306. if (rc != SQLITE_ROW)
  307. {
  308. stmt.clear();
  309. return NULL;
  310. }
  311. RtlDynamicRowBuilder rowBuilder(resultAllocator);
  312. SqLite3RowBuilder sqliteRowBuilder(stmt);
  313. const RtlTypeInfo *typeInfo = resultAllocator->queryOutputMeta()->queryTypeInfo();
  314. assertex(typeInfo);
  315. RtlFieldStrInfo dummyField("<row>", NULL, typeInfo);
  316. size32_t len = typeInfo->build(rowBuilder, 0, &dummyField, sqliteRowBuilder);
  317. return rowBuilder.finalizeRowClear(len);
  318. }
  319. virtual void stop()
  320. {
  321. resultAllocator.clear();
  322. stmt.clear();
  323. }
  324. protected:
  325. Linked<IEngineRowAllocator> resultAllocator;
  326. OwnedStatement stmt;
  327. };
  328. // Each call to a SqLite3 function will use a new SqLite3EmbedFunctionContext object
  329. class SqLite3EmbedFunctionContext : public CInterfaceOf<IEmbedFunctionContext>
  330. {
  331. public:
  332. SqLite3EmbedFunctionContext(unsigned _flags, const char *options)
  333. : flags(_flags), db(NULL)
  334. {
  335. const char *dbname = NULL;
  336. StringArray opts;
  337. opts.appendList(options, ",");
  338. ForEachItemIn(idx, opts)
  339. {
  340. const char *opt = opts.item(idx);
  341. const char *val = strchr(opt, '=');
  342. if (val)
  343. {
  344. StringBuffer optName(val-opt, opt);
  345. val++;
  346. if (stricmp(optName, "file")==0)
  347. dbname = val; // Note that lifetime of val is adequate for this to be safe
  348. }
  349. }
  350. if (!dbname)
  351. rtlFail(0, "sqlite3: no filename specified");
  352. int rc = sqlite3_open(dbname, &db);
  353. checkSqliteError(rc);
  354. }
  355. ~SqLite3EmbedFunctionContext()
  356. {
  357. if (db)
  358. sqlite3_close(db);
  359. }
  360. void checkSqliteError(int rc)
  361. {
  362. if (rc != SQLITE_OK)
  363. {
  364. VStringBuffer msg("sqlite: error %d - %s", rc, sqlite3_errmsg(db));
  365. rtlFail(rc, msg.str());
  366. }
  367. }
  368. virtual bool getBooleanResult()
  369. {
  370. return sqlite3embed::getBooleanResult(NULL, getScalarResult());
  371. }
  372. virtual void getDataResult(size32_t &len, void * &result)
  373. {
  374. sqlite3embed::getDataResult(NULL, getScalarResult(), len, result);
  375. }
  376. virtual double getRealResult()
  377. {
  378. return sqlite3embed::getRealResult(NULL, getScalarResult());
  379. }
  380. virtual __int64 getSignedResult()
  381. {
  382. return sqlite3embed::getSignedResult(NULL, getScalarResult());
  383. }
  384. virtual unsigned __int64 getUnsignedResult()
  385. {
  386. return sqlite3embed::getUnsignedResult(NULL, getScalarResult());
  387. }
  388. virtual void getStringResult(size32_t &chars, char * &result)
  389. {
  390. sqlite3embed::getStringResult(NULL, getScalarResult(), chars, result);
  391. }
  392. virtual void getUTF8Result(size32_t &chars, char * &result)
  393. {
  394. sqlite3embed::getUTF8Result(NULL, getScalarResult(), chars, result);
  395. }
  396. virtual void getUnicodeResult(size32_t &chars, UChar * &result)
  397. {
  398. sqlite3embed::getUnicodeResult(NULL, getScalarResult(), chars, result);
  399. }
  400. virtual void getDecimalResult(Decimal &value)
  401. {
  402. double ret = sqlite3embed::getRealResult(NULL, getScalarResult());
  403. value.setReal(ret);
  404. }
  405. virtual void getSetResult(bool & __isAllResult, size32_t & __resultBytes, void * & __result, int elemType, size32_t elemSize)
  406. {
  407. UNSUPPORTED("SET results");
  408. }
  409. virtual IRowStream *getDatasetResult(IEngineRowAllocator * _resultAllocator)
  410. {
  411. return new SqLite3RowStream(stmt.getClear(), _resultAllocator);
  412. }
  413. virtual byte * getRowResult(IEngineRowAllocator * _resultAllocator)
  414. {
  415. RtlDynamicRowBuilder rowBuilder(_resultAllocator);
  416. SqLite3RowBuilder sqliteRowBuilder(stmt);
  417. const RtlTypeInfo *typeInfo = _resultAllocator->queryOutputMeta()->queryTypeInfo();
  418. assertex(typeInfo);
  419. RtlFieldStrInfo dummyField("<row>", NULL, typeInfo);
  420. size32_t len = typeInfo->build(rowBuilder, 0, &dummyField, sqliteRowBuilder);
  421. return (byte *) rowBuilder.finalizeRowClear(len);
  422. }
  423. virtual size32_t getTransformResult(ARowBuilder & rowBuilder)
  424. {
  425. SqLite3RowBuilder sqliteRowBuilder(stmt);
  426. const RtlTypeInfo *typeInfo = rowBuilder.queryAllocator()->queryOutputMeta()->queryTypeInfo();
  427. assertex(typeInfo);
  428. RtlFieldStrInfo dummyField("<row>", NULL, typeInfo);
  429. return typeInfo->build(rowBuilder, 0, &dummyField, sqliteRowBuilder);
  430. }
  431. virtual void bindRowParam(const char *name, IOutputMetaData & metaVal, byte *val)
  432. {
  433. UNSUPPORTED("Row parameters"); // Probably SHOULD support - see MySQL plugin
  434. }
  435. virtual void bindDatasetParam(const char *name, IOutputMetaData & metaVal, IRowStream * val)
  436. {
  437. UNSUPPORTED("Dataset parameters"); // Should support...
  438. }
  439. virtual void bindBooleanParam(const char *name, bool val)
  440. {
  441. checkSqliteError(sqlite3_bind_int64(stmt, findParameter(name), val ? 1 : 0));
  442. }
  443. virtual void bindDataParam(const char *name, size32_t len, const void *val)
  444. {
  445. checkSqliteError(sqlite3_bind_blob(stmt, findParameter(name), val, len, SQLITE_TRANSIENT));
  446. }
  447. virtual void bindFloatParam(const char *name, float val)
  448. {
  449. checkSqliteError(sqlite3_bind_double(stmt, findParameter(name), (double) val));
  450. }
  451. virtual void bindRealParam(const char *name, double val)
  452. {
  453. checkSqliteError(sqlite3_bind_double(stmt, findParameter(name), val));
  454. }
  455. virtual void bindSignedSizeParam(const char *name, int size, __int64 val)
  456. {
  457. bindSignedParam(name, val);
  458. }
  459. virtual void bindSignedParam(const char *name, __int64 val)
  460. {
  461. checkSqliteError(sqlite3_bind_int64(stmt, findParameter(name), val));
  462. }
  463. virtual void bindUnsignedSizeParam(const char *name, int size, unsigned __int64 val)
  464. {
  465. bindUnsignedParam(name, val);
  466. }
  467. virtual void bindUnsignedParam(const char *name, unsigned __int64 val)
  468. {
  469. checkSqliteError(sqlite3_bind_int64(stmt, findParameter(name), val));
  470. }
  471. virtual void bindStringParam(const char *name, size32_t len, const char *val)
  472. {
  473. size32_t utf8chars;
  474. char *utf8;
  475. rtlStrToUtf8X(utf8chars, utf8, len, val);
  476. checkSqliteError(sqlite3_bind_text(stmt, findParameter(name), utf8, rtlUtf8Size(len, utf8), rtlFree));
  477. }
  478. virtual void bindVStringParam(const char *name, const char *val)
  479. {
  480. bindStringParam(name, strlen(val), val);
  481. }
  482. virtual void bindUTF8Param(const char *name, size32_t chars, const char *val)
  483. {
  484. size32_t sizeBytes = rtlUtf8Size(chars, val);
  485. checkSqliteError(sqlite3_bind_text(stmt, findParameter(name), val, sizeBytes, SQLITE_TRANSIENT)); // NOTE - requires size in bytes not chars
  486. }
  487. virtual void bindUnicodeParam(const char *name, size32_t chars, const UChar *val)
  488. {
  489. size32_t sizeBytes = chars * sizeof(UChar);
  490. checkSqliteError(sqlite3_bind_text16(stmt, findParameter(name), val, sizeBytes, SQLITE_TRANSIENT)); // NOTE - requires size in bytes not chars
  491. }
  492. virtual void bindSetParam(const char *name, int elemType, size32_t elemSize, bool isAll, size32_t totalBytes, const void *setData)
  493. {
  494. UNSUPPORTED("SET parameters");
  495. }
  496. virtual IInterface *bindParamWriter(IInterface *esdl, const char *esdlservice, const char *esdltype, const char *name)
  497. {
  498. return NULL;
  499. }
  500. virtual void paramWriterCommit(IInterface *writer)
  501. {
  502. }
  503. virtual void writeResult(IInterface *esdl, const char *esdlservice, const char *esdltype, IInterface *writer)
  504. {
  505. }
  506. virtual void importFunction(size32_t lenChars, const char *text)
  507. {
  508. throwUnexpected();
  509. }
  510. virtual void compileEmbeddedScript(size32_t chars, const char *script)
  511. {
  512. size32_t len = rtlUtf8Size(chars, script);
  513. int rc = sqlite3_prepare_v2(db, script, len, stmt.ref(), NULL);
  514. checkSqliteError(rc);
  515. }
  516. virtual void callFunction()
  517. {
  518. assertex(stmt);
  519. int rc = sqlite3_reset(stmt);
  520. checkSqliteError(rc);
  521. if (flags & EFnoreturn)
  522. {
  523. rc = sqlite3_step(stmt);
  524. if (rc != SQLITE_DONE)
  525. checkSqliteError(rc);
  526. }
  527. }
  528. protected:
  529. sqlite3_value *getScalarResult()
  530. {
  531. int rc = sqlite3_step(stmt);
  532. if (rc != SQLITE_ROW || sqlite3_column_count(stmt) != 1)
  533. typeError("scalar", NULL);
  534. return sqlite3_column_value(stmt, 0);
  535. }
  536. inline int findParameter(const char *name)
  537. {
  538. VStringBuffer pname(":%s", name);
  539. int idx = sqlite3_bind_parameter_index(stmt, pname);
  540. if (!idx)
  541. {
  542. VStringBuffer msg("sqlite3: bound parameter %s not found", name);
  543. rtlFail(0, msg.str());
  544. }
  545. return idx;
  546. }
  547. OwnedStatement stmt;
  548. sqlite3 *db;
  549. unsigned flags;
  550. };
  551. class SqLite3EmbedContext : public CInterfaceOf<IEmbedContext>
  552. {
  553. public:
  554. virtual IEmbedFunctionContext *createFunctionContext(unsigned flags, const char *options)
  555. {
  556. return createFunctionContextEx(NULL, flags, options);
  557. }
  558. virtual IEmbedFunctionContext *createFunctionContextEx(ICodeContext * ctx, unsigned flags, const char *options)
  559. {
  560. if (flags & EFimport)
  561. UNSUPPORTED("IMPORT");
  562. else
  563. return new SqLite3EmbedFunctionContext(flags, options);
  564. }
  565. virtual IEmbedServiceContext *createServiceContext(const char *service, unsigned flags, const char *options)
  566. {
  567. throwUnexpected();
  568. }
  569. };
  570. extern IEmbedContext* getEmbedContext()
  571. {
  572. return new SqLite3EmbedContext();
  573. }
  574. extern bool syntaxCheck(const char *script)
  575. {
  576. return true; // MORE
  577. }
  578. } // namespace