PageRenderTime 63ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 2ms

/modules/SQL/Community.CsharpSqlite.shell/src/shell.cs

https://bitbucket.org/ipre/calico
C# | 4244 lines | 3465 code | 172 blank | 607 comment | 813 complexity | 0ec7fe9f92b91852c8649a6ec6aeded5 MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-3.0, GPL-2.0, GPL-3.0, LGPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. using System;
  2. using System.Diagnostics;
  3. using System.IO;
  4. using System.Runtime.InteropServices;
  5. using System.Text;
  6. using FILE = System.IO.TextWriter;
  7. using GETPROCTIMES = System.IntPtr;
  8. using HANDLE = System.IntPtr;
  9. using HINSTANCE = System.IntPtr;
  10. using sqlite3_int64 = System.Int64;
  11. using u32 = System.UInt32;
  12. using va_list = System.Object;
  13. using Community.CsharpSqlite;
  14. namespace SQL
  15. {
  16. using dxCallback = Sqlite3.dxCallback;
  17. using FILETIME = Sqlite3.FILETIME;
  18. using sqlite3 = Sqlite3.sqlite3;
  19. using sqlite3_stmt = Sqlite3.Vdbe;
  20. using sqlite3_value = Sqlite3.Mem;
  21. public class Shell
  22. {
  23. /*
  24. ** 2001 September 15
  25. **
  26. ** The author disclaims copyright to this source code. In place of
  27. ** a legal notice, here is a blessing:
  28. **
  29. ** May you do good and not evil.
  30. ** May you find forgiveness for yourself and forgive others.
  31. ** May you share freely, never taking more than you give.
  32. **
  33. *************************************************************************
  34. ** This file contains code to implement the "sqlite" command line
  35. ** utility for accessing SQLite databases.
  36. *************************************************************************
  37. ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart
  38. ** C#-SQLite is an independent reimplementation of the SQLite software library
  39. **
  40. *************************************************************************
  41. */
  42. //#if defined(_WIN32) || defined(WIN32)
  43. ///* This needs to come before any includes for MSVC compiler */
  44. //#define _CRT_SECURE_NO_WARNINGS
  45. //#endif
  46. //#include <stdlib.h>
  47. //#include <string.h>
  48. //#include <stdio.h>
  49. //#include <Debug.Assert.h>
  50. //#include "sqlite3.h"
  51. //#include <ctype.h>
  52. //#include <stdarg.h>
  53. //#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__)
  54. //# include <signal.h>
  55. //# if !defined(__RTP__) && !defined(_WRS_KERNEL)
  56. //# include <pwd.h>
  57. //# endif
  58. //# include <unistd.h>
  59. //# include <sys/types.h>
  60. //#endif
  61. //#if __OS2__
  62. //# include <unistd.h>
  63. //#endif
  64. //#if HAVE_EDITLINE
  65. //# include <editline/editline.h>
  66. //#endif
  67. //#if defined(HAVE_READLINE) && HAVE_READLINE==1
  68. //# include <readline/readline.h>
  69. //# include <readline/history.h>
  70. //#endif
  71. #if !(HAVE_EDITLINE) //&& (!(HAVE_READLINE) || HAVE_READLINE!=1)
  72. //# define readline(p) local_getline(p,stdin)
  73. static string readline(string p)
  74. {
  75. return local_getline(p, stdin);
  76. }
  77. //# define add_history(X)
  78. static void add_history(object p) { }
  79. //# define read_history(X)
  80. static void read_history(object p) { }
  81. //# define write_history(X)
  82. static void write_history(object p) { }
  83. //# define stifle_history(X)
  84. static void stifle_history(object p) { }
  85. #endif
  86. #if (_WIN32) || (WIN32)
  87. //# include <io.h>
  88. //#define isatty(h) _isatty(h)
  89. static bool isatty(object h) { return stdin.Equals(Console.In); }
  90. //#define access(f,m) _access((f),(m))
  91. #else
  92. /* Make sure isatty() has a prototype.
  93. */
  94. extern int isatty();
  95. #endif
  96. //#if defined(_WIN32_WCE)
  97. ///* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty()
  98. // * thus we always assume that we have a console. That can be
  99. // * overridden with the -batch command line option.
  100. // */
  101. //#define isatty(x) 1
  102. //#endif
  103. /* True if the timer is enabled */
  104. static bool enableTimer = false;
  105. #if FALSE//!defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) && !defined(__RTP__) && !defined(_WRS_KERNEL)
  106. //#include <sys/time.h>
  107. //#include <sys/resource.h>
  108. ///* Saved resource information for the beginning of an operation */
  109. //static struct rusage sBegin;
  110. ///*
  111. //** Begin timing an operation
  112. //*/
  113. //static void beginTimer(){
  114. // if( enableTimer ){
  115. // getrusage(RUSAGE_SELF, sBegin);
  116. // }
  117. //}
  118. ///* Return the difference of two time_structs in seconds */
  119. //static double timeDiff(timeval pStart, struct timeval pEnd){
  120. // return (pEnd.tv_usec - pStart.tv_usec)*0.000001 +
  121. // (double)(pEnd.tv_sec - pStart.tv_sec);
  122. //}
  123. ///*
  124. //** Print the timing results.
  125. //*/
  126. //static void endTimer(){
  127. // if( enableTimer ){
  128. // struct rusage sEnd;
  129. // getrusage(RUSAGE_SELF, sEnd);
  130. // printf("CPU Time: user %f sys %f\n",
  131. // timeDiff(sBegin.ru_utime, sEnd.ru_utime),
  132. // timeDiff(sBegin.ru_stime, sEnd.ru_stime));
  133. // }
  134. //}
  135. //#define BEGIN_TIMER beginTimer()
  136. //#define END_TIMER endTimer()
  137. //#define HAS_TIMER 1
  138. #elif ((_WIN32) || (WIN32))
  139. //#include <windows.h>
  140. /* Saved resource information for the beginning of an operation */
  141. static Process hProcess;
  142. //static FILETIME ftKernelBegin;
  143. //static FILETIME ftUserBegin;
  144. static TimeSpan tsUserBegin;
  145. static TimeSpan tsKernelBegin;
  146. //typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME, LPFILETIME, LPFILETIME);
  147. /*
  148. ** Check to see if we have timer support. Return 1 if necessary
  149. ** support found (or found previously).
  150. */
  151. //static bool has_timer()
  152. //{
  153. // if (getProcessTimesAddr != IntPtr.Zero)
  154. // {
  155. // return true;
  156. // }
  157. // else
  158. // {
  159. // /* GetProcessTimes() isn't supported in WIN95 and some other Windows versions.
  160. // ** See if the version we are running on has it, and if it does, save off
  161. // ** a pointer to it and the current process handle.
  162. // */
  163. // hProcess = Process.GetCurrentProcess();
  164. // if (hProcess != null)
  165. // {
  166. // HINSTANCE hinstLib = LoadLibrary("Kernel32.dll");
  167. // if (null != hinstLib)
  168. // {
  169. // getProcessTimesAddr = (GETPROCTIMES)GetProcAddress(hinstLib, "GetProcessTimes");
  170. // if (null != getProcessTimesAddr)
  171. // {
  172. // return true;
  173. // }
  174. // FreeLibrary(hinstLib);
  175. // }
  176. // }
  177. // }
  178. // return true;
  179. //}
  180. /*
  181. ** Begin timing an operation
  182. */
  183. static void beginTimer()
  184. {
  185. if (enableTimer)//&& getProcessTimesAddr != IntPtr.Zero)
  186. {
  187. //FILETIME ftCreation, ftExit;
  188. //getProcessTimesAddr(hProcess, ftCreation, ftExit, ftKernelBegin, ftUserBegin);
  189. tsUserBegin = Process.GetCurrentProcess().UserProcessorTime;
  190. tsKernelBegin = Process.GetCurrentProcess().TotalProcessorTime - Process.GetCurrentProcess().UserProcessorTime;
  191. }
  192. }
  193. /* Return the difference of two TimeSpan structs in seconds */
  194. static double timeDiff(TimeSpan pStart, TimeSpan pEnd)
  195. {
  196. //sqlite3_int64 i64Start = ((sqlite3_int64)pStart.dwLowDateTime);
  197. //sqlite3_int64 i64End = ((sqlite3_int64)pEnd.dwLowDateTime);
  198. //return (double)((i64End - i64Start) / 10000000.0);
  199. return timeDiff(pStart, pEnd) / 10000000.0;
  200. }
  201. /*
  202. ** Print the timing results.
  203. */
  204. static void endTimer()
  205. {
  206. if (enableTimer)// && getProcessTimesAddr != IntPtr.Zero)
  207. {
  208. //FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
  209. //getProcessTimesAddr(hProcess, ftCreation, ftExit, ftKernelEnd, ftUserEnd);
  210. TimeSpan tsKernelEnd, tsUserEnd;
  211. tsUserEnd = Process.GetCurrentProcess().UserProcessorTime;
  212. tsKernelEnd = Process.GetCurrentProcess().TotalProcessorTime - Process.GetCurrentProcess().UserProcessorTime;
  213. printf("CPU Time: user %f sys %f\n",
  214. timeDiff(tsUserBegin, tsUserEnd),
  215. timeDiff(tsKernelBegin, tsKernelEnd));
  216. }
  217. }
  218. //#define BEGIN_TIMER beginTimer()
  219. //#define END_TIMER endTimer()
  220. //#define HAS_TIMER HAS_TIMER
  221. static bool HAS_TIMER = true;
  222. #else
  223. //#define BEGIN_TIMER
  224. //#define END_TIMER
  225. //#define HAS_TIMER 0
  226. #endif
  227. /*
  228. ** Used to prevent warnings about unused parameters
  229. */
  230. //#define UNUSED_PARAMETER(x) ()(x)
  231. static void UNUSED_PARAMETER<T>(T x) { }
  232. /*
  233. ** If the following flag is set, then command execution stops
  234. ** at an error if we are not interactive.
  235. */
  236. static bool bail_on_error = false;
  237. /*
  238. ** Threat stdin as an interactive input if the following variable
  239. ** is true. Otherwise, assume stdin is connected to a file or pipe.
  240. */
  241. static bool stdin_is_interactive = true;
  242. /*
  243. ** The following is the open SQLite database. We make a pointer
  244. ** to this database a static variable so that it can be accessed
  245. ** by the SIGINT handler to interrupt database processing.
  246. */
  247. static sqlite3 db = null;
  248. /*
  249. ** True if an interrupt (Control-C) has been received.
  250. */
  251. static bool seenInterrupt = false;
  252. /*
  253. ** This is the name of our program. It is set in main(), used
  254. ** in a number of other places, mostly for error messages.
  255. */
  256. static string Argv0;
  257. /*
  258. ** Prompt strings. Initialized in main. Settable with
  259. ** .prompt main continue
  260. */
  261. static string mainPrompt; /* First line prompt. default: "sqlite> "*/
  262. static string continuePrompt; /* Continuation prompt. default: " ...> " */
  263. /*
  264. ** Write I/O traces to the following stream.
  265. */
  266. #if SQLITE_ENABLE_IOTRACE
  267. static FILE iotrace = null;
  268. #endif
  269. /*
  270. ** This routine works like printf in that its first argument is a
  271. ** format string and subsequent arguments are values to be substituted
  272. ** in place of % fields. The result of formatting this string
  273. ** is written to iotrace.
  274. */
  275. #if SQLITE_ENABLE_IOTRACE
  276. static void iotracePrintf(string zFormat, ...){
  277. va_list ap;
  278. string z;
  279. if( iotrace== null ) return;
  280. va_start(ap, zFormat);
  281. z = Sqlite3.SQLITE_vmprintf(zFormat, ap);
  282. va_end(ap);
  283. fprintf(iotrace, "%s", z);
  284. Sqlite3.sqlite3_free(z);
  285. }
  286. #endif
  287. /*
  288. ** Determines if a string is a number of not.
  289. */
  290. //static int isNumber(string z, ref int realnum){
  291. // if( *z=='-' || *z=='+' ) z++;
  292. // if( !isdigit(*z) ){
  293. // return 0;
  294. // }
  295. // z++;
  296. // //if( realnum ) *realnum = 0;
  297. // realnum = 0;
  298. // while( isdigit(*z) ){ z++; }
  299. // if( *z=='.' ){
  300. // z++;
  301. // if( !isdigit(*z) ) return 0;
  302. // while( isdigit(*z) ){ z++; }
  303. // //if( realnum ) *realnum = 1;
  304. // realnum = 1;
  305. // }
  306. // if( *z=='e' || *z=='E' ){
  307. // z++;
  308. // if( *z=='+' || *z=='-' ) z++;
  309. // if( !isdigit(*z) ) return 0;
  310. // while( isdigit(*z) ){ z++; }
  311. // //if( realnum ) *realnum = 1;
  312. // realnum = 1;
  313. // }
  314. // return *z== null;
  315. //}
  316. static bool isNumber(string z)
  317. {
  318. int i = 0;
  319. return isNumber(z, ref i);
  320. }
  321. static bool isNumber(string z, int i)
  322. {
  323. return isNumber(z, ref i);
  324. }
  325. static bool isNumber(string z, ref int realnum)
  326. {
  327. int zIdx = 0;
  328. if (z[zIdx] == '-' || z[zIdx] == '+')
  329. zIdx++;
  330. if (zIdx == z.Length || !isdigit(z[zIdx]))
  331. {
  332. return false;
  333. }
  334. zIdx++;
  335. realnum = 0;
  336. while (zIdx < z.Length && isdigit(z[zIdx]))
  337. {
  338. zIdx++;
  339. }
  340. if (z[zIdx] == '.')
  341. {
  342. zIdx++;
  343. if (zIdx < z.Length && !isdigit(z[zIdx]))
  344. return false;
  345. while (zIdx < z.Length && isdigit(z[zIdx]))
  346. {
  347. zIdx++;
  348. }
  349. realnum = 1;
  350. }
  351. if (z[zIdx] == 'e' || z[zIdx] == 'E')
  352. {
  353. zIdx++;
  354. if (zIdx < z.Length && (z[zIdx] == '+' || z[zIdx] == '-'))
  355. zIdx++;
  356. if (zIdx == z.Length || !isdigit(z[zIdx]))
  357. return false;
  358. while (zIdx < z.Length && isdigit(z[zIdx]))
  359. {
  360. zIdx++;
  361. }
  362. realnum = 1;
  363. }
  364. return zIdx == z.Length;
  365. }
  366. /*
  367. ** A global char* and an SQL function to access its current value
  368. ** from within an SQL statement. This program used to use the
  369. ** Sqlite3.sqlite3_exec_printf() API to substitue a string into an SQL statement.
  370. ** The correct way to do this with sqlite3 is to use the bind API, but
  371. ** since the shell is built around the callback paradigm it would be a lot
  372. ** of work. Instead just use this hack, which is quite harmless.
  373. */
  374. static string zShellStatic = "";
  375. static void shellstaticFunc(
  376. Sqlite3.sqlite3_context context,
  377. int argc,
  378. sqlite3_value[] argv
  379. )
  380. {
  381. Debug.Assert(0 == argc);
  382. Debug.Assert(String.IsNullOrEmpty(zShellStatic));
  383. UNUSED_PARAMETER(argc);
  384. UNUSED_PARAMETER(argv);
  385. Sqlite3.sqlite3_result_text(context, zShellStatic, -1, Sqlite3.SQLITE_STATIC);
  386. }
  387. /*
  388. ** This routine reads a line of text from FILE in, stores
  389. ** the text in memory obtained from malloc() and returns a pointer
  390. ** to the text. null is returned at end of file, or if malloc()
  391. ** fails.
  392. **
  393. ** The interface is like "readline" but no command-line editing
  394. ** is done.
  395. */
  396. static string local_getline(string zPrompt, TextReader In)
  397. {
  398. StringBuilder zIn = new StringBuilder();
  399. StringBuilder zLine;
  400. int nLine;
  401. int n;
  402. bool eol;
  403. if (zPrompt != null)
  404. {
  405. printf("%s", zPrompt);
  406. fflush(stdout);
  407. }
  408. nLine = 100;
  409. zLine = new StringBuilder(nLine);//malloc( nLine );
  410. //if( zLine== null ) return 0;
  411. n = 0;
  412. eol = false;
  413. while (!eol)
  414. {
  415. if (n + 100 > nLine)
  416. {
  417. nLine = nLine * 2 + 100;
  418. zLine.Capacity = (nLine);//= realloc(zLine, nLine);
  419. //if (zLine == null)
  420. // return null;
  421. }
  422. if (fgets(zIn, nLine - n, In) == 0)
  423. {
  424. if (zLine.Length == 0)
  425. {
  426. zLine = null;//free(zLine);
  427. return null;
  428. }
  429. //zLine[n] = 0;
  430. eol = true;
  431. break;
  432. }
  433. n = 0;
  434. while (n < zLine.Length && zLine[n] != '\0') { n++; }
  435. n = zIn.Length - 1;
  436. if (zIn[n] == '\n')
  437. {
  438. n--;
  439. if (n > 0 && zIn[n - 1] == '\r')
  440. n--;
  441. zIn.Length = n + 1;
  442. eol = true;
  443. }
  444. zLine.Append(zIn);
  445. }
  446. //zLine = realloc( zLine, n+1 );
  447. return zLine.ToString();
  448. }
  449. /*
  450. ** Retrieve a single line of input text.
  451. **
  452. ** zPrior is a string of prior text retrieved. If not the empty
  453. ** string, then issue a continuation prompt.
  454. */
  455. static string one_input_line(string zPrior, TextReader In)
  456. {
  457. string zPrompt;
  458. string zResult;
  459. if (In != null)
  460. {
  461. return local_getline("", In).ToString();
  462. }
  463. if (zPrior != null && zPrior.Length > 0)
  464. {
  465. zPrompt = continuePrompt;
  466. }
  467. else
  468. {
  469. zPrompt = mainPrompt;
  470. }
  471. zResult = readline(zPrompt);
  472. #if (HAVE_READLINE) //&& HAVE_READLINE==1
  473. if( zResult && *zResult ) add_history(zResult);
  474. #endif
  475. return zResult;
  476. }
  477. public class previous_mode_data
  478. {
  479. public bool valid; /* Is there legit data in here? */
  480. public int mode;
  481. public bool showHeader;
  482. public int[] colWidth = new int[200];
  483. };
  484. /*
  485. ** An pointer to an instance of this structure is passed from
  486. ** the main program to the callback. This is used to communicate
  487. ** state and mode information.
  488. */
  489. public class callback_data
  490. {
  491. public sqlite3 db; /* The database */
  492. public bool echoOn; /* True to echo input commands */
  493. public bool statsOn; /* True to display memory stats before each finalize */
  494. public int cnt; /* Number of records displayed so far */
  495. public FILE Out; /* Write results here */
  496. public int mode; /* An output mode setting */
  497. public bool writableSchema; /* True if PRAGMA writable_schema=ON */
  498. public bool showHeader; /* True to show column names in List or Column mode */
  499. public string zDestTable; /* Name of destination table when MODE_Insert */
  500. public string separator = ""; /* Separator character for MODE_List */
  501. public int[] colWidth = new int[200]; /* Requested width of each column when in column mode*/
  502. public int[] actualWidth = new int[200]; /* Actual width of each column */
  503. public string nullvalue = "NULL"; /* The text to print when a null comes back from
  504. ** the database */
  505. public previous_mode_data explainPrev = new previous_mode_data();
  506. /* Holds the mode information just before
  507. ** .explain ON */
  508. public StringBuilder outfile = new StringBuilder(260); /* Filename for Out */
  509. public string zDbFilename; /* name of the database file */
  510. public string zVfs; /* Name of VFS to use */
  511. public sqlite3_stmt pStmt; /* Current statement if any. */
  512. public FILE pLog; /* Write log output here */
  513. internal callback_data Copy()
  514. {
  515. return (callback_data)this.MemberwiseClone();
  516. }
  517. };
  518. // Store callback data variant
  519. class callback_data_extra
  520. {
  521. public string[] azCols; //(string *)pData; /* Names of result columns */
  522. public string[] azVals;//azCols[nCol]; /* Results */
  523. public int[] aiTypes; //(int *)&azVals[nCol]; /* Result types */
  524. }
  525. /*
  526. ** These are the allowed modes.
  527. */
  528. //#define MODE_Line 0 /* One column per line. Blank line between records */
  529. //#define MODE_Column 1 /* One record per line in neat columns */
  530. //#define MODE_List 2 /* One record per line with a separator */
  531. //#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */
  532. //#define MODE_Html 4 /* Generate an XHTML table */
  533. //#define MODE_Insert 5 /* Generate SQL "insert" statements */
  534. //#define MODE_Tcl 6 /* Generate ANSI-C or TCL quoted elements */
  535. //#define MODE_Csv 7 /* Quote strings, numbers are plain */
  536. //#define MODE_Explain 8 /* Like MODE_Column, but do not truncate data */
  537. const int MODE_Line = 0;
  538. const int MODE_Column = 1;
  539. const int MODE_List = 2;
  540. const int MODE_Semi = 3;
  541. const int MODE_Html = 4;
  542. const int MODE_Insert = 5;
  543. const int MODE_Tcl = 6;
  544. const int MODE_Csv = 7;
  545. const int MODE_Explain = 8;
  546. static string[] modeDescr = new string[] {
  547. "line",
  548. "column",
  549. "list",
  550. "semi",
  551. "html",
  552. "insert",
  553. "tcl",
  554. "csv",
  555. "explain",
  556. };
  557. /*
  558. ** Number of elements in an array
  559. */
  560. //#define ArraySize(X) (int)(sizeof(X)/sizeof(X[0]))
  561. static int ArraySize<T>(T[] X) { return X.Length; }
  562. /*
  563. ** Compute a string length that is limited to what can be stored in
  564. ** lower 30 bits of a 32-bit signed integer.
  565. */
  566. static int strlen30(StringBuilder z)
  567. {
  568. //string z2 = z;
  569. //while( *z2 ){ z2++; }
  570. return 0x3fffffff & z.Length;//(int)(z2 - z);
  571. }
  572. static int strlen30(string z)
  573. {
  574. //string z2 = z;
  575. //while( *z2 ){ z2++; }
  576. return 0x3fffffff & z.Length;//(int)(z2 - z);
  577. }
  578. /*
  579. ** A callback for the Sqlite3.SQLITE_log() interface.
  580. */
  581. static void shellLog(object pArg, int iErrCode, string zMsg)
  582. {
  583. callback_data p = (callback_data)pArg;
  584. if (p.pLog == null)
  585. return;
  586. fprintf(p.pLog, "(%d) %s\n", iErrCode, zMsg);
  587. fflush(p.pLog);
  588. }
  589. /*
  590. ** Output the given string as a hex-encoded blob (eg. X'1234' )
  591. */
  592. static void output_hex_blob(FILE Out, byte[] pBlob, int nBlob)
  593. {
  594. int i;
  595. //string zBlob = (string )pBlob;
  596. fprintf(Out, "X'");
  597. for (i = 0; i < nBlob; i++) { fprintf(Out, "%02x", pBlob[i]); }
  598. fprintf(Out, "'");
  599. }
  600. /*
  601. ** Output the given string as a quoted string using SQL quoting conventions.
  602. */
  603. static void output_quoted_string(TextWriter Out, string z)
  604. {
  605. int i;
  606. int nSingle = 0;
  607. for (i = 0; z[i] != '\0'; i++)
  608. {
  609. if (z[i] == '\'')
  610. nSingle++;
  611. }
  612. if (nSingle == 0)
  613. {
  614. fprintf(Out, "'%s'", z);
  615. }
  616. else
  617. {
  618. fprintf(Out, "'");
  619. while (z != "")
  620. {
  621. for (i = 0; i < z.Length && z[i] != '\''; i++)
  622. {
  623. }
  624. if (i == 0)
  625. {
  626. fprintf(Out, "''");
  627. //z++;
  628. }
  629. else if (z[i] == '\'')
  630. {
  631. fprintf(Out, "%.*s''", i, z);
  632. //z += i + 1;
  633. }
  634. else
  635. {
  636. fprintf(Out, "%s", z);
  637. break;
  638. }
  639. }
  640. fprintf(Out, "'");
  641. }
  642. }
  643. /*
  644. ** Output the given string as a quoted according to C or TCL quoting rules.
  645. */
  646. static void output_c_string(TextWriter Out, string z)
  647. {
  648. char c;
  649. fputc('"', Out);
  650. int zIdx = 0;
  651. while (zIdx < z.Length && (c = z[zIdx++]) != '\0')
  652. {
  653. if (c == '\\')
  654. {
  655. fputc(c, Out);
  656. fputc(c, Out);
  657. }
  658. else if (c == '\t')
  659. {
  660. fputc('\\', Out);
  661. fputc('t', Out);
  662. }
  663. else if (c == '\n')
  664. {
  665. fputc('\\', Out);
  666. fputc('n', Out);
  667. }
  668. else if (c == '\r')
  669. {
  670. fputc('\\', Out);
  671. fputc('r', Out);
  672. }
  673. else if (!isprint(c))
  674. {
  675. fprintf(Out, "\\%03o", c & 0xff);
  676. }
  677. else
  678. {
  679. fputc(c, Out);
  680. }
  681. }
  682. fputc('"', Out);
  683. }
  684. /*
  685. ** Output the given string with characters that are special to
  686. ** HTML escaped.
  687. */
  688. static void output_html_string(TextWriter Out, string z)
  689. {
  690. int i;
  691. while (z != "")
  692. {
  693. for (i = 0; i < z.Length && z[i] != '<' && z[i] != '&'; i++)
  694. {
  695. }
  696. if (i > 0)
  697. {
  698. fprintf(Out, "%.*s", i, z);
  699. }
  700. if (i < z.Length && z[i] == '<')
  701. {
  702. fprintf(Out, "&lt;");
  703. }
  704. else if (i < z.Length && z[i] == '&')
  705. {
  706. fprintf(Out, "&amp;");
  707. }
  708. else if (i < z.Length && z[i] == '\"')
  709. {
  710. fprintf(Out, "&quot;");
  711. }
  712. else if (i < z.Length && z[i] == '\'')
  713. {
  714. fprintf(Out, "&#39;");
  715. }
  716. else
  717. {
  718. break;
  719. }
  720. z += i + 1;
  721. }
  722. }
  723. /*
  724. ** If a field contains any character identified by a 1 in the following
  725. ** array, then the string must be quoted for CSV.
  726. */
  727. static byte[] needCsvQuote = new byte[] {
  728. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  729. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  730. 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
  731. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  732. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  733. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  734. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  735. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
  736. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  737. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  738. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  739. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  740. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  741. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  742. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  743. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  744. };
  745. /*
  746. ** Output a single term of CSV. Actually, p.separator is used for
  747. ** the separator, which may or may not be a comma. p.nullvalue is
  748. ** the null value. Strings are quoted using ANSI-C rules. Numbers
  749. ** appear outside of quotes.
  750. */
  751. static void output_csv(callback_data p, string z, bool bSep)
  752. {
  753. TextWriter Out = p.Out;
  754. if (z == null)
  755. {
  756. fprintf(Out, "%s", p.nullvalue);
  757. }
  758. else
  759. {
  760. int i;
  761. int nSep = strlen30(p.separator);
  762. for (i = 0; i < z.Length; i++)
  763. {
  764. if (needCsvQuote[z[i]] != 0
  765. || (z[i] == p.separator[0] &&
  766. (nSep == 1 || z == p.separator)))
  767. {
  768. i = 0;
  769. break;
  770. }
  771. }
  772. if (i == 0)
  773. {
  774. putc('"', Out);
  775. for (i = 0; i < z.Length; i++)
  776. {
  777. if (z[i] == '"')
  778. putc('"', Out);
  779. putc(z[i], Out);
  780. }
  781. putc('"', Out);
  782. }
  783. else
  784. {
  785. fprintf(Out, "%s", z);
  786. }
  787. }
  788. if (bSep)
  789. {
  790. fprintf(p.Out, "%s", p.separator);
  791. }
  792. }
  793. #if SIGINT
  794. /*
  795. ** This routine runs when the user presses Ctrl-C
  796. */
  797. static void interrupt_handler(int NotUsed){
  798. UNUSED_PARAMETER(NotUsed);
  799. seenInterrupt = 1;
  800. if( db ) Sqlite3.SQLITE_interrupt(db);
  801. }
  802. #endif
  803. /*
  804. ** This is the callback routine that the shell
  805. ** invokes for each row of a query result.
  806. */
  807. static int shell_callback(object pArg, sqlite3_int64 nArg, object p2, object p3)
  808. {
  809. int i;
  810. callback_data p = (callback_data)pArg;
  811. //Unpack
  812. string[] azArg = ((callback_data_extra)p2).azVals;
  813. string[] azCol = ((callback_data_extra)p2).azCols;
  814. int[] aiType = ((callback_data_extra)p2).aiTypes;
  815. switch (p.mode)
  816. {
  817. case MODE_Line:
  818. {
  819. int w = 5;
  820. if (azArg == null)
  821. break;
  822. for (i = 0; i < nArg; i++)
  823. {
  824. int len = strlen30(azCol[i] != null ? azCol[i] : "");
  825. if (len > w)
  826. w = len;
  827. }
  828. if (p.cnt++ > 0)
  829. fprintf(p.Out, "\n");
  830. for (i = 0; i < nArg; i++)
  831. {
  832. fprintf(p.Out, "%*s = %s\n", w, azCol[i],
  833. azArg[i] != null ? azArg[i] : p.nullvalue);
  834. }
  835. break;
  836. }
  837. case MODE_Explain:
  838. case MODE_Column:
  839. {
  840. if (p.cnt++ == 0)
  841. {
  842. for (i = 0; i < nArg; i++)
  843. {
  844. int w, n;
  845. if (i < ArraySize(p.colWidth))
  846. {
  847. w = p.colWidth[i];
  848. }
  849. else
  850. {
  851. w = 0;
  852. }
  853. if (w <= 0)
  854. {
  855. w = strlen30(azCol[i] != null ? azCol[i] : "");
  856. if (w < 10)
  857. w = 10;
  858. n = strlen30(azArg != null && azArg[i] != null ? azArg[i] : p.nullvalue);
  859. if (w < n)
  860. w = n;
  861. }
  862. if (i < ArraySize(p.actualWidth))
  863. {
  864. p.actualWidth[i] = w;
  865. }
  866. if (p.showHeader)
  867. {
  868. fprintf(p.Out, "%-*.*s%s", w, w, azCol[i], i == nArg - 1 ? "\n" : " ");
  869. }
  870. }
  871. if (p.showHeader)
  872. {
  873. for (i = 0; i < nArg; i++)
  874. {
  875. int w;
  876. if (i < ArraySize(p.actualWidth))
  877. {
  878. w = p.actualWidth[i];
  879. }
  880. else
  881. {
  882. w = 10;
  883. }
  884. fprintf(p.Out, "%-*.*s%s", w, w, "-----------------------------------" +
  885. "----------------------------------------------------------",
  886. i == nArg - 1 ? "\n" : " ");
  887. }
  888. }
  889. }
  890. if (azArg == null)
  891. break;
  892. for (i = 0; i < nArg; i++)
  893. {
  894. int w;
  895. if (i < ArraySize(p.actualWidth))
  896. {
  897. w = p.actualWidth[i];
  898. }
  899. else
  900. {
  901. w = 10;
  902. }
  903. if (p.mode == MODE_Explain && azArg[i] != null &&
  904. strlen30(azArg[i]) > w)
  905. {
  906. w = strlen30(azArg[i]);
  907. }
  908. fprintf(p.Out, "%-*.*s%s", w, w,
  909. azArg[i] != null ? azArg[i] : p.nullvalue, i == nArg - 1 ? "\n" : " ");
  910. }
  911. break;
  912. }
  913. case MODE_Semi:
  914. case MODE_List:
  915. {
  916. if (p.cnt++ == null && p.showHeader)
  917. {
  918. for (i = 0; i < nArg; i++)
  919. {
  920. fprintf(p.Out, "%s%s", azCol[i], i == nArg - 1 ? "\n" : p.separator);
  921. }
  922. }
  923. if (azArg == null)
  924. break;
  925. for (i = 0; i < nArg; i++)
  926. {
  927. string z = azArg[i];
  928. if (z == null)
  929. z = p.nullvalue;
  930. fprintf(p.Out, "%s", z);
  931. if (i < nArg - 1)
  932. {
  933. fprintf(p.Out, "%s", p.separator);
  934. }
  935. else if (p.mode == MODE_Semi)
  936. {
  937. fprintf(p.Out, ";\n");
  938. }
  939. else
  940. {
  941. fprintf(p.Out, "\n");
  942. }
  943. }
  944. break;
  945. }
  946. case MODE_Html:
  947. {
  948. if (p.cnt++ == null && p.showHeader)
  949. {
  950. fprintf(p.Out, "<TR>");
  951. for (i = 0; i < nArg; i++)
  952. {
  953. fprintf(p.Out, "<TH>");
  954. output_html_string(p.Out, azCol[i]);
  955. fprintf(p.Out, "</TH>\n");
  956. }
  957. fprintf(p.Out, "</TR>\n");
  958. }
  959. if (azArg == null)
  960. break;
  961. fprintf(p.Out, "<TR>");
  962. for (i = 0; i < nArg; i++)
  963. {
  964. fprintf(p.Out, "<TD>");
  965. output_html_string(p.Out, azArg[i] != null ? azArg[i] : p.nullvalue);
  966. fprintf(p.Out, "</TD>\n");
  967. }
  968. fprintf(p.Out, "</TR>\n");
  969. break;
  970. }
  971. case MODE_Tcl:
  972. {
  973. if (p.cnt++ == null && p.showHeader)
  974. {
  975. for (i = 0; i < nArg; i++)
  976. {
  977. output_c_string(p.Out, azCol[i] != null ? azCol[i] : "");
  978. fprintf(p.Out, "%s", p.separator);
  979. }
  980. fprintf(p.Out, "\n");
  981. }
  982. if (azArg == null)
  983. break;
  984. for (i = 0; i < nArg; i++)
  985. {
  986. output_c_string(p.Out, azArg[i] != null ? azArg[i] : p.nullvalue);
  987. fprintf(p.Out, "%s", p.separator);
  988. }
  989. fprintf(p.Out, "\n");
  990. break;
  991. }
  992. case MODE_Csv:
  993. {
  994. if (p.cnt++ == null && p.showHeader)
  995. {
  996. for (i = 0; i < nArg; i++)
  997. {
  998. output_csv(p, azCol[i] != null ? azCol[i] : "", i < nArg - 1);
  999. }
  1000. fprintf(p.Out, "\n");
  1001. }
  1002. if (azArg == null)
  1003. break;
  1004. for (i = 0; i < nArg; i++)
  1005. {
  1006. output_csv(p, azArg[i], i < nArg - 1);
  1007. }
  1008. fprintf(p.Out, "\n");
  1009. break;
  1010. }
  1011. case MODE_Insert:
  1012. {
  1013. p.cnt++;
  1014. if (azArg == null)
  1015. break;
  1016. fprintf(p.Out, "INSERT INTO %s VALUES(", p.zDestTable);
  1017. for (i = 0; i < nArg; i++)
  1018. {
  1019. string zSep = i > 0 ? "," : "";
  1020. if ((azArg[i] == null) || (aiType != null && i < aiType.Length && aiType[i] == Sqlite3.SQLITE_NULL))
  1021. {
  1022. fprintf(p.Out, "%snull", zSep);
  1023. }
  1024. else if (aiType != null && aiType[i] == Sqlite3.SQLITE_TEXT)
  1025. {
  1026. if (!String.IsNullOrEmpty(zSep))
  1027. fprintf(p.Out, "%s", zSep);
  1028. output_quoted_string(p.Out, azArg[i]);
  1029. }
  1030. else if (aiType != null && (aiType[i] == Sqlite3.SQLITE_INTEGER || aiType[i] == Sqlite3.SQLITE_FLOAT))
  1031. {
  1032. fprintf(p.Out, "%s%s", zSep, azArg[i]);
  1033. }
  1034. else if (aiType != null && aiType[i] == Sqlite3.SQLITE_BLOB && p.pStmt != null)
  1035. {
  1036. byte[] pBlob = Sqlite3.sqlite3_column_blob(p.pStmt, i);
  1037. int nBlob = Sqlite3.sqlite3_column_bytes(p.pStmt, i);
  1038. if (!String.IsNullOrEmpty(zSep))
  1039. fprintf(p.Out, "%s", zSep);
  1040. output_hex_blob(p.Out, pBlob, nBlob);
  1041. }
  1042. else if (isNumber(azArg[i], 0))
  1043. {
  1044. fprintf(p.Out, "%s%s", zSep, azArg[i]);
  1045. }
  1046. else
  1047. {
  1048. if (!String.IsNullOrEmpty(zSep))
  1049. fprintf(p.Out, "%s", zSep);
  1050. output_quoted_string(p.Out, azArg[i]);
  1051. }
  1052. }
  1053. fprintf(p.Out, ");\n");
  1054. break;
  1055. }
  1056. }
  1057. return 0;
  1058. }
  1059. /*
  1060. ** This is the callback routine that the SQLite library
  1061. ** invokes for each row of a query result.
  1062. */
  1063. static int callback(object pArg, sqlite3_int64 nArg, object azArg, object azCol)
  1064. {
  1065. /* since we don't have type info, call the shell_callback with a null value */
  1066. callback_data_extra cde = new callback_data_extra();
  1067. cde.azVals = (string[])azArg;
  1068. cde.azCols = (string[])azCol;
  1069. cde.aiTypes = null;
  1070. return shell_callback(pArg, (int)nArg, cde, null);
  1071. }
  1072. /*
  1073. ** Set the destination table field of the callback_data structure to
  1074. ** the name of the table given. Escape any quote characters in the
  1075. ** table name.
  1076. */
  1077. static void set_table_name(callback_data p, string zName)
  1078. {
  1079. int i, n;
  1080. bool needQuote;
  1081. string z = "";
  1082. if (p.zDestTable != null)
  1083. {
  1084. //free(ref p.zDestTable);
  1085. p.zDestTable = null;
  1086. }
  1087. if (zName == null)
  1088. return;
  1089. needQuote = !isalpha(zName[0]) && zName != "_";
  1090. for (i = n = 0; i < zName.Length; i++, n++)
  1091. {
  1092. if (!isalnum(zName[i]) && zName[i] != '_')
  1093. {
  1094. needQuote = true;
  1095. if (zName[i] == '\'')
  1096. n++;
  1097. }
  1098. }
  1099. if (needQuote)
  1100. n += 2;
  1101. //z = p.zDestTable = malloc( n + 1 );
  1102. //if ( z == 0 )
  1103. //{
  1104. // fprintf( stderr, "Out of memory!\n" );
  1105. // exit( 1 );
  1106. //}
  1107. //n = 0;
  1108. if (needQuote)
  1109. z += '\'';
  1110. for (i = 0; i < zName.Length; i++)
  1111. {
  1112. z += zName[i];
  1113. if (zName[i] == '\'')
  1114. z += '\'';
  1115. }
  1116. if (needQuote)
  1117. z += '\'';
  1118. //z[n] = 0;
  1119. p.zDestTable = z;
  1120. }
  1121. /* zIn is either a pointer to a null-terminated string in memory obtained
  1122. ** from malloc(), or a null pointer. The string pointed to by zAppend is
  1123. ** added to zIn, and the result returned in memory obtained from malloc().
  1124. ** zIn, if it was not null, is freed.
  1125. **
  1126. ** If the third argument, quote, is not '\0', then it is used as a
  1127. ** quote character for zAppend.
  1128. */
  1129. static void appendText(StringBuilder zIn, string zAppend, int noQuote)
  1130. { appendText(zIn, zAppend, '\0'); }
  1131. static void appendText(StringBuilder zIn, string zAppend, char quote)
  1132. {
  1133. int len;
  1134. int i;
  1135. int nAppend = strlen30(zAppend);
  1136. int nIn = (zIn != null ? strlen30(zIn) : 0);
  1137. len = nAppend + nIn;
  1138. if (quote != '\0')
  1139. {
  1140. len += 2;
  1141. for (i = 0; i < nAppend; i++)
  1142. {
  1143. if (zAppend[i] == quote)
  1144. len++;
  1145. }
  1146. }
  1147. //zIn = realloc( zIn, len );
  1148. //if ( !zIn )
  1149. //{
  1150. // return 0;
  1151. //}
  1152. if (quote != '\0')
  1153. {
  1154. zIn.Append(quote);
  1155. for (i = 0; i < nAppend; i++)
  1156. {
  1157. zIn.Append(zAppend[i]);
  1158. if (zAppend[i] == quote)
  1159. zIn.Append(quote);
  1160. }
  1161. zIn.Append(quote);
  1162. //zCsr++ = '\0';
  1163. Debug.Assert(zIn.Length == len);
  1164. }
  1165. else
  1166. {
  1167. zIn.Append(zAppend);//memcpy( zIn[nIn], zAppend, nAppend );
  1168. //zIn[len - 1] = '\0';
  1169. }
  1170. }
  1171. /*
  1172. ** Execute a query statement that has a single result column. Print
  1173. ** that result column on a line by itself with a semicolon terminator.
  1174. **
  1175. ** This is used, for example, to show the schema of the database by
  1176. ** querying the Sqlite3.SQLITE_MASTER table.
  1177. */
  1178. static int run_table_dump_query(
  1179. FILE Out, /* Send output here */
  1180. sqlite3 db, /* Database to query */
  1181. StringBuilder zSelect, /* SELECT statement to extract content */
  1182. string zFirstRow /* Print before first row, if not null */
  1183. )
  1184. { return run_table_dump_query(Out, db, zSelect.ToString(), zFirstRow); }
  1185. static int run_table_dump_query(
  1186. FILE Out, /* Send output here */
  1187. sqlite3 db, /* Database to query */
  1188. string zSelect, /* SELECT statement to extract content */
  1189. string zFirstRow /* Print before first row, if not null */
  1190. )
  1191. {
  1192. sqlite3_stmt pSelect = null;
  1193. int rc;
  1194. rc = Sqlite3.sqlite3_prepare(db, zSelect, -1, ref pSelect, 0);
  1195. if (rc != Sqlite3.SQLITE_OK || null == pSelect)
  1196. {
  1197. return rc;
  1198. }
  1199. rc = Sqlite3.sqlite3_step(pSelect);
  1200. while (rc == Sqlite3.SQLITE_ROW)
  1201. {
  1202. if (zFirstRow != null)
  1203. {
  1204. fprintf(Out, "%s", zFirstRow);
  1205. zFirstRow = null;
  1206. }
  1207. fprintf(Out, "%s;\n", Sqlite3.sqlite3_column_text(pSelect, 0));
  1208. rc = Sqlite3.sqlite3_step(pSelect);
  1209. }
  1210. return Sqlite3.sqlite3_finalize(pSelect);
  1211. }
  1212. /*
  1213. ** Allocate space and save off current error string.
  1214. */
  1215. static string save_err_msg(
  1216. sqlite3 db /* Database to query */
  1217. )
  1218. {
  1219. //int nErrMsg = 1 + strlen30(Sqlite3.sqlite3_errmsg(db));
  1220. //string zErrMsg = Sqlite3.sqlite3_malloc(nErrMsg);
  1221. //if (zErrMsg != null)
  1222. //{
  1223. // memcpy(zErrMsg, Sqlite3.sqlite3_errmsg(db), nErrMsg);
  1224. //}
  1225. return Sqlite3.sqlite3_errmsg(db); //zErrMsg;
  1226. }
  1227. /*
  1228. ** Display memory stats.
  1229. */
  1230. static int display_stats(
  1231. sqlite3 db, /* Database to query */
  1232. callback_data pArg, /* Pointer to struct callback_data */
  1233. int bReset /* True to reset the stats */
  1234. )
  1235. {
  1236. int iCur;
  1237. int iHiwtr;
  1238. if (pArg != null && pArg.Out != null)
  1239. {
  1240. iHiwtr = iCur = -1;
  1241. Sqlite3.sqlite3_status(Sqlite3.SQLITE_STATUS_MEMORY_USED, ref iCur, ref iHiwtr, bReset);
  1242. fprintf(pArg.Out, "Memory Used: %d (max %d) bytes\n", iCur, iHiwtr);
  1243. iHiwtr = iCur = -1;
  1244. Sqlite3.sqlite3_status(Sqlite3.SQLITE_STATUS_MALLOC_COUNT, ref iCur, ref iHiwtr, bReset);
  1245. fprintf(pArg.Out, "Number of Outstanding Allocations: %d (max %d)\n", iCur, iHiwtr);
  1246. /*
  1247. ** Not currently used by the CLI.
  1248. ** iHiwtr = iCur = -1;
  1249. ** Sqlite3.SQLITE_status(Sqlite3.SQLITE_STATUS_PAGECACHE_USED,ref iCur,ref iHiwtr, bReset);
  1250. ** fprintf(pArg.Out, "Number of Pcache Pages Used: %d (max %d) pages\n", iCur, iHiwtr);
  1251. */
  1252. iHiwtr = iCur = -1;
  1253. Sqlite3.sqlite3_status(Sqlite3.SQLITE_STATUS_PAGECACHE_OVERFLOW, ref iCur, ref iHiwtr, bReset);
  1254. fprintf(pArg.Out, "Number of Pcache Overflow Bytes: %d (max %d) bytes\n", iCur, iHiwtr);
  1255. /*
  1256. ** Not currently used by the CLI.
  1257. ** iHiwtr = iCur = -1;
  1258. ** Sqlite3.SQLITE_status(Sqlite3.SQLITE_STATUS_SCRATCH_USED,ref iCur,ref iHiwtr, bReset);
  1259. ** fprintf(pArg.Out, "Number of Scratch Allocations Used: %d (max %d)\n", iCur, iHiwtr);
  1260. */
  1261. iHiwtr = iCur = -1;
  1262. Sqlite3.sqlite3_status(Sqlite3.SQLITE_STATUS_SCRATCH_OVERFLOW, ref iCur, ref iHiwtr, bReset);
  1263. fprintf(pArg.Out, "Number of Scratch Overflow Bytes: %d (max %d) bytes\n", iCur, iHiwtr);
  1264. iHiwtr = iCur = -1;
  1265. Sqlite3.sqlite3_status(Sqlite3.SQLITE_STATUS_MALLOC_SIZE, ref iCur, ref iHiwtr, bReset);
  1266. fprintf(pArg.Out, "Largest Allocation: %d bytes\n", iHiwtr);
  1267. iHiwtr = iCur = -1;
  1268. Sqlite3.sqlite3_status(Sqlite3.SQLITE_STATUS_PAGECACHE_SIZE, ref iCur, ref iHiwtr, bReset);
  1269. fprintf(pArg.Out, "Largest Pcache Allocation: %d bytes\n", iHiwtr);
  1270. iHiwtr = iCur = -1;
  1271. Sqlite3.sqlite3_status(Sqlite3.SQLITE_STATUS_SCRATCH_SIZE, ref iCur, ref iHiwtr, bReset);
  1272. fprintf(pArg.Out, "Largest Scratch Allocation: %d bytes\n", iHiwtr);
  1273. #if YYTRACKMAXSTACKDEPTH
  1274. iHiwtr = iCur = -1;
  1275. Sqlite3.SQLITE_status(Sqlite3.SQLITE_STATUS_PARSER_STACK,ref iCur,ref iHiwtr, bReset);
  1276. fprintf(pArg.Out, "Deepest Parser Stack: %d (max %d)\n", iCur, iHiwtr);
  1277. #endif
  1278. }
  1279. if (pArg != null && pArg.Out != null && db != null)
  1280. {
  1281. iHiwtr = iCur = -1;
  1282. Sqlite3.sqlite3_db_status(db, Sqlite3.SQLITE_DBSTATUS_LOOKASIDE_USED, ref iCur, ref iHiwtr, bReset);
  1283. fprintf(pArg.Out, "Lookaside Slots Used: %d (max %d)\n", iCur, iHiwtr);
  1284. Sqlite3.sqlite3_db_status(db, Sqlite3.SQLITE_DBSTATUS_LOOKASIDE_HIT, ref iCur, ref iHiwtr, bReset);
  1285. fprintf(pArg.Out, "Successful lookaside attempts: %d\n", iHiwtr);
  1286. Sqlite3.sqlite3_db_status(db, Sqlite3.SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, ref iCur, ref iHiwtr, bReset);
  1287. fprintf(pArg.Out, "Lookaside failures due to size: %d\n", iHiwtr);

Large files files are truncated, but you can click here to view the full file