10181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* DO NOT EDIT!
20181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This file is automatically generated by the script in the canonical
30181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** SQLite source tree at tool/mkshellc.tcl.  That script combines source
40181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** code from various constituent source files of SQLite into this single
50181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** "shell.c" file used to implement the SQLite command-line shell.
60181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
70181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Most of the code found below comes from the "src/shell.c.in" file in
80181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** the canonical SQLite source tree.  That main file contains "INCLUDE"
90181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** lines that specify other files in the canonical source tree that are
100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** inserted to getnerate this complete program source file.
110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The code from multiple files is combined into this single "shell.c"
130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** source file to help make the command-line program easier to compile.
140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** To modify this program, get a copy of the canonical SQLite source tree,
160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** edit the src/shell.c.in" and/or some of the other files that are included
170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** by "src/shell.c.in", then rerun the tool/mkshellc.tcl script.
180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
197790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
207790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** 2001 September 15
217790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project**
227790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** The author disclaims copyright to this source code.  In place of
237790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** a legal notice, here is a blessing:
247790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project**
257790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project**    May you do good and not evil.
267790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project**    May you find forgiveness for yourself and forgive others.
277790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project**    May you share freely, never taking more than you give.
287790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project**
297790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*************************************************************************
307790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** This file contains code to implement the "sqlite" command line
317790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** utility for accessing SQLite databases.
327790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
3390ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown#if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS)
34a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori/* This needs to come before any includes for MSVC compiler */
35a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori#define _CRT_SECURE_NO_WARNINGS
367790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#endif
377790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
3890ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown/*
390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Warning pragmas copied from msvc.h in the core.
400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if defined(_MSC_VER)
420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#pragma warning(disable : 4054)
430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#pragma warning(disable : 4055)
440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#pragma warning(disable : 4100)
450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#pragma warning(disable : 4127)
460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#pragma warning(disable : 4130)
470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#pragma warning(disable : 4152)
480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#pragma warning(disable : 4189)
490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#pragma warning(disable : 4206)
500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#pragma warning(disable : 4210)
510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#pragma warning(disable : 4232)
520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#pragma warning(disable : 4244)
530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#pragma warning(disable : 4305)
540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#pragma warning(disable : 4306)
550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#pragma warning(disable : 4702)
560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#pragma warning(disable : 4706)
570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif /* defined(_MSC_VER) */
583fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
593fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich/*
603fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich** No support for loadable extensions in VxWorks.
613fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich*/
623fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION
633fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich# define SQLITE_OMIT_LOAD_EXTENSION 1
643fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#endif
653fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
663fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich/*
6790ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown** Enable large-file support for fopen() and friends on unix.
6890ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown*/
6990ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown#ifndef SQLITE_DISABLE_LFS
7090ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown# define _LARGE_FILE       1
7190ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown# ifndef _FILE_OFFSET_BITS
7290ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown#   define _FILE_OFFSET_BITS 64
7390ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown# endif
7490ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown# define _LARGEFILE_SOURCE 1
7590ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown#endif
7690ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown
777790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#include <stdlib.h>
787790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#include <string.h>
797790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#include <stdio.h>
807790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#include <assert.h>
817790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#include "sqlite3.h"
820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef sqlite3_int64 i64;
830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef sqlite3_uint64 u64;
840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef unsigned char u8;
853fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#if SQLITE_USER_AUTHENTICATION
863fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich# include "sqlite3userauth.h"
873fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#endif
887790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#include <ctype.h>
897790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#include <stdarg.h>
90c296bf9f8755fadd4e87c76f0a66d9e626c51b55Vasu Nori// Begin Android Add
91c296bf9f8755fadd4e87c76f0a66d9e626c51b55Vasu Nori#ifndef NO_ANDROID_FUNCS
9255536230a14a7c199bbe41a83893c7d82e0c0a24Neil Fuller#include "IcuUtils.h"
93c296bf9f8755fadd4e87c76f0a66d9e626c51b55Vasu Nori#include <sqlite3_android.h>
94c296bf9f8755fadd4e87c76f0a66d9e626c51b55Vasu Nori#endif
95c296bf9f8755fadd4e87c76f0a66d9e626c51b55Vasu Nori// End Android Add
96c296bf9f8755fadd4e87c76f0a66d9e626c51b55Vasu Nori
978fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich#if !defined(_WIN32) && !defined(WIN32)
987790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project# include <signal.h>
99a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori# if !defined(__RTP__) && !defined(_WRS_KERNEL)
100a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori#  include <pwd.h>
101a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori# endif
1020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
1030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if (!defined(_WIN32) && !defined(WIN32)) || defined(__MINGW32__)
1047790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project# include <unistd.h>
1050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# include <dirent.h>
1060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# if defined(__MINGW32__)
1070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#  define DIRENT dirent
1080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#  ifndef S_ISLNK
1090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#   define S_ISLNK(mode) (0)
1100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#  endif
1110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# endif
1127790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#endif
1130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <sys/types.h>
1140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <sys/stat.h>
1157790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
1163fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#if HAVE_READLINE
1177790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project# include <readline/readline.h>
1187790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project# include <readline/history.h>
1198fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich#endif
1203fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
1213fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#if HAVE_EDITLINE
1228fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich# include <editline/readline.h>
12390ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown#endif
1243fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
1253fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#if HAVE_EDITLINE || HAVE_READLINE
1263fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
1273fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich# define shell_add_history(X) add_history(X)
1283fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich# define shell_read_history(X) read_history(X)
1293fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich# define shell_write_history(X) write_history(X)
1303fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich# define shell_stifle_history(X) stifle_history(X)
1313fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich# define shell_readline(X) readline(X)
1323fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
1333fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#elif HAVE_LINENOISE
1343fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
1353fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich# include "linenoise.h"
1363fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich# define shell_add_history(X) linenoiseHistoryAdd(X)
1373fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich# define shell_read_history(X) linenoiseHistoryLoad(X)
1383fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich# define shell_write_history(X) linenoiseHistorySave(X)
1393fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich# define shell_stifle_history(X) linenoiseHistorySetMaxLen(X)
1403fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich# define shell_readline(X) linenoise(X)
1413fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
1423fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#else
1433fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
14460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis# define shell_read_history(X)
1453fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich# define shell_write_history(X)
1463fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich# define shell_stifle_history(X)
1473fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
1483fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich# define SHELL_USE_LOCAL_GETLINE 1
1497790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#endif
1507790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
1513fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
1527790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#if defined(_WIN32) || defined(WIN32)
1537790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project# include <io.h>
1549bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown# include <fcntl.h>
155253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich# define isatty(h) _isatty(h)
156253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich# ifndef access
157253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich#  define access(f,m) _access((f),(m))
158253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich# endif
159253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich# undef popen
160253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich# define popen _popen
161253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich# undef pclose
162253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich# define pclose _pclose
1637790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#else
164253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich /* Make sure isatty() has a prototype. */
165253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich extern int isatty(int);
1663fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
167253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich# if !defined(__RTP__) && !defined(_WRS_KERNEL)
168253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich  /* popen and pclose are not C89 functions and so are
169253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich  ** sometimes omitted from the <stdio.h> header */
170253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich   extern FILE *popen(const char*,const char*);
171253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich   extern int pclose(FILE*);
172253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich# else
173253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich#  define SQLITE_OMIT_POPEN 1
174253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich# endif
1757790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#endif
1767790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
1777790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#if defined(_WIN32_WCE)
1787790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty()
1797790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project * thus we always assume that we have a console. That can be
1807790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project * overridden with the -batch command line option.
1817790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project */
1827790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#define isatty(x) 1
1837790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#endif
1847790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
18590ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown/* ctype macros that work with signed characters */
18690ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown#define IsSpace(X)  isspace((unsigned char)X)
18790ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown#define IsDigit(X)  isdigit((unsigned char)X)
18890ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown#define ToLower(X)  (char)tolower((unsigned char)X)
18990ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown
19060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#if defined(_WIN32) || defined(WIN32)
19160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#include <windows.h>
19260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
19360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis/* string conversion routines only needed on Win32 */
19460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidisextern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
19560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidisextern char *sqlite3_win32_mbcs_to_utf8_v2(const char *, int);
19660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidisextern char *sqlite3_win32_utf8_to_mbcs_v2(const char *, int);
19708f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidisextern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText);
19860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#endif
19960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
2003fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich/* On Windows, we normally run with output mode of TEXT so that \n characters
2013fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich** are automatically translated into \r\n.  However, this behavior needs
2023fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich** to be disabled in some cases (ex: when generating CSV output and when
2033fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich** rendering quoted strings that contain \n characters).  The following
2043fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich** routines take care of that.
2053fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich*/
2063fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#if defined(_WIN32) || defined(WIN32)
20760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidisstatic void setBinaryMode(FILE *file, int isOutput){
20860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  if( isOutput ) fflush(file);
20960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  _setmode(_fileno(file), _O_BINARY);
2103fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich}
21160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidisstatic void setTextMode(FILE *file, int isOutput){
21260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  if( isOutput ) fflush(file);
21360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  _setmode(_fileno(file), _O_TEXT);
2143fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich}
2153fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#else
21660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis# define setBinaryMode(X,Y)
21760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis# define setTextMode(X,Y)
2183fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#endif
2193fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
2208fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
2218fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich/* True if the timer is enabled */
2228fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevichstatic int enableTimer = 0;
2238fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
2248fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich/* Return the current wall-clock time */
2258fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevichstatic sqlite3_int64 timeOfDay(void){
2268fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  static sqlite3_vfs *clockVfs = 0;
2278fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  sqlite3_int64 t;
2288fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
22960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
2308fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    clockVfs->xCurrentTimeInt64(clockVfs, &t);
2318fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }else{
2328fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    double r;
2338fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    clockVfs->xCurrentTime(clockVfs, &r);
2348fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    t = (sqlite3_int64)(r*86400000.0);
2358fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }
2368fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  return t;
2378fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich}
2388fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
2393fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux)
2407790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#include <sys/time.h>
2417790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#include <sys/resource.h>
2427790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
2433fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich/* VxWorks does not support getrusage() as far as we can determine */
2443fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#if defined(_WRS_KERNEL) || defined(__RTP__)
2453fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichstruct rusage {
2463fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  struct timeval ru_utime; /* user CPU time used */
2473fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  struct timeval ru_stime; /* system CPU time used */
2483fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich};
2493fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#define getrusage(A,B) memset(B,0,sizeof(*B))
2503fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#endif
2513fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
2527790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/* Saved resource information for the beginning of an operation */
2538fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevichstatic struct rusage sBegin;  /* CPU time at start */
2548fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevichstatic sqlite3_int64 iBegin;  /* Wall-clock time at start */
2557790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
2567790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
2577790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** Begin timing an operation
2587790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
2597790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Projectstatic void beginTimer(void){
2607790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if( enableTimer ){
2617790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    getrusage(RUSAGE_SELF, &sBegin);
2628fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    iBegin = timeOfDay();
2637790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
2647790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
2657790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
266a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori/* Return the difference of two time_structs in seconds */
267a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Noristatic double timeDiff(struct timeval *pStart, struct timeval *pEnd){
26860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  return (pEnd->tv_usec - pStart->tv_usec)*0.000001 +
269a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori         (double)(pEnd->tv_sec - pStart->tv_sec);
2707790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
2717790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
2727790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
2737790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** Print the timing results.
2747790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
2757790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Projectstatic void endTimer(void){
2767790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if( enableTimer ){
2778fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    sqlite3_int64 iEnd = timeOfDay();
2783fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    struct rusage sEnd;
2797790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    getrusage(RUSAGE_SELF, &sEnd);
2808fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    printf("Run Time: real %.3f user %f sys %f\n",
2818fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich       (iEnd - iBegin)*0.001,
282a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori       timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
283a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori       timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
2847790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
2857790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
286a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori
2877790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#define BEGIN_TIMER beginTimer()
2887790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#define END_TIMER endTimer()
2897790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#define HAS_TIMER 1
290a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori
291a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori#elif (defined(_WIN32) || defined(WIN32))
292a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori
293a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori/* Saved resource information for the beginning of an operation */
294a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Noristatic HANDLE hProcess;
295a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Noristatic FILETIME ftKernelBegin;
296a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Noristatic FILETIME ftUserBegin;
2978fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevichstatic sqlite3_int64 ftWallBegin;
2983fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichtypedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME,
2993fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich                                    LPFILETIME, LPFILETIME);
300a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Noristatic GETPROCTIMES getProcessTimesAddr = NULL;
301a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori
302a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori/*
303a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori** Check to see if we have timer support.  Return 1 if necessary
304a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori** support found (or found previously).
305a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori*/
306a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Noristatic int hasTimer(void){
307a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  if( getProcessTimesAddr ){
308a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    return 1;
309a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  } else {
3103fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    /* GetProcessTimes() isn't supported in WIN95 and some other Windows
3113fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    ** versions. See if the version we are running on has it, and if it
3123fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    ** does, save off a pointer to it and the current process handle.
313a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    */
314a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    hProcess = GetCurrentProcess();
315a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    if( hProcess ){
316a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
317a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      if( NULL != hinstLib ){
3183fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        getProcessTimesAddr =
3193fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich            (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
320a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori        if( NULL != getProcessTimesAddr ){
321a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori          return 1;
322a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori        }
32360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        FreeLibrary(hinstLib);
324a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      }
325a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }
326a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  }
327a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  return 0;
328a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori}
329a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori
330a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori/*
331a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori** Begin timing an operation
332a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori*/
333a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Noristatic void beginTimer(void){
334a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  if( enableTimer && getProcessTimesAddr ){
335a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    FILETIME ftCreation, ftExit;
3363fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    getProcessTimesAddr(hProcess,&ftCreation,&ftExit,
3373fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich                        &ftKernelBegin,&ftUserBegin);
3388fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    ftWallBegin = timeOfDay();
339a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  }
340a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori}
341a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori
342a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori/* Return the difference of two FILETIME structs in seconds */
343a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Noristatic double timeDiff(FILETIME *pStart, FILETIME *pEnd){
344a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  sqlite_int64 i64Start = *((sqlite_int64 *) pStart);
345a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  sqlite_int64 i64End = *((sqlite_int64 *) pEnd);
346a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  return (double) ((i64End - i64Start) / 10000000.0);
347a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori}
348a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori
349a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori/*
350a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori** Print the timing results.
351a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori*/
352a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Noristatic void endTimer(void){
353a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  if( enableTimer && getProcessTimesAddr){
354a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
3558fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    sqlite3_int64 ftWallEnd = timeOfDay();
3563fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
3578fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    printf("Run Time: real %.3f user %f sys %f\n",
3588fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich       (ftWallEnd - ftWallBegin)*0.001,
359a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori       timeDiff(&ftUserBegin, &ftUserEnd),
360a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori       timeDiff(&ftKernelBegin, &ftKernelEnd));
361a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  }
362a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori}
363a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori
364a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori#define BEGIN_TIMER beginTimer()
365a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori#define END_TIMER endTimer()
366a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori#define HAS_TIMER hasTimer()
367a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori
3687790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#else
36960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#define BEGIN_TIMER
3707790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#define END_TIMER
3717790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#define HAS_TIMER 0
3727790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#endif
3737790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
374a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori/*
375a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori** Used to prevent warnings about unused parameters
376a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori*/
377a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori#define UNUSED_PARAMETER(x) (void)(x)
378a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori
3797790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
3800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Number of elements in an array
3810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
3820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define ArraySize(X)  (int)(sizeof(X)/sizeof(X[0]))
3830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
3840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
3857790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** If the following flag is set, then command execution stops
3867790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** at an error if we are not interactive.
3877790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
3887790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Projectstatic int bail_on_error = 0;
3897790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
3907790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
3917790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** Threat stdin as an interactive input if the following variable
3927790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** is true.  Otherwise, assume stdin is connected to a file or pipe.
3937790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
3947790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Projectstatic int stdin_is_interactive = 1;
3957790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
3967790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
39760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** On Windows systems we have to know if standard output is a console
39860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** in order to translate UTF-8 into MBCS.  The following variable is
39960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** true if translation is required.
40060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis*/
40160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidisstatic int stdout_is_console = 1;
40260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
40360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis/*
4047790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** The following is the open SQLite database.  We make a pointer
4057790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** to this database a static variable so that it can be accessed
4067790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** by the SIGINT handler to interrupt database processing.
4077790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
4083a6c79f802fabdb94367177310663397420e319fNick Kralevichstatic sqlite3 *globalDb = 0;
4097790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
4107790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
4117790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** True if an interrupt (Control-C) has been received.
4127790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
4137790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Projectstatic volatile int seenInterrupt = 0;
4147790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
4157790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
4167790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** This is the name of our program. It is set in main(), used
4177790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** in a number of other places, mostly for error messages.
4187790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
4197790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Projectstatic char *Argv0;
4207790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
4217790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
4227790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** Prompt strings. Initialized in main. Settable with
4237790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project**   .prompt main continue
4247790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
4257790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Projectstatic char mainPrompt[20];     /* First line prompt. default: "sqlite> "*/
4267790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Projectstatic char continuePrompt[20]; /* Continuation prompt. default: "   ...> " */
4277790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
4287790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
42960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** Render output like fprintf().  Except, if the output is going to the
43060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** console and if this is running on a Windows machine, translate the
43160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** output from UTF-8 into MBCS.
43260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis*/
43360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#if defined(_WIN32) || defined(WIN32)
43460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidisvoid utf8_printf(FILE *out, const char *zFormat, ...){
43560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  va_list ap;
43660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  va_start(ap, zFormat);
43760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  if( stdout_is_console && (out==stdout || out==stderr) ){
43860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    char *z1 = sqlite3_vmprintf(zFormat, ap);
43960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0);
44060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    sqlite3_free(z1);
44160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    fputs(z2, out);
44260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    sqlite3_free(z2);
44360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  }else{
44460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    vfprintf(out, zFormat, ap);
44560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  }
44660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  va_end(ap);
44760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis}
44860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#elif !defined(utf8_printf)
44960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis# define utf8_printf fprintf
45060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#endif
45160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
45260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis/*
45360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** Render output like fprintf().  This should not be used on anything that
45460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** includes string formatting (e.g. "%s").
45560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis*/
45660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#if !defined(raw_printf)
45760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis# define raw_printf fprintf
45860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#endif
45960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
46060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis/*
4617790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** Write I/O traces to the following stream.
4627790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
4637790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#ifdef SQLITE_ENABLE_IOTRACE
4647790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Projectstatic FILE *iotrace = 0;
4657790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#endif
4667790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
4677790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
4687790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** This routine works like printf in that its first argument is a
4697790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** format string and subsequent arguments are values to be substituted
4707790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** in place of % fields.  The result of formatting this string
4717790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** is written to iotrace.
4727790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
4737790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#ifdef SQLITE_ENABLE_IOTRACE
4743fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichstatic void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){
4757790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  va_list ap;
4767790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  char *z;
4777790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if( iotrace==0 ) return;
4787790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  va_start(ap, zFormat);
4797790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  z = sqlite3_vmprintf(zFormat, ap);
4807790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  va_end(ap);
48160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  utf8_printf(iotrace, "%s", z);
4827790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  sqlite3_free(z);
4837790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
4847790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#endif
4857790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
486b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis/*
487b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis** Output string zUtf to stream pOut as w characters.  If w is negative,
488b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis** then right-justify the text.  W is the width in UTF-8 characters, not
489b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis** in bytes.  This is different from the %*.*s specification in printf
490b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis** since with %*.*s the width is measured in bytes, not characters.
491b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis*/
492b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidisstatic void utf8_width_print(FILE *pOut, int w, const char *zUtf){
493b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  int i;
494b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  int n;
495b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  int aw = w<0 ? -w : w;
496b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  char zBuf[1000];
497b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  if( aw>(int)sizeof(zBuf)/3 ) aw = (int)sizeof(zBuf)/3;
498b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  for(i=n=0; zUtf[i]; i++){
499b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    if( (zUtf[i]&0xc0)!=0x80 ){
500b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      n++;
501b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      if( n==aw ){
502b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis        do{ i++; }while( (zUtf[i]&0xc0)==0x80 );
503b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis        break;
504b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      }
505b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    }
506b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  }
507b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  if( n>=aw ){
508b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    utf8_printf(pOut, "%.*s", i, zUtf);
509b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  }else if( w<0 ){
510b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    utf8_printf(pOut, "%*s%s", aw-n, "", zUtf);
511b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  }else{
512b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    utf8_printf(pOut, "%s%*s", zUtf, aw-n, "");
513b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  }
514b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis}
515b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis
5167790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
5177790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
5187790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** Determines if a string is a number of not.
5197790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
5207790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Projectstatic int isNumber(const char *z, int *realnum){
5217790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if( *z=='-' || *z=='+' ) z++;
52290ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  if( !IsDigit(*z) ){
5237790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    return 0;
5247790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
5257790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  z++;
5267790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if( realnum ) *realnum = 0;
52790ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  while( IsDigit(*z) ){ z++; }
5287790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if( *z=='.' ){
5297790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    z++;
53090ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    if( !IsDigit(*z) ) return 0;
53190ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    while( IsDigit(*z) ){ z++; }
5327790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( realnum ) *realnum = 1;
5337790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
5347790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if( *z=='e' || *z=='E' ){
5357790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    z++;
5367790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( *z=='+' || *z=='-' ) z++;
53790ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    if( !IsDigit(*z) ) return 0;
53890ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    while( IsDigit(*z) ){ z++; }
5397790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( realnum ) *realnum = 1;
5407790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
5417790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  return *z==0;
5427790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
5437790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
5447790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
54560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** Compute a string length that is limited to what can be stored in
54660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** lower 30 bits of a 32-bit signed integer.
54760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis*/
54860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidisstatic int strlen30(const char *z){
54960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  const char *z2 = z;
55060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  while( *z2 ){ z2++; }
55160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  return 0x3fffffff & (int)(z2 - z);
55260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis}
55360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
55460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis/*
5550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Return the length of a string in characters.  Multibyte UTF8 characters
5560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** count as a single character.
5570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
5580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int strlenChar(const char *z){
5590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int n = 0;
5600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  while( *z ){
5610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( (0xc0&*(z++))!=0x80 ) n++;
5620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
5630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return n;
5640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
5650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
5660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
5677790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** This routine reads a line of text from FILE in, stores
5687790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** the text in memory obtained from malloc() and returns a pointer
5697790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** to the text.  NULL is returned at end of file, or if malloc()
5707790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** fails.
5717790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project**
5728fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** If zLine is not NULL then it is a malloced buffer returned from
5738fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** a previous call to this routine that may be reused.
5747790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
5758fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevichstatic char *local_getline(char *zLine, FILE *in){
5768fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int nLine = zLine==0 ? 0 : 100;
5778fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int n = 0;
5787790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
57990ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  while( 1 ){
5807790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( n+100>nLine ){
5817790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      nLine = nLine*2 + 100;
5827790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      zLine = realloc(zLine, nLine);
5837790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      if( zLine==0 ) return 0;
5847790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
5857790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( fgets(&zLine[n], nLine - n, in)==0 ){
5867790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      if( n==0 ){
5877790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        free(zLine);
5887790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        return 0;
5897790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
5907790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      zLine[n] = 0;
5917790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      break;
5927790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
5938fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    while( zLine[n] ) n++;
5948fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( n>0 && zLine[n-1]=='\n' ){
5957790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      n--;
596a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      if( n>0 && zLine[n-1]=='\r' ) n--;
5977790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      zLine[n] = 0;
59890ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      break;
5997790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
6007790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
60160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#if defined(_WIN32) || defined(WIN32)
60260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  /* For interactive input on Windows systems, translate the
60360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  ** multi-byte characterset characters into UTF-8. */
60408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  if( stdin_is_interactive && in==stdin ){
60560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0);
60660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    if( zTrans ){
60760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      int nTrans = strlen30(zTrans)+1;
60860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( nTrans>nLine ){
60960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        zLine = realloc(zLine, nTrans);
61060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        if( zLine==0 ){
61160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          sqlite3_free(zTrans);
61260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          return 0;
61360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        }
61460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }
61560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      memcpy(zLine, zTrans, nTrans);
61660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      sqlite3_free(zTrans);
61760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }
61860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  }
61960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#endif /* defined(_WIN32) || defined(WIN32) */
6207790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  return zLine;
6217790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
6227790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
6237790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
6247790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** Retrieve a single line of input text.
6257790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project**
6268fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** If in==0 then read from standard input and prompt before each line.
6278fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** If isContinuation is true, then a continuation prompt is appropriate.
6288fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** If isContinuation is zero, then the main prompt should be used.
6298fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich**
6308fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** If zPrior is not NULL then it is a buffer from a prior call to this
6318fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** routine that can be reused.
6328fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich**
6338fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** The result is stored in space obtained from malloc() and must either
6348fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** be freed by the caller or else passed back into this routine via the
6358fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** zPrior argument for reuse.
6367790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
6378fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevichstatic char *one_input_line(FILE *in, char *zPrior, int isContinuation){
6387790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  char *zPrompt;
6397790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  char *zResult;
6407790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if( in!=0 ){
6418fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    zResult = local_getline(zPrior, in);
6427790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else{
6438fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    zPrompt = isContinuation ? continuePrompt : mainPrompt;
6443fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#if SHELL_USE_LOCAL_GETLINE
6458fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    printf("%s", zPrompt);
6468fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    fflush(stdout);
6478fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    zResult = local_getline(zPrior, stdin);
6483fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#else
6493fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    free(zPrior);
6503fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    zResult = shell_readline(zPrompt);
6513fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    if( zResult && *zResult ) shell_add_history(zResult);
6527790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#endif
6538fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }
6547790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  return zResult;
6557790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
6560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
6570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
6580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
6590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Return the value of a hexadecimal digit.  Return -1 if the input
6600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** is not a hex digit.
6610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
6620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int hexDigitValue(char c){
6630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( c>='0' && c<='9' ) return c - '0';
6640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( c>='a' && c<='f' ) return c - 'a' + 10;
6650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( c>='A' && c<='F' ) return c - 'A' + 10;
6660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return -1;
6670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
6680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
6690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
6700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Interpret zArg as an integer value, possibly with suffixes.
6710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
6720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic sqlite3_int64 integerValue(const char *zArg){
6730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_int64 v = 0;
6740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  static const struct { char *zSuffix; int iMult; } aMult[] = {
6750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    { "KiB", 1024 },
6760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    { "MiB", 1024*1024 },
6770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    { "GiB", 1024*1024*1024 },
6780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    { "KB",  1000 },
6790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    { "MB",  1000000 },
6800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    { "GB",  1000000000 },
6810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    { "K",   1000 },
6820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    { "M",   1000000 },
6830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    { "G",   1000000000 },
6840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  };
6850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int i;
6860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int isNeg = 0;
6870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( zArg[0]=='-' ){
6880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    isNeg = 1;
6890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zArg++;
6900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else if( zArg[0]=='+' ){
6910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zArg++;
6920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
6930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( zArg[0]=='0' && zArg[1]=='x' ){
6940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int x;
6950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zArg += 2;
6960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    while( (x = hexDigitValue(zArg[0]))>=0 ){
6970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      v = (v<<4) + x;
6980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zArg++;
6990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
7000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
7010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    while( IsDigit(zArg[0]) ){
7020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      v = v*10 + zArg[0] - '0';
7030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zArg++;
7040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
7050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
7060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(i=0; i<ArraySize(aMult); i++){
7070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
7080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      v *= aMult[i].iMult;
7090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
7100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
7110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
7120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return isNeg? -v : v;
7130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
7140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
715b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis/*
716b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** A variable length string to which one can append text.
717b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis*/
718b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidistypedef struct ShellText ShellText;
719b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidisstruct ShellText {
720b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  char *z;
721b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  int n;
722b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  int nAlloc;
723b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis};
724b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
725b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis/*
726b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** Initialize and destroy a ShellText object
727b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis*/
728b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidisstatic void initText(ShellText *p){
729b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  memset(p, 0, sizeof(*p));
730b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis}
731b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidisstatic void freeText(ShellText *p){
732b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  free(p->z);
733b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  initText(p);
734b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis}
735b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
736b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis/* zIn is either a pointer to a NULL-terminated string in memory obtained
737b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** from malloc(), or a NULL pointer. The string pointed to by zAppend is
738b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** added to zIn, and the result returned in memory obtained from malloc().
739b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** zIn, if it was not NULL, is freed.
740b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis**
741b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** If the third argument, quote, is not '\0', then it is used as a
742b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** quote character for zAppend.
743b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis*/
744b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidisstatic void appendText(ShellText *p, char const *zAppend, char quote){
745b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  int len;
746b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  int i;
747b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  int nAppend = strlen30(zAppend);
748b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
749b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  len = nAppend+p->n+1;
750b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  if( quote ){
751b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    len += 2;
752b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    for(i=0; i<nAppend; i++){
753b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      if( zAppend[i]==quote ) len++;
754b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }
755b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }
756b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
757b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  if( p->n+len>=p->nAlloc ){
758b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    p->nAlloc = p->nAlloc*2 + len + 20;
759b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    p->z = realloc(p->z, p->nAlloc);
760b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    if( p->z==0 ){
761b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      memset(p, 0, sizeof(*p));
762b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      return;
763b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }
764b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }
765b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
766b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  if( quote ){
767b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    char *zCsr = p->z+p->n;
768b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    *zCsr++ = quote;
769b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    for(i=0; i<nAppend; i++){
770b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      *zCsr++ = zAppend[i];
771b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      if( zAppend[i]==quote ) *zCsr++ = quote;
772b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }
773b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    *zCsr++ = quote;
774b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    p->n = (int)(zCsr - p->z);
775b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    *zCsr = '\0';
776b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }else{
777b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    memcpy(p->z+p->n, zAppend, nAppend);
778b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    p->n += nAppend;
779b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    p->z[p->n] = '\0';
780b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }
781b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis}
782b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
783b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis/*
784b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** Attempt to determine if identifier zName needs to be quoted, either
785b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** because it contains non-alphanumeric characters, or because it is an
786b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** SQLite keyword.  Be conservative in this estimate:  When in doubt assume
787b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** that quoting is required.
788b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis**
789b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** Return '"' if quoting is required.  Return 0 if no quoting is required.
790b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis*/
791b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidisstatic char quoteChar(const char *zName){
792b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  /* All SQLite keywords, in alphabetical order */
793b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  static const char *azKeywords[] = {
794b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS",
795b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY",
796b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT",
797b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE",
798b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE",
799b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH",
800b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN",
801b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF",
802b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER",
803b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY",
804b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL",
805b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA",
806b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP",
807b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT",
808b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP",
809b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE",
810b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE",
811b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "WITH", "WITHOUT",
812b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  };
813b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  int i, lwr, upr, mid, c;
814b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"';
815b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  for(i=0; zName[i]; i++){
816b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"';
817b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }
818b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  lwr = 0;
819b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  upr = sizeof(azKeywords)/sizeof(azKeywords[0]) - 1;
820b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  while( lwr<=upr ){
821b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    mid = (lwr+upr)/2;
822b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    c = sqlite3_stricmp(azKeywords[mid], zName);
823b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    if( c==0 ) return '"';
824b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    if( c<0 ){
825b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      lwr = mid+1;
826b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }else{
827b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      upr = mid-1;
828b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }
829b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }
830b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  return 0;
831b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis}
832b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
833b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis/*
8340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Construct a fake object name and column list to describe the structure
8350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** of the view, virtual table, or table valued function zSchema.zName.
836b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis*/
8370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic char *shellFakeSchema(
8380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *db,            /* The database connection containing the vtab */
8390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zSchema,    /* Schema of the database holding the vtab */
8400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zName       /* The name of the virtual table */
8410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
8420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_stmt *pStmt = 0;
8430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zSql;
8440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ShellText s;
8450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char cQuote;
8460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zDiv = "(";
8470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nRow = 0;
8480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
8490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;",
8500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                         zSchema ? zSchema : "main", zName);
8510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
8520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(zSql);
8530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  initText(&s);
8540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( zSchema ){
8550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    cQuote = quoteChar(zSchema);
8560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0;
8570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    appendText(&s, zSchema, cQuote);
8580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    appendText(&s, ".", 0);
8590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
8600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  cQuote = quoteChar(zName);
8610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  appendText(&s, zName, cQuote);
8620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  while( sqlite3_step(pStmt)==SQLITE_ROW ){
8630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const char *zCol = (const char*)sqlite3_column_text(pStmt, 1);
8640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    nRow++;
8650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    appendText(&s, zDiv, 0);
8660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zDiv = ",";
8670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    cQuote = quoteChar(zCol);
8680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    appendText(&s, zCol, cQuote);
8690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
8700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  appendText(&s, ")", 0);
8710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_finalize(pStmt);
8720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( nRow==0 ){
8730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    freeText(&s);
8740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    s.z = 0;
875b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }
8760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return s.z;
877b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis}
878b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
879b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis/*
8800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** SQL function:  shell_module_schema(X)
8810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
8820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Return a fake schema for the table-valued function or eponymous virtual
8830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** table X.
884b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis*/
8850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void shellModuleSchema(
8860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_context *pCtx,
8870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nVal,
8880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_value **apVal
8890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
8900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zName = (const char*)sqlite3_value_text(apVal[0]);
8910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zFake = shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName);
8920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  UNUSED_PARAMETER(nVal);
8930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( zFake ){
8940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
8950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                        -1, sqlite3_free);
8960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    free(zFake);
897b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }
898b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis}
899b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
900b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis/*
9010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** SQL function:  shell_add_schema(S,X)
9020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
9030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Add the schema name X to the CREATE statement in S and return the result.
9040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Examples:
9050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
9060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    CREATE TABLE t1(x)   ->   CREATE TABLE xyz.t1(x);
9070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
9080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Also works on
9090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
9100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    CREATE INDEX
9110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    CREATE UNIQUE INDEX
9120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    CREATE VIEW
9130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    CREATE TRIGGER
9140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    CREATE VIRTUAL TABLE
9150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
9160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This UDF is used by the .schema command to insert the schema name of
9170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** attached databases into the middle of the sqlite_master.sql field.
918b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis*/
9190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void shellAddSchemaName(
9200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_context *pCtx,
9210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nVal,
9220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_value **apVal
923b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis){
9240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  static const char *aPrefix[] = {
9250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov     "TABLE",
9260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov     "INDEX",
9270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov     "UNIQUE INDEX",
9280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov     "VIEW",
9290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov     "TRIGGER",
9300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov     "VIRTUAL TABLE"
9310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  };
9320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int i = 0;
9330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zIn = (const char*)sqlite3_value_text(apVal[0]);
9340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zSchema = (const char*)sqlite3_value_text(apVal[1]);
9350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zName = (const char*)sqlite3_value_text(apVal[2]);
9360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *db = sqlite3_context_db_handle(pCtx);
9370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  UNUSED_PARAMETER(nVal);
9380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){
9390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    for(i=0; i<(int)(sizeof(aPrefix)/sizeof(aPrefix[0])); i++){
9400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int n = strlen30(aPrefix[i]);
9410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
9420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        char *z = 0;
9430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        char *zFake = 0;
9440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( zSchema ){
9450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          char cQuote = quoteChar(zSchema);
9460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( cQuote && sqlite3_stricmp(zSchema,"temp")!=0 ){
9470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8);
9480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }else{
9490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8);
9500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
9510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
9520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( zName
9530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov         && aPrefix[i][0]=='V'
9540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov         && (zFake = shellFakeSchema(db, zSchema, zName))!=0
9550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        ){
9560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( z==0 ){
9570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            z = sqlite3_mprintf("%s\n/* %s */", zIn, zFake);
9580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }else{
9590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            z = sqlite3_mprintf("%z\n/* %s */", z, zFake);
9600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
9610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          free(zFake);
9620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
9630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( z ){
9640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          sqlite3_result_text(pCtx, z, -1, sqlite3_free);
9650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          return;
9660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
967b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      }
968b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }
969b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }
9700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_result_value(pCtx, apVal[0]);
971b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis}
972b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
973b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis/*
9740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The source code for several run-time loadable extensions is inserted
9750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** below by the ../tool/mkshellc.tcl script.  Before processing that included
9760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** code, we need to override some macros to make the included program code
9770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** work here in the middle of this regular program.
978b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis*/
9790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define SQLITE_EXTENSION_INIT1
9800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define SQLITE_EXTENSION_INIT2(X) (void)(X)
981b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
9820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if defined(_WIN32) && defined(_MSC_VER)
9830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/************************* Begin test_windirent.h ******************/
984b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis/*
9850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** 2015 November 30
986b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis**
9870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The author disclaims copyright to this source code.  In place of
9880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** a legal notice, here is a blessing:
9890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
9900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you do good and not evil.
9910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you find forgiveness for yourself and forgive others.
9920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you share freely, never taking more than you give.
9930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
9940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*************************************************************************
9950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This file contains declarations for most of the opendir() family of
9960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** POSIX functions on Win32 using the MSVCRT.
9970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
9980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
9990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if defined(_WIN32) && defined(_MSC_VER) && !defined(SQLITE_WINDIRENT_H)
10000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define SQLITE_WINDIRENT_H
10010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
10020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
10030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** We need several data types from the Windows SDK header.
10040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
10050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
10060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define WIN32_LEAN_AND_MEAN
10070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include "windows.h"
10080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
10090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
10100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** We need several support functions from the SQLite core.
10110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
10120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
10130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
10140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
10150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** We need several things from the ANSI and MSVCRT headers.
10160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
10170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
10180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <stdio.h>
10190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <stdlib.h>
10200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <errno.h>
10210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <io.h>
10220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <limits.h>
10230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <sys/types.h>
10240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <sys/stat.h>
10250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
10260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
10270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** We may need several defines that should have been in "sys/stat.h".
10280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
10290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
10300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifndef S_ISREG
10310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
10320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
10330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
10340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifndef S_ISDIR
10350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
10360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
10370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
10380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifndef S_ISLNK
10390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define S_ISLNK(mode) (0)
10400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
10410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
10420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
10430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** We may need to provide the "mode_t" type.
10440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
10450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
10460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifndef MODE_T_DEFINED
10470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  #define MODE_T_DEFINED
10480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  typedef unsigned short mode_t;
10490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
10500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
10510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
10520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** We may need to provide the "ino_t" type.
10530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
10540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
10550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifndef INO_T_DEFINED
10560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  #define INO_T_DEFINED
10570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  typedef unsigned short ino_t;
10580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
10590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
10600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
10610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** We need to define "NAME_MAX" if it was not present in "limits.h".
10620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
10630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
10640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifndef NAME_MAX
10650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#  ifdef FILENAME_MAX
10660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#    define NAME_MAX (FILENAME_MAX)
10670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#  else
10680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#    define NAME_MAX (260)
10690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#  endif
10700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
10710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
10720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
10730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** We need to define "NULL_INTPTR_T" and "BAD_INTPTR_T".
10740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
10750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
10760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifndef NULL_INTPTR_T
10770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#  define NULL_INTPTR_T ((intptr_t)(0))
10780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
10790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
10800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifndef BAD_INTPTR_T
10810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#  define BAD_INTPTR_T ((intptr_t)(-1))
10820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
10830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
10840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
10850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** We need to provide the necessary structures and related types.
10860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
10870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
10880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifndef DIRENT_DEFINED
10890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define DIRENT_DEFINED
10900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct DIRENT DIRENT;
10910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef DIRENT *LPDIRENT;
10920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct DIRENT {
10930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ino_t d_ino;               /* Sequence number, do not use. */
10940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  unsigned d_attributes;     /* Win32 file attributes. */
10950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char d_name[NAME_MAX + 1]; /* Name within the directory. */
10960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
10970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
10980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
10990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifndef DIR_DEFINED
11000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define DIR_DEFINED
11010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct DIR DIR;
11020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef DIR *LPDIR;
11030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct DIR {
11040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  intptr_t d_handle; /* Value returned by "_findfirst". */
11050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  DIRENT d_first;    /* DIRENT constructed based on "_findfirst". */
11060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  DIRENT d_next;     /* DIRENT constructed based on "_findnext". */
11070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
11080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
11090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
11100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
11110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Provide a macro, for use by the implementation, to determine if a
11120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** particular directory entry should be skipped over when searching for
11130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** the next directory entry that should be returned by the readdir() or
11140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** readdir_r() functions.
11150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
11160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
11170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifndef is_filtered
11180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#  define is_filtered(a) ((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM))
11190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
11200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
11210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
11220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Provide the function prototype for the POSIX compatiable getenv()
11230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** function.  This function is not thread-safe.
11240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
11250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
11260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovextern const char *windirent_getenv(const char *name);
11270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
11280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
11290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Finally, we can provide the function prototypes for the opendir(),
11300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** readdir(), readdir_r(), and closedir() POSIX functions.
11310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
11320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
11330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovextern LPDIR opendir(const char *dirname);
11340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovextern LPDIRENT readdir(LPDIR dirp);
11350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovextern INT readdir_r(LPDIR dirp, LPDIRENT entry, LPDIRENT *result);
11360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovextern INT closedir(LPDIR dirp);
11370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
11380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif /* defined(WIN32) && defined(_MSC_VER) */
11390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
11400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/************************* End test_windirent.h ********************/
11410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/************************* Begin test_windirent.c ******************/
11420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
11430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** 2015 November 30
11440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
11450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The author disclaims copyright to this source code.  In place of
11460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** a legal notice, here is a blessing:
11470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
11480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you do good and not evil.
11490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you find forgiveness for yourself and forgive others.
11500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you share freely, never taking more than you give.
11510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
11520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*************************************************************************
11530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This file contains code to implement most of the opendir() family of
11540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** POSIX functions on Win32 using the MSVCRT.
11550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
11560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
11570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if defined(_WIN32) && defined(_MSC_VER)
11580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* #include "test_windirent.h" */
11590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
11600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
11610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Implementation of the POSIX getenv() function using the Win32 API.
11620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This function is not thread-safe.
11630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
11640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovconst char *windirent_getenv(
11650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *name
11660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
11670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  static char value[32768]; /* Maximum length, per MSDN */
11680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  DWORD dwSize = sizeof(value) / sizeof(char); /* Size in chars */
11690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  DWORD dwRet; /* Value returned by GetEnvironmentVariableA() */
11700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
11710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  memset(value, 0, sizeof(value));
11720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  dwRet = GetEnvironmentVariableA(name, value, dwSize);
11730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( dwRet==0 || dwRet>dwSize ){
11740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    /*
11750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ** The function call to GetEnvironmentVariableA() failed -OR-
11760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ** the buffer is not large enough.  Either way, return NULL.
11770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    */
11780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return 0;
11790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
11800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    /*
11810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ** The function call to GetEnvironmentVariableA() succeeded
11820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ** -AND- the buffer contains the entire value.
11830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    */
11840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return value;
11850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
11860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
11870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
11880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
11890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Implementation of the POSIX opendir() function using the MSVCRT.
11900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
11910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor KupolovLPDIR opendir(
11920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *dirname
11930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
11940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  struct _finddata_t data;
11950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR));
11960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]);
11970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
11980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( dirp==NULL ) return NULL;
11990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  memset(dirp, 0, sizeof(DIR));
12000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
12010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* TODO: Remove this if Unix-style root paths are not used. */
12020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( sqlite3_stricmp(dirname, "/")==0 ){
12030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    dirname = windirent_getenv("SystemDrive");
12040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
12050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
12060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  memset(&data, 0, sizeof(struct _finddata_t));
12070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  _snprintf(data.name, namesize, "%s\\*", dirname);
12080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  dirp->d_handle = _findfirst(data.name, &data);
12090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
12100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( dirp->d_handle==BAD_INTPTR_T ){
12110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    closedir(dirp);
12120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return NULL;
12130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
12140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
12150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* TODO: Remove this block to allow hidden and/or system files. */
12160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( is_filtered(data) ){
12170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovnext:
12180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
12190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    memset(&data, 0, sizeof(struct _finddata_t));
12200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( _findnext(dirp->d_handle, &data)==-1 ){
12210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      closedir(dirp);
12220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      return NULL;
12230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
12240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
12250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    /* TODO: Remove this block to allow hidden and/or system files. */
12260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( is_filtered(data) ) goto next;
12270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
12280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
12290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  dirp->d_first.d_attributes = data.attrib;
12300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  strncpy(dirp->d_first.d_name, data.name, NAME_MAX);
12310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  dirp->d_first.d_name[NAME_MAX] = '\0';
12320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
12330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return dirp;
12340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
12350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
12360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
12370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Implementation of the POSIX readdir() function using the MSVCRT.
12380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
12390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor KupolovLPDIRENT readdir(
12400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  LPDIR dirp
12410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
12420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  struct _finddata_t data;
12430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
12440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( dirp==NULL ) return NULL;
12450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
12460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( dirp->d_first.d_ino==0 ){
12470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    dirp->d_first.d_ino++;
12480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    dirp->d_next.d_ino++;
12490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
12500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return &dirp->d_first;
12510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
12520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
12530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovnext:
12540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
12550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  memset(&data, 0, sizeof(struct _finddata_t));
12560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( _findnext(dirp->d_handle, &data)==-1 ) return NULL;
12570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
12580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* TODO: Remove this block to allow hidden and/or system files. */
12590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( is_filtered(data) ) goto next;
12600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
12610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  dirp->d_next.d_ino++;
12620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  dirp->d_next.d_attributes = data.attrib;
12630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  strncpy(dirp->d_next.d_name, data.name, NAME_MAX);
12640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  dirp->d_next.d_name[NAME_MAX] = '\0';
12650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
12660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return &dirp->d_next;
12670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
12680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
12690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
12700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Implementation of the POSIX readdir_r() function using the MSVCRT.
12710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
12720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor KupolovINT readdir_r(
12730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  LPDIR dirp,
12740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  LPDIRENT entry,
12750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  LPDIRENT *result
12760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
12770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  struct _finddata_t data;
12780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
12790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( dirp==NULL ) return EBADF;
12800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
12810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( dirp->d_first.d_ino==0 ){
12820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    dirp->d_first.d_ino++;
12830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    dirp->d_next.d_ino++;
12840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
12850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    entry->d_ino = dirp->d_first.d_ino;
12860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    entry->d_attributes = dirp->d_first.d_attributes;
12870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    strncpy(entry->d_name, dirp->d_first.d_name, NAME_MAX);
12880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    entry->d_name[NAME_MAX] = '\0';
12890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
12900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    *result = entry;
12910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return 0;
12920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
12930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
12940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovnext:
12950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
12960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  memset(&data, 0, sizeof(struct _finddata_t));
12970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( _findnext(dirp->d_handle, &data)==-1 ){
12980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    *result = NULL;
12990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return ENOENT;
13000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
13010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
13020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* TODO: Remove this block to allow hidden and/or system files. */
13030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( is_filtered(data) ) goto next;
13040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
13050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  entry->d_ino = (ino_t)-1; /* not available */
13060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  entry->d_attributes = data.attrib;
13070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  strncpy(entry->d_name, data.name, NAME_MAX);
13080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  entry->d_name[NAME_MAX] = '\0';
13090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
13100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  *result = entry;
13110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return 0;
13120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
13130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
13140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
13150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Implementation of the POSIX closedir() function using the MSVCRT.
13160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
13170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor KupolovINT closedir(
13180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  LPDIR dirp
13190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
13200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  INT result = 0;
13210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
13220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( dirp==NULL ) return EINVAL;
13230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
13240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( dirp->d_handle!=NULL_INTPTR_T && dirp->d_handle!=BAD_INTPTR_T ){
13250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    result = _findclose(dirp->d_handle);
13260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
13270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
13280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(dirp);
13290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return result;
13300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
13310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
13320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif /* defined(WIN32) && defined(_MSC_VER) */
13330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
13340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/************************* End test_windirent.c ********************/
13350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define dirent DIRENT
13360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
13370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/************************* Begin ../ext/misc/shathree.c ******************/
13380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
13390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** 2017-03-08
13400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
13410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The author disclaims copyright to this source code.  In place of
13420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** a legal notice, here is a blessing:
13430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
13440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you do good and not evil.
13450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you find forgiveness for yourself and forgive others.
13460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you share freely, never taking more than you give.
13470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
13480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov******************************************************************************
13490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
13500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This SQLite extension implements a functions that compute SHA1 hashes.
13510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Two SQL functions are implemented:
13520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
13530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     sha3(X,SIZE)
13540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     sha3_query(Y,SIZE)
13550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
13560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The sha3(X) function computes the SHA3 hash of the input X, or NULL if
13570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** X is NULL.
13580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
13590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The sha3_query(Y) function evalutes all queries in the SQL statements of Y
13600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** and returns a hash of their results.
13610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
13620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The SIZE argument is optional.  If omitted, the SHA3-256 hash algorithm
13630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** is used.  If SIZE is included it must be one of the integers 224, 256,
13640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** 384, or 512, to determine SHA3 hash variant that is computed.
13650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
13660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor KupolovSQLITE_EXTENSION_INIT1
13670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <assert.h>
13680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <string.h>
13690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <stdarg.h>
13700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* typedef sqlite3_uint64 u64; */
13710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
13720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/******************************************************************************
13730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The Hash Engine
13740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
13750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
13760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Macros to determine whether the machine is big or little endian,
13770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** and whether or not that determination is run-time or compile-time.
13780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
13790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** For best performance, an attempt is made to guess at the byte-order
13800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** using C-preprocessor macros.  If that is unsuccessful, or if
13810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** -DSHA3_BYTEORDER=0 is set, then byte-order is determined
13820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** at run-time.
13830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
13840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifndef SHA3_BYTEORDER
13850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# if defined(i386)     || defined(__i386__)   || defined(_M_IX86) ||    \
13860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov     defined(__x86_64) || defined(__x86_64__) || defined(_M_X64)  ||    \
13870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov     defined(_M_AMD64) || defined(_M_ARM)     || defined(__x86)   ||    \
13880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov     defined(__arm__)
13890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#   define SHA3_BYTEORDER    1234
13900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# elif defined(sparc)    || defined(__ppc__)
13910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#   define SHA3_BYTEORDER    4321
13920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# else
13930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#   define SHA3_BYTEORDER 0
13940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# endif
13950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
13960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
13970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
13980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
13990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** State structure for a SHA3 hash in progress
14000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
14010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct SHA3Context SHA3Context;
14020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct SHA3Context {
14030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  union {
14040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    u64 s[25];                /* Keccak state. 5x5 lines of 64 bits each */
14050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    unsigned char x[1600];    /* ... or 1600 bytes */
14060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  } u;
14070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  unsigned nRate;        /* Bytes of input accepted per Keccak iteration */
14080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  unsigned nLoaded;      /* Input bytes loaded into u.x[] so far this cycle */
14090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  unsigned ixMask;       /* Insert next input into u.x[nLoaded^ixMask]. */
14100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
14110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
14120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
14130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** A single step of the Keccak mixing function for a 1600-bit state
14140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
14150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void KeccakF1600Step(SHA3Context *p){
14160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int i;
14170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u64 b0, b1, b2, b3, b4;
14180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u64 c0, c1, c2, c3, c4;
14190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u64 d0, d1, d2, d3, d4;
14200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  static const u64 RC[] = {
14210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0x0000000000000001ULL,  0x0000000000008082ULL,
14220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0x800000000000808aULL,  0x8000000080008000ULL,
14230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0x000000000000808bULL,  0x0000000080000001ULL,
14240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0x8000000080008081ULL,  0x8000000000008009ULL,
14250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0x000000000000008aULL,  0x0000000000000088ULL,
14260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0x0000000080008009ULL,  0x000000008000000aULL,
14270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0x000000008000808bULL,  0x800000000000008bULL,
14280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0x8000000000008089ULL,  0x8000000000008003ULL,
14290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0x8000000000008002ULL,  0x8000000000000080ULL,
14300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0x000000000000800aULL,  0x800000008000000aULL,
14310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0x8000000080008081ULL,  0x8000000000008080ULL,
14320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0x0000000080000001ULL,  0x8000000080008008ULL
14330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  };
14340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define a00 (p->u.s[0])
14350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define a01 (p->u.s[1])
14360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define a02 (p->u.s[2])
14370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define a03 (p->u.s[3])
14380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define a04 (p->u.s[4])
14390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define a10 (p->u.s[5])
14400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define a11 (p->u.s[6])
14410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define a12 (p->u.s[7])
14420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define a13 (p->u.s[8])
14430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define a14 (p->u.s[9])
14440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define a20 (p->u.s[10])
14450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define a21 (p->u.s[11])
14460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define a22 (p->u.s[12])
14470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define a23 (p->u.s[13])
14480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define a24 (p->u.s[14])
14490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define a30 (p->u.s[15])
14500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define a31 (p->u.s[16])
14510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define a32 (p->u.s[17])
14520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define a33 (p->u.s[18])
14530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define a34 (p->u.s[19])
14540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define a40 (p->u.s[20])
14550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define a41 (p->u.s[21])
14560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define a42 (p->u.s[22])
14570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define a43 (p->u.s[23])
14580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define a44 (p->u.s[24])
14590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define ROL64(a,x) ((a<<x)|(a>>(64-x)))
14600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
14610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(i=0; i<24; i+=4){
14620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    c0 = a00^a10^a20^a30^a40;
14630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    c1 = a01^a11^a21^a31^a41;
14640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    c2 = a02^a12^a22^a32^a42;
14650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    c3 = a03^a13^a23^a33^a43;
14660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    c4 = a04^a14^a24^a34^a44;
14670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    d0 = c4^ROL64(c1, 1);
14680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    d1 = c0^ROL64(c2, 1);
14690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    d2 = c1^ROL64(c3, 1);
14700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    d3 = c2^ROL64(c4, 1);
14710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    d4 = c3^ROL64(c0, 1);
14720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
14730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b0 = (a00^d0);
14740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b1 = ROL64((a11^d1), 44);
14750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b2 = ROL64((a22^d2), 43);
14760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b3 = ROL64((a33^d3), 21);
14770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b4 = ROL64((a44^d4), 14);
14780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a00 =   b0 ^((~b1)&  b2 );
14790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a00 ^= RC[i];
14800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a11 =   b1 ^((~b2)&  b3 );
14810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a22 =   b2 ^((~b3)&  b4 );
14820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a33 =   b3 ^((~b4)&  b0 );
14830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a44 =   b4 ^((~b0)&  b1 );
14840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
14850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b2 = ROL64((a20^d0), 3);
14860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b3 = ROL64((a31^d1), 45);
14870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b4 = ROL64((a42^d2), 61);
14880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b0 = ROL64((a03^d3), 28);
14890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b1 = ROL64((a14^d4), 20);
14900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a20 =   b0 ^((~b1)&  b2 );
14910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a31 =   b1 ^((~b2)&  b3 );
14920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a42 =   b2 ^((~b3)&  b4 );
14930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a03 =   b3 ^((~b4)&  b0 );
14940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a14 =   b4 ^((~b0)&  b1 );
14950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
14960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b4 = ROL64((a40^d0), 18);
14970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b0 = ROL64((a01^d1), 1);
14980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b1 = ROL64((a12^d2), 6);
14990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b2 = ROL64((a23^d3), 25);
15000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b3 = ROL64((a34^d4), 8);
15010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a40 =   b0 ^((~b1)&  b2 );
15020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a01 =   b1 ^((~b2)&  b3 );
15030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a12 =   b2 ^((~b3)&  b4 );
15040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a23 =   b3 ^((~b4)&  b0 );
15050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a34 =   b4 ^((~b0)&  b1 );
15060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
15070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b1 = ROL64((a10^d0), 36);
15080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b2 = ROL64((a21^d1), 10);
15090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b3 = ROL64((a32^d2), 15);
15100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b4 = ROL64((a43^d3), 56);
15110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b0 = ROL64((a04^d4), 27);
15120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a10 =   b0 ^((~b1)&  b2 );
15130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a21 =   b1 ^((~b2)&  b3 );
15140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a32 =   b2 ^((~b3)&  b4 );
15150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a43 =   b3 ^((~b4)&  b0 );
15160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a04 =   b4 ^((~b0)&  b1 );
15170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
15180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b3 = ROL64((a30^d0), 41);
15190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b4 = ROL64((a41^d1), 2);
15200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b0 = ROL64((a02^d2), 62);
15210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b1 = ROL64((a13^d3), 55);
15220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b2 = ROL64((a24^d4), 39);
15230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a30 =   b0 ^((~b1)&  b2 );
15240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a41 =   b1 ^((~b2)&  b3 );
15250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a02 =   b2 ^((~b3)&  b4 );
15260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a13 =   b3 ^((~b4)&  b0 );
15270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a24 =   b4 ^((~b0)&  b1 );
15280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
15290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    c0 = a00^a20^a40^a10^a30;
15300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    c1 = a11^a31^a01^a21^a41;
15310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    c2 = a22^a42^a12^a32^a02;
15320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    c3 = a33^a03^a23^a43^a13;
15330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    c4 = a44^a14^a34^a04^a24;
15340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    d0 = c4^ROL64(c1, 1);
15350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    d1 = c0^ROL64(c2, 1);
15360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    d2 = c1^ROL64(c3, 1);
15370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    d3 = c2^ROL64(c4, 1);
15380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    d4 = c3^ROL64(c0, 1);
15390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
15400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b0 = (a00^d0);
15410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b1 = ROL64((a31^d1), 44);
15420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b2 = ROL64((a12^d2), 43);
15430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b3 = ROL64((a43^d3), 21);
15440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b4 = ROL64((a24^d4), 14);
15450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a00 =   b0 ^((~b1)&  b2 );
15460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a00 ^= RC[i+1];
15470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a31 =   b1 ^((~b2)&  b3 );
15480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a12 =   b2 ^((~b3)&  b4 );
15490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a43 =   b3 ^((~b4)&  b0 );
15500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a24 =   b4 ^((~b0)&  b1 );
15510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
15520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b2 = ROL64((a40^d0), 3);
15530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b3 = ROL64((a21^d1), 45);
15540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b4 = ROL64((a02^d2), 61);
15550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b0 = ROL64((a33^d3), 28);
15560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b1 = ROL64((a14^d4), 20);
15570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a40 =   b0 ^((~b1)&  b2 );
15580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a21 =   b1 ^((~b2)&  b3 );
15590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a02 =   b2 ^((~b3)&  b4 );
15600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a33 =   b3 ^((~b4)&  b0 );
15610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a14 =   b4 ^((~b0)&  b1 );
15620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
15630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b4 = ROL64((a30^d0), 18);
15640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b0 = ROL64((a11^d1), 1);
15650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b1 = ROL64((a42^d2), 6);
15660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b2 = ROL64((a23^d3), 25);
15670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b3 = ROL64((a04^d4), 8);
15680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a30 =   b0 ^((~b1)&  b2 );
15690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a11 =   b1 ^((~b2)&  b3 );
15700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a42 =   b2 ^((~b3)&  b4 );
15710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a23 =   b3 ^((~b4)&  b0 );
15720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a04 =   b4 ^((~b0)&  b1 );
15730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
15740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b1 = ROL64((a20^d0), 36);
15750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b2 = ROL64((a01^d1), 10);
15760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b3 = ROL64((a32^d2), 15);
15770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b4 = ROL64((a13^d3), 56);
15780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b0 = ROL64((a44^d4), 27);
15790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a20 =   b0 ^((~b1)&  b2 );
15800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a01 =   b1 ^((~b2)&  b3 );
15810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a32 =   b2 ^((~b3)&  b4 );
15820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a13 =   b3 ^((~b4)&  b0 );
15830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a44 =   b4 ^((~b0)&  b1 );
15840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
15850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b3 = ROL64((a10^d0), 41);
15860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b4 = ROL64((a41^d1), 2);
15870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b0 = ROL64((a22^d2), 62);
15880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b1 = ROL64((a03^d3), 55);
15890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b2 = ROL64((a34^d4), 39);
15900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a10 =   b0 ^((~b1)&  b2 );
15910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a41 =   b1 ^((~b2)&  b3 );
15920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a22 =   b2 ^((~b3)&  b4 );
15930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a03 =   b3 ^((~b4)&  b0 );
15940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a34 =   b4 ^((~b0)&  b1 );
15950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
15960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    c0 = a00^a40^a30^a20^a10;
15970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    c1 = a31^a21^a11^a01^a41;
15980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    c2 = a12^a02^a42^a32^a22;
15990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    c3 = a43^a33^a23^a13^a03;
16000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    c4 = a24^a14^a04^a44^a34;
16010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    d0 = c4^ROL64(c1, 1);
16020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    d1 = c0^ROL64(c2, 1);
16030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    d2 = c1^ROL64(c3, 1);
16040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    d3 = c2^ROL64(c4, 1);
16050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    d4 = c3^ROL64(c0, 1);
16060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
16070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b0 = (a00^d0);
16080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b1 = ROL64((a21^d1), 44);
16090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b2 = ROL64((a42^d2), 43);
16100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b3 = ROL64((a13^d3), 21);
16110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b4 = ROL64((a34^d4), 14);
16120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a00 =   b0 ^((~b1)&  b2 );
16130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a00 ^= RC[i+2];
16140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a21 =   b1 ^((~b2)&  b3 );
16150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a42 =   b2 ^((~b3)&  b4 );
16160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a13 =   b3 ^((~b4)&  b0 );
16170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a34 =   b4 ^((~b0)&  b1 );
16180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
16190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b2 = ROL64((a30^d0), 3);
16200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b3 = ROL64((a01^d1), 45);
16210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b4 = ROL64((a22^d2), 61);
16220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b0 = ROL64((a43^d3), 28);
16230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b1 = ROL64((a14^d4), 20);
16240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a30 =   b0 ^((~b1)&  b2 );
16250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a01 =   b1 ^((~b2)&  b3 );
16260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a22 =   b2 ^((~b3)&  b4 );
16270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a43 =   b3 ^((~b4)&  b0 );
16280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a14 =   b4 ^((~b0)&  b1 );
16290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
16300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b4 = ROL64((a10^d0), 18);
16310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b0 = ROL64((a31^d1), 1);
16320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b1 = ROL64((a02^d2), 6);
16330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b2 = ROL64((a23^d3), 25);
16340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b3 = ROL64((a44^d4), 8);
16350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a10 =   b0 ^((~b1)&  b2 );
16360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a31 =   b1 ^((~b2)&  b3 );
16370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a02 =   b2 ^((~b3)&  b4 );
16380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a23 =   b3 ^((~b4)&  b0 );
16390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a44 =   b4 ^((~b0)&  b1 );
16400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
16410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b1 = ROL64((a40^d0), 36);
16420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b2 = ROL64((a11^d1), 10);
16430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b3 = ROL64((a32^d2), 15);
16440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b4 = ROL64((a03^d3), 56);
16450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b0 = ROL64((a24^d4), 27);
16460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a40 =   b0 ^((~b1)&  b2 );
16470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a11 =   b1 ^((~b2)&  b3 );
16480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a32 =   b2 ^((~b3)&  b4 );
16490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a03 =   b3 ^((~b4)&  b0 );
16500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a24 =   b4 ^((~b0)&  b1 );
16510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
16520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b3 = ROL64((a20^d0), 41);
16530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b4 = ROL64((a41^d1), 2);
16540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b0 = ROL64((a12^d2), 62);
16550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b1 = ROL64((a33^d3), 55);
16560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b2 = ROL64((a04^d4), 39);
16570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a20 =   b0 ^((~b1)&  b2 );
16580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a41 =   b1 ^((~b2)&  b3 );
16590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a12 =   b2 ^((~b3)&  b4 );
16600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a33 =   b3 ^((~b4)&  b0 );
16610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a04 =   b4 ^((~b0)&  b1 );
16620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
16630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    c0 = a00^a30^a10^a40^a20;
16640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    c1 = a21^a01^a31^a11^a41;
16650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    c2 = a42^a22^a02^a32^a12;
16660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    c3 = a13^a43^a23^a03^a33;
16670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    c4 = a34^a14^a44^a24^a04;
16680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    d0 = c4^ROL64(c1, 1);
16690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    d1 = c0^ROL64(c2, 1);
16700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    d2 = c1^ROL64(c3, 1);
16710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    d3 = c2^ROL64(c4, 1);
16720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    d4 = c3^ROL64(c0, 1);
16730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
16740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b0 = (a00^d0);
16750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b1 = ROL64((a01^d1), 44);
16760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b2 = ROL64((a02^d2), 43);
16770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b3 = ROL64((a03^d3), 21);
16780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b4 = ROL64((a04^d4), 14);
16790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a00 =   b0 ^((~b1)&  b2 );
16800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a00 ^= RC[i+3];
16810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a01 =   b1 ^((~b2)&  b3 );
16820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a02 =   b2 ^((~b3)&  b4 );
16830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a03 =   b3 ^((~b4)&  b0 );
16840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a04 =   b4 ^((~b0)&  b1 );
16850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
16860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b2 = ROL64((a10^d0), 3);
16870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b3 = ROL64((a11^d1), 45);
16880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b4 = ROL64((a12^d2), 61);
16890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b0 = ROL64((a13^d3), 28);
16900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b1 = ROL64((a14^d4), 20);
16910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a10 =   b0 ^((~b1)&  b2 );
16920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a11 =   b1 ^((~b2)&  b3 );
16930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a12 =   b2 ^((~b3)&  b4 );
16940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a13 =   b3 ^((~b4)&  b0 );
16950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a14 =   b4 ^((~b0)&  b1 );
16960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
16970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b4 = ROL64((a20^d0), 18);
16980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b0 = ROL64((a21^d1), 1);
16990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b1 = ROL64((a22^d2), 6);
17000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b2 = ROL64((a23^d3), 25);
17010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b3 = ROL64((a24^d4), 8);
17020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a20 =   b0 ^((~b1)&  b2 );
17030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a21 =   b1 ^((~b2)&  b3 );
17040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a22 =   b2 ^((~b3)&  b4 );
17050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a23 =   b3 ^((~b4)&  b0 );
17060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a24 =   b4 ^((~b0)&  b1 );
17070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
17080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b1 = ROL64((a30^d0), 36);
17090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b2 = ROL64((a31^d1), 10);
17100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b3 = ROL64((a32^d2), 15);
17110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b4 = ROL64((a33^d3), 56);
17120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b0 = ROL64((a34^d4), 27);
17130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a30 =   b0 ^((~b1)&  b2 );
17140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a31 =   b1 ^((~b2)&  b3 );
17150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a32 =   b2 ^((~b3)&  b4 );
17160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a33 =   b3 ^((~b4)&  b0 );
17170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a34 =   b4 ^((~b0)&  b1 );
17180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
17190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b3 = ROL64((a40^d0), 41);
17200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b4 = ROL64((a41^d1), 2);
17210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b0 = ROL64((a42^d2), 62);
17220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b1 = ROL64((a43^d3), 55);
17230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    b2 = ROL64((a44^d4), 39);
17240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a40 =   b0 ^((~b1)&  b2 );
17250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a41 =   b1 ^((~b2)&  b3 );
17260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a42 =   b2 ^((~b3)&  b4 );
17270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a43 =   b3 ^((~b4)&  b0 );
17280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a44 =   b4 ^((~b0)&  b1 );
17290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
17300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
17310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
17320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
17330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Initialize a new hash.  iSize determines the size of the hash
17340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** in bits and should be one of 224, 256, 384, or 512.  Or iSize
17350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** can be zero to use the default hash size of 256 bits.
17360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
17370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void SHA3Init(SHA3Context *p, int iSize){
17380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  memset(p, 0, sizeof(*p));
17390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( iSize>=128 && iSize<=512 ){
17400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    p->nRate = (1600 - ((iSize + 31)&~31)*2)/8;
17410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
17420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    p->nRate = (1600 - 2*256)/8;
17430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
17440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if SHA3_BYTEORDER==1234
17450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* Known to be little-endian at compile-time. No-op */
17460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#elif SHA3_BYTEORDER==4321
17470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  p->ixMask = 7;  /* Big-endian */
17480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#else
17490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  {
17500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    static unsigned int one = 1;
17510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( 1==*(unsigned char*)&one ){
17520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      /* Little endian.  No byte swapping. */
17530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      p->ixMask = 0;
17540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
17550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      /* Big endian.  Byte swap. */
17560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      p->ixMask = 7;
17570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
17580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
17590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
17600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
17610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
17620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
17630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Make consecutive calls to the SHA3Update function to add new content
17640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** to the hash
17650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
17660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void SHA3Update(
17670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  SHA3Context *p,
17680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const unsigned char *aData,
17690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  unsigned int nData
17700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
17710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  unsigned int i = 0;
17720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if SHA3_BYTEORDER==1234
17730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){
17740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    for(; i+7<nData; i+=8){
17750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      p->u.s[p->nLoaded/8] ^= *(u64*)&aData[i];
17760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      p->nLoaded += 8;
17770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( p->nLoaded>=p->nRate ){
17780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        KeccakF1600Step(p);
17790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        p->nLoaded = 0;
17800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
17810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
17820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
17830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
17840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(; i<nData; i++){
17850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if SHA3_BYTEORDER==1234
17860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    p->u.x[p->nLoaded] ^= aData[i];
17870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#elif SHA3_BYTEORDER==4321
17880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    p->u.x[p->nLoaded^0x07] ^= aData[i];
17890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#else
17900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    p->u.x[p->nLoaded^p->ixMask] ^= aData[i];
17910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
17920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    p->nLoaded++;
17930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( p->nLoaded==p->nRate ){
17940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      KeccakF1600Step(p);
17950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      p->nLoaded = 0;
17960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
17970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
17980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
17990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
18000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
18010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** After all content has been added, invoke SHA3Final() to compute
18020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** the final hash.  The function returns a pointer to the binary
18030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** hash value.
18040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
18050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic unsigned char *SHA3Final(SHA3Context *p){
18060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  unsigned int i;
18070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( p->nLoaded==p->nRate-1 ){
18080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const unsigned char c1 = 0x86;
18090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    SHA3Update(p, &c1, 1);
18100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
18110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const unsigned char c2 = 0x06;
18120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const unsigned char c3 = 0x80;
18130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    SHA3Update(p, &c2, 1);
18140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    p->nLoaded = p->nRate - 1;
18150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    SHA3Update(p, &c3, 1);
18160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
18170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(i=0; i<p->nRate; i++){
18180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    p->u.x[i+p->nRate] = p->u.x[i^p->ixMask];
18190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
18200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return &p->u.x[p->nRate];
18210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
18220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* End of the hashing logic
18230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*****************************************************************************/
18240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
18250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
18260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Implementation of the sha3(X,SIZE) function.
18270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
18280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Return a BLOB which is the SIZE-bit SHA3 hash of X.  The default
18290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** size is 256.  If X is a BLOB, it is hashed as is.
18300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** For all other non-NULL types of input, X is converted into a UTF-8 string
18310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** and the string is hashed without the trailing 0x00 terminator.  The hash
18320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** of a NULL value is NULL.
18330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
18340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void sha3Func(
18350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_context *context,
18360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int argc,
18370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_value **argv
18380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
18390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  SHA3Context cx;
18400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int eType = sqlite3_value_type(argv[0]);
18410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nByte = sqlite3_value_bytes(argv[0]);
18420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int iSize;
18430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( argc==1 ){
18440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    iSize = 256;
18450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
18460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    iSize = sqlite3_value_int(argv[1]);
18470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){
18480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_error(context, "SHA3 size should be one of: 224 256 "
18490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                                    "384 512", -1);
18500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      return;
18510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
18520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
18530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( eType==SQLITE_NULL ) return;
18540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  SHA3Init(&cx, iSize);
18550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( eType==SQLITE_BLOB ){
18560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    SHA3Update(&cx, sqlite3_value_blob(argv[0]), nByte);
18570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
18580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    SHA3Update(&cx, sqlite3_value_text(argv[0]), nByte);
18590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
18600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT);
18610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
18620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
18630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* Compute a string using sqlite3_vsnprintf() with a maximum length
18640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** of 50 bytes and add it to the hash.
18650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
18660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void hash_step_vformat(
18670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  SHA3Context *p,                 /* Add content to this context */
18680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zFormat,
18690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ...
18700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
18710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  va_list ap;
18720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int n;
18730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char zBuf[50];
18740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  va_start(ap, zFormat);
18750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap);
18760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  va_end(ap);
18770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  n = (int)strlen(zBuf);
18780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  SHA3Update(p, (unsigned char*)zBuf, n);
18790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
18800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
18810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
18820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Implementation of the sha3_query(SQL,SIZE) function.
18830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
18840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This function compiles and runs the SQL statement(s) given in the
18850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** argument. The results are hashed using a SIZE-bit SHA3.  The default
18860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** size is 256.
18870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
18880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The format of the byte stream that is hashed is summarized as follows:
18890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
18900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**       S<n>:<sql>
18910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**       R
18920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**       N
18930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**       I<int>
18940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**       F<ieee-float>
18950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**       B<size>:<bytes>
18960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**       T<size>:<text>
18970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
18980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** <sql> is the original SQL text for each statement run and <n> is
18990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** the size of that text.  The SQL text is UTF-8.  A single R character
19000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** occurs before the start of each row.  N means a NULL value.
19010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** I mean an 8-byte little-endian integer <int>.  F is a floating point
19020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** number with an 8-byte little-endian IEEE floating point value <ieee-float>.
19030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** B means blobs of <size> bytes.  T means text rendered as <size>
19040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** bytes of UTF-8.  The <n> and <size> values are expressed as an ASCII
19050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** text integers.
19060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
19070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** For each SQL statement in the X input, there is one S segment.  Each
19080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** S segment is followed by zero or more R segments, one for each row in the
19090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** result set.  After each R, there are one or more N, I, F, B, or T segments,
19100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** one for each column in the result set.  Segments are concatentated directly
19110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** with no delimiters of any kind.
19120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
19130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void sha3QueryFunc(
19140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_context *context,
19150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int argc,
19160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_value **argv
19170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
19180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *db = sqlite3_context_db_handle(context);
19190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zSql = (const char*)sqlite3_value_text(argv[0]);
19200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_stmt *pStmt = 0;
19210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nCol;                   /* Number of columns in the result set */
19220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int i;                      /* Loop counter */
19230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;
19240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int n;
19250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *z;
1926b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  SHA3Context cx;
1927b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  int iSize;
19280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
1929b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  if( argc==1 ){
1930b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    iSize = 256;
1931b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }else{
19320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    iSize = sqlite3_value_int(argv[1]);
19330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){
19340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_error(context, "SHA3 size should be one of: 224 256 "
19350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                                    "384 512", -1);
19360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      return;
19370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
19380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
19390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( zSql==0 ) return;
19400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  SHA3Init(&cx, iSize);
19410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  while( zSql[0] ){
19420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql);
19430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( rc ){
19440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s",
19450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                                   zSql, sqlite3_errmsg(db));
19460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_finalize(pStmt);
19470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_error(context, zMsg, -1);
19480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_free(zMsg);
19490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      return;
19500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
19510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( !sqlite3_stmt_readonly(pStmt) ){
19520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt));
19530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_finalize(pStmt);
19540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_error(context, zMsg, -1);
19550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_free(zMsg);
19560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      return;
19570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
19580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    nCol = sqlite3_column_count(pStmt);
19590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    z = sqlite3_sql(pStmt);
19600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    n = (int)strlen(z);
19610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    hash_step_vformat(&cx,"S%d:",n);
19620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    SHA3Update(&cx,(unsigned char*)z,n);
19630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
19640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    /* Compute a hash over the result of the query */
19650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    while( SQLITE_ROW==sqlite3_step(pStmt) ){
19660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      SHA3Update(&cx,(const unsigned char*)"R",1);
19670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      for(i=0; i<nCol; i++){
19680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        switch( sqlite3_column_type(pStmt,i) ){
19690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          case SQLITE_NULL: {
19700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            SHA3Update(&cx, (const unsigned char*)"N",1);
19710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            break;
19720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
19730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          case SQLITE_INTEGER: {
19740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            sqlite3_uint64 u;
19750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            int j;
19760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            unsigned char x[9];
19770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            sqlite3_int64 v = sqlite3_column_int64(pStmt,i);
19780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            memcpy(&u, &v, 8);
19790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            for(j=8; j>=1; j--){
19800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov              x[j] = u & 0xff;
19810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov              u >>= 8;
19820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            }
19830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            x[0] = 'I';
19840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            SHA3Update(&cx, x, 9);
19850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            break;
19860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
19870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          case SQLITE_FLOAT: {
19880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            sqlite3_uint64 u;
19890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            int j;
19900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            unsigned char x[9];
19910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            double r = sqlite3_column_double(pStmt,i);
19920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            memcpy(&u, &r, 8);
19930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            for(j=8; j>=1; j--){
19940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov              x[j] = u & 0xff;
19950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov              u >>= 8;
19960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            }
19970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            x[0] = 'F';
19980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            SHA3Update(&cx,x,9);
19990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            break;
20000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
20010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          case SQLITE_TEXT: {
20020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            int n2 = sqlite3_column_bytes(pStmt, i);
20030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            const unsigned char *z2 = sqlite3_column_text(pStmt, i);
20040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            hash_step_vformat(&cx,"T%d:",n2);
20050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            SHA3Update(&cx, z2, n2);
20060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            break;
20070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
20080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          case SQLITE_BLOB: {
20090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            int n2 = sqlite3_column_bytes(pStmt, i);
20100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            const unsigned char *z2 = sqlite3_column_blob(pStmt, i);
20110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            hash_step_vformat(&cx,"B%d:",n2);
20120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            SHA3Update(&cx, z2, n2);
20130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            break;
20140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
20150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
20160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
20170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
20180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_finalize(pStmt);
20190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
20200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT);
20210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
20220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
20230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
20240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifdef _WIN32
20250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
20260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
20270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovint sqlite3_shathree_init(
20280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *db,
20290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErrMsg,
20300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const sqlite3_api_routines *pApi
20310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
20320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
20330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  SQLITE_EXTENSION_INIT2(pApi);
20340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)pzErrMsg;  /* Unused parameter */
20350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = sqlite3_create_function(db, "sha3", 1, SQLITE_UTF8, 0,
20360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                               sha3Func, 0, 0);
20370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
20380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = sqlite3_create_function(db, "sha3", 2, SQLITE_UTF8, 0,
20390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                                 sha3Func, 0, 0);
20400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
20410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
20420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = sqlite3_create_function(db, "sha3_query", 1, SQLITE_UTF8, 0,
20430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                                 sha3QueryFunc, 0, 0);
20440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
20450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
20460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = sqlite3_create_function(db, "sha3_query", 2, SQLITE_UTF8, 0,
20470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                                 sha3QueryFunc, 0, 0);
20480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
20490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
20500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
20510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
20520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/************************* End ../ext/misc/shathree.c ********************/
20530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/************************* Begin ../ext/misc/fileio.c ******************/
20540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
20550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** 2014-06-13
20560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
20570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The author disclaims copyright to this source code.  In place of
20580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** a legal notice, here is a blessing:
20590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
20600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you do good and not evil.
20610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you find forgiveness for yourself and forgive others.
20620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you share freely, never taking more than you give.
20630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
20640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov******************************************************************************
20650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
20660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This SQLite extension implements SQL functions readfile() and
20670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** writefile(), and eponymous virtual type "fsdir".
20680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
20690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** WRITEFILE(FILE, DATA [, MODE [, MTIME]]):
20700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
20710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   If neither of the optional arguments is present, then this UDF
20720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   function writes blob DATA to file FILE. If successful, the number
20730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   of bytes written is returned. If an error occurs, NULL is returned.
20740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
20750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   If the first option argument - MODE - is present, then it must
20760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   be passed an integer value that corresponds to a POSIX mode
20770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   value (file type + permissions, as returned in the stat.st_mode
20780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   field by the stat() system call). Three types of files may
20790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   be written/created:
20800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
20810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     regular files:  (mode & 0170000)==0100000
20820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     symbolic links: (mode & 0170000)==0120000
20830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     directories:    (mode & 0170000)==0040000
20840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
20850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   For a directory, the DATA is ignored. For a symbolic link, it is
20860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   interpreted as text and used as the target of the link. For a
20870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   regular file, it is interpreted as a blob and written into the
20880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   named file. Regardless of the type of file, its permissions are
20890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   set to (mode & 0777) before returning.
20900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
20910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   If the optional MTIME argument is present, then it is interpreted
20920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   as an integer - the number of seconds since the unix epoch. The
20930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   modification-time of the target file is set to this value before
20940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   returning.
20950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
20960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   If three or more arguments are passed to this function and an
20970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   error is encountered, an exception is raised.
20980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
20990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** READFILE(FILE):
21000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
21010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   Read and return the contents of file FILE (type blob) from disk.
21020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
21030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** FSDIR:
21040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
21050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   Used as follows:
21060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
21070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     SELECT * FROM fsdir($path [, $dir]);
21080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
21090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   Parameter $path is an absolute or relative pathname. If the file that it
21100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   refers to does not exist, it is an error. If the path refers to a regular
21110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   file or symbolic link, it returns a single row. Or, if the path refers
21120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   to a directory, it returns one row for the directory, and one row for each
21130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   file within the hierarchy rooted at $path.
21140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
21150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   Each row has the following columns:
21160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
21170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     name:  Path to file or directory (text value).
21180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     mode:  Value of stat.st_mode for directory entry (an integer).
21190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     mtime: Value of stat.st_mtime for directory entry (an integer).
21200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     data:  For a regular file, a blob containing the file data. For a
21210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**            symlink, a text value containing the text of the link. For a
21220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**            directory, NULL.
21230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
21240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   If a non-NULL value is specified for the optional $dir parameter and
21250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   $path is a relative path, then $path is interpreted relative to $dir.
21260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   And the paths returned in the "name" column of the table are also
21270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   relative to directory $dir.
21280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
21290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor KupolovSQLITE_EXTENSION_INIT1
21300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <stdio.h>
21310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <string.h>
21320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <assert.h>
21330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
21340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <sys/types.h>
21350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <sys/stat.h>
21360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <fcntl.h>
21370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if !defined(_WIN32) && !defined(WIN32)
21380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#  include <unistd.h>
21390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#  include <dirent.h>
21400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#  include <utime.h>
21410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#  include <sys/time.h>
21420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#else
21430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#  include "windows.h"
21440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#  include <io.h>
21450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#  include <direct.h>
21460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* #  include "test_windirent.h" */
21470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#  define dirent DIRENT
21480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#  ifndef stat
21490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#    define stat _stat
21500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#  endif
21510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#  define mkdir(path,mode) _mkdir(path)
21520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#  define lstat(path,buf) stat(path,buf)
21530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
21540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <time.h>
21550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <errno.h>
21560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
21570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
21580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)"
21590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
21600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
21610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Set the result stored by context ctx to a blob containing the
21620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** contents of file zName.
21630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
21640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void readFileContents(sqlite3_context *ctx, const char *zName){
21650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  FILE *in;
21660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  long nIn;
21670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  void *pBuf;
21680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
21690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  in = fopen(zName, "rb");
21700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( in==0 ) return;
21710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  fseek(in, 0, SEEK_END);
21720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  nIn = ftell(in);
21730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rewind(in);
21740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pBuf = sqlite3_malloc( nIn );
21750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
21760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_result_blob(ctx, pBuf, nIn, sqlite3_free);
21770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
21780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(pBuf);
21790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
21800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  fclose(in);
21810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
21820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
21830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
21840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Implementation of the "readfile(X)" SQL function.  The entire content
21850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** of the file named X is read and returned as a BLOB.  NULL is returned
21860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** if the file does not exist or is unreadable.
21870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
21880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void readfileFunc(
21890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_context *context,
21900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int argc,
21910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_value **argv
21920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
21930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zName;
21940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)(argc);  /* Unused parameter */
21950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zName = (const char*)sqlite3_value_text(argv[0]);
21960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( zName==0 ) return;
21970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  readFileContents(context, zName);
21980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
21990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
22000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
22010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Set the error message contained in context ctx to the results of
22020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** vprintf(zFmt, ...).
22030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
22040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void ctxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
22050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zMsg = 0;
22060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  va_list ap;
22070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  va_start(ap, zFmt);
22080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zMsg = sqlite3_vmprintf(zFmt, ap);
22090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_result_error(ctx, zMsg, -1);
22100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(zMsg);
22110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  va_end(ap);
22120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
22130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
22140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
22150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Argument zFile is the name of a file that will be created and/or written
22160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** by SQL function writefile(). This function ensures that the directory
22170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** zFile will be written to exists, creating it if required. The permissions
22180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** for any path components created by this function are set to (mode&0777).
22190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
22200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** If an OOM condition is encountered, SQLITE_NOMEM is returned. Otherwise,
22210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** SQLITE_OK is returned if the directory is successfully created, or
22220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** SQLITE_ERROR otherwise.
22230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
22240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int makeDirectory(
22250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zFile,
22260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  mode_t mode
22270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
22280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zCopy = sqlite3_mprintf("%s", zFile);
22290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
22300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
22310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( zCopy==0 ){
22320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = SQLITE_NOMEM;
22330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
22340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int nCopy = (int)strlen(zCopy);
22350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int i = 1;
22360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
22370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    while( rc==SQLITE_OK ){
22380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      struct stat sStat;
22390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int rc2;
22400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
22410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      for(; zCopy[i]!='/' && i<nCopy; i++);
22420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( i==nCopy ) break;
22430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zCopy[i] = '\0';
22440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
22450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc2 = stat(zCopy, &sStat);
22460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( rc2!=0 ){
22470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( mkdir(zCopy, mode & 0777) ) rc = SQLITE_ERROR;
22480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else{
22490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( !S_ISDIR(sStat.st_mode) ) rc = SQLITE_ERROR;
22500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
22510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zCopy[i] = '/';
22520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      i++;
22530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
22540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
22550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(zCopy);
22560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
22570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
22580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
22590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
22600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
22610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
22620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This function does the work for the writefile() UDF. Refer to
22630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** header comments at the top of this file for details.
22640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
22650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int writeFile(
22660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_context *pCtx,          /* Context to return bytes written in */
22670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zFile,              /* File to write */
22680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_value *pData,           /* Data to write */
22690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  mode_t mode,                    /* MODE parameter passed to writefile() */
22700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_int64 mtime             /* MTIME parameter (or -1 to not set time) */
22710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
22720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if !defined(_WIN32) && !defined(WIN32)
22730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( S_ISLNK(mode) ){
22740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const char *zTo = (const char*)sqlite3_value_text(pData);
22750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( symlink(zTo, zFile)<0 ) return 1;
22760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else
22770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
22780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  {
22790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( S_ISDIR(mode) ){
22800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( mkdir(zFile, mode) ){
22810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        /* The mkdir() call to create the directory failed. This might not
22820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        ** be an error though - if there is already a directory at the same
22830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        ** path and either the permissions already match or can be changed
22840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        ** to do so using chmod(), it is not an error.  */
22850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        struct stat sStat;
22860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( errno!=EEXIST
22870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov         || 0!=stat(zFile, &sStat)
22880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov         || !S_ISDIR(sStat.st_mode)
22890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov         || ((sStat.st_mode&0777)!=(mode&0777) && 0!=chmod(zFile, mode&0777))
22900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        ){
22910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          return 1;
22920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
22930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
22940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
22950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_int64 nWrite = 0;
22960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      const char *z;
22970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int rc = 0;
22980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      FILE *out = fopen(zFile, "wb");
22990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( out==0 ) return 1;
23000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      z = (const char*)sqlite3_value_blob(pData);
23010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( z ){
23020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_int64 n = fwrite(z, 1, sqlite3_value_bytes(pData), out);
23030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        nWrite = sqlite3_value_bytes(pData);
23040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( nWrite!=n ){
23050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          rc = 1;
23060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
23070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
23080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      fclose(out);
23090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( rc==0 && mode && chmod(zFile, mode & 0777) ){
23100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        rc = 1;
23110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
23120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( rc ) return 2;
23130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_int64(pCtx, nWrite);
23140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
23150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
23160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
23170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( mtime>=0 ){
23180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if defined(_WIN32)
23190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    /* Windows */
23200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    FILETIME lastAccess;
23210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    FILETIME lastWrite;
23220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    SYSTEMTIME currentTime;
23230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    LONGLONG intervals;
23240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    HANDLE hFile;
23250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    GetSystemTime(&currentTime);
23260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    SystemTimeToFileTime(&currentTime, &lastAccess);
23270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    intervals = Int32x32To64(mtime, 10000000) + 116444736000000000;
23280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    lastWrite.dwLowDateTime = (DWORD)intervals;
23290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    lastWrite.dwHighDateTime = intervals >> 32;
23300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    hFile = CreateFile(
23310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zFile, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
23320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      FILE_FLAG_BACKUP_SEMANTICS, NULL
23330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    );
23340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( hFile!=INVALID_HANDLE_VALUE ){
23350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      BOOL bResult = SetFileTime(hFile, NULL, &lastAccess, &lastWrite);
23360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      CloseHandle(hFile);
23370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      return !bResult;
23380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
23390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      return 1;
23400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
23410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#elif defined(AT_FDCWD) && 0 /* utimensat() is not univerally available */
23420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    /* Recent unix */
23430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    struct timespec times[2];
23440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    times[0].tv_nsec = times[1].tv_nsec = 0;
23450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    times[0].tv_sec = time(0);
23460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    times[1].tv_sec = mtime;
23470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( utimensat(AT_FDCWD, zFile, times, AT_SYMLINK_NOFOLLOW) ){
23480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      return 1;
23490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
23500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#else
23510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    /* Legacy unix */
23520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    struct timeval times[2];
23530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    times[0].tv_usec = times[1].tv_usec = 0;
23540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    times[0].tv_sec = time(0);
23550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    times[1].tv_sec = mtime;
23560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( utimes(zFile, times) ){
23570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      return 1;
23580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
23590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
23600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
23610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
23620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return 0;
23630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
23640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
23650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
23660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Implementation of the "writefile(W,X[,Y[,Z]]])" SQL function.
23670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Refer to header comments at the top of this file for details.
23680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
23690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void writefileFunc(
23700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_context *context,
23710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int argc,
23720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_value **argv
23730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
23740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zFile;
23750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  mode_t mode = 0;
23760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int res;
23770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_int64 mtime = -1;
23780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
23790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( argc<2 || argc>4 ){
23800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_result_error(context,
23810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "wrong number of arguments to function writefile()", -1
23820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    );
23830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return;
23840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
23850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
23860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zFile = (const char*)sqlite3_value_text(argv[0]);
23870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( zFile==0 ) return;
23880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( argc>=3 ){
23890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    mode = (mode_t)sqlite3_value_int(argv[2]);
23900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
23910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( argc==4 ){
23920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    mtime = sqlite3_value_int64(argv[3]);
23930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
23940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
23950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  res = writeFile(context, zFile, argv[1], mode, mtime);
23960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( res==1 && errno==ENOENT ){
23970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( makeDirectory(zFile, mode)==SQLITE_OK ){
23980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      res = writeFile(context, zFile, argv[1], mode, mtime);
23990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
24000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
24010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
24020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( argc>2 && res!=0 ){
24030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( S_ISLNK(mode) ){
24040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      ctxErrorMsg(context, "failed to create symlink: %s", zFile);
24050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else if( S_ISDIR(mode) ){
24060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      ctxErrorMsg(context, "failed to create directory: %s", zFile);
24070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
24080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      ctxErrorMsg(context, "failed to write file: %s", zFile);
24090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
24100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
24110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
24120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
24130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
24140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** SQL function:   lsmode(MODE)
24150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
24160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Given a numberic st_mode from stat(), convert it into a human-readable
24170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** text string in the style of "ls -l".
24180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
24190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void lsModeFunc(
24200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_context *context,
24210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int argc,
24220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_value **argv
24230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
24240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int i;
24250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int iMode = sqlite3_value_int(argv[0]);
24260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char z[16];
24270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)argc;
24280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( S_ISLNK(iMode) ){
24290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    z[0] = 'l';
24300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else if( S_ISREG(iMode) ){
24310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    z[0] = '-';
24320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else if( S_ISDIR(iMode) ){
24330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    z[0] = 'd';
24340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
24350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    z[0] = '?';
24360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
24370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(i=0; i<3; i++){
24380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int m = (iMode >> ((2-i)*3));
24390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    char *a = &z[1 + i*3];
24400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a[0] = (m & 0x4) ? 'r' : '-';
24410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a[1] = (m & 0x2) ? 'w' : '-';
24420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a[2] = (m & 0x1) ? 'x' : '-';
24430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
24440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  z[10] = '\0';
24450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT);
24460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
24470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
24480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifndef SQLITE_OMIT_VIRTUALTABLE
24490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
24500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
24510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Cursor type for recursively iterating through a directory structure.
24520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
24530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct fsdir_cursor fsdir_cursor;
24540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct FsdirLevel FsdirLevel;
24550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
24560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct FsdirLevel {
24570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  DIR *pDir;                 /* From opendir() */
24580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zDir;                /* Name of directory (nul-terminated) */
24590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
24600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
24610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct fsdir_cursor {
24620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vtab_cursor base;  /* Base class - must be first */
24630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
24640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nLvl;                  /* Number of entries in aLvl[] array */
24650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int iLvl;                  /* Index of current entry */
24660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  FsdirLevel *aLvl;          /* Hierarchy of directories being traversed */
24670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
24680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zBase;
24690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nBase;
24700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
24710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  struct stat sStat;         /* Current lstat() results */
24720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zPath;               /* Path to current entry */
24730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_int64 iRowid;      /* Current rowid */
24740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
24750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
24760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct fsdir_tab fsdir_tab;
24770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct fsdir_tab {
24780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vtab base;         /* Base class - must be first */
24790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
24800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
24810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
24820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Construct a new fsdir virtual table object.
24830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
24840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int fsdirConnect(
24850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *db,
24860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  void *pAux,
24870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int argc, const char *const*argv,
24880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vtab **ppVtab,
24890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErr
24900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
24910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  fsdir_tab *pNew = 0;
24920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;
24930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)pAux;
24940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)argc;
24950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)argv;
24960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)pzErr;
24970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = sqlite3_declare_vtab(db, "CREATE TABLE x" FSDIR_SCHEMA);
24980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
24990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNew = (fsdir_tab*)sqlite3_malloc( sizeof(*pNew) );
25000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pNew==0 ) return SQLITE_NOMEM;
25010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    memset(pNew, 0, sizeof(*pNew));
25020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
25030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  *ppVtab = (sqlite3_vtab*)pNew;
25040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
25050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
25060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
25070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
25080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This method is the destructor for fsdir vtab objects.
25090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
25100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int fsdirDisconnect(sqlite3_vtab *pVtab){
25110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(pVtab);
25120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
25130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
25140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
25150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
25160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Constructor for a new fsdir_cursor object.
25170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
25180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int fsdirOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
25190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  fsdir_cursor *pCur;
25200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)p;
25210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCur = sqlite3_malloc( sizeof(*pCur) );
25220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pCur==0 ) return SQLITE_NOMEM;
25230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  memset(pCur, 0, sizeof(*pCur));
25240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCur->iLvl = -1;
25250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  *ppCursor = &pCur->base;
25260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
25270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
25280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
25290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
25300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Reset a cursor back to the state it was in when first returned
25310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** by fsdirOpen().
25320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
25330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void fsdirResetCursor(fsdir_cursor *pCur){
25340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int i;
25350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(i=0; i<=pCur->iLvl; i++){
25360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    FsdirLevel *pLvl = &pCur->aLvl[i];
25370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pLvl->pDir ) closedir(pLvl->pDir);
25380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(pLvl->zDir);
25390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
25400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(pCur->zPath);
25410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCur->aLvl = 0;
25420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCur->zPath = 0;
25430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCur->zBase = 0;
25440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCur->nBase = 0;
25450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCur->iLvl = -1;
25460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCur->iRowid = 1;
25470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
25480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
25490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
25500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Destructor for an fsdir_cursor.
25510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
25520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int fsdirClose(sqlite3_vtab_cursor *cur){
25530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  fsdir_cursor *pCur = (fsdir_cursor*)cur;
25540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
25550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  fsdirResetCursor(pCur);
25560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(pCur->aLvl);
25570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(pCur);
25580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
25590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
25600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
25610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
25620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Set the error message for the virtual table associated with cursor
25630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** pCur to the results of vprintf(zFmt, ...).
25640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
25650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void fsdirSetErrmsg(fsdir_cursor *pCur, const char *zFmt, ...){
25660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  va_list ap;
25670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  va_start(ap, zFmt);
25680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCur->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
25690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  va_end(ap);
25700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
25710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
25720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
25730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
25740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Advance an fsdir_cursor to its next row of output.
25750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
25760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int fsdirNext(sqlite3_vtab_cursor *cur){
25770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  fsdir_cursor *pCur = (fsdir_cursor*)cur;
25780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  mode_t m = pCur->sStat.st_mode;
25790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
25800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCur->iRowid++;
25810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( S_ISDIR(m) ){
25820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    /* Descend into this directory */
25830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int iNew = pCur->iLvl + 1;
25840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    FsdirLevel *pLvl;
25850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( iNew>=pCur->nLvl ){
25860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int nNew = iNew+1;
25870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int nByte = nNew*sizeof(FsdirLevel);
25880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      FsdirLevel *aNew = (FsdirLevel*)sqlite3_realloc(pCur->aLvl, nByte);
25890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( aNew==0 ) return SQLITE_NOMEM;
25900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      memset(&aNew[pCur->nLvl], 0, sizeof(FsdirLevel)*(nNew-pCur->nLvl));
25910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pCur->aLvl = aNew;
25920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pCur->nLvl = nNew;
25930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
25940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCur->iLvl = iNew;
25950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pLvl = &pCur->aLvl[iNew];
25960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
25970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pLvl->zDir = pCur->zPath;
25980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCur->zPath = 0;
25990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pLvl->pDir = opendir(pLvl->zDir);
26000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pLvl->pDir==0 ){
26010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      fsdirSetErrmsg(pCur, "cannot read directory: %s", pCur->zPath);
26020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      return SQLITE_ERROR;
26030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
26040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
26050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
26060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  while( pCur->iLvl>=0 ){
26070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    FsdirLevel *pLvl = &pCur->aLvl[pCur->iLvl];
26080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    struct dirent *pEntry = readdir(pLvl->pDir);
26090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pEntry ){
26100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( pEntry->d_name[0]=='.' ){
26110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov       if( pEntry->d_name[1]=='.' && pEntry->d_name[2]=='\0' ) continue;
26120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov       if( pEntry->d_name[1]=='\0' ) continue;
26130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
26140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_free(pCur->zPath);
26150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pCur->zPath = sqlite3_mprintf("%s/%s", pLvl->zDir, pEntry->d_name);
26160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( pCur->zPath==0 ) return SQLITE_NOMEM;
26170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( lstat(pCur->zPath, &pCur->sStat) ){
26180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
26190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        return SQLITE_ERROR;
26200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
26210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      return SQLITE_OK;
26220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
26230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    closedir(pLvl->pDir);
26240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(pLvl->zDir);
26250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pLvl->pDir = 0;
26260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pLvl->zDir = 0;
26270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCur->iLvl--;
26280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
26290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
26300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* EOF */
26310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(pCur->zPath);
26320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCur->zPath = 0;
26330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
26340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
26350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
26360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
26370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Return values of columns for the row at which the series_cursor
26380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** is currently pointing.
26390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
26400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int fsdirColumn(
26410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vtab_cursor *cur,   /* The cursor */
26420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
26430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int i                       /* Which column to return */
26440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
26450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  fsdir_cursor *pCur = (fsdir_cursor*)cur;
26460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  switch( i ){
26470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case 0: { /* name */
26480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_text(ctx, &pCur->zPath[pCur->nBase], -1, SQLITE_TRANSIENT);
26490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
26500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
26510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
26520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case 1: /* mode */
26530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_int64(ctx, pCur->sStat.st_mode);
26540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
26550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
26560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case 2: /* mtime */
26570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_int64(ctx, pCur->sStat.st_mtime);
26580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
26590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
26600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case 3: { /* data */
26610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      mode_t m = pCur->sStat.st_mode;
26620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( S_ISDIR(m) ){
26630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_result_null(ctx);
26640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if !defined(_WIN32) && !defined(WIN32)
26650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else if( S_ISLNK(m) ){
26660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        char aStatic[64];
26670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        char *aBuf = aStatic;
26680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        int nBuf = 64;
26690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        int n;
26700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
26710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        while( 1 ){
26720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          n = readlink(pCur->zPath, aBuf, nBuf);
26730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( n<nBuf ) break;
26740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( aBuf!=aStatic ) sqlite3_free(aBuf);
26750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          nBuf = nBuf*2;
26760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          aBuf = sqlite3_malloc(nBuf);
26770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( aBuf==0 ){
26780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            sqlite3_result_error_nomem(ctx);
26790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            return SQLITE_NOMEM;
26800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
26810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
26820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
26830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_result_text(ctx, aBuf, n, SQLITE_TRANSIENT);
26840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( aBuf!=aStatic ) sqlite3_free(aBuf);
26850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
26860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else{
26870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        readFileContents(ctx, pCur->zPath);
26880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
26890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
26900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
26910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
26920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
26930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
26940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
26950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Return the rowid for the current row. In this implementation, the
26960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** first row returned is assigned rowid value 1, and each subsequent
26970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** row a value 1 more than that of the previous.
26980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
26990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int fsdirRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
27000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  fsdir_cursor *pCur = (fsdir_cursor*)cur;
27010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  *pRowid = pCur->iRowid;
27020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
27030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
27040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
27050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
27060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Return TRUE if the cursor has been moved off of the last
27070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** row of output.
27080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
27090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int fsdirEof(sqlite3_vtab_cursor *cur){
27100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  fsdir_cursor *pCur = (fsdir_cursor*)cur;
27110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return (pCur->zPath==0);
27120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
27130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
27140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
27150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** xFilter callback.
27160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
27170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int fsdirFilter(
27180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vtab_cursor *cur,
27190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int idxNum, const char *idxStr,
27200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int argc, sqlite3_value **argv
27210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
27220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zDir = 0;
27230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  fsdir_cursor *pCur = (fsdir_cursor*)cur;
27240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)idxStr;
27250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  fsdirResetCursor(pCur);
27260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
27270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( idxNum==0 ){
27280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    fsdirSetErrmsg(pCur, "table function fsdir requires an argument");
27290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return SQLITE_ERROR;
27300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
27310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
27320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( argc==idxNum && (argc==1 || argc==2) );
27330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zDir = (const char*)sqlite3_value_text(argv[0]);
27340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( zDir==0 ){
27350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    fsdirSetErrmsg(pCur, "table function fsdir requires a non-NULL argument");
27360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return SQLITE_ERROR;
27370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
27380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( argc==2 ){
27390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCur->zBase = (const char*)sqlite3_value_text(argv[1]);
27400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
27410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pCur->zBase ){
27420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCur->nBase = (int)strlen(pCur->zBase)+1;
27430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCur->zPath = sqlite3_mprintf("%s/%s", pCur->zBase, zDir);
27440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
27450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCur->zPath = sqlite3_mprintf("%s", zDir);
27460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
27470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
27480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pCur->zPath==0 ){
27490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return SQLITE_NOMEM;
27500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
27510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( lstat(pCur->zPath, &pCur->sStat) ){
27520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
27530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return SQLITE_ERROR;
27540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
27550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
27560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
27570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
27580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
27590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
27600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** SQLite will invoke this method one or more times while planning a query
27610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** that uses the generate_series virtual table.  This routine needs to create
27620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** a query plan for each invocation and compute an estimated cost for that
27630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** plan.
27640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
27650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** In this implementation idxNum is used to represent the
27660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** query plan.  idxStr is unused.
27670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
27680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The query plan is represented by bits in idxNum:
27690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
27700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**  (1)  start = $value  -- constraint exists
27710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**  (2)  stop = $value   -- constraint exists
27720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**  (4)  step = $value   -- constraint exists
27730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**  (8)  output in descending order
27740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
27750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int fsdirBestIndex(
27760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vtab *tab,
27770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_index_info *pIdxInfo
27780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
27790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int i;                 /* Loop over constraints */
27800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int idx4 = -1;
27810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int idx5 = -1;
27820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const struct sqlite3_index_constraint *pConstraint;
27830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
27840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)tab;
27850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pConstraint = pIdxInfo->aConstraint;
27860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
27870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pConstraint->usable==0 ) continue;
27880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
27890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pConstraint->iColumn==4 ) idx4 = i;
27900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pConstraint->iColumn==5 ) idx5 = i;
27910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
27920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
27930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( idx4<0 ){
27940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pIdxInfo->idxNum = 0;
27950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pIdxInfo->estimatedCost = (double)(((sqlite3_int64)1) << 50);
27960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
27970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pIdxInfo->aConstraintUsage[idx4].omit = 1;
27980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pIdxInfo->aConstraintUsage[idx4].argvIndex = 1;
27990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( idx5>=0 ){
28000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pIdxInfo->aConstraintUsage[idx5].omit = 1;
28010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pIdxInfo->aConstraintUsage[idx5].argvIndex = 2;
28020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pIdxInfo->idxNum = 2;
28030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pIdxInfo->estimatedCost = 10.0;
28040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
28050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pIdxInfo->idxNum = 1;
28060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pIdxInfo->estimatedCost = 100.0;
28070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
28080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
28090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
28100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
28110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
28120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
28130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
28140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Register the "fsdir" virtual table.
28150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
28160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int fsdirRegister(sqlite3 *db){
28170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  static sqlite3_module fsdirModule = {
28180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0,                         /* iVersion */
28190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0,                         /* xCreate */
28200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    fsdirConnect,              /* xConnect */
28210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    fsdirBestIndex,            /* xBestIndex */
28220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    fsdirDisconnect,           /* xDisconnect */
28230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0,                         /* xDestroy */
28240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    fsdirOpen,                 /* xOpen - open a cursor */
28250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    fsdirClose,                /* xClose - close a cursor */
28260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    fsdirFilter,               /* xFilter - configure scan constraints */
28270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    fsdirNext,                 /* xNext - advance a cursor */
28280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    fsdirEof,                  /* xEof - check for end of scan */
28290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    fsdirColumn,               /* xColumn - read data */
28300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    fsdirRowid,                /* xRowid - read data */
28310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0,                         /* xUpdate */
28320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0,                         /* xBegin */
28330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0,                         /* xSync */
28340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0,                         /* xCommit */
28350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0,                         /* xRollback */
28360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0,                         /* xFindMethod */
28370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0,                         /* xRename */
28380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0,                         /* xSavepoint */
28390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0,                         /* xRelease */
28400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0                          /* xRollbackTo */
28410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  };
28420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
28430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = sqlite3_create_module(db, "fsdir", &fsdirModule, 0);
28440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
28450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
28460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#else         /* SQLITE_OMIT_VIRTUALTABLE */
28470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define fsdirRegister(x) SQLITE_OK
28480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
28490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
28500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifdef _WIN32
28510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
28520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
28530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovint sqlite3_fileio_init(
28540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *db,
28550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErrMsg,
28560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const sqlite3_api_routines *pApi
28570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
28580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
28590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  SQLITE_EXTENSION_INIT2(pApi);
28600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)pzErrMsg;  /* Unused parameter */
28610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0,
28620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                               readfileFunc, 0, 0);
28630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
28640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = sqlite3_create_function(db, "writefile", -1, SQLITE_UTF8, 0,
28650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                                 writefileFunc, 0, 0);
28660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
28670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
28680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = sqlite3_create_function(db, "lsmode", 1, SQLITE_UTF8, 0,
28690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                                 lsModeFunc, 0, 0);
28700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
28710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
28720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = fsdirRegister(db);
28730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
28740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
28750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
28760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
28770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/************************* End ../ext/misc/fileio.c ********************/
28780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/************************* Begin ../ext/misc/completion.c ******************/
28790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
28800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** 2017-07-10
28810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
28820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The author disclaims copyright to this source code.  In place of
28830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** a legal notice, here is a blessing:
28840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
28850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you do good and not evil.
28860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you find forgiveness for yourself and forgive others.
28870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you share freely, never taking more than you give.
28880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
28890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*************************************************************************
28900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
28910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This file implements an eponymous virtual table that returns suggested
28920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** completions for a partial SQL input.
28930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
28940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Suggested usage:
28950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
28960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     SELECT DISTINCT candidate COLLATE nocase
28970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**       FROM completion($prefix,$wholeline)
28980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**      ORDER BY 1;
28990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
29000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The two query parameters are optional.  $prefix is the text of the
29010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** current word being typed and that is to be completed.  $wholeline is
29020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** the complete input line, used for context.
29030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
29040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The raw completion() table might return the same candidate multiple
29050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** times, for example if the same column name is used to two or more
29060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** tables.  And the candidates are returned in an arbitrary order.  Hence,
29070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** the DISTINCT and ORDER BY are recommended.
29080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
29090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This virtual table operates at the speed of human typing, and so there
29100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** is no attempt to make it fast.  Even a slow implementation will be much
29110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** faster than any human can type.
29120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
29130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
29140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor KupolovSQLITE_EXTENSION_INIT1
29150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <assert.h>
29160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <string.h>
29170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <ctype.h>
29180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
29190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifndef SQLITE_OMIT_VIRTUALTABLE
29200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
29210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* completion_vtab is a subclass of sqlite3_vtab which will
29220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** serve as the underlying representation of a completion virtual table
29230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
29240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct completion_vtab completion_vtab;
29250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct completion_vtab {
29260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vtab base;  /* Base class - must be first */
29270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *db;        /* Database connection for this completion vtab */
29280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
29290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
29300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* completion_cursor is a subclass of sqlite3_vtab_cursor which will
29310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** serve as the underlying representation of a cursor that scans
29320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** over rows of the result
29330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
29340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct completion_cursor completion_cursor;
29350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct completion_cursor {
29360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vtab_cursor base;  /* Base class - must be first */
29370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *db;               /* Database connection for this cursor */
29380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nPrefix, nLine;        /* Number of bytes in zPrefix and zLine */
29390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zPrefix;             /* The prefix for the word we want to complete */
29400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zLine;               /* The whole that we want to complete */
29410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zCurrentRow;   /* Current output row */
29420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_stmt *pStmt;       /* Current statement */
29430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_int64 iRowid;      /* The rowid */
29440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int ePhase;                /* Current phase */
29450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int j;                     /* inter-phase counter */
29460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
29470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
29480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* Values for ePhase:
29490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
29500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define COMPLETION_FIRST_PHASE   1
29510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define COMPLETION_KEYWORDS      1
29520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define COMPLETION_PRAGMAS       2
29530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define COMPLETION_FUNCTIONS     3
29540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define COMPLETION_COLLATIONS    4
29550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define COMPLETION_INDEXES       5
29560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define COMPLETION_TRIGGERS      6
29570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define COMPLETION_DATABASES     7
29580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define COMPLETION_TABLES        8
29590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define COMPLETION_COLUMNS       9
29600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define COMPLETION_MODULES       10
29610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define COMPLETION_EOF           11
29620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
29630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
29640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The completionConnect() method is invoked to create a new
29650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** completion_vtab that describes the completion virtual table.
29660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
29670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Think of this routine as the constructor for completion_vtab objects.
29680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
29690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** All this routine needs to do is:
29700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
29710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    (1) Allocate the completion_vtab object and initialize all fields.
29720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
29730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
29740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**        result set of queries against completion will look like.
29750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
29760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int completionConnect(
29770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *db,
29780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  void *pAux,
29790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int argc, const char *const*argv,
29800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vtab **ppVtab,
29810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErr
29820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
29830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  completion_vtab *pNew;
29840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;
29850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
29860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)(pAux);    /* Unused parameter */
29870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)(argc);    /* Unused parameter */
29880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)(argv);    /* Unused parameter */
29890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)(pzErr);   /* Unused parameter */
29900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
29910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* Column numbers */
29920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define COMPLETION_COLUMN_CANDIDATE 0  /* Suggested completion of the input */
29930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define COMPLETION_COLUMN_PREFIX    1  /* Prefix of the word to be completed */
29940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define COMPLETION_COLUMN_WHOLELINE 2  /* Entire line seen so far */
29950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define COMPLETION_COLUMN_PHASE     3  /* ePhase - used for debugging only */
29960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
29970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = sqlite3_declare_vtab(db,
29980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      "CREATE TABLE x("
29990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      "  candidate TEXT,"
30000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      "  prefix TEXT HIDDEN,"
30010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      "  wholeline TEXT HIDDEN,"
30020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      "  phase INT HIDDEN"        /* Used for debugging only */
30030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      ")");
30040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
30050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNew = sqlite3_malloc( sizeof(*pNew) );
30060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    *ppVtab = (sqlite3_vtab*)pNew;
30070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pNew==0 ) return SQLITE_NOMEM;
30080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    memset(pNew, 0, sizeof(*pNew));
30090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNew->db = db;
30100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
30110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
30120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
30130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
30140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
30150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This method is the destructor for completion_cursor objects.
30160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
30170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int completionDisconnect(sqlite3_vtab *pVtab){
30180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(pVtab);
30190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
30200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
30210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
30220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
30230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Constructor for a new completion_cursor object.
30240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
30250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int completionOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
30260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  completion_cursor *pCur;
30270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCur = sqlite3_malloc( sizeof(*pCur) );
30280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pCur==0 ) return SQLITE_NOMEM;
30290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  memset(pCur, 0, sizeof(*pCur));
30300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCur->db = ((completion_vtab*)p)->db;
30310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  *ppCursor = &pCur->base;
30320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
30330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
30340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
30350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
30360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Reset the completion_cursor.
30370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
30380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void completionCursorReset(completion_cursor *pCur){
30390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(pCur->zPrefix);   pCur->zPrefix = 0;  pCur->nPrefix = 0;
30400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(pCur->zLine);     pCur->zLine = 0;    pCur->nLine = 0;
30410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_finalize(pCur->pStmt); pCur->pStmt = 0;
30420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCur->j = 0;
30430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
30440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
30450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
30460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Destructor for a completion_cursor.
30470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
30480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int completionClose(sqlite3_vtab_cursor *cur){
30490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  completionCursorReset((completion_cursor*)cur);
30500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(cur);
30510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
30520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
30530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
30540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
30550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** All SQL keywords understood by SQLite
30560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
30570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic const char *completionKwrds[] = {
30580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  "ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS",
30590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  "ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY",
30600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT",
30610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE",
30620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE",
30630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH",
30640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN",
30650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  "FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF",
30660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER",
30670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY",
30680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  "LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL",
30690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  "NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA",
30700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  "PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP",
30710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  "REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT",
30720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  "ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP",
30730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  "TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE",
30740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  "UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE",
30750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  "WITH", "WITHOUT",
30760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
30770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define completionKwCount \
30780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov   (int)(sizeof(completionKwrds)/sizeof(completionKwrds[0]))
30790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
30800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
30810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Advance a completion_cursor to its next row of output.
30820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
30830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The ->ePhase, ->j, and ->pStmt fields of the completion_cursor object
30840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** record the current state of the scan.  This routine sets ->zCurrentRow
30850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** to the current row of output and then returns.  If no more rows remain,
30860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** then ->ePhase is set to COMPLETION_EOF which will signal the virtual
30870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** table that has reached the end of its scan.
30880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
30890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The current implementation just lists potential identifiers and
30900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** keywords and filters them by zPrefix.  Future enhancements should
30910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** take zLine into account to try to restrict the set of identifiers and
30920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** keywords based on what would be legal at the current point of input.
30930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
30940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int completionNext(sqlite3_vtab_cursor *cur){
30950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  completion_cursor *pCur = (completion_cursor*)cur;
30960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int eNextPhase = 0;  /* Next phase to try if current phase reaches end */
30970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int iCol = -1;       /* If >=0, step pCur->pStmt and use the i-th column */
30980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCur->iRowid++;
30990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  while( pCur->ePhase!=COMPLETION_EOF ){
31000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    switch( pCur->ePhase ){
31010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      case COMPLETION_KEYWORDS: {
31020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( pCur->j >= completionKwCount ){
31030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          pCur->zCurrentRow = 0;
31040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          pCur->ePhase = COMPLETION_DATABASES;
31050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }else{
31060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          pCur->zCurrentRow = completionKwrds[pCur->j++];
31070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
31080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        iCol = -1;
31090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        break;
31100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
31110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      case COMPLETION_DATABASES: {
31120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( pCur->pStmt==0 ){
31130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1,
31140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                             &pCur->pStmt, 0);
31150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
31160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        iCol = 1;
31170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        eNextPhase = COMPLETION_TABLES;
31180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        break;
31190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
31200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      case COMPLETION_TABLES: {
31210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( pCur->pStmt==0 ){
31220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          sqlite3_stmt *pS2;
31230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          char *zSql = 0;
31240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          const char *zSep = "";
31250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
31260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          while( sqlite3_step(pS2)==SQLITE_ROW ){
31270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
31280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            zSql = sqlite3_mprintf(
31290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov               "%z%s"
31300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov               "SELECT name FROM \"%w\".sqlite_master"
31310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov               " WHERE type='table'",
31320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov               zSql, zSep, zDb
31330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            );
31340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            if( zSql==0 ) return SQLITE_NOMEM;
31350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            zSep = " UNION ";
31360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
31370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          sqlite3_finalize(pS2);
31380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
31390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          sqlite3_free(zSql);
31400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
31410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        iCol = 0;
31420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        eNextPhase = COMPLETION_COLUMNS;
31430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        break;
31440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
31450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      case COMPLETION_COLUMNS: {
31460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( pCur->pStmt==0 ){
31470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          sqlite3_stmt *pS2;
31480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          char *zSql = 0;
31490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          const char *zSep = "";
31500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
31510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          while( sqlite3_step(pS2)==SQLITE_ROW ){
31520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
31530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            zSql = sqlite3_mprintf(
31540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov               "%z%s"
31550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov               "SELECT pti.name FROM \"%w\".sqlite_master AS sm"
31560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                       " JOIN pragma_table_info(sm.name,%Q) AS pti"
31570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov               " WHERE sm.type='table'",
31580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov               zSql, zSep, zDb, zDb
31590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            );
31600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            if( zSql==0 ) return SQLITE_NOMEM;
31610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            zSep = " UNION ";
31620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
31630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          sqlite3_finalize(pS2);
31640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
31650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          sqlite3_free(zSql);
31660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
31670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        iCol = 0;
31680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        eNextPhase = COMPLETION_EOF;
31690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        break;
31700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
31710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
31720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( iCol<0 ){
31730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      /* This case is when the phase presets zCurrentRow */
31740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( pCur->zCurrentRow==0 ) continue;
31750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
31760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( sqlite3_step(pCur->pStmt)==SQLITE_ROW ){
31770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        /* Extract the next row of content */
31780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        pCur->zCurrentRow = (const char*)sqlite3_column_text(pCur->pStmt, iCol);
31790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else{
31800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        /* When all rows are finished, advance to the next phase */
31810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_finalize(pCur->pStmt);
31820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        pCur->pStmt = 0;
31830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        pCur->ePhase = eNextPhase;
31840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        continue;
31850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
31860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
31870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pCur->nPrefix==0 ) break;
31880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( sqlite3_strnicmp(pCur->zPrefix, pCur->zCurrentRow, pCur->nPrefix)==0 ){
31890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
31900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
31910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
31920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
31930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
31940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
31950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
31960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
31970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Return values of columns for the row at which the completion_cursor
31980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** is currently pointing.
31990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
32000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int completionColumn(
32010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vtab_cursor *cur,   /* The cursor */
32020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
32030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int i                       /* Which column to return */
32040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
32050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  completion_cursor *pCur = (completion_cursor*)cur;
32060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  switch( i ){
32070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case COMPLETION_COLUMN_CANDIDATE: {
32080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_text(ctx, pCur->zCurrentRow, -1, SQLITE_TRANSIENT);
32090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
32100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
32110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case COMPLETION_COLUMN_PREFIX: {
32120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_text(ctx, pCur->zPrefix, -1, SQLITE_TRANSIENT);
32130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
32140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
32150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case COMPLETION_COLUMN_WHOLELINE: {
32160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_text(ctx, pCur->zLine, -1, SQLITE_TRANSIENT);
32170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
32180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
32190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case COMPLETION_COLUMN_PHASE: {
32200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_int(ctx, pCur->ePhase);
32210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
32220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
32230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
32240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
32250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
32260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
32270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
32280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Return the rowid for the current row.  In this implementation, the
32290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** rowid is the same as the output value.
32300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
32310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int completionRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
32320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  completion_cursor *pCur = (completion_cursor*)cur;
32330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  *pRowid = pCur->iRowid;
32340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
32350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
32360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
32370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
32380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Return TRUE if the cursor has been moved off of the last
32390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** row of output.
32400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
32410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int completionEof(sqlite3_vtab_cursor *cur){
32420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  completion_cursor *pCur = (completion_cursor*)cur;
32430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return pCur->ePhase >= COMPLETION_EOF;
32440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
32450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
32460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
32470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This method is called to "rewind" the completion_cursor object back
32480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** to the first row of output.  This method is always called at least
32490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** once prior to any call to completionColumn() or completionRowid() or
32500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** completionEof().
32510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
32520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int completionFilter(
32530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vtab_cursor *pVtabCursor,
32540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int idxNum, const char *idxStr,
32550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int argc, sqlite3_value **argv
32560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
32570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  completion_cursor *pCur = (completion_cursor *)pVtabCursor;
32580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int iArg = 0;
32590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)(idxStr);   /* Unused parameter */
32600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)(argc);     /* Unused parameter */
32610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  completionCursorReset(pCur);
32620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( idxNum & 1 ){
32630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCur->nPrefix = sqlite3_value_bytes(argv[iArg]);
32640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pCur->nPrefix>0 ){
32650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pCur->zPrefix = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
32660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
32670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
32680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    iArg++;
32690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
32700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( idxNum & 2 ){
32710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCur->nLine = sqlite3_value_bytes(argv[iArg]);
32720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pCur->nLine>0 ){
32730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pCur->zLine = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
32740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( pCur->zLine==0 ) return SQLITE_NOMEM;
32750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
32760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    iArg++;
32770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
32780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pCur->zLine!=0 && pCur->zPrefix==0 ){
32790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int i = pCur->nLine;
32800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    while( i>0 && (isalnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){
32810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      i--;
32820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
32830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCur->nPrefix = pCur->nLine - i;
32840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pCur->nPrefix>0 ){
32850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pCur->zPrefix = sqlite3_mprintf("%.*s", pCur->nPrefix, pCur->zLine + i);
32860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
32870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
32880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
32890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCur->iRowid = 0;
32900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCur->ePhase = COMPLETION_FIRST_PHASE;
32910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return completionNext(pVtabCursor);
32920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
32930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
32940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
32950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** SQLite will invoke this method one or more times while planning a query
32960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** that uses the completion virtual table.  This routine needs to create
32970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** a query plan for each invocation and compute an estimated cost for that
32980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** plan.
32990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
33000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** There are two hidden parameters that act as arguments to the table-valued
33010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** function:  "prefix" and "wholeline".  Bit 0 of idxNum is set if "prefix"
33020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** is available and bit 1 is set if "wholeline" is available.
33030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
33040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int completionBestIndex(
33050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vtab *tab,
33060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_index_info *pIdxInfo
33070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
33080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int i;                 /* Loop over constraints */
33090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int idxNum = 0;        /* The query plan bitmask */
33100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int prefixIdx = -1;    /* Index of the start= constraint, or -1 if none */
33110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int wholelineIdx = -1; /* Index of the stop= constraint, or -1 if none */
33120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nArg = 0;          /* Number of arguments that completeFilter() expects */
33130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const struct sqlite3_index_constraint *pConstraint;
33140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
33150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)(tab);    /* Unused parameter */
33160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pConstraint = pIdxInfo->aConstraint;
33170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
33180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pConstraint->usable==0 ) continue;
33190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
33200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    switch( pConstraint->iColumn ){
33210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      case COMPLETION_COLUMN_PREFIX:
33220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        prefixIdx = i;
33230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        idxNum |= 1;
33240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        break;
33250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      case COMPLETION_COLUMN_WHOLELINE:
33260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        wholelineIdx = i;
33270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        idxNum |= 2;
33280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        break;
33290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
33300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
33310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( prefixIdx>=0 ){
33320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pIdxInfo->aConstraintUsage[prefixIdx].argvIndex = ++nArg;
33330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pIdxInfo->aConstraintUsage[prefixIdx].omit = 1;
33340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
33350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( wholelineIdx>=0 ){
33360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pIdxInfo->aConstraintUsage[wholelineIdx].argvIndex = ++nArg;
33370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pIdxInfo->aConstraintUsage[wholelineIdx].omit = 1;
33380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
33390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pIdxInfo->idxNum = idxNum;
33400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pIdxInfo->estimatedCost = (double)5000 - 1000*nArg;
33410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pIdxInfo->estimatedRows = 500 - 100*nArg;
33420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
33430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
33440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
33450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
33460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This following structure defines all the methods for the
33470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** completion virtual table.
33480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
33490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic sqlite3_module completionModule = {
33500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  0,                         /* iVersion */
33510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  0,                         /* xCreate */
33520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  completionConnect,         /* xConnect */
33530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  completionBestIndex,       /* xBestIndex */
33540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  completionDisconnect,      /* xDisconnect */
33550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  0,                         /* xDestroy */
33560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  completionOpen,            /* xOpen - open a cursor */
33570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  completionClose,           /* xClose - close a cursor */
33580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  completionFilter,          /* xFilter - configure scan constraints */
33590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  completionNext,            /* xNext - advance a cursor */
33600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  completionEof,             /* xEof - check for end of scan */
33610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  completionColumn,          /* xColumn - read data */
33620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  completionRowid,           /* xRowid - read data */
33630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  0,                         /* xUpdate */
33640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  0,                         /* xBegin */
33650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  0,                         /* xSync */
33660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  0,                         /* xCommit */
33670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  0,                         /* xRollback */
33680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  0,                         /* xFindMethod */
33690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  0,                         /* xRename */
33700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  0,                         /* xSavepoint */
33710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  0,                         /* xRelease */
33720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  0                          /* xRollbackTo */
33730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
33740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
33750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif /* SQLITE_OMIT_VIRTUALTABLE */
33760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
33770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovint sqlite3CompletionVtabInit(sqlite3 *db){
33780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
33790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifndef SQLITE_OMIT_VIRTUALTABLE
33800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = sqlite3_create_module(db, "completion", &completionModule, 0);
33810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
33820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
33830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
33840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
33850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifdef _WIN32
33860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
33870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
33880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovint sqlite3_completion_init(
33890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *db,
33900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErrMsg,
33910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const sqlite3_api_routines *pApi
33920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
33930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
33940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  SQLITE_EXTENSION_INIT2(pApi);
33950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)(pzErrMsg);  /* Unused parameter */
33960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifndef SQLITE_OMIT_VIRTUALTABLE
33970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = sqlite3CompletionVtabInit(db);
33980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
33990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
34000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
34010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
34020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/************************* End ../ext/misc/completion.c ********************/
34030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/************************* Begin ../ext/misc/appendvfs.c ******************/
34040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
34050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** 2017-10-20
34060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
34070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The author disclaims copyright to this source code.  In place of
34080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** a legal notice, here is a blessing:
34090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
34100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you do good and not evil.
34110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you find forgiveness for yourself and forgive others.
34120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you share freely, never taking more than you give.
34130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
34140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov******************************************************************************
34150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
34160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This file implements a VFS shim that allows an SQLite database to be
34170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** appended onto the end of some other file, such as an executable.
34180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
34190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** A special record must appear at the end of the file that identifies the
34200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** file as an appended database and provides an offset to page 1.  For
34210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** best performance page 1 should be located at a disk page boundary, though
34220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** that is not required.
34230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
34240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** When opening a database using this VFS, the connection might treat
34250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** the file as an ordinary SQLite database, or it might treat is as a
34260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** database appended onto some other file.  Here are the rules:
34270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
34280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**  (1)  When opening a new empty file, that file is treated as an ordinary
34290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**       database.
34300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
34310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**  (2)  When opening a file that begins with the standard SQLite prefix
34320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**       string "SQLite format 3", that file is treated as an ordinary
34330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**       database.
34340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
34350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**  (3)  When opening a file that ends with the appendvfs trailer string
34360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**       "Start-Of-SQLite3-NNNNNNNN" that file is treated as an appended
34370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**       database.
34380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
34390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**  (4)  If none of the above apply and the SQLITE_OPEN_CREATE flag is
34400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**       set, then a new database is appended to the already existing file.
34410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
34420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**  (5)  Otherwise, SQLITE_CANTOPEN is returned.
34430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
34440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** To avoid unnecessary complications with the PENDING_BYTE, the size of
34450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** the file containing the database is limited to 1GB.  This VFS will refuse
34460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** to read or write past the 1GB mark.  This restriction might be lifted in
34470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** future versions.  For now, if you need a large database, then keep the
34480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** database in a separate file.
34490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
34500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** If the file being opened is not an appended database, then this shim is
34510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** a pass-through into the default underlying VFS.
34520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**/
34530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor KupolovSQLITE_EXTENSION_INIT1
34540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <string.h>
34550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <assert.h>
34560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
34570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* The append mark at the end of the database is:
34580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
34590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     Start-Of-SQLite3-NNNNNNNN
34600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     123456789 123456789 12345
34610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
34620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The NNNNNNNN represents a 64-bit big-endian unsigned integer which is
34630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** the offset to page 1.
34640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
34650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define APND_MARK_PREFIX     "Start-Of-SQLite3-"
34660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define APND_MARK_PREFIX_SZ  17
34670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define APND_MARK_SIZE       25
34680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
34690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
34700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Maximum size of the combined prefix + database + append-mark.  This
34710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** must be less than 0x40000000 to avoid locking issues on Windows.
34720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
34730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define APND_MAX_SIZE  (65536*15259)
34740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
34750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
34760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Forward declaration of objects used by this utility
34770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
34780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct sqlite3_vfs ApndVfs;
34790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct ApndFile ApndFile;
34800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
34810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* Access to a lower-level VFS that (might) implement dynamic loading,
34820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** access to randomness, etc.
34830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
34840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define ORIGVFS(p)  ((sqlite3_vfs*)((p)->pAppData))
34850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define ORIGFILE(p) ((sqlite3_file*)(((ApndFile*)(p))+1))
34860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
34870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* An open file */
34880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct ApndFile {
34890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_file base;              /* IO methods */
34900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_int64 iPgOne;           /* File offset to page 1 */
34910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_int64 iMark;            /* Start of the append-mark */
34920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
34930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
34940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
34950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Methods for ApndFile
34960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
34970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndClose(sqlite3_file*);
34980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
34990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
35000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndTruncate(sqlite3_file*, sqlite3_int64 size);
35010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndSync(sqlite3_file*, int flags);
35020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndFileSize(sqlite3_file*, sqlite3_int64 *pSize);
35030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndLock(sqlite3_file*, int);
35040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndUnlock(sqlite3_file*, int);
35050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndCheckReservedLock(sqlite3_file*, int *pResOut);
35060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndFileControl(sqlite3_file*, int op, void *pArg);
35070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndSectorSize(sqlite3_file*);
35080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndDeviceCharacteristics(sqlite3_file*);
35090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndShmMap(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
35100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndShmLock(sqlite3_file*, int offset, int n, int flags);
35110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void apndShmBarrier(sqlite3_file*);
35120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndShmUnmap(sqlite3_file*, int deleteFlag);
35130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
35140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
35150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
35160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
35170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Methods for ApndVfs
35180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
35190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
35200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndDelete(sqlite3_vfs*, const char *zName, int syncDir);
35210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndAccess(sqlite3_vfs*, const char *zName, int flags, int *);
35220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
35230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void *apndDlOpen(sqlite3_vfs*, const char *zFilename);
35240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void apndDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
35250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
35260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void apndDlClose(sqlite3_vfs*, void*);
35270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndRandomness(sqlite3_vfs*, int nByte, char *zOut);
35280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndSleep(sqlite3_vfs*, int microseconds);
35290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndCurrentTime(sqlite3_vfs*, double*);
35300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndGetLastError(sqlite3_vfs*, int, char *);
35310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
35320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndSetSystemCall(sqlite3_vfs*, const char*,sqlite3_syscall_ptr);
35330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic sqlite3_syscall_ptr apndGetSystemCall(sqlite3_vfs*, const char *z);
35340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic const char *apndNextSystemCall(sqlite3_vfs*, const char *zName);
35350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
35360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic sqlite3_vfs apnd_vfs = {
35370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  3,                            /* iVersion (set when registered) */
35380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  0,                            /* szOsFile (set when registered) */
35390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  1024,                         /* mxPathname */
35400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  0,                            /* pNext */
35410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  "apndvfs",                    /* zName */
35420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  0,                            /* pAppData (set when registered) */
35430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndOpen,                     /* xOpen */
35440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndDelete,                   /* xDelete */
35450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndAccess,                   /* xAccess */
35460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndFullPathname,             /* xFullPathname */
35470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndDlOpen,                   /* xDlOpen */
35480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndDlError,                  /* xDlError */
35490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndDlSym,                    /* xDlSym */
35500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndDlClose,                  /* xDlClose */
35510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndRandomness,               /* xRandomness */
35520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndSleep,                    /* xSleep */
35530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndCurrentTime,              /* xCurrentTime */
35540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndGetLastError,             /* xGetLastError */
35550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndCurrentTimeInt64,         /* xCurrentTimeInt64 */
35560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndSetSystemCall,            /* xSetSystemCall */
35570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndGetSystemCall,            /* xGetSystemCall */
35580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndNextSystemCall            /* xNextSystemCall */
35590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
35600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
35610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic const sqlite3_io_methods apnd_io_methods = {
35620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  3,                              /* iVersion */
35630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndClose,                      /* xClose */
35640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndRead,                       /* xRead */
35650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndWrite,                      /* xWrite */
35660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndTruncate,                   /* xTruncate */
35670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndSync,                       /* xSync */
35680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndFileSize,                   /* xFileSize */
35690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndLock,                       /* xLock */
35700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndUnlock,                     /* xUnlock */
35710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndCheckReservedLock,          /* xCheckReservedLock */
35720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndFileControl,                /* xFileControl */
35730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndSectorSize,                 /* xSectorSize */
35740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndDeviceCharacteristics,      /* xDeviceCharacteristics */
35750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndShmMap,                     /* xShmMap */
35760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndShmLock,                    /* xShmLock */
35770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndShmBarrier,                 /* xShmBarrier */
35780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndShmUnmap,                   /* xShmUnmap */
35790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndFetch,                      /* xFetch */
35800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apndUnfetch                     /* xUnfetch */
35810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
35820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
35830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
35840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
35850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
35860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Close an apnd-file.
35870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
35880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndClose(sqlite3_file *pFile){
35890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pFile = ORIGFILE(pFile);
35900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return pFile->pMethods->xClose(pFile);
35910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
35920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
35930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
35940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Read data from an apnd-file.
35950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
35960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndRead(
35970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_file *pFile,
35980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  void *zBuf,
35990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int iAmt,
36000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite_int64 iOfst
36010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
36020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ApndFile *p = (ApndFile *)pFile;
36030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pFile = ORIGFILE(pFile);
36040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return pFile->pMethods->xRead(pFile, zBuf, iAmt, iOfst+p->iPgOne);
36050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
36060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
36070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
36080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Add the append-mark onto the end of the file.
36090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
36100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndWriteMark(ApndFile *p, sqlite3_file *pFile){
36110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int i;
36120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  unsigned char a[APND_MARK_SIZE];
36130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  memcpy(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ);
36140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(i=0; i<8; i++){
36150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    a[APND_MARK_PREFIX_SZ+i] = (p->iPgOne >> (56 - i*8)) & 0xff;
36160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
36170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return pFile->pMethods->xWrite(pFile, a, APND_MARK_SIZE, p->iMark);
36180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
36190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
36200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
36210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Write data to an apnd-file.
36220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
36230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndWrite(
36240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_file *pFile,
36250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const void *zBuf,
36260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int iAmt,
36270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite_int64 iOfst
36280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
36290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;
36300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ApndFile *p = (ApndFile *)pFile;
36310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pFile = ORIGFILE(pFile);
36320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( iOfst+iAmt>=APND_MAX_SIZE ) return SQLITE_FULL;
36330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = pFile->pMethods->xWrite(pFile, zBuf, iAmt, iOfst+p->iPgOne);
36340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK &&  iOfst + iAmt + p->iPgOne > p->iMark ){
36350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_int64 sz = 0;
36360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = pFile->pMethods->xFileSize(pFile, &sz);
36370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( rc==SQLITE_OK ){
36380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      p->iMark = sz - APND_MARK_SIZE;
36390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( iOfst + iAmt + p->iPgOne > p->iMark ){
36400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        p->iMark = p->iPgOne + iOfst + iAmt;
36410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        rc = apndWriteMark(p, pFile);
36420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
36430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
36440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
36450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
36460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
36470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
36480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
36490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Truncate an apnd-file.
36500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
36510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndTruncate(sqlite3_file *pFile, sqlite_int64 size){
36520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;
36530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ApndFile *p = (ApndFile *)pFile;
36540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pFile = ORIGFILE(pFile);
36550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = pFile->pMethods->xTruncate(pFile, size+p->iPgOne+APND_MARK_SIZE);
36560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
36570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    p->iMark = p->iPgOne+size;
36580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = apndWriteMark(p, pFile);
36590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
36600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
36610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
36620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
36630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
36640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Sync an apnd-file.
36650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
36660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndSync(sqlite3_file *pFile, int flags){
36670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pFile = ORIGFILE(pFile);
36680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return pFile->pMethods->xSync(pFile, flags);
36690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
36700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
36710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
36720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Return the current file-size of an apnd-file.
36730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
36740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
36750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ApndFile *p = (ApndFile *)pFile;
36760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;
36770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pFile = ORIGFILE(p);
36780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = pFile->pMethods->xFileSize(pFile, pSize);
36790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK && p->iPgOne ){
36800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    *pSize -= p->iPgOne + APND_MARK_SIZE;
36810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
36820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
36830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
36840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
36850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
36860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Lock an apnd-file.
36870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
36880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndLock(sqlite3_file *pFile, int eLock){
36890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pFile = ORIGFILE(pFile);
36900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return pFile->pMethods->xLock(pFile, eLock);
36910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
36920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
36930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
36940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Unlock an apnd-file.
36950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
36960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndUnlock(sqlite3_file *pFile, int eLock){
36970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pFile = ORIGFILE(pFile);
36980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return pFile->pMethods->xUnlock(pFile, eLock);
36990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
37000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
37010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
37020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Check if another file-handle holds a RESERVED lock on an apnd-file.
37030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
37040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndCheckReservedLock(sqlite3_file *pFile, int *pResOut){
37050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pFile = ORIGFILE(pFile);
37060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return pFile->pMethods->xCheckReservedLock(pFile, pResOut);
37070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
37080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
37090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
37100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** File control method. For custom operations on an apnd-file.
37110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
37120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndFileControl(sqlite3_file *pFile, int op, void *pArg){
37130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ApndFile *p = (ApndFile *)pFile;
37140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;
37150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pFile = ORIGFILE(pFile);
37160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = pFile->pMethods->xFileControl(pFile, op, pArg);
37170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){
37180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    *(char**)pArg = sqlite3_mprintf("apnd(%lld)/%z", p->iPgOne, *(char**)pArg);
37190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
37200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
37210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
37220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
37230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
37240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Return the sector-size in bytes for an apnd-file.
37250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
37260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndSectorSize(sqlite3_file *pFile){
37270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pFile = ORIGFILE(pFile);
37280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return pFile->pMethods->xSectorSize(pFile);
37290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
37300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
37310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
37320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Return the device characteristic flags supported by an apnd-file.
37330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
37340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndDeviceCharacteristics(sqlite3_file *pFile){
37350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pFile = ORIGFILE(pFile);
37360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return pFile->pMethods->xDeviceCharacteristics(pFile);
37370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
37380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
37390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* Create a shared memory file mapping */
37400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndShmMap(
37410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_file *pFile,
37420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int iPg,
37430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int pgsz,
37440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int bExtend,
37450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  void volatile **pp
37460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
37470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pFile = ORIGFILE(pFile);
37480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return pFile->pMethods->xShmMap(pFile,iPg,pgsz,bExtend,pp);
37490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
37500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
37510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* Perform locking on a shared-memory segment */
37520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndShmLock(sqlite3_file *pFile, int offset, int n, int flags){
37530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pFile = ORIGFILE(pFile);
37540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return pFile->pMethods->xShmLock(pFile,offset,n,flags);
37550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
37560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
37570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* Memory barrier operation on shared memory */
37580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void apndShmBarrier(sqlite3_file *pFile){
37590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pFile = ORIGFILE(pFile);
37600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pFile->pMethods->xShmBarrier(pFile);
37610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
37620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
37630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* Unmap a shared memory segment */
37640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndShmUnmap(sqlite3_file *pFile, int deleteFlag){
37650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pFile = ORIGFILE(pFile);
37660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return pFile->pMethods->xShmUnmap(pFile,deleteFlag);
37670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
37680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
37690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* Fetch a page of a memory-mapped file */
37700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndFetch(
37710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_file *pFile,
37720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_int64 iOfst,
37730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int iAmt,
37740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  void **pp
37750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
37760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ApndFile *p = (ApndFile *)pFile;
37770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pFile = ORIGFILE(pFile);
37780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return pFile->pMethods->xFetch(pFile, iOfst+p->iPgOne, iAmt, pp);
37790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
37800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
37810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* Release a memory-mapped page */
37820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
37830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ApndFile *p = (ApndFile *)pFile;
37840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pFile = ORIGFILE(pFile);
37850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return pFile->pMethods->xUnfetch(pFile, iOfst+p->iPgOne, pPage);
37860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
37870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
37880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
37890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Check to see if the file is an ordinary SQLite database file.
37900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
37910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndIsOrdinaryDatabaseFile(sqlite3_int64 sz, sqlite3_file *pFile){
37920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;
37930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char zHdr[16];
37940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  static const char aSqliteHdr[] = "SQLite format 3";
37950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( sz<512 ) return 0;
37960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), 0);
37970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc ) return 0;
37980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return memcmp(zHdr, aSqliteHdr, sizeof(zHdr))==0;
37990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
38000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
38010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
38020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Try to read the append-mark off the end of a file.  Return the
38030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** start of the appended database if the append-mark is present.  If
38040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** there is no append-mark, return -1;
38050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
38060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic sqlite3_int64 apndReadMark(sqlite3_int64 sz, sqlite3_file *pFile){
38070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc, i;
38080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_int64 iMark;
38090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  unsigned char a[APND_MARK_SIZE];
38100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
38110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( sz<=APND_MARK_SIZE ) return -1;
38120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = pFile->pMethods->xRead(pFile, a, APND_MARK_SIZE, sz-APND_MARK_SIZE);
38130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc ) return -1;
38140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( memcmp(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ)!=0 ) return -1;
38150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  iMark = ((sqlite3_int64)(a[APND_MARK_PREFIX_SZ]&0x7f))<<56;
38160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(i=1; i<8; i++){
38170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    iMark += (sqlite3_int64)a[APND_MARK_PREFIX_SZ+i]<<(56-8*i);
38180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
38190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return iMark;
38200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
38210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
38220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
38230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Open an apnd file handle.
38240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
38250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndOpen(
38260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vfs *pVfs,
38270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zName,
38280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_file *pFile,
38290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int flags,
38300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int *pOutFlags
38310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
38320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ApndFile *p;
38330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_file *pSubFile;
38340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vfs *pSubVfs;
38350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;
38360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_int64 sz;
38370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pSubVfs = ORIGVFS(pVfs);
38380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
38390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return pSubVfs->xOpen(pSubVfs, zName, pFile, flags, pOutFlags);
38400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
38410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  p = (ApndFile*)pFile;
38420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  memset(p, 0, sizeof(*p));
38430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pSubFile = ORIGFILE(pFile);
38440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  p->base.pMethods = &apnd_io_methods;
38450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = pSubVfs->xOpen(pSubVfs, zName, pSubFile, flags, pOutFlags);
38460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc ) goto apnd_open_done;
38470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = pSubFile->pMethods->xFileSize(pSubFile, &sz);
38480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc ){
38490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pSubFile->pMethods->xClose(pSubFile);
38500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    goto apnd_open_done;
38510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
38520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( apndIsOrdinaryDatabaseFile(sz, pSubFile) ){
38530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    memmove(pFile, pSubFile, pSubVfs->szOsFile);
38540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return SQLITE_OK;
38550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
38560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  p->iMark = 0;
38570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  p->iPgOne = apndReadMark(sz, pFile);
38580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( p->iPgOne>0 ){
38590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return SQLITE_OK;
38600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
38610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( (flags & SQLITE_OPEN_CREATE)==0 ){
38620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pSubFile->pMethods->xClose(pSubFile);
38630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = SQLITE_CANTOPEN;
38640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
38650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  p->iPgOne = (sz+0xfff) & ~(sqlite3_int64)0xfff;
38660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovapnd_open_done:
38670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc ) pFile->pMethods = 0;
38680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
38690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
38700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
38710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
38720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** All other VFS methods are pass-thrus.
38730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
38740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
38750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return ORIGVFS(pVfs)->xDelete(ORIGVFS(pVfs), zPath, dirSync);
38760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
38770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndAccess(
38780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vfs *pVfs,
38790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zPath,
38800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int flags,
38810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int *pResOut
38820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
38830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return ORIGVFS(pVfs)->xAccess(ORIGVFS(pVfs), zPath, flags, pResOut);
38840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
38850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndFullPathname(
38860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vfs *pVfs,
38870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zPath,
38880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nOut,
38890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zOut
38900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
38910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return ORIGVFS(pVfs)->xFullPathname(ORIGVFS(pVfs),zPath,nOut,zOut);
38920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
38930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void *apndDlOpen(sqlite3_vfs *pVfs, const char *zPath){
38940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
38950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
38960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void apndDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
38970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
38980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
38990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
39000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
39010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
39020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void apndDlClose(sqlite3_vfs *pVfs, void *pHandle){
39030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
39040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
39050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
39060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
39070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
39080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndSleep(sqlite3_vfs *pVfs, int nMicro){
39090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
39100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
39110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
39120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
39130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
39140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndGetLastError(sqlite3_vfs *pVfs, int a, char *b){
39150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
39160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
39170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
39180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
39190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
39200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int apndSetSystemCall(
39210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vfs *pVfs,
39220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zName,
39230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_syscall_ptr pCall
39240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
39250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return ORIGVFS(pVfs)->xSetSystemCall(ORIGVFS(pVfs),zName,pCall);
39260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
39270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic sqlite3_syscall_ptr apndGetSystemCall(
39280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vfs *pVfs,
39290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zName
39300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
39310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return ORIGVFS(pVfs)->xGetSystemCall(ORIGVFS(pVfs),zName);
39320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
39330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic const char *apndNextSystemCall(sqlite3_vfs *pVfs, const char *zName){
39340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return ORIGVFS(pVfs)->xNextSystemCall(ORIGVFS(pVfs), zName);
39350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
39360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
39370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
39380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifdef _WIN32
39390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
39400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
39410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
39420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This routine is called when the extension is loaded.
39430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Register the new VFS.
39440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
39450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovint sqlite3_appendvfs_init(
39460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *db,
39470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErrMsg,
39480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const sqlite3_api_routines *pApi
39490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
39500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
39510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vfs *pOrig;
39520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  SQLITE_EXTENSION_INIT2(pApi);
39530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)pzErrMsg;
39540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)db;
39550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pOrig = sqlite3_vfs_find(0);
39560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apnd_vfs.iVersion = pOrig->iVersion;
39570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apnd_vfs.pAppData = pOrig;
39580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  apnd_vfs.szOsFile = pOrig->szOsFile + sizeof(ApndFile);
39590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = sqlite3_vfs_register(&apnd_vfs, 0);
39600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifdef APPENDVFS_TEST
39610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
39620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = sqlite3_auto_extension((void(*)(void))apndvfsRegister);
39630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
39640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
39650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY;
39660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
39670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
39680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
39690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/************************* End ../ext/misc/appendvfs.c ********************/
39700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifdef SQLITE_HAVE_ZLIB
39710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/************************* Begin ../ext/misc/zipfile.c ******************/
39720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
39730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** 2017-12-26
39740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
39750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The author disclaims copyright to this source code.  In place of
39760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** a legal notice, here is a blessing:
39770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
39780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you do good and not evil.
39790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you find forgiveness for yourself and forgive others.
39800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you share freely, never taking more than you give.
39810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
39820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov******************************************************************************
39830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
39840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This file implements a virtual table for reading and writing ZIP archive
39850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** files.
39860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
39870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Usage example:
39880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
39890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     SELECT name, sz, datetime(mtime,'unixepoch') FROM zipfile($filename);
39900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
39910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Current limitations:
39920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
39930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    *  No support for encryption
39940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    *  No support for ZIP archives spanning multiple files
39950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    *  No support for zip64 extensions
39960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    *  Only the "inflate/deflate" (zlib) compression method is supported
39970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
39980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor KupolovSQLITE_EXTENSION_INIT1
39990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <stdio.h>
40000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <string.h>
40010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <assert.h>
40020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
40030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <sys/types.h>
40040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <sys/stat.h>
40050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <fcntl.h>
40060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if !defined(_WIN32) && !defined(WIN32)
40070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#  include <unistd.h>
40080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#  include <dirent.h>
40090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#  include <utime.h>
40100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#else
40110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#  include <io.h>
40120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
40130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <time.h>
40140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <errno.h>
40150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
40160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <zlib.h>
40170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
40180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifndef SQLITE_OMIT_VIRTUALTABLE
40190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
40200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifndef SQLITE_AMALGAMATION
40210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* typedef sqlite3_int64 i64; */
40220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* typedef unsigned char u8; */
40230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef unsigned short u16;
40240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef unsigned long u32;
40250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define MIN(a,b) ((a)<(b) ? (a) : (b))
40260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
40270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
40280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic const char ZIPFILE_SCHEMA[] =
40290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  "CREATE TABLE y("
40300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "name PRIMARY KEY,"  /* 0: Name of file in zip archive */
40310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "mode,"              /* 1: POSIX mode for file */
40320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "mtime,"             /* 2: Last modification time (secs since 1970)*/
40330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "sz,"                /* 3: Size of object */
40340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "rawdata,"           /* 4: Raw data */
40350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "data,"              /* 5: Uncompressed data */
40360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "method,"            /* 6: Compression method (integer) */
40370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "z HIDDEN"           /* 7: Name of zip file */
40380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ") WITHOUT ROWID;";
40390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
40400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define ZIPFILE_F_COLUMN_IDX 7    /* Index of column "file" in the above */
40410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define ZIPFILE_BUFFER_SIZE (64*1024)
40420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
40430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
40440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
40450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Magic numbers used to read and write zip files.
40460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
40470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** ZIPFILE_NEWENTRY_MADEBY:
40480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   Use this value for the "version-made-by" field in new zip file
40490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   entries. The upper byte indicates "unix", and the lower byte
40500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   indicates that the zip file matches pkzip specification 3.0.
40510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   This is what info-zip seems to do.
40520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
40530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** ZIPFILE_NEWENTRY_REQUIRED:
40540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   Value for "version-required-to-extract" field of new entries.
40550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   Version 2.0 is required to support folders and deflate compression.
40560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
40570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** ZIPFILE_NEWENTRY_FLAGS:
40580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   Value for "general-purpose-bit-flags" field of new entries. Bit
40590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   11 means "utf-8 filename and comment".
40600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
40610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** ZIPFILE_SIGNATURE_CDS:
40620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   First 4 bytes of a valid CDS record.
40630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
40640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** ZIPFILE_SIGNATURE_LFH:
40650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   First 4 bytes of a valid LFH record.
40660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
40670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define ZIPFILE_EXTRA_TIMESTAMP   0x5455
40680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define ZIPFILE_NEWENTRY_MADEBY   ((3<<8) + 30)
40690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define ZIPFILE_NEWENTRY_REQUIRED 20
40700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define ZIPFILE_NEWENTRY_FLAGS    0x800
40710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define ZIPFILE_SIGNATURE_CDS     0x02014b50
40720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define ZIPFILE_SIGNATURE_LFH     0x04034b50
40730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define ZIPFILE_SIGNATURE_EOCD    0x06054b50
40740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define ZIPFILE_LFH_FIXED_SZ      30
40750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
40760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
40770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Set the error message contained in context ctx to the results of
40780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** vprintf(zFmt, ...).
40790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
40800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void zipfileCtxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
40810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zMsg = 0;
40820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  va_list ap;
40830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  va_start(ap, zFmt);
40840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zMsg = sqlite3_vmprintf(zFmt, ap);
40850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_result_error(ctx, zMsg, -1);
40860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(zMsg);
40870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  va_end(ap);
40880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
40890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
40900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
40910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
40920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*** 4.3.16  End of central directory record:
40930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***
40940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   end of central dir signature    4 bytes  (0x06054b50)
40950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   number of this disk             2 bytes
40960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   number of the disk with the
40970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   start of the central directory  2 bytes
40980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   total number of entries in the
40990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   central directory on this disk  2 bytes
41000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   total number of entries in
41010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   the central directory           2 bytes
41020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   size of the central directory   4 bytes
41030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   offset of start of central
41040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   directory with respect to
41050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   the starting disk number        4 bytes
41060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   .ZIP file comment length        2 bytes
41070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   .ZIP file comment       (variable size)
41080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
41090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct ZipfileEOCD ZipfileEOCD;
41100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct ZipfileEOCD {
41110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u16 iDisk;
41120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u16 iFirstDisk;
41130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u16 nEntry;
41140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u16 nEntryTotal;
41150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u32 nSize;
41160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u32 iOffset;
41170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
41180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
41190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
41200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*** 4.3.12  Central directory structure:
41210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***
41220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*** ...
41230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***
41240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   central file header signature   4 bytes  (0x02014b50)
41250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   version made by                 2 bytes
41260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   version needed to extract       2 bytes
41270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   general purpose bit flag        2 bytes
41280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   compression method              2 bytes
41290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   last mod file time              2 bytes
41300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   last mod file date              2 bytes
41310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   crc-32                          4 bytes
41320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   compressed size                 4 bytes
41330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   uncompressed size               4 bytes
41340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   file name length                2 bytes
41350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   extra field length              2 bytes
41360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   file comment length             2 bytes
41370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   disk number start               2 bytes
41380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   internal file attributes        2 bytes
41390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   external file attributes        4 bytes
41400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   relative offset of local header 4 bytes
41410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
41420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct ZipfileCDS ZipfileCDS;
41430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct ZipfileCDS {
41440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u16 iVersionMadeBy;
41450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u16 iVersionExtract;
41460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u16 flags;
41470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u16 iCompression;
41480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u16 mTime;
41490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u16 mDate;
41500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u32 crc32;
41510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u32 szCompressed;
41520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u32 szUncompressed;
41530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u16 nFile;
41540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u16 nExtra;
41550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u16 nComment;
41560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u16 iDiskStart;
41570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u16 iInternalAttr;
41580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u32 iExternalAttr;
41590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u32 iOffset;
41600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zFile;                    /* Filename (sqlite3_malloc()) */
41610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
41620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
41630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
41640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*** 4.3.7  Local file header:
41650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***
41660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   local file header signature     4 bytes  (0x04034b50)
41670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   version needed to extract       2 bytes
41680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   general purpose bit flag        2 bytes
41690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   compression method              2 bytes
41700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   last mod file time              2 bytes
41710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   last mod file date              2 bytes
41720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   crc-32                          4 bytes
41730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   compressed size                 4 bytes
41740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   uncompressed size               4 bytes
41750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   file name length                2 bytes
41760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***   extra field length              2 bytes
41770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov***
41780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
41790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct ZipfileLFH ZipfileLFH;
41800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct ZipfileLFH {
41810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u16 iVersionExtract;
41820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u16 flags;
41830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u16 iCompression;
41840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u16 mTime;
41850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u16 mDate;
41860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u32 crc32;
41870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u32 szCompressed;
41880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u32 szUncompressed;
41890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u16 nFile;
41900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u16 nExtra;
41910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
41920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
41930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct ZipfileEntry ZipfileEntry;
41940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct ZipfileEntry {
41950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zPath;               /* Path of zipfile entry */
41960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 *aCdsEntry;             /* Buffer containing entire CDS entry */
41970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nCdsEntry;             /* Size of buffer aCdsEntry[] in bytes */
41980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int bDeleted;              /* True if entry has been deleted */
41990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileEntry *pNext;       /* Next element in in-memory CDS */
42000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
42010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
42020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
42030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Cursor type for recursively iterating through a directory structure.
42040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
42050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct ZipfileCsr ZipfileCsr;
42060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct ZipfileCsr {
42070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vtab_cursor base;  /* Base class - must be first */
42080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  i64 iId;                   /* Cursor ID */
42090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int bEof;                  /* True when at EOF */
42100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
42110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* Used outside of write transactions */
42120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  FILE *pFile;               /* Zip file */
42130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  i64 iNextOff;              /* Offset of next record in central directory */
42140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileEOCD eocd;          /* Parse of central directory record */
42150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
42160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* Used inside write transactions */
42170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileEntry *pCurrent;
42180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
42190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileCDS cds;            /* Central Directory Structure */
42200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileLFH lfh;            /* Local File Header for current entry */
42210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  i64 iDataOff;              /* Offset in zipfile to data */
42220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u32 mTime;                 /* Extended mtime value */
42230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int flags;                 /* Flags byte (see below for bits) */
42240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileCsr *pCsrNext;      /* Next cursor on same virtual table */
42250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
42260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
42270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
42280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Values for ZipfileCsr.flags.
42290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
42300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define ZIPFILE_MTIME_VALID 0x0001
42310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
42320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct ZipfileTab ZipfileTab;
42330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct ZipfileTab {
42340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vtab base;         /* Base class - must be first */
42350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zFile;               /* Zip file this table accesses (may be NULL) */
42360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 *aBuffer;               /* Temporary buffer used for various tasks */
42370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
42380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileCsr *pCsrList;      /* List of cursors */
42390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  i64 iNextCsrid;
42400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
42410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* The following are used by write transactions only */
42420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileEntry *pFirstEntry; /* Linked list of all files (if pWriteFd!=0) */
42430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileEntry *pLastEntry;  /* Last element in pFirstEntry list */
42440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  FILE *pWriteFd;            /* File handle open on zip archive */
42450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  i64 szCurrent;             /* Current size of zip archive */
42460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  i64 szOrig;                /* Size of archive at start of transaction */
42470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
42480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
42490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void zipfileDequote(char *zIn){
42500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char q = zIn[0];
42510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( q=='"' || q=='\'' || q=='`' || q=='[' ){
42520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    char c;
42530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int iIn = 1;
42540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int iOut = 0;
42550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( q=='[' ) q = ']';
42560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    while( (c = zIn[iIn++]) ){
42570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( c==q ){
42580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( zIn[iIn++]!=q ) break;
42590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
42600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zIn[iOut++] = c;
42610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
42620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zIn[iOut] = '\0';
42630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
42640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
42650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
42660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
42670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Construct a new ZipfileTab virtual table object.
42680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
42690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   argv[0]   -> module name  ("zipfile")
42700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   argv[1]   -> database name
42710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   argv[2]   -> table name
42720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   argv[...] -> "column name" and other module argument fields.
42730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
42740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileConnect(
42750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *db,
42760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  void *pAux,
42770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int argc, const char *const*argv,
42780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vtab **ppVtab,
42790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErr
42800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
42810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nByte = sizeof(ZipfileTab) + ZIPFILE_BUFFER_SIZE;
42820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nFile = 0;
42830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zFile = 0;
42840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileTab *pNew = 0;
42850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;
42860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
42870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( argc>3 ){
42880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zFile = argv[3];
42890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    nFile = (int)strlen(zFile)+1;
42900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
42910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
42920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA);
42930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
42940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNew = (ZipfileTab*)sqlite3_malloc(nByte+nFile);
42950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pNew==0 ) return SQLITE_NOMEM;
42960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    memset(pNew, 0, nByte+nFile);
42970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNew->aBuffer = (u8*)&pNew[1];
42980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( zFile ){
42990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pNew->zFile = (char*)&pNew->aBuffer[ZIPFILE_BUFFER_SIZE];
43000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      memcpy(pNew->zFile, zFile, nFile);
43010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zipfileDequote(pNew->zFile);
43020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
43030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
43040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  *ppVtab = (sqlite3_vtab*)pNew;
43050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
43060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
43070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
43080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
43090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This method is the destructor for zipfile vtab objects.
43100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
43110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileDisconnect(sqlite3_vtab *pVtab){
43120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(pVtab);
43130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
43140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
43150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
43160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
43170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Constructor for a new ZipfileCsr object.
43180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
43190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCsr){
43200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileTab *pTab = (ZipfileTab*)p;
43210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileCsr *pCsr;
43220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCsr = sqlite3_malloc(sizeof(*pCsr));
43230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  *ppCsr = (sqlite3_vtab_cursor*)pCsr;
43240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pCsr==0 ){
43250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return SQLITE_NOMEM;
43260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
43270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  memset(pCsr, 0, sizeof(*pCsr));
43280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCsr->iId = ++pTab->iNextCsrid;
43290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCsr->pCsrNext = pTab->pCsrList;
43300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pTab->pCsrList = pCsr;
43310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
43320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
43330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
43340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
43350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Reset a cursor back to the state it was in when first returned
43360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** by zipfileOpen().
43370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
43380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void zipfileResetCursor(ZipfileCsr *pCsr){
43390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(pCsr->cds.zFile);
43400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCsr->cds.zFile = 0;
43410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCsr->bEof = 0;
43420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pCsr->pFile ){
43430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    fclose(pCsr->pFile);
43440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCsr->pFile = 0;
43450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
43460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
43470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
43480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
43490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Destructor for an ZipfileCsr.
43500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
43510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileClose(sqlite3_vtab_cursor *cur){
43520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileCsr *pCsr = (ZipfileCsr*)cur;
43530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileTab *pTab = (ZipfileTab*)(pCsr->base.pVtab);
43540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileCsr **pp;
43550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zipfileResetCursor(pCsr);
43560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
43570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* Remove this cursor from the ZipfileTab.pCsrList list. */
43580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(pp=&pTab->pCsrList; *pp; pp=&((*pp)->pCsrNext)){
43590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( *pp==pCsr ){
43600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      *pp = pCsr->pCsrNext;
43610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
43620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
43630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
43640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
43650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(pCsr);
43660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
43670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
43680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
43690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
43700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Set the error message for the virtual table associated with cursor
43710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** pCsr to the results of vprintf(zFmt, ...).
43720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
43730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void zipfileSetErrmsg(ZipfileCsr *pCsr, const char *zFmt, ...){
43740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  va_list ap;
43750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  va_start(ap, zFmt);
43760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCsr->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
43770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  va_end(ap);
43780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
43790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
43800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileReadData(
43810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  FILE *pFile,                    /* Read from this file */
43820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 *aRead,                      /* Read into this buffer */
43830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nRead,                      /* Number of bytes to read */
43840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  i64 iOff,                       /* Offset to read from */
43850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErrmsg                 /* OUT: Error message (from sqlite3_malloc) */
43860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
43870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  size_t n;
43880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  fseek(pFile, (long)iOff, SEEK_SET);
43890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  n = fread(aRead, 1, nRead, pFile);
43900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( (int)n!=nRead ){
43910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    *pzErrmsg = sqlite3_mprintf("error in fread()");
43920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return SQLITE_ERROR;
43930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
43940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
43950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
43960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
43970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileAppendData(
43980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileTab *pTab,
43990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const u8 *aWrite,
44000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nWrite
44010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
44020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  size_t n;
44030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET);
44040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd);
44050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( (int)n!=nWrite ){
44060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()");
44070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return SQLITE_ERROR;
44080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
44090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pTab->szCurrent += nWrite;
44100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
44110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
44120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
44130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic u16 zipfileGetU16(const u8 *aBuf){
44140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return (aBuf[1] << 8) + aBuf[0];
44150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
44160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic u32 zipfileGetU32(const u8 *aBuf){
44170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return ((u32)(aBuf[3]) << 24)
44180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov       + ((u32)(aBuf[2]) << 16)
44190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov       + ((u32)(aBuf[1]) <<  8)
44200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov       + ((u32)(aBuf[0]) <<  0);
44210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
44220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
44230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void zipfilePutU16(u8 *aBuf, u16 val){
44240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  aBuf[0] = val & 0xFF;
44250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  aBuf[1] = (val>>8) & 0xFF;
44260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
44270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void zipfilePutU32(u8 *aBuf, u32 val){
44280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  aBuf[0] = val & 0xFF;
44290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  aBuf[1] = (val>>8) & 0xFF;
44300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  aBuf[2] = (val>>16) & 0xFF;
44310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  aBuf[3] = (val>>24) & 0xFF;
44320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
44330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
44340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define zipfileRead32(aBuf) ( aBuf+=4, zipfileGetU32(aBuf-4) )
44350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define zipfileRead16(aBuf) ( aBuf+=2, zipfileGetU16(aBuf-2) )
44360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
44370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define zipfileWrite32(aBuf,val) { zipfilePutU32(aBuf,val); aBuf+=4; }
44380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define zipfileWrite16(aBuf,val) { zipfilePutU16(aBuf,val); aBuf+=2; }
44390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
44400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic u8* zipfileCsrBuffer(ZipfileCsr *pCsr){
44410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return ((ZipfileTab*)(pCsr->base.pVtab))->aBuffer;
44420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
44430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
44440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
44450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Magic numbers used to read CDS records.
44460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
44470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define ZIPFILE_CDS_FIXED_SZ         46
44480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define ZIPFILE_CDS_NFILE_OFF        28
44490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
44500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
44510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Decode the CDS record in buffer aBuf into (*pCDS). Return SQLITE_ERROR
44520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** if the record is not well-formed, or SQLITE_OK otherwise.
44530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
44540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileReadCDS(u8 *aBuf, ZipfileCDS *pCDS){
44550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 *aRead = aBuf;
44560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u32 sig = zipfileRead32(aRead);
44570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
44580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( sig!=ZIPFILE_SIGNATURE_CDS ){
44590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = SQLITE_ERROR;
44600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
44610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCDS->iVersionMadeBy = zipfileRead16(aRead);
44620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCDS->iVersionExtract = zipfileRead16(aRead);
44630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCDS->flags = zipfileRead16(aRead);
44640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCDS->iCompression = zipfileRead16(aRead);
44650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCDS->mTime = zipfileRead16(aRead);
44660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCDS->mDate = zipfileRead16(aRead);
44670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCDS->crc32 = zipfileRead32(aRead);
44680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCDS->szCompressed = zipfileRead32(aRead);
44690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCDS->szUncompressed = zipfileRead32(aRead);
44700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    assert( aRead==&aBuf[ZIPFILE_CDS_NFILE_OFF] );
44710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCDS->nFile = zipfileRead16(aRead);
44720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCDS->nExtra = zipfileRead16(aRead);
44730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCDS->nComment = zipfileRead16(aRead);
44740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCDS->iDiskStart = zipfileRead16(aRead);
44750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCDS->iInternalAttr = zipfileRead16(aRead);
44760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCDS->iExternalAttr = zipfileRead32(aRead);
44770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCDS->iOffset = zipfileRead32(aRead);
44780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    assert( aRead==&aBuf[ZIPFILE_CDS_FIXED_SZ] );
44790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
44800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
44810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
44820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
44830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
44840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
44850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Read the CDS record for the current entry from disk into pCsr->cds.
44860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
44870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileCsrReadCDS(ZipfileCsr *pCsr){
44880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErr = &pCsr->base.pVtab->zErrMsg;
44890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 *aRead;
44900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
44910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
44920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(pCsr->cds.zFile);
44930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCsr->cds.zFile = 0;
44940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
44950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pCsr->pCurrent==0 ){
44960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    aRead = zipfileCsrBuffer(pCsr);
44970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = zipfileReadData(
44980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        pCsr->pFile, aRead, ZIPFILE_CDS_FIXED_SZ, pCsr->iNextOff, pzErr
44990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    );
45000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
45010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    aRead = pCsr->pCurrent->aCdsEntry;
45020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
45030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
45040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
45050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = zipfileReadCDS(aRead, &pCsr->cds);
45060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( rc!=SQLITE_OK ){
45070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      assert( pCsr->pCurrent==0 );
45080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zipfileSetErrmsg(pCsr,"failed to read CDS at offset %lld",pCsr->iNextOff);
45090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
45100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int nRead;
45110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( pCsr->pCurrent==0 ){
45120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        nRead = pCsr->cds.nFile + pCsr->cds.nExtra;
45130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        aRead = zipfileCsrBuffer(pCsr);
45140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        pCsr->iNextOff += ZIPFILE_CDS_FIXED_SZ;
45150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        rc = zipfileReadData(pCsr->pFile, aRead, nRead, pCsr->iNextOff, pzErr);
45160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else{
45170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        aRead = &aRead[ZIPFILE_CDS_FIXED_SZ];
45180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
45190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
45200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( rc==SQLITE_OK ){
45210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        pCsr->cds.zFile = sqlite3_mprintf("%.*s", (int)pCsr->cds.nFile, aRead);
45220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        pCsr->iNextOff += pCsr->cds.nFile;
45230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        pCsr->iNextOff += pCsr->cds.nExtra;
45240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        pCsr->iNextOff += pCsr->cds.nComment;
45250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
45260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
45270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      /* Scan the cds.nExtra bytes of "extra" fields for any that can
45280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      ** be interpreted. The general format of an extra field is:
45290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      **
45300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      **   Header ID    2 bytes
45310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      **   Data Size    2 bytes
45320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      **   Data         N bytes
45330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      **
45340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      */
45350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( rc==SQLITE_OK ){
45360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        u8 *p = &aRead[pCsr->cds.nFile];
45370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        u8 *pEnd = &p[pCsr->cds.nExtra];
45380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
45390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        while( p<pEnd ){
45400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          u16 id = zipfileRead16(p);
45410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          u16 nByte = zipfileRead16(p);
45420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
45430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          switch( id ){
45440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            case ZIPFILE_EXTRA_TIMESTAMP: {
45450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov              u8 b = p[0];
45460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov              if( b & 0x01 ){     /* 0x01 -> modtime is present */
45470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                pCsr->mTime = zipfileGetU32(&p[1]);
45480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                pCsr->flags |= ZIPFILE_MTIME_VALID;
45490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov              }
45500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov              break;
45510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            }
45520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
45530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
45540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          p += nByte;
45550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
45560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
45570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
45580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
45590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
45600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
45610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
45620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
45630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic FILE *zipfileGetFd(ZipfileCsr *pCsr){
45640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pCsr->pFile ) return pCsr->pFile;
45650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return ((ZipfileTab*)(pCsr->base.pVtab))->pWriteFd;
45660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
45670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
45680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileReadLFH(
45690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  FILE *pFd,
45700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  i64 iOffset,
45710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 *aTmp,
45720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileLFH *pLFH,
45730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErr
45740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
45750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 *aRead = aTmp;
45760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  static const int szFix = ZIPFILE_LFH_FIXED_SZ;
45770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;
45780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
45790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = zipfileReadData(pFd, aRead, szFix, iOffset, pzErr);
45800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
45810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    u32 sig = zipfileRead32(aRead);
45820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( sig!=ZIPFILE_SIGNATURE_LFH ){
45830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      *pzErr = sqlite3_mprintf("failed to read LFH at offset %d", (int)iOffset);
45840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = SQLITE_ERROR;
45850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
45860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pLFH->iVersionExtract = zipfileRead16(aRead);
45870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pLFH->flags = zipfileRead16(aRead);
45880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pLFH->iCompression = zipfileRead16(aRead);
45890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pLFH->mTime = zipfileRead16(aRead);
45900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pLFH->mDate = zipfileRead16(aRead);
45910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pLFH->crc32 = zipfileRead32(aRead);
45920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pLFH->szCompressed = zipfileRead32(aRead);
45930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pLFH->szUncompressed = zipfileRead32(aRead);
45940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pLFH->nFile = zipfileRead16(aRead);
45950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pLFH->nExtra = zipfileRead16(aRead);
45960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      assert( aRead==&aTmp[szFix] );
45970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
45980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
45990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
46000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
46010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
46020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileCsrReadLFH(ZipfileCsr *pCsr){
46030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  FILE *pFile = zipfileGetFd(pCsr);
46040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErr = &pCsr->base.pVtab->zErrMsg;
46050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 *aRead = zipfileCsrBuffer(pCsr);
46060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = zipfileReadLFH(pFile, pCsr->cds.iOffset, aRead, &pCsr->lfh, pzErr);
46070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCsr->iDataOff =  pCsr->cds.iOffset + ZIPFILE_LFH_FIXED_SZ;
46080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCsr->iDataOff += pCsr->lfh.nFile+pCsr->lfh.nExtra;
46090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
46100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
46110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
46120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
46130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
46140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Advance an ZipfileCsr to its next row of output.
46150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
46160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileNext(sqlite3_vtab_cursor *cur){
46170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileCsr *pCsr = (ZipfileCsr*)cur;
46180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
46190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCsr->flags = 0;
46200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
46210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pCsr->pCurrent==0 ){
46220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    i64 iEof = pCsr->eocd.iOffset + pCsr->eocd.nSize;
46230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pCsr->iNextOff>=iEof ){
46240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pCsr->bEof = 1;
46250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
46260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
46270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    assert( pCsr->pFile==0 );
46280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    do {
46290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pCsr->pCurrent = pCsr->pCurrent->pNext;
46300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }while( pCsr->pCurrent && pCsr->pCurrent->bDeleted );
46310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pCsr->pCurrent==0 ){
46320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pCsr->bEof = 1;
46330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
46340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
46350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
46360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pCsr->bEof==0 ){
46370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = zipfileCsrReadCDS(pCsr);
46380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( rc==SQLITE_OK ){
46390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = zipfileCsrReadLFH(pCsr);
46400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
46410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
46420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
46430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
46440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
46450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
46460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
46470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** "Standard" MS-DOS time format:
46480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
46490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   File modification time:
46500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     Bits 00-04: seconds divided by 2
46510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     Bits 05-10: minute
46520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     Bits 11-15: hour
46530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   File modification date:
46540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     Bits 00-04: day
46550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     Bits 05-08: month (1-12)
46560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     Bits 09-15: years from 1980
46570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
46580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic time_t zipfileMtime(ZipfileCsr *pCsr){
46590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  struct tm t;
46600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  memset(&t, 0, sizeof(t));
46610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  t.tm_sec = (pCsr->cds.mTime & 0x1F)*2;
46620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  t.tm_min = (pCsr->cds.mTime >> 5) & 0x2F;
46630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  t.tm_hour = (pCsr->cds.mTime >> 11) & 0x1F;
46640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
46650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  t.tm_mday = (pCsr->cds.mDate & 0x1F);
46660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  t.tm_mon = ((pCsr->cds.mDate >> 5) & 0x0F) - 1;
46670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  t.tm_year = 80 + ((pCsr->cds.mDate >> 9) & 0x7F);
46680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
46690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return mktime(&t);
46700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
46710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
46720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void zipfileMtimeToDos(ZipfileCDS *pCds, u32 mTime){
46730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  time_t t = (time_t)mTime;
46740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  struct tm res;
46750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
46760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if !defined(_WIN32) && !defined(WIN32)
46770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  localtime_r(&t, &res);
46780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#else
46790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  memcpy(&res, localtime(&t), sizeof(struct tm));
46800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
46810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
46820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCds->mTime = (u16)(
46830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    (res.tm_sec / 2) +
46840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    (res.tm_min << 5) +
46850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    (res.tm_hour << 11));
46860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
46870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCds->mDate = (u16)(
46880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    (res.tm_mday-1) +
46890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ((res.tm_mon+1) << 5) +
46900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ((res.tm_year-80) << 9));
46910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
46920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
46930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void zipfileInflate(
46940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_context *pCtx,          /* Store error here, if any */
46950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const u8 *aIn,                  /* Compressed data */
46960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nIn,                        /* Size of buffer aIn[] in bytes */
46970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nOut                        /* Expected output size */
46980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
46990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 *aRes = sqlite3_malloc(nOut);
47000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( aRes==0 ){
47010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_result_error_nomem(pCtx);
47020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
47030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int err;
47040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    z_stream str;
47050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    memset(&str, 0, sizeof(str));
47060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
47070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    str.next_in = (Byte*)aIn;
47080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    str.avail_in = nIn;
47090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    str.next_out = (Byte*)aRes;
47100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    str.avail_out = nOut;
47110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
47120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    err = inflateInit2(&str, -15);
47130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( err!=Z_OK ){
47140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zipfileCtxErrorMsg(pCtx, "inflateInit2() failed (%d)", err);
47150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
47160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      err = inflate(&str, Z_NO_FLUSH);
47170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( err!=Z_STREAM_END ){
47180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        zipfileCtxErrorMsg(pCtx, "inflate() failed (%d)", err);
47190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else{
47200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_result_blob(pCtx, aRes, nOut, SQLITE_TRANSIENT);
47210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
47220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
47230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(aRes);
47240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    inflateEnd(&str);
47250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
47260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
47270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
47280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileDeflate(
47290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileTab *pTab,               /* Set error message here */
47300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const u8 *aIn, int nIn,         /* Input */
47310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 **ppOut, int *pnOut          /* Output */
47320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
47330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nAlloc = (int)compressBound(nIn);
47340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 *aOut;
47350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
47360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
47370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  aOut = (u8*)sqlite3_malloc(nAlloc);
47380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( aOut==0 ){
47390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = SQLITE_NOMEM;
47400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
47410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int res;
47420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    z_stream str;
47430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    memset(&str, 0, sizeof(str));
47440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    str.next_in = (Bytef*)aIn;
47450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    str.avail_in = nIn;
47460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    str.next_out = aOut;
47470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    str.avail_out = nAlloc;
47480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
47490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
47500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    res = deflate(&str, Z_FINISH);
47510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
47520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( res==Z_STREAM_END ){
47530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      *ppOut = aOut;
47540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      *pnOut = (int)str.total_out;
47550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
47560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_free(aOut);
47570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pTab->base.zErrMsg = sqlite3_mprintf("zipfile: deflate() error");
47580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = SQLITE_ERROR;
47590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
47600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    deflateEnd(&str);
47610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
47620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
47630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
47640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
47650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
47660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
47670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
47680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Return values of columns for the row at which the series_cursor
47690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** is currently pointing.
47700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
47710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileColumn(
47720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vtab_cursor *cur,   /* The cursor */
47730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
47740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int i                       /* Which column to return */
47750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
47760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileCsr *pCsr = (ZipfileCsr*)cur;
47770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
47780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  switch( i ){
47790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case 0:   /* name */
47800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_text(ctx, pCsr->cds.zFile, -1, SQLITE_TRANSIENT);
47810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
47820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case 1:   /* mode */
47830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      /* TODO: Whether or not the following is correct surely depends on
47840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      ** the platform on which the archive was created.  */
47850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_int(ctx, pCsr->cds.iExternalAttr >> 16);
47860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
47870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case 2: { /* mtime */
47880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( pCsr->flags & ZIPFILE_MTIME_VALID ){
47890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_result_int64(ctx, pCsr->mTime);
47900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else{
47910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_result_int64(ctx, zipfileMtime(pCsr));
47920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
47930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
47940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
47950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case 3: { /* sz */
47960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( sqlite3_vtab_nochange(ctx)==0 ){
47970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_result_int64(ctx, pCsr->cds.szUncompressed);
47980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
47990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
48000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
48010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case 4:   /* rawdata */
48020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( sqlite3_vtab_nochange(ctx) ) break;
48030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case 5: { /* data */
48040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( i==4 || pCsr->cds.iCompression==0 || pCsr->cds.iCompression==8 ){
48050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        int sz = pCsr->cds.szCompressed;
48060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        int szFinal = pCsr->cds.szUncompressed;
48070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( szFinal>0 ){
48080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          u8 *aBuf = sqlite3_malloc(sz);
48090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( aBuf==0 ){
48100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            rc = SQLITE_NOMEM;
48110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }else{
48120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            FILE *pFile = zipfileGetFd(pCsr);
48130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            rc = zipfileReadData(pFile, aBuf, sz, pCsr->iDataOff,
48140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                &pCsr->base.pVtab->zErrMsg
48150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            );
48160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
48170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( rc==SQLITE_OK ){
48180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            if( i==5 && pCsr->cds.iCompression ){
48190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov              zipfileInflate(ctx, aBuf, sz, szFinal);
48200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            }else{
48210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov              sqlite3_result_blob(ctx, aBuf, sz, SQLITE_TRANSIENT);
48220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            }
48230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            sqlite3_free(aBuf);
48240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
48250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }else{
48260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          /* Figure out if this is a directory or a zero-sized file. Consider
48270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          ** it to be a directory either if the mode suggests so, or if
48280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          ** the final character in the name is '/'.  */
48290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          u32 mode = pCsr->cds.iExternalAttr >> 16;
48300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( !(mode & S_IFDIR) && pCsr->cds.zFile[pCsr->cds.nFile-1]!='/' ){
48310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            sqlite3_result_blob(ctx, "", 0, SQLITE_STATIC);
48320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
48330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
48340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
48350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
48360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
48370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case 6:   /* method */
48380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_int(ctx, pCsr->cds.iCompression);
48390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
48400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case 7:   /* z */
48410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_int64(ctx, pCsr->iId);
48420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
48430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
48440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
48450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
48460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
48470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
48480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
48490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Return the rowid for the current row.
48500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
48510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
48520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( 0 );
48530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
48540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
48550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
48560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
48570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Return TRUE if the cursor has been moved off of the last
48580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** row of output.
48590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
48600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileEof(sqlite3_vtab_cursor *cur){
48610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileCsr *pCsr = (ZipfileCsr*)cur;
48620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return pCsr->bEof;
48630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
48640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
48650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
48660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
48670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileReadEOCD(
48680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileTab *pTab,               /* Return errors here */
48690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  FILE *pFile,                    /* Read from this file */
48700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileEOCD *pEOCD              /* Object to populate */
48710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
48720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 *aRead = pTab->aBuffer;      /* Temporary buffer */
48730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  i64 szFile;                     /* Total size of file in bytes */
48740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nRead;                      /* Bytes to read from file */
48750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  i64 iOff;                       /* Offset to read from */
48760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;
48770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
48780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  fseek(pFile, 0, SEEK_END);
48790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  szFile = (i64)ftell(pFile);
48800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( szFile==0 ){
48810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    memset(pEOCD, 0, sizeof(ZipfileEOCD));
48820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return SQLITE_OK;
48830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
48840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  nRead = (int)(MIN(szFile, ZIPFILE_BUFFER_SIZE));
48850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  iOff = szFile - nRead;
48860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
48870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = zipfileReadData(pFile, aRead, nRead, iOff, &pTab->base.zErrMsg);
48880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
48890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int i;
48900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
48910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    /* Scan backwards looking for the signature bytes */
48920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    for(i=nRead-20; i>=0; i--){
48930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( aRead[i]==0x50 && aRead[i+1]==0x4b
48940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov       && aRead[i+2]==0x05 && aRead[i+3]==0x06
48950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      ){
48960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        break;
48970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
48980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
48990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( i<0 ){
49000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pTab->base.zErrMsg = sqlite3_mprintf(
49010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          "cannot find end of central directory record"
49020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      );
49030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      return SQLITE_ERROR;
49040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
49050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
49060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    aRead += i+4;
49070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pEOCD->iDisk = zipfileRead16(aRead);
49080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pEOCD->iFirstDisk = zipfileRead16(aRead);
49090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pEOCD->nEntry = zipfileRead16(aRead);
49100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pEOCD->nEntryTotal = zipfileRead16(aRead);
49110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pEOCD->nSize = zipfileRead32(aRead);
49120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pEOCD->iOffset = zipfileRead32(aRead);
49130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
49140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if 0
49150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    printf("iDisk=%d  iFirstDisk=%d  nEntry=%d  "
49160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov           "nEntryTotal=%d  nSize=%d  iOffset=%d",
49170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov           (int)pEOCD->iDisk, (int)pEOCD->iFirstDisk, (int)pEOCD->nEntry,
49180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov           (int)pEOCD->nEntryTotal, (int)pEOCD->nSize, (int)pEOCD->iOffset
49190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    );
49200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
49210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
49220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
49230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
49240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
49250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
49260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
49270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** xFilter callback.
49280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
49290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileFilter(
49300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vtab_cursor *cur,
49310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int idxNum, const char *idxStr,
49320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int argc, sqlite3_value **argv
49330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
49340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileTab *pTab = (ZipfileTab*)cur->pVtab;
49350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileCsr *pCsr = (ZipfileCsr*)cur;
49360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zFile;              /* Zip file to scan */
49370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;             /* Return Code */
49380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
49390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zipfileResetCursor(pCsr);
49400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
49410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pTab->zFile ){
49420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zFile = pTab->zFile;
49430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else if( idxNum==0 ){
49440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    /* Error. This is an eponymous virtual table and the user has not
49450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ** supplied a file name. */
49460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileSetErrmsg(pCsr, "table function zipfile() requires an argument");
49470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return SQLITE_ERROR;
49480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
49490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zFile = (const char*)sqlite3_value_text(argv[0]);
49500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
49510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
49520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pTab->pWriteFd==0 ){
49530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCsr->pFile = fopen(zFile, "rb");
49540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pCsr->pFile==0 ){
49550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zipfileSetErrmsg(pCsr, "cannot open file: %s", zFile);
49560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = SQLITE_ERROR;
49570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
49580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = zipfileReadEOCD(pTab, pCsr->pFile, &pCsr->eocd);
49590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( rc==SQLITE_OK ){
49600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( pCsr->eocd.nEntry==0 ){
49610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          pCsr->bEof = 1;
49620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }else{
49630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          pCsr->iNextOff = pCsr->eocd.iOffset;
49640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          rc = zipfileNext(cur);
49650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
49660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
49670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
49680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
49690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ZipfileEntry e;
49700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    memset(&e, 0, sizeof(e));
49710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    e.pNext = pTab->pFirstEntry;
49720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCsr->pCurrent = &e;
49730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = zipfileNext(cur);
49740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    assert( pCsr->pCurrent!=&e );
49750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
49760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
49770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
49780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
49790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
49800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
49810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** xBestIndex callback.
49820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
49830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileBestIndex(
49840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vtab *tab,
49850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_index_info *pIdxInfo
49860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
49870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int i;
49880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
49890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(i=0; i<pIdxInfo->nConstraint; i++){
49900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i];
49910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pCons->usable==0 ) continue;
49920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pCons->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
49930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pCons->iColumn!=ZIPFILE_F_COLUMN_IDX ) continue;
49940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    break;
49950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
49960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
49970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( i<pIdxInfo->nConstraint ){
49980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pIdxInfo->aConstraintUsage[i].argvIndex = 1;
49990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pIdxInfo->aConstraintUsage[i].omit = 1;
50000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pIdxInfo->estimatedCost = 1000.0;
50010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pIdxInfo->idxNum = 1;
50020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
50030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pIdxInfo->estimatedCost = (double)(((sqlite3_int64)1) << 50);
50040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pIdxInfo->idxNum = 0;
50050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
50060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
50070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
50080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
50090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
50100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
50110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Add object pNew to the end of the linked list that begins at
50120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** ZipfileTab.pFirstEntry and ends with pLastEntry.
50130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
50140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void zipfileAddEntry(
50150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileTab *pTab,
50160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileEntry *pBefore,
50170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileEntry *pNew
50180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
50190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( (pTab->pFirstEntry==0)==(pTab->pLastEntry==0) );
50200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( pNew->pNext==0 );
50210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pBefore==0 ){
50220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pTab->pFirstEntry==0 ){
50230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pTab->pFirstEntry = pTab->pLastEntry = pNew;
50240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
50250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      assert( pTab->pLastEntry->pNext==0 );
50260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pTab->pLastEntry->pNext = pNew;
50270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pTab->pLastEntry = pNew;
50280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
50290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
50300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ZipfileEntry **pp;
50310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    for(pp=&pTab->pFirstEntry; *pp!=pBefore; pp=&((*pp)->pNext));
50320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNew->pNext = pBefore;
50330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    *pp = pNew;
50340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
50350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
50360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
50370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileLoadDirectory(ZipfileTab *pTab){
50380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileEOCD eocd;
50390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;
50400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
50410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = zipfileReadEOCD(pTab, pTab->pWriteFd, &eocd);
50420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK && eocd.nEntry>0 ){
50430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int i;
50440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int iOff = 0;
50450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    u8 *aBuf = sqlite3_malloc(eocd.nSize);
50460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( aBuf==0 ){
50470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = SQLITE_NOMEM;
50480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
50490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = zipfileReadData(
50500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          pTab->pWriteFd, aBuf, eocd.nSize, eocd.iOffset, &pTab->base.zErrMsg
50510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      );
50520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
50530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
50540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    for(i=0; rc==SQLITE_OK && i<eocd.nEntry; i++){
50550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      u16 nFile;
50560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      u16 nExtra;
50570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      u16 nComment;
50580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      ZipfileEntry *pNew;
50590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      u8 *aRec = &aBuf[iOff];
50600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
50610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      nFile = zipfileGetU16(&aRec[ZIPFILE_CDS_NFILE_OFF]);
50620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      nExtra = zipfileGetU16(&aRec[ZIPFILE_CDS_NFILE_OFF+2]);
50630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      nComment = zipfileGetU16(&aRec[ZIPFILE_CDS_NFILE_OFF+4]);
50640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
50650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pNew = sqlite3_malloc(
50660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          sizeof(ZipfileEntry)
50670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        + nFile+1
50680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        + ZIPFILE_CDS_FIXED_SZ+nFile+nExtra+nComment
50690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      );
50700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( pNew==0 ){
50710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        rc = SQLITE_NOMEM;
50720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else{
50730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        memset(pNew, 0, sizeof(ZipfileEntry));
50740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        pNew->zPath = (char*)&pNew[1];
50750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        memcpy(pNew->zPath, &aRec[ZIPFILE_CDS_FIXED_SZ], nFile);
50760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        pNew->zPath[nFile] = '\0';
50770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        pNew->aCdsEntry = (u8*)&pNew->zPath[nFile+1];
50780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        pNew->nCdsEntry = ZIPFILE_CDS_FIXED_SZ+nFile+nExtra+nComment;
50790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        memcpy(pNew->aCdsEntry, aRec, pNew->nCdsEntry);
50800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        zipfileAddEntry(pTab, 0, pNew);
50810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
50820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
50830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      iOff += ZIPFILE_CDS_FIXED_SZ+nFile+nExtra+nComment;
50840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
50850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
50860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(aBuf);
50870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
50880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
50890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
50900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
50910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
50920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic ZipfileEntry *zipfileNewEntry(
50930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileCDS *pCds,               /* Values for fixed size part of CDS */
50940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zPath,              /* Path for new entry */
50950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nPath,                      /* strlen(zPath) */
50960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u32 mTime                       /* Modification time (or 0) */
50970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
50980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 *aWrite;
50990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileEntry *pNew;
51000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCds->nFile = (u16)nPath;
51010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCds->nExtra = mTime ? 9 : 0;
51020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pNew = (ZipfileEntry*)sqlite3_malloc(
51030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sizeof(ZipfileEntry) +
51040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    nPath+1 +
51050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ZIPFILE_CDS_FIXED_SZ + nPath + pCds->nExtra
51060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  );
51070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
51080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pNew ){
51090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    memset(pNew, 0, sizeof(ZipfileEntry));
51100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNew->zPath = (char*)&pNew[1];
51110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNew->aCdsEntry = (u8*)&pNew->zPath[nPath+1];
51120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNew->nCdsEntry = ZIPFILE_CDS_FIXED_SZ + nPath + pCds->nExtra;
51130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    memcpy(pNew->zPath, zPath, nPath+1);
51140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
51150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    aWrite = pNew->aCdsEntry;
51160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileWrite32(aWrite, ZIPFILE_SIGNATURE_CDS);
51170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileWrite16(aWrite, pCds->iVersionMadeBy);
51180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileWrite16(aWrite, pCds->iVersionExtract);
51190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileWrite16(aWrite, pCds->flags);
51200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileWrite16(aWrite, pCds->iCompression);
51210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileWrite16(aWrite, pCds->mTime);
51220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileWrite16(aWrite, pCds->mDate);
51230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileWrite32(aWrite, pCds->crc32);
51240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileWrite32(aWrite, pCds->szCompressed);
51250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileWrite32(aWrite, pCds->szUncompressed);
51260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileWrite16(aWrite, pCds->nFile);
51270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileWrite16(aWrite, pCds->nExtra);
51280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileWrite16(aWrite, pCds->nComment);      assert( pCds->nComment==0 );
51290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileWrite16(aWrite, pCds->iDiskStart);
51300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileWrite16(aWrite, pCds->iInternalAttr);
51310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileWrite32(aWrite, pCds->iExternalAttr);
51320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileWrite32(aWrite, pCds->iOffset);
51330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    assert( aWrite==&pNew->aCdsEntry[ZIPFILE_CDS_FIXED_SZ] );
51340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    memcpy(aWrite, zPath, nPath);
51350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pCds->nExtra ){
51360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      aWrite += nPath;
51370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zipfileWrite16(aWrite, ZIPFILE_EXTRA_TIMESTAMP);
51380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zipfileWrite16(aWrite, 5);
51390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      *aWrite++ = 0x01;
51400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zipfileWrite32(aWrite, mTime);
51410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
51420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
51430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
51440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return pNew;
51450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
51460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
51470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileAppendEntry(
51480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileTab *pTab,
51490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileCDS *pCds,
51500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zPath,              /* Path for new entry */
51510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nPath,                      /* strlen(zPath) */
51520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const u8 *pData,
51530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nData,
51540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u32 mTime
51550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
51560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 *aBuf = pTab->aBuffer;
51570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;
51580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
51590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zipfileWrite32(aBuf, ZIPFILE_SIGNATURE_LFH);
51600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zipfileWrite16(aBuf, pCds->iVersionExtract);
51610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zipfileWrite16(aBuf, pCds->flags);
51620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zipfileWrite16(aBuf, pCds->iCompression);
51630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zipfileWrite16(aBuf, pCds->mTime);
51640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zipfileWrite16(aBuf, pCds->mDate);
51650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zipfileWrite32(aBuf, pCds->crc32);
51660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zipfileWrite32(aBuf, pCds->szCompressed);
51670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zipfileWrite32(aBuf, pCds->szUncompressed);
51680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zipfileWrite16(aBuf, (u16)nPath);
51690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zipfileWrite16(aBuf, pCds->nExtra);
51700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( aBuf==&pTab->aBuffer[ZIPFILE_LFH_FIXED_SZ] );
51710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = zipfileAppendData(pTab, pTab->aBuffer, (int)(aBuf - pTab->aBuffer));
51720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
51730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = zipfileAppendData(pTab, (const u8*)zPath, nPath);
51740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
51750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
51760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK && pCds->nExtra ){
51770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    aBuf = pTab->aBuffer;
51780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileWrite16(aBuf, ZIPFILE_EXTRA_TIMESTAMP);
51790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileWrite16(aBuf, 5);
51800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    *aBuf++ = 0x01;
51810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileWrite32(aBuf, mTime);
51820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = zipfileAppendData(pTab, pTab->aBuffer, 9);
51830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
51840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
51850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
51860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = zipfileAppendData(pTab, pData, nData);
51870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
51880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
51890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
51900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
51910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
51920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileGetMode(
51930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileTab *pTab,
51940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_value *pVal,
51950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u32 defaultMode,                /* Value to use if pVal IS NULL */
51960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u32 *pMode
51970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
51980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *z = (const char*)sqlite3_value_text(pVal);
51990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u32 mode = 0;
52000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( z==0 ){
52010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    mode = defaultMode;
52020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else if( z[0]>='0' && z[0]<='9' ){
52030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    mode = (unsigned int)sqlite3_value_int(pVal);
52040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
52050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const char zTemplate[11] = "-rwxrwxrwx";
52060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int i;
52070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( strlen(z)!=10 ) goto parse_error;
52080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    switch( z[0] ){
52090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      case '-': mode |= S_IFREG; break;
52100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      case 'd': mode |= S_IFDIR; break;
52110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if !defined(_WIN32) && !defined(WIN32)
52120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      case 'l': mode |= S_IFLNK; break;
52130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
52140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      default: goto parse_error;
52150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
52160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    for(i=1; i<10; i++){
52170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( z[i]==zTemplate[i] ) mode |= 1 << (9-i);
52180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      else if( z[i]!='-' ) goto parse_error;
52190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
52200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
52210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  *pMode = mode;
52220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
52230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
52240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov parse_error:
52250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pTab->base.zErrMsg = sqlite3_mprintf("zipfile: parse error in mode: %s", z);
52260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_ERROR;
52270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
52280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
52290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
52300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Both (const char*) arguments point to nul-terminated strings. Argument
52310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** nB is the value of strlen(zB). This function returns 0 if the strings are
52320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** identical, ignoring any trailing '/' character in either path.  */
52330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileComparePath(const char *zA, const char *zB, int nB){
52340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nA = (int)strlen(zA);
52350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( zA[nA-1]=='/' ) nA--;
52360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( zB[nB-1]=='/' ) nB--;
52370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0;
52380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return 1;
52390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
52400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
52410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
52420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** xUpdate method.
52430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
52440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileUpdate(
52450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vtab *pVtab,
52460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nVal,
52470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_value **apVal,
52480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite_int64 *pRowid
52490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
52500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileTab *pTab = (ZipfileTab*)pVtab;
52510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;             /* Return Code */
52520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileEntry *pNew = 0;         /* New in-memory CDS entry */
52530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
52540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u32 mode = 0;                   /* Mode for new entry */
52550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  i64 mTime = 0;                  /* Modification time for new entry */
52560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  i64 sz = 0;                     /* Uncompressed size */
52570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zPath = 0;          /* Path for new entry */
52580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nPath = 0;                  /* strlen(zPath) */
52590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const u8 *pData = 0;            /* Pointer to buffer containing content */
52600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nData = 0;                  /* Size of pData buffer in bytes */
52610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int iMethod = 0;                /* Compression method for new entry */
52620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 *pFree = 0;                  /* Free this */
52630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zFree = 0;                /* Also free this */
52640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileCDS cds;                 /* New Central Directory Structure entry */
52650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileEntry *pOld = 0;
52660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int bIsDir = 0;
52670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u32 iCrc32 = 0;
52680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
52690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( pTab->zFile );
52700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( pTab->pWriteFd );
52710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
52720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
52730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const char *zDelete = (const char*)sqlite3_value_text(apVal[0]);
52740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int nDelete = (int)strlen(zDelete);
52750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    for(pOld=pTab->pFirstEntry; 1; pOld=pOld->pNext){
52760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( pOld->bDeleted ) continue;
52770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( zipfileComparePath(pOld->zPath, zDelete, nDelete)==0 ){
52780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        pOld->bDeleted = 1;
52790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        break;
52800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
52810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      assert( pOld->pNext );
52820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
52830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( nVal==1 ) return SQLITE_OK;
52840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
52850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
52860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* Check that "sz" and "rawdata" are both NULL: */
52870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( sqlite3_value_type(apVal[5])!=SQLITE_NULL
52880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov   || sqlite3_value_type(apVal[6])!=SQLITE_NULL
52890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ){
52900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = SQLITE_CONSTRAINT;
52910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
52920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
52930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
52940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( sqlite3_value_type(apVal[7])==SQLITE_NULL ){
52950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      /* data=NULL. A directory */
52960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      bIsDir = 1;
52970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
52980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      /* Value specified for "data", and possibly "method". This must be
52990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      ** a regular file or a symlink. */
53000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      const u8 *aIn = sqlite3_value_blob(apVal[7]);
53010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int nIn = sqlite3_value_bytes(apVal[7]);
53020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int bAuto = sqlite3_value_type(apVal[8])==SQLITE_NULL;
53030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
53040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      iMethod = sqlite3_value_int(apVal[8]);
53050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sz = nIn;
53060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pData = aIn;
53070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      nData = nIn;
53080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( iMethod!=0 && iMethod!=8 ){
53090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        rc = SQLITE_CONSTRAINT;
53100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else{
53110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( bAuto || iMethod ){
53120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          int nCmp;
53130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          rc = zipfileDeflate(pTab, aIn, nIn, &pFree, &nCmp);
53140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( rc==SQLITE_OK ){
53150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            if( iMethod || nCmp<nIn ){
53160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov              iMethod = 8;
53170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov              pData = pFree;
53180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov              nData = nCmp;
53190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            }
53200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
53210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
53220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        iCrc32 = crc32(0, aIn, nIn);
53230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
53240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
53250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
53260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
53270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
53280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = zipfileGetMode(pTab, apVal[3],
53290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        (bIsDir ? (S_IFDIR + 0755) : (S_IFREG + 0644)), &mode
53300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    );
53310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( rc==SQLITE_OK && (bIsDir == ((mode & S_IFDIR)==0)) ){
53320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      /* The "mode" attribute is a directory, but data has been specified.
53330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      ** Or vice-versa - no data but "mode" is a file or symlink.  */
53340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = SQLITE_CONSTRAINT;
53350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
53360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
53370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
53380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
53390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zPath = (const char*)sqlite3_value_text(apVal[2]);
53400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    nPath = (int)strlen(zPath);
53410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( sqlite3_value_type(apVal[4])==SQLITE_NULL ){
53420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      mTime = (sqlite3_int64)time(0);
53430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
53440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      mTime = sqlite3_value_int64(apVal[4]);
53450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
53460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
53470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
53480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK && bIsDir ){
53490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    /* For a directory, check that the last character in the path is a
53500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ** '/'. This appears to be required for compatibility with info-zip
53510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ** (the unzip command on unix). It does not create directories
53520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ** otherwise.  */
53530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( zPath[nPath-1]!='/' ){
53540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zFree = sqlite3_mprintf("%s/", zPath);
53550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( zFree==0 ){ rc = SQLITE_NOMEM; }
53560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zPath = (const char*)zFree;
53570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      nPath++;
53580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
53590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
53600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
53610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* Check that we're not inserting a duplicate entry */
53620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
53630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ZipfileEntry *p;
53640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    for(p=pTab->pFirstEntry; p; p=p->pNext){
53650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( p->bDeleted ) continue;
53660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( zipfileComparePath(p->zPath, zPath, nPath)==0 ){
53670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        rc = SQLITE_CONSTRAINT;
53680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        break;
53690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
53700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
53710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
53720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
53730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
53740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    /* Create the new CDS record. */
53750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    memset(&cds, 0, sizeof(cds));
53760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY;
53770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED;
53780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    cds.flags = ZIPFILE_NEWENTRY_FLAGS;
53790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    cds.iCompression = (u16)iMethod;
53800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileMtimeToDos(&cds, (u32)mTime);
53810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    cds.crc32 = iCrc32;
53820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    cds.szCompressed = nData;
53830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    cds.szUncompressed = (u32)sz;
53840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    cds.iExternalAttr = (mode<<16);
53850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    cds.iOffset = (u32)pTab->szCurrent;
53860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNew = zipfileNewEntry(&cds, zPath, nPath, (u32)mTime);
53870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pNew==0 ){
53880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = SQLITE_NOMEM;
53890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
53900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zipfileAddEntry(pTab, pOld, pNew);
53910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
53920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
53930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
53940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* Append the new header+file to the archive */
53950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
53960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = zipfileAppendEntry(pTab, &cds, zPath, nPath, pData, nData, (u32)mTime);
53970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
53980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
53990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc!=SQLITE_OK && pOld ){
54000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pOld->bDeleted = 0;
54010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
54020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(pFree);
54030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(zFree);
54040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
54050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
54060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
54070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileAppendEOCD(ZipfileTab *pTab, ZipfileEOCD *p){
54080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 *aBuf = pTab->aBuffer;
54090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
54100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zipfileWrite32(aBuf, ZIPFILE_SIGNATURE_EOCD);
54110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zipfileWrite16(aBuf, p->iDisk);
54120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zipfileWrite16(aBuf, p->iFirstDisk);
54130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zipfileWrite16(aBuf, p->nEntry);
54140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zipfileWrite16(aBuf, p->nEntryTotal);
54150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zipfileWrite32(aBuf, p->nSize);
54160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zipfileWrite32(aBuf, p->iOffset);
54170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zipfileWrite16(aBuf, 0);        /* Size of trailing comment in bytes*/
54180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
54190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( (aBuf-pTab->aBuffer)==22 );
54200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return zipfileAppendData(pTab, pTab->aBuffer, (int)(aBuf - pTab->aBuffer));
54210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
54220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
54230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void zipfileCleanupTransaction(ZipfileTab *pTab){
54240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileEntry *pEntry;
54250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileEntry *pNext;
54260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
54270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(pEntry=pTab->pFirstEntry; pEntry; pEntry=pNext){
54280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNext = pEntry->pNext;
54290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(pEntry);
54300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
54310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pTab->pFirstEntry = 0;
54320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pTab->pLastEntry = 0;
54330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  fclose(pTab->pWriteFd);
54340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pTab->pWriteFd = 0;
54350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pTab->szCurrent = 0;
54360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pTab->szOrig = 0;
54370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
54380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
54390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileBegin(sqlite3_vtab *pVtab){
54400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileTab *pTab = (ZipfileTab*)pVtab;
54410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
54420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
54430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( pTab->pWriteFd==0 );
54440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
54450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* This table is only writable if a default archive path was specified
54460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ** as part of the CREATE VIRTUAL TABLE statement. */
54470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pTab->zFile==0 ){
54480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pTab->base.zErrMsg = sqlite3_mprintf(
54490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "zipfile: writing requires a default archive"
54500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    );
54510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return SQLITE_ERROR;
54520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
54530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
54540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* Open a write fd on the file. Also load the entire central directory
54550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ** structure into memory. During the transaction any new file data is
54560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ** appended to the archive file, but the central directory is accumulated
54570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ** in main-memory until the transaction is committed.  */
54580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pTab->pWriteFd = fopen(pTab->zFile, "ab+");
54590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pTab->pWriteFd==0 ){
54600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pTab->base.zErrMsg = sqlite3_mprintf(
54610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "zipfile: failed to open file %s for writing", pTab->zFile
54620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    );
54630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = SQLITE_ERROR;
54640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
54650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    fseek(pTab->pWriteFd, 0, SEEK_END);
54660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pTab->szCurrent = pTab->szOrig = (i64)ftell(pTab->pWriteFd);
54670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = zipfileLoadDirectory(pTab);
54680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
54690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
54700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc!=SQLITE_OK ){
54710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileCleanupTransaction(pTab);
54720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
54730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
54740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
54750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
54760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
54770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileCommit(sqlite3_vtab *pVtab){
54780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileTab *pTab = (ZipfileTab*)pVtab;
54790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
54800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pTab->pWriteFd ){
54810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    i64 iOffset = pTab->szCurrent;
54820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ZipfileEntry *p;
54830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ZipfileEOCD eocd;
54840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int nEntry = 0;
54850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
54860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    /* Write out all undeleted entries */
54870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    for(p=pTab->pFirstEntry; rc==SQLITE_OK && p; p=p->pNext){
54880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( p->bDeleted ) continue;
54890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = zipfileAppendData(pTab, p->aCdsEntry, p->nCdsEntry);
54900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      nEntry++;
54910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
54920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
54930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    /* Write out the EOCD record */
54940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    eocd.iDisk = 0;
54950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    eocd.iFirstDisk = 0;
54960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    eocd.nEntry = (u16)nEntry;
54970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    eocd.nEntryTotal = (u16)nEntry;
54980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    eocd.nSize = (u32)(pTab->szCurrent - iOffset);
54990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    eocd.iOffset = (u32)iOffset;
55000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = zipfileAppendEOCD(pTab, &eocd);
55010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
55020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileCleanupTransaction(pTab);
55030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
55040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
55050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
55060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
55070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileRollback(sqlite3_vtab *pVtab){
55080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return zipfileCommit(pVtab);
55090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
55100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
55110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic ZipfileCsr *zipfileFindCursor(ZipfileTab *pTab, i64 iId){
55120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileCsr *pCsr;
55130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){
55140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( iId==pCsr->iId ) break;
55150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
55160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return pCsr;
55170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
55180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
55190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void zipfileFunctionCds(
55200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_context *context,
55210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int argc,
55220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_value **argv
55230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
55240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileCsr *pCsr;
55250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ZipfileTab *pTab = (ZipfileTab*)sqlite3_user_data(context);
55260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( argc>0 );
55270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
55280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCsr = zipfileFindCursor(pTab, sqlite3_value_int64(argv[0]));
55290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pCsr ){
55300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ZipfileCDS *p = &pCsr->cds;
55310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    char *zRes = sqlite3_mprintf("{"
55320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "\"version-made-by\" : %u, "
55330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "\"version-to-extract\" : %u, "
55340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "\"flags\" : %u, "
55350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "\"compression\" : %u, "
55360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "\"time\" : %u, "
55370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "\"date\" : %u, "
55380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "\"crc32\" : %u, "
55390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "\"compressed-size\" : %u, "
55400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "\"uncompressed-size\" : %u, "
55410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "\"file-name-length\" : %u, "
55420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "\"extra-field-length\" : %u, "
55430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "\"file-comment-length\" : %u, "
55440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "\"disk-number-start\" : %u, "
55450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "\"internal-attr\" : %u, "
55460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "\"external-attr\" : %u, "
55470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "\"offset\" : %u }",
55480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        (u32)p->iVersionMadeBy, (u32)p->iVersionExtract,
55490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        (u32)p->flags, (u32)p->iCompression,
55500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        (u32)p->mTime, (u32)p->mDate,
55510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        (u32)p->crc32, (u32)p->szCompressed,
55520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        (u32)p->szUncompressed, (u32)p->nFile,
55530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        (u32)p->nExtra, (u32)p->nComment,
55540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        (u32)p->iDiskStart, (u32)p->iInternalAttr,
55550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        (u32)p->iExternalAttr, (u32)p->iOffset
55560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    );
55570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
55580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( zRes==0 ){
55590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_error_nomem(context);
55600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
55610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
55620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_free(zRes);
55630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
55640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
55650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
55660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
55670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
55680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
55690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** xFindFunction method.
55700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
55710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileFindFunction(
55720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vtab *pVtab,            /* Virtual table handle */
55730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nArg,                       /* Number of SQL function arguments */
55740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zName,              /* Name of SQL function */
55750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */
55760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  void **ppArg                    /* OUT: User data for *pxFunc */
55770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
55780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( nArg>0 ){
55790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( sqlite3_stricmp("zipfile_cds", zName)==0 ){
55800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      *pxFunc = zipfileFunctionCds;
55810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      *ppArg = (void*)pVtab;
55820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      return 1;
55830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
55840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
55850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
55860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return 0;
55870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
55880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
55890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
55900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Register the "zipfile" virtual table.
55910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
55920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int zipfileRegister(sqlite3 *db){
55930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  static sqlite3_module zipfileModule = {
55940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    1,                         /* iVersion */
55950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileConnect,            /* xCreate */
55960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileConnect,            /* xConnect */
55970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileBestIndex,          /* xBestIndex */
55980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileDisconnect,         /* xDisconnect */
55990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileDisconnect,         /* xDestroy */
56000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileOpen,               /* xOpen - open a cursor */
56010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileClose,              /* xClose - close a cursor */
56020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileFilter,             /* xFilter - configure scan constraints */
56030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileNext,               /* xNext - advance a cursor */
56040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileEof,                /* xEof - check for end of scan */
56050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileColumn,             /* xColumn - read data */
56060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileRowid,              /* xRowid - read data */
56070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileUpdate,             /* xUpdate */
56080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileBegin,              /* xBegin */
56090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0,                         /* xSync */
56100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileCommit,             /* xCommit */
56110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileRollback,           /* xRollback */
56120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zipfileFindFunction,       /* xFindMethod */
56130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0,                         /* xRename */
56140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  };
56150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
56160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = sqlite3_create_module(db, "zipfile"  , &zipfileModule, 0);
56170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
56180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = sqlite3_overload_function(db, "zipfile_cds", -1);
56190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
56200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
56210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
56220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#else         /* SQLITE_OMIT_VIRTUALTABLE */
56230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov# define zipfileRegister(x) SQLITE_OK
56240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
56250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
56260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifdef _WIN32
56270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
56280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
56290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovint sqlite3_zipfile_init(
56300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *db,
56310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErrMsg,
56320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const sqlite3_api_routines *pApi
56330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
56340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  SQLITE_EXTENSION_INIT2(pApi);
56350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)pzErrMsg;  /* Unused parameter */
56360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return zipfileRegister(db);
56370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
56380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
56390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/************************* End ../ext/misc/zipfile.c ********************/
56400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/************************* Begin ../ext/misc/sqlar.c ******************/
56410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
56420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** 2017-12-17
56430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
56440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The author disclaims copyright to this source code.  In place of
56450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** a legal notice, here is a blessing:
56460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
56470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you do good and not evil.
56480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you find forgiveness for yourself and forgive others.
56490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you share freely, never taking more than you give.
56500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
56510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov******************************************************************************
56520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
56530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Utility functions sqlar_compress() and sqlar_uncompress(). Useful
56540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** for working with sqlar archives and used by the shell tool's built-in
56550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** sqlar support.
56560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
56570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor KupolovSQLITE_EXTENSION_INIT1
56580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <zlib.h>
56590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
56600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
56610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Implementation of the "sqlar_compress(X)" SQL function.
56620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
56630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** If the type of X is SQLITE_BLOB, and compressing that blob using
56640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** zlib utility function compress() yields a smaller blob, return the
56650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** compressed blob. Otherwise, return a copy of X.
56660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
56670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** SQLar uses the "zlib format" for compressed content.  The zlib format
56680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** contains a two-byte identification header and a four-byte checksum at
56690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** the end.  This is different from ZIP which uses the raw deflate format.
56700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
56710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Future enhancements to SQLar might add support for new compression formats.
56720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** If so, those new formats will be identified by alternative headers in the
56730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** compressed data.
56740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
56750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void sqlarCompressFunc(
56760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_context *context,
56770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int argc,
56780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_value **argv
56790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
56800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( argc==1 );
56810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
56820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const Bytef *pData = sqlite3_value_blob(argv[0]);
56830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    uLong nData = sqlite3_value_bytes(argv[0]);
56840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    uLongf nOut = compressBound(nData);
56850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    Bytef *pOut;
56860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
56870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pOut = (Bytef*)sqlite3_malloc(nOut);
56880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pOut==0 ){
56890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_error_nomem(context);
56900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      return;
56910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
56920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( Z_OK!=compress(pOut, &nOut, pData, nData) ){
56930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_result_error(context, "error in compress()", -1);
56940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else if( nOut<nData ){
56950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_result_blob(context, pOut, nOut, SQLITE_TRANSIENT);
56960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else{
56970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_result_value(context, argv[0]);
56980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
56990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_free(pOut);
57000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
57010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
57020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_result_value(context, argv[0]);
57030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
57040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
57050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
57060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
57070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Implementation of the "sqlar_uncompress(X,SZ)" SQL function
57080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
57090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Parameter SZ is interpreted as an integer. If it is less than or
57100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** equal to zero, then this function returns a copy of X. Or, if
57110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** SZ is equal to the size of X when interpreted as a blob, also
57120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** return a copy of X. Otherwise, decompress blob X using zlib
57130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** utility function uncompress() and return the results (another
57140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** blob).
57150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
57160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void sqlarUncompressFunc(
57170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_context *context,
57180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int argc,
57190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_value **argv
57200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
57210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  uLong nData;
57220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  uLongf sz;
57230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
57240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( argc==2 );
57250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sz = sqlite3_value_int(argv[1]);
57260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
57270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( sz<=0 || sz==(nData = sqlite3_value_bytes(argv[0])) ){
57280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_result_value(context, argv[0]);
57290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
57300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const Bytef *pData= sqlite3_value_blob(argv[0]);
57310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    Bytef *pOut = sqlite3_malloc(sz);
57320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( Z_OK!=uncompress(pOut, &sz, pData, nData) ){
57330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_error(context, "error in uncompress()", -1);
57340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
57350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_blob(context, pOut, sz, SQLITE_TRANSIENT);
57360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
57370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(pOut);
57380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
57390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
57400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
57410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
57420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifdef _WIN32
57430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
57440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
57450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovint sqlite3_sqlar_init(
57460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *db,
57470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErrMsg,
57480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const sqlite3_api_routines *pApi
57490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
57500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
57510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  SQLITE_EXTENSION_INIT2(pApi);
57520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)pzErrMsg;  /* Unused parameter */
57530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = sqlite3_create_function(db, "sqlar_compress", 1, SQLITE_UTF8, 0,
57540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                               sqlarCompressFunc, 0, 0);
57550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
57560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = sqlite3_create_function(db, "sqlar_uncompress", 2, SQLITE_UTF8, 0,
57570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                                 sqlarUncompressFunc, 0, 0);
57580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
57590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
57600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
57610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
57620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/************************* End ../ext/misc/sqlar.c ********************/
57630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
57640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/************************* Begin ../ext/expert/sqlite3expert.h ******************/
57650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
57660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** 2017 April 07
57670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
57680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The author disclaims copyright to this source code.  In place of
57690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** a legal notice, here is a blessing:
57700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
57710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you do good and not evil.
57720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you find forgiveness for yourself and forgive others.
57730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you share freely, never taking more than you give.
57740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
57750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*************************************************************************
57760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
57770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
57780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
57790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
57800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct sqlite3expert sqlite3expert;
57810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
57820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
57830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Create a new sqlite3expert object.
57840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
57850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** If successful, a pointer to the new object is returned and (*pzErr) set
57860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** to NULL. Or, if an error occurs, NULL is returned and (*pzErr) set to
57870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** an English-language error message. In this case it is the responsibility
57880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** of the caller to eventually free the error message buffer using
57890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** sqlite3_free().
57900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
57910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovsqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErr);
57920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
57930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
57940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Configure an sqlite3expert object.
57950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
57960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** EXPERT_CONFIG_SAMPLE:
57970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   By default, sqlite3_expert_analyze() generates sqlite_stat1 data for
57980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   each candidate index. This involves scanning and sorting the entire
57990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   contents of each user database table once for each candidate index
58000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   associated with the table. For large databases, this can be
58010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   prohibitively slow. This option allows the sqlite3expert object to
58020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   be configured so that sqlite_stat1 data is instead generated based on a
58030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   subset of each table, or so that no sqlite_stat1 data is used at all.
58040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
58050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   A single integer argument is passed to this option. If the value is less
58060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   than or equal to zero, then no sqlite_stat1 data is generated or used by
58070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   the analysis - indexes are recommended based on the database schema only.
58080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   Or, if the value is 100 or greater, complete sqlite_stat1 data is
58090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   generated for each candidate index (this is the default). Finally, if the
58100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   value falls between 0 and 100, then it represents the percentage of user
58110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   table rows that should be considered when generating sqlite_stat1 data.
58120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
58130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   Examples:
58140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
58150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     // Do not generate any sqlite_stat1 data
58160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     sqlite3_expert_config(pExpert, EXPERT_CONFIG_SAMPLE, 0);
58170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
58180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     // Generate sqlite_stat1 data based on 10% of the rows in each table.
58190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     sqlite3_expert_config(pExpert, EXPERT_CONFIG_SAMPLE, 10);
58200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
58210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovint sqlite3_expert_config(sqlite3expert *p, int op, ...);
58220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
58230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define EXPERT_CONFIG_SAMPLE 1    /* int */
58240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
58250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
58260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Specify zero or more SQL statements to be included in the analysis.
58270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
58280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Buffer zSql must contain zero or more complete SQL statements. This
58290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** function parses all statements contained in the buffer and adds them
58300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** to the internal list of statements to analyze. If successful, SQLITE_OK
58310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** is returned and (*pzErr) set to NULL. Or, if an error occurs - for example
58320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** due to a error in the SQL - an SQLite error code is returned and (*pzErr)
58330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** may be set to point to an English language error message. In this case
58340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** the caller is responsible for eventually freeing the error message buffer
58350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** using sqlite3_free().
58360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
58370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** If an error does occur while processing one of the statements in the
58380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** buffer passed as the second argument, none of the statements in the
58390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** buffer are added to the analysis.
58400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
58410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This function must be called before sqlite3_expert_analyze(). If a call
58420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** to this function is made on an sqlite3expert object that has already
58430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** been passed to sqlite3_expert_analyze() SQLITE_MISUSE is returned
58440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** immediately and no statements are added to the analysis.
58450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
58460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovint sqlite3_expert_sql(
58470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3expert *p,               /* From a successful sqlite3_expert_new() */
58480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zSql,               /* SQL statement(s) to add */
58490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErr                    /* OUT: Error message (if any) */
58500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov);
58510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
58520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
58530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
58540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This function is called after the sqlite3expert object has been configured
58550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** with all SQL statements using sqlite3_expert_sql() to actually perform
58560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** the analysis. Once this function has been called, it is not possible to
58570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** add further SQL statements to the analysis.
58580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
58590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** If successful, SQLITE_OK is returned and (*pzErr) is set to NULL. Or, if
58600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** an error occurs, an SQLite error code is returned and (*pzErr) set to
58610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** point to a buffer containing an English language error message. In this
58620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** case it is the responsibility of the caller to eventually free the buffer
58630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** using sqlite3_free().
58640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
58650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** If an error does occur within this function, the sqlite3expert object
58660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** is no longer useful for any purpose. At that point it is no longer
58670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** possible to add further SQL statements to the object or to re-attempt
58680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** the analysis. The sqlite3expert object must still be freed using a call
58690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** sqlite3_expert_destroy().
58700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
58710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovint sqlite3_expert_analyze(sqlite3expert *p, char **pzErr);
58720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
58730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
58740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Return the total number of statements loaded using sqlite3_expert_sql().
58750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The total number of SQL statements may be different from the total number
58760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** to calls to sqlite3_expert_sql().
58770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
58780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovint sqlite3_expert_count(sqlite3expert*);
58790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
58800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
58810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Return a component of the report.
58820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
58830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This function is called after sqlite3_expert_analyze() to extract the
58840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** results of the analysis. Each call to this function returns either a
58850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** NULL pointer or a pointer to a buffer containing a nul-terminated string.
58860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The value passed as the third argument must be one of the EXPERT_REPORT_*
58870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** #define constants defined below.
58880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
58890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** For some EXPERT_REPORT_* parameters, the buffer returned contains
58900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** information relating to a specific SQL statement. In these cases that
58910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** SQL statement is identified by the value passed as the second argument.
58920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** SQL statements are numbered from 0 in the order in which they are parsed.
58930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** If an out-of-range value (less than zero or equal to or greater than the
58940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** value returned by sqlite3_expert_count()) is passed as the second argument
58950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** along with such an EXPERT_REPORT_* parameter, NULL is always returned.
58960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
58970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** EXPERT_REPORT_SQL:
58980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   Return the text of SQL statement iStmt.
58990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
59000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** EXPERT_REPORT_INDEXES:
59010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   Return a buffer containing the CREATE INDEX statements for all recommended
59020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   indexes for statement iStmt. If there are no new recommeded indexes, NULL
59030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   is returned.
59040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
59050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** EXPERT_REPORT_PLAN:
59060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   Return a buffer containing the EXPLAIN QUERY PLAN output for SQL query
59070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   iStmt after the proposed indexes have been added to the database schema.
59080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
59090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** EXPERT_REPORT_CANDIDATES:
59100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   Return a pointer to a buffer containing the CREATE INDEX statements
59110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   for all indexes that were tested (for all SQL statements). The iStmt
59120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   parameter is ignored for EXPERT_REPORT_CANDIDATES calls.
59130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
59140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovconst char *sqlite3_expert_report(sqlite3expert*, int iStmt, int eReport);
59150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
59160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
59170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Values for the third argument passed to sqlite3_expert_report().
59180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
59190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define EXPERT_REPORT_SQL        1
59200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define EXPERT_REPORT_INDEXES    2
59210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define EXPERT_REPORT_PLAN       3
59220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define EXPERT_REPORT_CANDIDATES 4
59230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
59240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
59250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Free an (sqlite3expert*) handle and all associated resources. There
59260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** should be one call to this function for each successful call to
59270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** sqlite3-expert_new().
59280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
59290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovvoid sqlite3_expert_destroy(sqlite3expert*);
59300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
59310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
59320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
59330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/************************* End ../ext/expert/sqlite3expert.h ********************/
59340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/************************* Begin ../ext/expert/sqlite3expert.c ******************/
59350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
59360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** 2017 April 09
59370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
59380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The author disclaims copyright to this source code.  In place of
59390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** a legal notice, here is a blessing:
59400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
59410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you do good and not evil.
59420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you find forgiveness for yourself and forgive others.
59430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**    May you share freely, never taking more than you give.
59440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
59450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*************************************************************************
59460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
59470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <assert.h>
59480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <string.h>
59490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#include <stdio.h>
59500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
59510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifndef SQLITE_OMIT_VIRTUALTABLE
59520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
59530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* typedef sqlite3_int64 i64; */
59540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* typedef sqlite3_uint64 u64; */
59550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
59560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct IdxColumn IdxColumn;
59570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct IdxConstraint IdxConstraint;
59580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct IdxScan IdxScan;
59590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct IdxStatement IdxStatement;
59600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct IdxTable IdxTable;
59610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct IdxWrite IdxWrite;
59620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
59630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define STRLEN  (int)strlen
59640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
59650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
59660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** A temp table name that we assume no user database will actually use.
59670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** If this assumption proves incorrect triggers on the table with the
59680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** conflicting name will be ignored.
59690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
59700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define UNIQUE_TABLE_NAME "t592690916721053953805701627921227776"
59710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
59720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
59730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** A single constraint. Equivalent to either "col = ?" or "col < ?" (or
59740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** any other type of single-ended range constraint on a column).
59750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
59760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** pLink:
59770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   Used to temporarily link IdxConstraint objects into lists while
59780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   creating candidate indexes.
59790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
59800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct IdxConstraint {
59810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zColl;                    /* Collation sequence */
59820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int bRange;                     /* True for range, false for eq */
59830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int iCol;                       /* Constrained table column */
59840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int bFlag;                      /* Used by idxFindCompatible() */
59850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int bDesc;                      /* True if ORDER BY <expr> DESC */
59860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxConstraint *pNext;           /* Next constraint in pEq or pRange list */
59870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxConstraint *pLink;           /* See above */
59880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
59890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
59900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
59910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** A single scan of a single table.
59920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
59930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct IdxScan {
59940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxTable *pTab;                 /* Associated table object */
59950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int iDb;                        /* Database containing table zTable */
59960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  i64 covering;                   /* Mask of columns required for cov. index */
59970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxConstraint *pOrder;          /* ORDER BY columns */
59980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxConstraint *pEq;             /* List of == constraints */
59990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxConstraint *pRange;          /* List of < constraints */
60000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxScan *pNextScan;             /* Next IdxScan object for same analysis */
60010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
60020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
60030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
60040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Information regarding a single database table. Extracted from
60050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** "PRAGMA table_info" by function idxGetTableInfo().
60060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
60070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct IdxColumn {
60080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zName;
60090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zColl;
60100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int iPk;
60110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
60120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct IdxTable {
60130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nCol;
60140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zName;                    /* Table name */
60150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxColumn *aCol;
60160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxTable *pNext;                /* Next table in linked list of all tables */
60170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
60180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
60190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
60200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** An object of the following type is created for each unique table/write-op
60210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** seen. The objects are stored in a singly-linked list beginning at
60220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** sqlite3expert.pWrite.
60230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
60240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct IdxWrite {
60250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxTable *pTab;
60260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int eOp;                        /* SQLITE_UPDATE, DELETE or INSERT */
60270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxWrite *pNext;
60280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
60290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
60300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
60310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Each statement being analyzed is represented by an instance of this
60320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** structure.
60330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
60340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct IdxStatement {
60350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int iId;                        /* Statement number */
60360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zSql;                     /* SQL statement */
60370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zIdx;                     /* Indexes */
60380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zEQP;                     /* Plan */
60390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxStatement *pNext;
60400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
60410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
60420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
60430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
60440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** A hash table for storing strings. With space for a payload string
60450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** with each entry. Methods are:
60460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
60470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   idxHashInit()
60480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   idxHashClear()
60490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   idxHashAdd()
60500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   idxHashSearch()
60510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
60520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define IDX_HASH_SIZE 1023
60530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct IdxHashEntry IdxHashEntry;
60540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct IdxHash IdxHash;
60550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct IdxHashEntry {
60560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zKey;                     /* nul-terminated key */
60570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zVal;                     /* nul-terminated value string */
60580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zVal2;                    /* nul-terminated value string 2 */
60590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxHashEntry *pHashNext;        /* Next entry in same hash bucket */
60600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxHashEntry *pNext;            /* Next entry in hash */
60610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
60620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct IdxHash {
60630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxHashEntry *pFirst;
60640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxHashEntry *aHash[IDX_HASH_SIZE];
60650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
60660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
60670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
60680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** sqlite3expert object.
60690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
60700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct sqlite3expert {
60710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int iSample;                    /* Percentage of tables to sample for stat1 */
60720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *db;                    /* User database */
60730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *dbm;                   /* In-memory db for this analysis */
60740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *dbv;                   /* Vtab schema for this analysis */
60750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxTable *pTable;               /* List of all IdxTable objects */
60760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxScan *pScan;                 /* List of scan objects */
60770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxWrite *pWrite;               /* List of write objects */
60780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxStatement *pStatement;       /* List of IdxStatement objects */
60790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int bRun;                       /* True once analysis has run */
60800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErrmsg;
60810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;                         /* Error code from whereinfo hook */
60820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxHash hIdx;                   /* Hash containing all candidate indexes */
60830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zCandidates;              /* For EXPERT_REPORT_CANDIDATES */
60840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
60850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
60860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
60870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
60880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Allocate and return nByte bytes of zeroed memory using sqlite3_malloc().
60890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** If the allocation fails, set *pRc to SQLITE_NOMEM and return NULL.
60900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
60910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void *idxMalloc(int *pRc, int nByte){
60920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  void *pRet;
60930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( *pRc==SQLITE_OK );
60940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( nByte>0 );
60950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pRet = sqlite3_malloc(nByte);
60960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pRet ){
60970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    memset(pRet, 0, nByte);
60980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
60990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    *pRc = SQLITE_NOMEM;
61000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
61010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return pRet;
61020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
61030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
61040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
61050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Initialize an IdxHash hash table.
61060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
61070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void idxHashInit(IdxHash *pHash){
61080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  memset(pHash, 0, sizeof(IdxHash));
61090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
61100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
61110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
61120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Reset an IdxHash hash table.
61130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
61140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void idxHashClear(IdxHash *pHash){
61150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int i;
61160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(i=0; i<IDX_HASH_SIZE; i++){
61170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    IdxHashEntry *pEntry;
61180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    IdxHashEntry *pNext;
61190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    for(pEntry=pHash->aHash[i]; pEntry; pEntry=pNext){
61200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pNext = pEntry->pHashNext;
61210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_free(pEntry->zVal2);
61220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_free(pEntry);
61230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
61240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
61250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  memset(pHash, 0, sizeof(IdxHash));
61260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
61270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
61280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
61290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Return the index of the hash bucket that the string specified by the
61300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** arguments to this function belongs.
61310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
61320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int idxHashString(const char *z, int n){
61330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  unsigned int ret = 0;
61340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int i;
61350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(i=0; i<n; i++){
61360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ret += (ret<<3) + (unsigned char)(z[i]);
61370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
61380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return (int)(ret % IDX_HASH_SIZE);
61390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
61400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
61410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
61420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** If zKey is already present in the hash table, return non-zero and do
61430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** nothing. Otherwise, add an entry with key zKey and payload string zVal to
61440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** the hash table passed as the second argument.
61450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
61460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int idxHashAdd(
61470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int *pRc,
61480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxHash *pHash,
61490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zKey,
61500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zVal
61510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
61520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nKey = STRLEN(zKey);
61530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int iHash = idxHashString(zKey, nKey);
61540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nVal = (zVal ? STRLEN(zVal) : 0);
61550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxHashEntry *pEntry;
61560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( iHash>=0 );
61570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){
61580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){
61590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      return 1;
61600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
61610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
61620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pEntry = idxMalloc(pRc, sizeof(IdxHashEntry) + nKey+1 + nVal+1);
61630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pEntry ){
61640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pEntry->zKey = (char*)&pEntry[1];
61650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    memcpy(pEntry->zKey, zKey, nKey);
61660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( zVal ){
61670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pEntry->zVal = &pEntry->zKey[nKey+1];
61680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      memcpy(pEntry->zVal, zVal, nVal);
61690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
61700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pEntry->pHashNext = pHash->aHash[iHash];
61710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pHash->aHash[iHash] = pEntry;
61720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
61730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pEntry->pNext = pHash->pFirst;
61740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pHash->pFirst = pEntry;
61750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
61760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return 0;
61770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
61780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
61790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
61800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** If zKey/nKey is present in the hash table, return a pointer to the
61810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** hash-entry object.
61820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
61830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic IdxHashEntry *idxHashFind(IdxHash *pHash, const char *zKey, int nKey){
61840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int iHash;
61850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxHashEntry *pEntry;
61860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( nKey<0 ) nKey = STRLEN(zKey);
61870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  iHash = idxHashString(zKey, nKey);
61880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( iHash>=0 );
61890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){
61900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){
61910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      return pEntry;
61920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
61930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
61940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return 0;
61950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
61960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
61970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
61980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** If the hash table contains an entry with a key equal to the string
61990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** passed as the final two arguments to this function, return a pointer
62000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** to the payload string. Otherwise, if zKey/nKey is not present in the
62010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** hash table, return NULL.
62020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
62030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic const char *idxHashSearch(IdxHash *pHash, const char *zKey, int nKey){
62040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxHashEntry *pEntry = idxHashFind(pHash, zKey, nKey);
62050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pEntry ) return pEntry->zVal;
62060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return 0;
62070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
62080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
62090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
62100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Allocate and return a new IdxConstraint object. Set the IdxConstraint.zColl
62110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** variable to point to a copy of nul-terminated string zColl.
62120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
62130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic IdxConstraint *idxNewConstraint(int *pRc, const char *zColl){
62140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxConstraint *pNew;
62150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nColl = STRLEN(zColl);
62160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
62170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( *pRc==SQLITE_OK );
62180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pNew = (IdxConstraint*)idxMalloc(pRc, sizeof(IdxConstraint) * nColl + 1);
62190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pNew ){
62200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNew->zColl = (char*)&pNew[1];
62210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    memcpy(pNew->zColl, zColl, nColl+1);
62220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
62230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return pNew;
62240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
62250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
62260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
62270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** An error associated with database handle db has just occurred. Pass
62280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** the error message to callback function xOut.
62290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
62300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void idxDatabaseError(
62310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *db,                    /* Database handle */
62320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErrmsg                 /* Write error here */
62330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
62340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db));
62350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
62360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
62370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
62380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Prepare an SQL statement.
62390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
62400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int idxPrepareStmt(
62410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *db,                    /* Database handle to compile against */
62420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_stmt **ppStmt,          /* OUT: Compiled SQL statement */
62430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErrmsg,                /* OUT: sqlite3_malloc()ed error message */
62440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zSql                /* SQL statement to compile */
62450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
62460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
62470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc!=SQLITE_OK ){
62480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    *ppStmt = 0;
62490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    idxDatabaseError(db, pzErrmsg);
62500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
62510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
62520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
62530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
62540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
62550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Prepare an SQL statement using the results of a printf() formatting.
62560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
62570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int idxPrintfPrepareStmt(
62580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *db,                    /* Database handle to compile against */
62590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_stmt **ppStmt,          /* OUT: Compiled SQL statement */
62600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErrmsg,                /* OUT: sqlite3_malloc()ed error message */
62610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zFmt,               /* printf() format of SQL statement */
62620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ...                             /* Trailing printf() arguments */
62630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
62640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  va_list ap;
62650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;
62660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zSql;
62670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  va_start(ap, zFmt);
62680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zSql = sqlite3_vmprintf(zFmt, ap);
62690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( zSql==0 ){
62700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = SQLITE_NOMEM;
62710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
62720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = idxPrepareStmt(db, ppStmt, pzErrmsg, zSql);
62730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(zSql);
62740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
62750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  va_end(ap);
62760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
62770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
62780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
62790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
62800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*************************************************************************
62810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Beginning of virtual table implementation.
62820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
62830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct ExpertVtab ExpertVtab;
62840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct ExpertVtab {
62850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vtab base;
62860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxTable *pTab;
62870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3expert *pExpert;
62880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
62890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
62900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct ExpertCsr ExpertCsr;
62910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct ExpertCsr {
62920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vtab_cursor base;
62930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_stmt *pData;
62940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
62950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
62960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic char *expertDequote(const char *zIn){
62970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int n = STRLEN(zIn);
62980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zRet = sqlite3_malloc(n);
62990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
63000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( zIn[0]=='\'' );
63010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( zIn[n-1]=='\'' );
63020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
63030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( zRet ){
63040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int iOut = 0;
63050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int iIn = 0;
63060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    for(iIn=1; iIn<(n-1); iIn++){
63070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( zIn[iIn]=='\'' ){
63080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        assert( zIn[iIn+1]=='\'' );
63090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        iIn++;
63100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
63110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zRet[iOut++] = zIn[iIn];
63120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
63130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zRet[iOut] = '\0';
63140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
63150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
63160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return zRet;
63170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
63180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
63190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
63200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This function is the implementation of both the xConnect and xCreate
63210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** methods of the r-tree virtual table.
63220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
63230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   argv[0]   -> module name
63240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   argv[1]   -> database name
63250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   argv[2]   -> table name
63260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**   argv[...] -> column names...
63270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
63280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int expertConnect(
63290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *db,
63300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  void *pAux,
63310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int argc, const char *const*argv,
63320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vtab **ppVtab,
63330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErr
63340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
63350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3expert *pExpert = (sqlite3expert*)pAux;
63360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ExpertVtab *p = 0;
63370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;
63380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
63390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( argc!=4 ){
63400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    *pzErr = sqlite3_mprintf("internal error!");
63410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = SQLITE_ERROR;
63420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
63430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    char *zCreateTable = expertDequote(argv[3]);
63440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( zCreateTable ){
63450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = sqlite3_declare_vtab(db, zCreateTable);
63460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( rc==SQLITE_OK ){
63470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        p = idxMalloc(&rc, sizeof(ExpertVtab));
63480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
63490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( rc==SQLITE_OK ){
63500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        p->pExpert = pExpert;
63510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        p->pTab = pExpert->pTable;
63520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        assert( sqlite3_stricmp(p->pTab->zName, argv[2])==0 );
63530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
63540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_free(zCreateTable);
63550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
63560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = SQLITE_NOMEM;
63570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
63580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
63590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
63600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  *ppVtab = (sqlite3_vtab*)p;
63610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
63620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
63630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
63640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int expertDisconnect(sqlite3_vtab *pVtab){
63650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ExpertVtab *p = (ExpertVtab*)pVtab;
63660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(p);
63670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
63680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
63690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
63700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int expertBestIndex(sqlite3_vtab *pVtab, sqlite3_index_info *pIdxInfo){
63710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ExpertVtab *p = (ExpertVtab*)pVtab;
63720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
63730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int n = 0;
63740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxScan *pScan;
63750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const int opmask =
63760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_GT |
63770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    SQLITE_INDEX_CONSTRAINT_LT | SQLITE_INDEX_CONSTRAINT_GE |
63780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    SQLITE_INDEX_CONSTRAINT_LE;
63790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
63800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pScan = idxMalloc(&rc, sizeof(IdxScan));
63810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pScan ){
63820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int i;
63830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
63840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    /* Link the new scan object into the list */
63850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pScan->pTab = p->pTab;
63860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pScan->pNextScan = p->pExpert->pScan;
63870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    p->pExpert->pScan = pScan;
63880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
63890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    /* Add the constraints to the IdxScan object */
63900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    for(i=0; i<pIdxInfo->nConstraint; i++){
63910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i];
63920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( pCons->usable
63930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov       && pCons->iColumn>=0
63940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov       && p->pTab->aCol[pCons->iColumn].iPk==0
63950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov       && (pCons->op & opmask)
63960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      ){
63970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        IdxConstraint *pNew;
63980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        const char *zColl = sqlite3_vtab_collation(pIdxInfo, i);
63990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        pNew = idxNewConstraint(&rc, zColl);
64000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( pNew ){
64010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          pNew->iCol = pCons->iColumn;
64020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){
64030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            pNew->pNext = pScan->pEq;
64040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            pScan->pEq = pNew;
64050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }else{
64060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            pNew->bRange = 1;
64070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            pNew->pNext = pScan->pRange;
64080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            pScan->pRange = pNew;
64090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
64100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
64110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        n++;
64120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        pIdxInfo->aConstraintUsage[i].argvIndex = n;
64130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
64140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
64150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
64160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    /* Add the ORDER BY to the IdxScan object */
64170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    for(i=pIdxInfo->nOrderBy-1; i>=0; i--){
64180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int iCol = pIdxInfo->aOrderBy[i].iColumn;
64190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( iCol>=0 ){
64200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        IdxConstraint *pNew = idxNewConstraint(&rc, p->pTab->aCol[iCol].zColl);
64210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( pNew ){
64220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          pNew->iCol = iCol;
64230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          pNew->bDesc = pIdxInfo->aOrderBy[i].desc;
64240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          pNew->pNext = pScan->pOrder;
64250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          pNew->pLink = pScan->pOrder;
64260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          pScan->pOrder = pNew;
64270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          n++;
64280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
64290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
64300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
64310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
64320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
64330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pIdxInfo->estimatedCost = 1000000.0 / (n+1);
64340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
64350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
64360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
64370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int expertUpdate(
64380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vtab *pVtab,
64390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nData,
64400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_value **azData,
64410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite_int64 *pRowid
64420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
64430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)pVtab;
64440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)nData;
64450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)azData;
64460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)pRowid;
64470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
64480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
64490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
64500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
64510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Virtual table module xOpen method.
64520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
64530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int expertOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
64540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
64550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ExpertCsr *pCsr;
64560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)pVTab;
64570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCsr = idxMalloc(&rc, sizeof(ExpertCsr));
64580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  *ppCursor = (sqlite3_vtab_cursor*)pCsr;
64590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
64600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
64610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
64620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
64630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Virtual table module xClose method.
64640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
64650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int expertClose(sqlite3_vtab_cursor *cur){
64660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ExpertCsr *pCsr = (ExpertCsr*)cur;
64670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_finalize(pCsr->pData);
64680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(pCsr);
64690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
64700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
64710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
64720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
64730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Virtual table module xEof method.
64740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
64750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Return non-zero if the cursor does not currently point to a valid
64760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** record (i.e if the scan has finished), or zero otherwise.
64770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
64780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int expertEof(sqlite3_vtab_cursor *cur){
64790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ExpertCsr *pCsr = (ExpertCsr*)cur;
64800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return pCsr->pData==0;
64810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
64820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
64830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
64840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Virtual table module xNext method.
64850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
64860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int expertNext(sqlite3_vtab_cursor *cur){
64870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ExpertCsr *pCsr = (ExpertCsr*)cur;
64880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
64890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
64900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( pCsr->pData );
64910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = sqlite3_step(pCsr->pData);
64920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc!=SQLITE_ROW ){
64930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = sqlite3_finalize(pCsr->pData);
64940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCsr->pData = 0;
64950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
64960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = SQLITE_OK;
64970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
64980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
64990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
65000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
65010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
65020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
65030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Virtual table module xRowid method.
65040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
65050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int expertRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
65060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)cur;
65070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  *pRowid = 0;
65080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
65090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
65100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
65110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
65120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Virtual table module xColumn method.
65130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
65140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int expertColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
65150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ExpertCsr *pCsr = (ExpertCsr*)cur;
65160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_value *pVal;
65170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pVal = sqlite3_column_value(pCsr->pData, i);
65180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pVal ){
65190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_result_value(ctx, pVal);
65200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
65210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
65220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
65230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
65240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
65250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Virtual table module xFilter method.
65260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
65270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int expertFilter(
65280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_vtab_cursor *cur,
65290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int idxNum, const char *idxStr,
65300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int argc, sqlite3_value **argv
65310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
65320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ExpertCsr *pCsr = (ExpertCsr*)cur;
65330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ExpertVtab *pVtab = (ExpertVtab*)(cur->pVtab);
65340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3expert *pExpert = pVtab->pExpert;
65350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;
65360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
65370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)idxNum;
65380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)idxStr;
65390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)argc;
65400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)argv;
65410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = sqlite3_finalize(pCsr->pData);
65420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pCsr->pData = 0;
65430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
65440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = idxPrintfPrepareStmt(pExpert->db, &pCsr->pData, &pVtab->base.zErrMsg,
65450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "SELECT * FROM main.%Q WHERE sample()", pVtab->pTab->zName
65460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    );
65470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
65480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
65490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
65500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = expertNext(cur);
65510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
65520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
65530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
65540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
65550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int idxRegisterVtab(sqlite3expert *p){
65560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  static sqlite3_module expertModule = {
65570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    2,                            /* iVersion */
65580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    expertConnect,                /* xCreate - create a table */
65590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    expertConnect,                /* xConnect - connect to an existing table */
65600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    expertBestIndex,              /* xBestIndex - Determine search strategy */
65610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    expertDisconnect,             /* xDisconnect - Disconnect from a table */
65620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    expertDisconnect,             /* xDestroy - Drop a table */
65630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    expertOpen,                   /* xOpen - open a cursor */
65640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    expertClose,                  /* xClose - close a cursor */
65650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    expertFilter,                 /* xFilter - configure scan constraints */
65660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    expertNext,                   /* xNext - advance a cursor */
65670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    expertEof,                    /* xEof */
65680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    expertColumn,                 /* xColumn - read data */
65690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    expertRowid,                  /* xRowid - read data */
65700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    expertUpdate,                 /* xUpdate - write data */
65710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0,                            /* xBegin - begin transaction */
65720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0,                            /* xSync - sync transaction */
65730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0,                            /* xCommit - commit transaction */
65740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0,                            /* xRollback - rollback transaction */
65750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0,                            /* xFindFunction - function overloading */
65760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0,                            /* xRename - rename the table */
65770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0,                            /* xSavepoint */
65780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0,                            /* xRelease */
65790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    0,                            /* xRollbackTo */
65800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  };
65810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
65820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return sqlite3_create_module(p->dbv, "expert", &expertModule, (void*)p);
65830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
65840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
65850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** End of virtual table implementation.
65860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*************************************************************************/
65870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
65880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Finalize SQL statement pStmt. If (*pRc) is SQLITE_OK when this function
65890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** is called, set it to the return value of sqlite3_finalize() before
65900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** returning. Otherwise, discard the sqlite3_finalize() return value.
65910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
65920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void idxFinalize(int *pRc, sqlite3_stmt *pStmt){
65930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = sqlite3_finalize(pStmt);
65940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( *pRc==SQLITE_OK ) *pRc = rc;
65950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
65960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
65970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
65980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Attempt to allocate an IdxTable structure corresponding to table zTab
65990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** in the main database of connection db. If successful, set (*ppOut) to
66000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** point to the new object and return SQLITE_OK. Otherwise, return an
66010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** SQLite error code and set (*ppOut) to NULL. In this case *pzErrmsg may be
66020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** set to point to an error string.
66030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
66040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** It is the responsibility of the caller to eventually free either the
66050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** IdxTable object or error message using sqlite3_free().
66060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
66070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int idxGetTableInfo(
66080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *db,                    /* Database connection to read details from */
66090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zTab,               /* Table name */
66100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxTable **ppOut,               /* OUT: New object (if successful) */
66110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErrmsg                 /* OUT: Error message (if not) */
66120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
66130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_stmt *p1 = 0;
66140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nCol = 0;
66150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nTab = STRLEN(zTab);
66160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nByte = sizeof(IdxTable) + nTab + 1;
66170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxTable *pNew = 0;
66180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc, rc2;
66190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *pCsr = 0;
66200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
66210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_info=%Q", zTab);
66220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
66230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const char *zCol = (const char*)sqlite3_column_text(p1, 1);
66240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    nByte += 1 + STRLEN(zCol);
66250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = sqlite3_table_column_metadata(
66260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        db, "main", zTab, zCol, 0, &zCol, 0, 0, 0
66270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    );
66280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    nByte += 1 + STRLEN(zCol);
66290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    nCol++;
66300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
66310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc2 = sqlite3_reset(p1);
66320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ) rc = rc2;
66330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
66340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  nByte += sizeof(IdxColumn) * nCol;
66350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
66360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNew = idxMalloc(&rc, nByte);
66370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
66380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
66390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNew->aCol = (IdxColumn*)&pNew[1];
66400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNew->nCol = nCol;
66410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCsr = (char*)&pNew->aCol[nCol];
66420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
66430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
66440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  nCol = 0;
66450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
66460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const char *zCol = (const char*)sqlite3_column_text(p1, 1);
66470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int nCopy = STRLEN(zCol) + 1;
66480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNew->aCol[nCol].zName = pCsr;
66490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNew->aCol[nCol].iPk = sqlite3_column_int(p1, 5);
66500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    memcpy(pCsr, zCol, nCopy);
66510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCsr += nCopy;
66520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
66530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = sqlite3_table_column_metadata(
66540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        db, "main", zTab, zCol, 0, &zCol, 0, 0, 0
66550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    );
66560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( rc==SQLITE_OK ){
66570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      nCopy = STRLEN(zCol) + 1;
66580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pNew->aCol[nCol].zColl = pCsr;
66590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      memcpy(pCsr, zCol, nCopy);
66600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pCsr += nCopy;
66610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
66620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
66630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    nCol++;
66640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
66650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  idxFinalize(&rc, p1);
66660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
66670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc!=SQLITE_OK ){
66680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(pNew);
66690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNew = 0;
66700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
66710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNew->zName = pCsr;
66720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    memcpy(pNew->zName, zTab, nTab+1);
66730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
66740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
66750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  *ppOut = pNew;
66760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
66770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
66780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
66790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
66800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This function is a no-op if *pRc is set to anything other than
66810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** SQLITE_OK when it is called.
66820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
66830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** If *pRc is initially set to SQLITE_OK, then the text specified by
66840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** the printf() style arguments is appended to zIn and the result returned
66850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** in a buffer allocated by sqlite3_malloc(). sqlite3_free() is called on
66860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** zIn before returning.
66870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
66880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic char *idxAppendText(int *pRc, char *zIn, const char *zFmt, ...){
66890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  va_list ap;
66900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zAppend = 0;
66910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zRet = 0;
66920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nIn = zIn ? STRLEN(zIn) : 0;
66930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nAppend = 0;
66940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  va_start(ap, zFmt);
66950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( *pRc==SQLITE_OK ){
66960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zAppend = sqlite3_vmprintf(zFmt, ap);
66970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( zAppend ){
66980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      nAppend = STRLEN(zAppend);
66990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zRet = (char*)sqlite3_malloc(nIn + nAppend + 1);
67000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
67010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( zAppend && zRet ){
67020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( nIn ) memcpy(zRet, zIn, nIn);
67030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      memcpy(&zRet[nIn], zAppend, nAppend+1);
67040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
67050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_free(zRet);
67060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zRet = 0;
67070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      *pRc = SQLITE_NOMEM;
67080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
67090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(zAppend);
67100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(zIn);
67110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
67120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  va_end(ap);
67130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return zRet;
67140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
67150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
67160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
67170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Return true if zId must be quoted in order to use it as an SQL
67180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** identifier, or false otherwise.
67190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
67200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int idxIdentifierRequiresQuotes(const char *zId){
67210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int i;
67220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(i=0; zId[i]; i++){
67230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( !(zId[i]=='_')
67240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov     && !(zId[i]>='0' && zId[i]<='9')
67250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov     && !(zId[i]>='a' && zId[i]<='z')
67260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov     && !(zId[i]>='A' && zId[i]<='Z')
67270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ){
67280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      return 1;
67290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
67300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
67310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return 0;
67320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
67330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
67340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
67350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This function appends an index column definition suitable for constraint
67360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** pCons to the string passed as zIn and returns the result.
67370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
67380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic char *idxAppendColDefn(
67390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int *pRc,                       /* IN/OUT: Error code */
67400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zIn,                      /* Column defn accumulated so far */
67410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxTable *pTab,                 /* Table index will be created on */
67420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxConstraint *pCons
67430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
67440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zRet = zIn;
67450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxColumn *p = &pTab->aCol[pCons->iCol];
67460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( zRet ) zRet = idxAppendText(pRc, zRet, ", ");
67470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
67480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( idxIdentifierRequiresQuotes(p->zName) ){
67490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zRet = idxAppendText(pRc, zRet, "%Q", p->zName);
67500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
67510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zRet = idxAppendText(pRc, zRet, "%s", p->zName);
67520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
67530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
67540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( sqlite3_stricmp(p->zColl, pCons->zColl) ){
67550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( idxIdentifierRequiresQuotes(pCons->zColl) ){
67560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zRet = idxAppendText(pRc, zRet, " COLLATE %Q", pCons->zColl);
67570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
67580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zRet = idxAppendText(pRc, zRet, " COLLATE %s", pCons->zColl);
67590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
67600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
67610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
67620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pCons->bDesc ){
67630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zRet = idxAppendText(pRc, zRet, " DESC");
67640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
67650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return zRet;
67660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
67670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
67680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
67690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Search database dbm for an index compatible with the one idxCreateFromCons()
67700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** would create from arguments pScan, pEq and pTail. If no error occurs and
67710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** such an index is found, return non-zero. Or, if no such index is found,
67720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** return zero.
67730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
67740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** If an error occurs, set *pRc to an SQLite error code and return zero.
67750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
67760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int idxFindCompatible(
67770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int *pRc,                       /* OUT: Error code */
67780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3* dbm,                   /* Database to search */
67790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxScan *pScan,                 /* Scan for table to search for index on */
67800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxConstraint *pEq,             /* List of == constraints */
67810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxConstraint *pTail            /* List of range constraints */
67820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
67830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zTbl = pScan->pTab->zName;
67840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_stmt *pIdxList = 0;
67850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxConstraint *pIter;
67860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nEq = 0;                    /* Number of elements in pEq */
67870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;
67880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
67890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* Count the elements in list pEq */
67900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(pIter=pEq; pIter; pIter=pIter->pLink) nEq++;
67910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
67920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = idxPrintfPrepareStmt(dbm, &pIdxList, 0, "PRAGMA index_list=%Q", zTbl);
67930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  while( rc==SQLITE_OK && sqlite3_step(pIdxList)==SQLITE_ROW ){
67940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int bMatch = 1;
67950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    IdxConstraint *pT = pTail;
67960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_stmt *pInfo = 0;
67970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const char *zIdx = (const char*)sqlite3_column_text(pIdxList, 1);
67980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
67990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    /* Zero the IdxConstraint.bFlag values in the pEq list */
68000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    for(pIter=pEq; pIter; pIter=pIter->pLink) pIter->bFlag = 0;
68010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
68020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = idxPrintfPrepareStmt(dbm, &pInfo, 0, "PRAGMA index_xInfo=%Q", zIdx);
68030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    while( rc==SQLITE_OK && sqlite3_step(pInfo)==SQLITE_ROW ){
68040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int iIdx = sqlite3_column_int(pInfo, 0);
68050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int iCol = sqlite3_column_int(pInfo, 1);
68060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      const char *zColl = (const char*)sqlite3_column_text(pInfo, 4);
68070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
68080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( iIdx<nEq ){
68090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        for(pIter=pEq; pIter; pIter=pIter->pLink){
68100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( pIter->bFlag ) continue;
68110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( pIter->iCol!=iCol ) continue;
68120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( sqlite3_stricmp(pIter->zColl, zColl) ) continue;
68130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          pIter->bFlag = 1;
68140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          break;
68150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
68160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( pIter==0 ){
68170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          bMatch = 0;
68180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          break;
68190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
68200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else{
68210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( pT ){
68220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( pT->iCol!=iCol || sqlite3_stricmp(pT->zColl, zColl) ){
68230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            bMatch = 0;
68240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            break;
68250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
68260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          pT = pT->pLink;
68270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
68280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
68290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
68300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    idxFinalize(&rc, pInfo);
68310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
68320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( rc==SQLITE_OK && bMatch ){
68330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_finalize(pIdxList);
68340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      return 1;
68350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
68360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
68370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  idxFinalize(&rc, pIdxList);
68380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
68390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  *pRc = rc;
68400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return 0;
68410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
68420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
68430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int idxCreateFromCons(
68440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3expert *p,
68450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxScan *pScan,
68460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxConstraint *pEq,
68470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxConstraint *pTail
68480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
68490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *dbm = p->dbm;
68500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
68510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( (pEq || pTail) && 0==idxFindCompatible(&rc, dbm, pScan, pEq, pTail) ){
68520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    IdxTable *pTab = pScan->pTab;
68530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    char *zCols = 0;
68540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    char *zIdx = 0;
68550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    IdxConstraint *pCons;
68560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    unsigned int h = 0;
68570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const char *zFmt;
68580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
68590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    for(pCons=pEq; pCons; pCons=pCons->pLink){
68600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zCols = idxAppendColDefn(&rc, zCols, pTab, pCons);
68610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
68620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    for(pCons=pTail; pCons; pCons=pCons->pLink){
68630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zCols = idxAppendColDefn(&rc, zCols, pTab, pCons);
68640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
68650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
68660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( rc==SQLITE_OK ){
68670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      /* Hash the list of columns to come up with a name for the index */
68680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      const char *zTable = pScan->pTab->zName;
68690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      char *zName;                /* Index name */
68700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int i;
68710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      for(i=0; zCols[i]; i++){
68720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        h += ((h<<3) + zCols[i]);
68730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
68740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zName = sqlite3_mprintf("%s_idx_%08x", zTable, h);
68750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( zName==0 ){
68760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        rc = SQLITE_NOMEM;
68770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else{
68780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( idxIdentifierRequiresQuotes(zTable) ){
68790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          zFmt = "CREATE INDEX '%q' ON %Q(%s)";
68800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }else{
68810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          zFmt = "CREATE INDEX %s ON %s(%s)";
68820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
68830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        zIdx = sqlite3_mprintf(zFmt, zName, zTable, zCols);
68840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( !zIdx ){
68850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          rc = SQLITE_NOMEM;
68860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }else{
68870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          rc = sqlite3_exec(dbm, zIdx, 0, 0, p->pzErrmsg);
68880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          idxHashAdd(&rc, &p->hIdx, zName, zIdx);
68890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
68900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_free(zName);
68910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_free(zIdx);
68920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
68930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
68940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
68950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(zCols);
68960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
68970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
68980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
68990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
69000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
69010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Return true if list pList (linked by IdxConstraint.pLink) contains
69020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** a constraint compatible with *p. Otherwise return false.
69030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
69040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int idxFindConstraint(IdxConstraint *pList, IdxConstraint *p){
69050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxConstraint *pCmp;
69060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(pCmp=pList; pCmp; pCmp=pCmp->pLink){
69070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( p->iCol==pCmp->iCol ) return 1;
69080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
69090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return 0;
69100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
69110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
69120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int idxCreateFromWhere(
69130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3expert *p,
69140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxScan *pScan,                 /* Create indexes for this scan */
69150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxConstraint *pTail            /* range/ORDER BY constraints for inclusion */
69160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
69170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxConstraint *p1 = 0;
69180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxConstraint *pCon;
69190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;
69200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
69210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* Gather up all the == constraints. */
69220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(pCon=pScan->pEq; pCon; pCon=pCon->pNext){
69230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){
69240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pCon->pLink = p1;
69250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      p1 = pCon;
69260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
69270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
69280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
69290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* Create an index using the == constraints collected above. And the
69300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ** range constraint/ORDER BY terms passed in by the caller, if any. */
69310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = idxCreateFromCons(p, pScan, p1, pTail);
69320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
69330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* If no range/ORDER BY passed by the caller, create a version of the
69340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ** index for each range constraint.  */
69350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pTail==0 ){
69360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    for(pCon=pScan->pRange; rc==SQLITE_OK && pCon; pCon=pCon->pNext){
69370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      assert( pCon->pLink==0 );
69380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){
69390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        rc = idxCreateFromCons(p, pScan, p1, pCon);
69400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
69410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
69420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
69430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
69440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
69450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
69460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
69470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
69480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Create candidate indexes in database [dbm] based on the data in
69490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** linked-list pScan.
69500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
69510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int idxCreateCandidates(sqlite3expert *p){
69520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
69530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxScan *pIter;
69540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
69550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(pIter=p->pScan; pIter && rc==SQLITE_OK; pIter=pIter->pNextScan){
69560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = idxCreateFromWhere(p, pIter, 0);
69570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( rc==SQLITE_OK && pIter->pOrder ){
69580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = idxCreateFromWhere(p, pIter, pIter->pOrder);
69590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
69600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
69610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
69620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
69630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
69640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
69650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
69660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Free all elements of the linked list starting at pConstraint.
69670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
69680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void idxConstraintFree(IdxConstraint *pConstraint){
69690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxConstraint *pNext;
69700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxConstraint *p;
69710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
69720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(p=pConstraint; p; p=pNext){
69730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNext = p->pNext;
69740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(p);
69750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
69760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
69770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
69780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
69790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Free all elements of the linked list starting from pScan up until pLast
69800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** (pLast is not freed).
69810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
69820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void idxScanFree(IdxScan *pScan, IdxScan *pLast){
69830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxScan *p;
69840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxScan *pNext;
69850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(p=pScan; p!=pLast; p=pNext){
69860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNext = p->pNextScan;
69870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    idxConstraintFree(p->pOrder);
69880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    idxConstraintFree(p->pEq);
69890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    idxConstraintFree(p->pRange);
69900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(p);
69910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
69920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
69930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
69940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
69950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Free all elements of the linked list starting from pStatement up
69960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** until pLast (pLast is not freed).
69970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
69980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void idxStatementFree(IdxStatement *pStatement, IdxStatement *pLast){
69990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxStatement *p;
70000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxStatement *pNext;
70010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(p=pStatement; p!=pLast; p=pNext){
70020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNext = p->pNext;
70030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(p->zEQP);
70040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(p->zIdx);
70050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(p);
70060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
70070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
70080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
70090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
70100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Free the linked list of IdxTable objects starting at pTab.
70110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
70120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void idxTableFree(IdxTable *pTab){
70130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxTable *pIter;
70140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxTable *pNext;
70150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(pIter=pTab; pIter; pIter=pNext){
70160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNext = pIter->pNext;
70170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(pIter);
70180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
70190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
70200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
70210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
70220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Free the linked list of IdxWrite objects starting at pTab.
70230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
70240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void idxWriteFree(IdxWrite *pTab){
70250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxWrite *pIter;
70260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxWrite *pNext;
70270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(pIter=pTab; pIter; pIter=pNext){
70280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNext = pIter->pNext;
70290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(pIter);
70300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
70310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
70320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
70330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
70340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
70350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
70360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This function is called after candidate indexes have been created. It
70370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** runs all the queries to see which indexes they prefer, and populates
70380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** IdxStatement.zIdx and IdxStatement.zEQP with the results.
70390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
70400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovint idxFindIndexes(
70410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3expert *p,
70420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErr                         /* OUT: Error message (sqlite3_malloc) */
70430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
70440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxStatement *pStmt;
70450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *dbm = p->dbm;
70460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
70470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
70480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxHash hIdx;
70490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  idxHashInit(&hIdx);
70500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
70510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(pStmt=p->pStatement; rc==SQLITE_OK && pStmt; pStmt=pStmt->pNext){
70520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    IdxHashEntry *pEntry;
70530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_stmt *pExplain = 0;
70540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    idxHashClear(&hIdx);
70550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = idxPrintfPrepareStmt(dbm, &pExplain, pzErr,
70560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "EXPLAIN QUERY PLAN %s", pStmt->zSql
70570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    );
70580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    while( rc==SQLITE_OK && sqlite3_step(pExplain)==SQLITE_ROW ){
70590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int iSelectid = sqlite3_column_int(pExplain, 0);
70600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int iOrder = sqlite3_column_int(pExplain, 1);
70610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int iFrom = sqlite3_column_int(pExplain, 2);
70620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3);
70630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int nDetail = STRLEN(zDetail);
70640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int i;
70650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
70660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      for(i=0; i<nDetail; i++){
70670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        const char *zIdx = 0;
70680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){
70690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          zIdx = &zDetail[i+13];
70700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }else if( memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0 ){
70710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          zIdx = &zDetail[i+22];
70720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
70730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( zIdx ){
70740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          const char *zSql;
70750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          int nIdx = 0;
70760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          while( zIdx[nIdx]!='\0' && (zIdx[nIdx]!=' ' || zIdx[nIdx+1]!='(') ){
70770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            nIdx++;
70780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
70790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          zSql = idxHashSearch(&p->hIdx, zIdx, nIdx);
70800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( zSql ){
70810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            idxHashAdd(&rc, &hIdx, zSql, 0);
70820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            if( rc ) goto find_indexes_out;
70830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
70840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          break;
70850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
70860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
70870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
70880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pStmt->zEQP = idxAppendText(&rc, pStmt->zEQP, "%d|%d|%d|%s\n",
70890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          iSelectid, iOrder, iFrom, zDetail
70900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      );
70910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
70920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
70930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    for(pEntry=hIdx.pFirst; pEntry; pEntry=pEntry->pNext){
70940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pStmt->zIdx = idxAppendText(&rc, pStmt->zIdx, "%s;\n", pEntry->zKey);
70950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
70960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
70970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    idxFinalize(&rc, pExplain);
70980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
70990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
71000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov find_indexes_out:
71010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  idxHashClear(&hIdx);
71020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
71030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
71040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
71050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int idxAuthCallback(
71060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  void *pCtx,
71070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int eOp,
71080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *z3,
71090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *z4,
71100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zDb,
71110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zTrigger
71120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
71130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
71140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)z4;
71150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)zTrigger;
71160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE || eOp==SQLITE_DELETE ){
71170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( sqlite3_stricmp(zDb, "main")==0 ){
71180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3expert *p = (sqlite3expert*)pCtx;
71190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      IdxTable *pTab;
71200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      for(pTab=p->pTable; pTab; pTab=pTab->pNext){
71210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( 0==sqlite3_stricmp(z3, pTab->zName) ) break;
71220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
71230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( pTab ){
71240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        IdxWrite *pWrite;
71250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        for(pWrite=p->pWrite; pWrite; pWrite=pWrite->pNext){
71260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( pWrite->pTab==pTab && pWrite->eOp==eOp ) break;
71270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
71280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( pWrite==0 ){
71290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          pWrite = idxMalloc(&rc, sizeof(IdxWrite));
71300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( rc==SQLITE_OK ){
71310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            pWrite->pTab = pTab;
71320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            pWrite->eOp = eOp;
71330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            pWrite->pNext = p->pWrite;
71340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            p->pWrite = pWrite;
71350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
71360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
71370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
71380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
71390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
71400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
71410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
71420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
71430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int idxProcessOneTrigger(
71440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3expert *p,
71450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxWrite *pWrite,
71460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErr
71470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
71480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  static const char *zInt = UNIQUE_TABLE_NAME;
71490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  static const char *zDrop = "DROP TABLE " UNIQUE_TABLE_NAME;
71500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxTable *pTab = pWrite->pTab;
71510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zTab = pTab->zName;
71520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zSql =
71530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "SELECT 'CREATE TEMP' || substr(sql, 7) FROM sqlite_master "
71540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "WHERE tbl_name = %Q AND type IN ('table', 'trigger') "
71550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "ORDER BY type;";
71560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_stmt *pSelect = 0;
71570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
71580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zWrite = 0;
71590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
71600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* Create the table and its triggers in the temp schema */
71610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = idxPrintfPrepareStmt(p->db, &pSelect, pzErr, zSql, zTab, zTab);
71620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSelect) ){
71630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const char *zCreate = (const char*)sqlite3_column_text(pSelect, 0);
71640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = sqlite3_exec(p->dbv, zCreate, 0, 0, pzErr);
71650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
71660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  idxFinalize(&rc, pSelect);
71670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
71680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* Rename the table in the temp schema to zInt */
71690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
71700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    char *z = sqlite3_mprintf("ALTER TABLE temp.%Q RENAME TO %Q", zTab, zInt);
71710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( z==0 ){
71720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = SQLITE_NOMEM;
71730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
71740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = sqlite3_exec(p->dbv, z, 0, 0, pzErr);
71750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_free(z);
71760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
71770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
71780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
71790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  switch( pWrite->eOp ){
71800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case SQLITE_INSERT: {
71810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int i;
71820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zWrite = idxAppendText(&rc, zWrite, "INSERT INTO %Q VALUES(", zInt);
71830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      for(i=0; i<pTab->nCol; i++){
71840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        zWrite = idxAppendText(&rc, zWrite, "%s?", i==0 ? "" : ", ");
71850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
71860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zWrite = idxAppendText(&rc, zWrite, ")");
71870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
71880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
71890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case SQLITE_UPDATE: {
71900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int i;
71910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zWrite = idxAppendText(&rc, zWrite, "UPDATE %Q SET ", zInt);
71920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      for(i=0; i<pTab->nCol; i++){
71930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        zWrite = idxAppendText(&rc, zWrite, "%s%Q=?", i==0 ? "" : ", ",
71940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            pTab->aCol[i].zName
71950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        );
71960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
71970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
71980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
71990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    default: {
72000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      assert( pWrite->eOp==SQLITE_DELETE );
72010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( rc==SQLITE_OK ){
72020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        zWrite = sqlite3_mprintf("DELETE FROM %Q", zInt);
72030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( zWrite==0 ) rc = SQLITE_NOMEM;
72040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
72050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
72060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
72070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
72080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
72090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_stmt *pX = 0;
72100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = sqlite3_prepare_v2(p->dbv, zWrite, -1, &pX, 0);
72110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    idxFinalize(&rc, pX);
72120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( rc!=SQLITE_OK ){
72130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      idxDatabaseError(p->dbv, pzErr);
72140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
72150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
72160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(zWrite);
72170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
72180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
72190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = sqlite3_exec(p->dbv, zDrop, 0, 0, pzErr);
72200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
72210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
72220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
72230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
72240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
72250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int idxProcessTriggers(sqlite3expert *p, char **pzErr){
72260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
72270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxWrite *pEnd = 0;
72280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxWrite *pFirst = p->pWrite;
72290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
72300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  while( rc==SQLITE_OK && pFirst!=pEnd ){
72310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    IdxWrite *pIter;
72320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    for(pIter=pFirst; rc==SQLITE_OK && pIter!=pEnd; pIter=pIter->pNext){
72330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = idxProcessOneTrigger(p, pIter, pzErr);
72340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
72350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pEnd = pFirst;
72360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pFirst = p->pWrite;
72370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
72380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
72390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
72400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
72410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
72420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
72430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
72440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = idxRegisterVtab(p);
72450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_stmt *pSchema = 0;
72460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
72470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* For each table in the main db schema:
72480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  **
72490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  **   1) Add an entry to the p->pTable list, and
72500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  **   2) Create the equivalent virtual table in dbv.
72510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  */
72520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = idxPrepareStmt(p->db, &pSchema, pzErrmsg,
72530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      "SELECT type, name, sql, 1 FROM sqlite_master "
72540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%%' "
72550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      " UNION ALL "
72560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      "SELECT type, name, sql, 2 FROM sqlite_master "
72570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      "WHERE type = 'trigger'"
72580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      "  AND tbl_name IN(SELECT name FROM sqlite_master WHERE type = 'view') "
72590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      "ORDER BY 4, 1"
72600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  );
72610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSchema) ){
72620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const char *zType = (const char*)sqlite3_column_text(pSchema, 0);
72630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const char *zName = (const char*)sqlite3_column_text(pSchema, 1);
72640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const char *zSql = (const char*)sqlite3_column_text(pSchema, 2);
72650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
72660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( zType[0]=='v' || zType[1]=='r' ){
72670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg);
72680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
72690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      IdxTable *pTab;
72700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg);
72710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( rc==SQLITE_OK ){
72720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        int i;
72730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        char *zInner = 0;
72740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        char *zOuter = 0;
72750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        pTab->pNext = p->pTable;
72760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        p->pTable = pTab;
72770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
72780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        /* The statement the vtab will pass to sqlite3_declare_vtab() */
72790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        zInner = idxAppendText(&rc, 0, "CREATE TABLE x(");
72800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        for(i=0; i<pTab->nCol; i++){
72810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          zInner = idxAppendText(&rc, zInner, "%s%Q COLLATE %s",
72820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov              (i==0 ? "" : ", "), pTab->aCol[i].zName, pTab->aCol[i].zColl
72830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          );
72840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
72850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        zInner = idxAppendText(&rc, zInner, ")");
72860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
72870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        /* The CVT statement to create the vtab */
72880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        zOuter = idxAppendText(&rc, 0,
72890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            "CREATE VIRTUAL TABLE %Q USING expert(%Q)", zName, zInner
72900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        );
72910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( rc==SQLITE_OK ){
72920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          rc = sqlite3_exec(p->dbv, zOuter, 0, 0, pzErrmsg);
72930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
72940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_free(zInner);
72950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_free(zOuter);
72960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
72970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
72980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
72990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  idxFinalize(&rc, pSchema);
73000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
73010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
73020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
73030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct IdxSampleCtx {
73040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int iTarget;
73050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  double target;                  /* Target nRet/nRow value */
73060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  double nRow;                    /* Number of rows seen */
73070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  double nRet;                    /* Number of rows returned */
73080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
73090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
73100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void idxSampleFunc(
73110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_context *pCtx,
73120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int argc,
73130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_value **argv
73140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
73150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  struct IdxSampleCtx *p = (struct IdxSampleCtx*)sqlite3_user_data(pCtx);
73160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int bRet;
73170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
73180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)argv;
73190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( argc==0 );
73200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( p->nRow==0.0 ){
73210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    bRet = 1;
73220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
73230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    bRet = (p->nRet / p->nRow) <= p->target;
73240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( bRet==0 ){
73250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      unsigned short rnd;
73260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_randomness(2, (void*)&rnd);
73270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      bRet = ((int)rnd % 100) <= p->iTarget;
73280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
73290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
73300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
73310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_result_int(pCtx, bRet);
73320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  p->nRow += 1.0;
73330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  p->nRet += (double)bRet;
73340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
73350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
73360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct IdxRemCtx {
73370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nSlot;
73380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  struct IdxRemSlot {
73390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int eType;                    /* SQLITE_NULL, INTEGER, REAL, TEXT, BLOB */
73400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    i64 iVal;                     /* SQLITE_INTEGER value */
73410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    double rVal;                  /* SQLITE_FLOAT value */
73420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int nByte;                    /* Bytes of space allocated at z */
73430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int n;                        /* Size of buffer z */
73440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    char *z;                      /* SQLITE_TEXT/BLOB value */
73450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  } aSlot[1];
73460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
73470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
73480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
73490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Implementation of scalar function rem().
73500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
73510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void idxRemFunc(
73520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_context *pCtx,
73530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int argc,
73540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_value **argv
73550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
73560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  struct IdxRemCtx *p = (struct IdxRemCtx*)sqlite3_user_data(pCtx);
73570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  struct IdxRemSlot *pSlot;
73580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int iSlot;
73590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( argc==2 );
73600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
73610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  iSlot = sqlite3_value_int(argv[0]);
73620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( iSlot<=p->nSlot );
73630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pSlot = &p->aSlot[iSlot];
73640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
73650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  switch( pSlot->eType ){
73660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case SQLITE_NULL:
73670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      /* no-op */
73680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
73690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
73700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case SQLITE_INTEGER:
73710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_int64(pCtx, pSlot->iVal);
73720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
73730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
73740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case SQLITE_FLOAT:
73750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_double(pCtx, pSlot->rVal);
73760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
73770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
73780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case SQLITE_BLOB:
73790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_blob(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT);
73800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
73810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
73820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case SQLITE_TEXT:
73830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_text(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT);
73840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
73850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
73860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
73870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pSlot->eType = sqlite3_value_type(argv[1]);
73880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  switch( pSlot->eType ){
73890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case SQLITE_NULL:
73900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      /* no-op */
73910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
73920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
73930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case SQLITE_INTEGER:
73940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pSlot->iVal = sqlite3_value_int64(argv[1]);
73950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
73960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
73970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case SQLITE_FLOAT:
73980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pSlot->rVal = sqlite3_value_double(argv[1]);
73990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
74000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
74010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case SQLITE_BLOB:
74020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case SQLITE_TEXT: {
74030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int nByte = sqlite3_value_bytes(argv[1]);
74040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( nByte>pSlot->nByte ){
74050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        char *zNew = (char*)sqlite3_realloc(pSlot->z, nByte*2);
74060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( zNew==0 ){
74070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          sqlite3_result_error_nomem(pCtx);
74080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          return;
74090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
74100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        pSlot->nByte = nByte*2;
74110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        pSlot->z = zNew;
74120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
74130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pSlot->n = nByte;
74140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( pSlot->eType==SQLITE_BLOB ){
74150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        memcpy(pSlot->z, sqlite3_value_blob(argv[1]), nByte);
74160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else{
74170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        memcpy(pSlot->z, sqlite3_value_text(argv[1]), nByte);
74180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
74190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
74200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
74210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
74220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
74230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
74240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int idxLargestIndex(sqlite3 *db, int *pnMax, char **pzErr){
74250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
74260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zMax =
74270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "SELECT max(i.seqno) FROM "
74280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "  sqlite_master AS s, "
74290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "  pragma_index_list(s.name) AS l, "
74300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "  pragma_index_info(l.name) AS i "
74310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "WHERE s.type = 'table'";
74320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_stmt *pMax = 0;
74330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
74340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  *pnMax = 0;
74350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = idxPrepareStmt(db, &pMax, pzErr, zMax);
74360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pMax) ){
74370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    *pnMax = sqlite3_column_int(pMax, 0) + 1;
74380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
74390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  idxFinalize(&rc, pMax);
74400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
74410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
74420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
74430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
74440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int idxPopulateOneStat1(
74450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3expert *p,
74460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_stmt *pIndexXInfo,
74470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_stmt *pWriteStat,
74480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zTab,
74490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zIdx,
74500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErr
74510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
74520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zCols = 0;
74530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zOrder = 0;
74540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zQuery = 0;
74550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nCol = 0;
74560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int i;
74570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_stmt *pQuery = 0;
74580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int *aStat = 0;
74590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
74600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
74610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( p->iSample>0 );
74620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
74630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* Formulate the query text */
74640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_bind_text(pIndexXInfo, 1, zIdx, -1, SQLITE_STATIC);
74650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  while( SQLITE_OK==rc && SQLITE_ROW==sqlite3_step(pIndexXInfo) ){
74660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const char *zComma = zCols==0 ? "" : ", ";
74670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const char *zName = (const char*)sqlite3_column_text(pIndexXInfo, 0);
74680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const char *zColl = (const char*)sqlite3_column_text(pIndexXInfo, 1);
74690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zCols = idxAppendText(&rc, zCols,
74700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "%sx.%Q IS rem(%d, x.%Q) COLLATE %s", zComma, zName, nCol, zName, zColl
74710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    );
74720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zOrder = idxAppendText(&rc, zOrder, "%s%d", zComma, ++nCol);
74730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
74740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_reset(pIndexXInfo);
74750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
74760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( p->iSample==100 ){
74770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zQuery = sqlite3_mprintf(
74780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          "SELECT %s FROM %Q x ORDER BY %s", zCols, zTab, zOrder
74790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      );
74800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
74810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zQuery = sqlite3_mprintf(
74820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          "SELECT %s FROM temp."UNIQUE_TABLE_NAME" x ORDER BY %s", zCols, zOrder
74830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      );
74840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
74850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
74860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(zCols);
74870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(zOrder);
74880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
74890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* Formulate the query text */
74900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
74910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv);
74920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = idxPrepareStmt(dbrem, &pQuery, pzErr, zQuery);
74930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
74940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(zQuery);
74950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
74960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
74970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    aStat = (int*)idxMalloc(&rc, sizeof(int)*(nCol+1));
74980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
74990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){
75000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    IdxHashEntry *pEntry;
75010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    char *zStat = 0;
75020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    for(i=0; i<=nCol; i++) aStat[i] = 1;
75030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){
75040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      aStat[0]++;
75050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      for(i=0; i<nCol; i++){
75060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( sqlite3_column_int(pQuery, i)==0 ) break;
75070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
75080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      for(/*no-op*/; i<nCol; i++){
75090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        aStat[i+1]++;
75100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
75110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
75120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
75130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( rc==SQLITE_OK ){
75140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int s0 = aStat[0];
75150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zStat = sqlite3_mprintf("%d", s0);
75160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( zStat==0 ) rc = SQLITE_NOMEM;
75170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      for(i=1; rc==SQLITE_OK && i<=nCol; i++){
75180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        zStat = idxAppendText(&rc, zStat, " %d", (s0+aStat[i]/2) / aStat[i]);
75190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
75200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
75210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
75220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( rc==SQLITE_OK ){
75230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_bind_text(pWriteStat, 1, zTab, -1, SQLITE_STATIC);
75240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_bind_text(pWriteStat, 2, zIdx, -1, SQLITE_STATIC);
75250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_bind_text(pWriteStat, 3, zStat, -1, SQLITE_STATIC);
75260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_step(pWriteStat);
75270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = sqlite3_reset(pWriteStat);
75280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
75290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
75300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pEntry = idxHashFind(&p->hIdx, zIdx, STRLEN(zIdx));
75310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pEntry ){
75320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      assert( pEntry->zVal2==0 );
75330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pEntry->zVal2 = zStat;
75340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
75350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_free(zStat);
75360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
75370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
75380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(aStat);
75390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  idxFinalize(&rc, pQuery);
75400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
75410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
75420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
75430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
75440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int idxBuildSampleTable(sqlite3expert *p, const char *zTab){
75450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;
75460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zSql;
75470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
75480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = sqlite3_exec(p->dbv,"DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0);
75490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc!=SQLITE_OK ) return rc;
75500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
75510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zSql = sqlite3_mprintf(
75520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      "CREATE TABLE temp." UNIQUE_TABLE_NAME " AS SELECT * FROM %Q", zTab
75530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  );
75540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( zSql==0 ) return SQLITE_NOMEM;
75550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = sqlite3_exec(p->dbv, zSql, 0, 0, 0);
75560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(zSql);
75570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
75580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
75590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
75600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
75610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
75620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This function is called as part of sqlite3_expert_analyze(). Candidate
75630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** indexes have already been created in database sqlite3expert.dbm, this
75640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** function populates sqlite_stat1 table in the same database.
75650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
75660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The stat1 data is generated by querying the
75670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
75680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int idxPopulateStat1(sqlite3expert *p, char **pzErr){
75690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
75700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nMax =0;
75710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  struct IdxRemCtx *pCtx = 0;
75720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  struct IdxSampleCtx samplectx;
75730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int i;
75740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  i64 iPrev = -100000;
75750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_stmt *pAllIndex = 0;
75760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_stmt *pIndexXInfo = 0;
75770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_stmt *pWrite = 0;
75780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
75790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zAllIndex =
75800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "SELECT s.rowid, s.name, l.name FROM "
75810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "  sqlite_master AS s, "
75820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "  pragma_index_list(s.name) AS l "
75830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "WHERE s.type = 'table'";
75840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zIndexXInfo =
75850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "SELECT name, coll FROM pragma_index_xinfo(?) WHERE key";
75860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zWrite = "INSERT INTO sqlite_stat1 VALUES(?, ?, ?)";
75870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
75880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* If iSample==0, no sqlite_stat1 data is required. */
75890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( p->iSample==0 ) return SQLITE_OK;
75900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
75910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = idxLargestIndex(p->dbm, &nMax, pzErr);
75920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( nMax<=0 || rc!=SQLITE_OK ) return rc;
75930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
75940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = sqlite3_exec(p->dbm, "ANALYZE; PRAGMA writable_schema=1", 0, 0, 0);
75950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
75960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
75970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int nByte = sizeof(struct IdxRemCtx) + (sizeof(struct IdxRemSlot) * nMax);
75980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCtx = (struct IdxRemCtx*)idxMalloc(&rc, nByte);
75990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
76000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
76010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
76020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv);
76030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = sqlite3_create_function(
76040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        dbrem, "rem", 2, SQLITE_UTF8, (void*)pCtx, idxRemFunc, 0, 0
76050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    );
76060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
76070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
76080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = sqlite3_create_function(
76090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        p->db, "sample", 0, SQLITE_UTF8, (void*)&samplectx, idxSampleFunc, 0, 0
76100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    );
76110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
76120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
76130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
76140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pCtx->nSlot = nMax+1;
76150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = idxPrepareStmt(p->dbm, &pAllIndex, pzErr, zAllIndex);
76160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
76170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
76180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = idxPrepareStmt(p->dbm, &pIndexXInfo, pzErr, zIndexXInfo);
76190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
76200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
76210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = idxPrepareStmt(p->dbm, &pWrite, pzErr, zWrite);
76220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
76230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
76240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pAllIndex) ){
76250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    i64 iRowid = sqlite3_column_int64(pAllIndex, 0);
76260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const char *zTab = (const char*)sqlite3_column_text(pAllIndex, 1);
76270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const char *zIdx = (const char*)sqlite3_column_text(pAllIndex, 2);
76280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( p->iSample<100 && iPrev!=iRowid ){
76290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      samplectx.target = (double)p->iSample / 100.0;
76300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      samplectx.iTarget = p->iSample;
76310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      samplectx.nRow = 0.0;
76320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      samplectx.nRet = 0.0;
76330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = idxBuildSampleTable(p, zTab);
76340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( rc!=SQLITE_OK ) break;
76350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
76360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = idxPopulateOneStat1(p, pIndexXInfo, pWrite, zTab, zIdx, pzErr);
76370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    iPrev = iRowid;
76380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
76390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK && p->iSample<100 ){
76400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = sqlite3_exec(p->dbv,
76410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "DROP TABLE IF EXISTS temp." UNIQUE_TABLE_NAME, 0,0,0
76420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    );
76430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
76440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
76450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  idxFinalize(&rc, pAllIndex);
76460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  idxFinalize(&rc, pIndexXInfo);
76470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  idxFinalize(&rc, pWrite);
76480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
76490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(i=0; i<pCtx->nSlot; i++){
76500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(pCtx->aSlot[i].z);
76510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
76520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(pCtx);
76530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
76540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
76550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = sqlite3_exec(p->dbm, "ANALYZE sqlite_master", 0, 0, 0);
76560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
76570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
76580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0);
76590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
76600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
76610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
76620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
76630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Allocate a new sqlite3expert object.
76640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
76650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovsqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){
76660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
76670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3expert *pNew;
76680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
76690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pNew = (sqlite3expert*)idxMalloc(&rc, sizeof(sqlite3expert));
76700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
76710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* Open two in-memory databases to work with. The "vtab database" (dbv)
76720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ** will contain a virtual table corresponding to each real table in
76730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ** the user database schema, and a copy of each view. It is used to
76740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ** collect information regarding the WHERE, ORDER BY and other clauses
76750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ** of the user's query.
76760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  */
76770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
76780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNew->db = db;
76790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNew->iSample = 100;
76800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = sqlite3_open(":memory:", &pNew->dbv);
76810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
76820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
76830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = sqlite3_open(":memory:", &pNew->dbm);
76840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( rc==SQLITE_OK ){
76850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_db_config(pNew->dbm, SQLITE_DBCONFIG_TRIGGER_EQP, 1, (int*)0);
7686b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }
7687b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }
76880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
76890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
76900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* Copy the entire schema of database [db] into [dbm]. */
76910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
76920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_stmt *pSql;
76930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg,
76940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "SELECT sql FROM sqlite_master WHERE name NOT LIKE 'sqlite_%%'"
76950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        " AND sql NOT LIKE 'CREATE VIRTUAL %%'"
76960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    );
76970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
76980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
76990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg);
77000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
77010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    idxFinalize(&rc, pSql);
7702b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }
77030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
77040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* Create the vtab schema */
77050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
77060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = idxCreateVtabSchema(pNew, pzErrmsg);
77070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
77080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
77090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* Register the auth callback with dbv */
77100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
77110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_set_authorizer(pNew->dbv, idxAuthCallback, (void*)pNew);
77120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
77130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
77140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* If an error has occurred, free the new object and reutrn NULL. Otherwise,
77150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ** return the new sqlite3expert handle.  */
77160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc!=SQLITE_OK ){
77170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_expert_destroy(pNew);
77180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pNew = 0;
77190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
77200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return pNew;
7721b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis}
7722b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
77230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
77240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Configure an sqlite3expert object.
7725b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis*/
77260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovint sqlite3_expert_config(sqlite3expert *p, int op, ...){
77270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
7728b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  va_list ap;
77290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  va_start(ap, op);
77300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  switch( op ){
77310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case EXPERT_CONFIG_SAMPLE: {
77320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int iVal = va_arg(ap, int);
77330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( iVal<0 ) iVal = 0;
77340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( iVal>100 ) iVal = 100;
77350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      p->iSample = iVal;
77360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
77370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
77380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    default:
77390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = SQLITE_NOTFOUND;
77400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
77410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
77420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
7743b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  va_end(ap);
77440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
7745b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis}
7746b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
7747b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis/*
77480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Add an SQL statement to the analysis.
7749b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis*/
77500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovint sqlite3_expert_sql(
77510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3expert *p,               /* From sqlite3_expert_new() */
77520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zSql,               /* SQL statement to add */
77530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErr                    /* OUT: Error message (if any) */
7754b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis){
77550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxScan *pScanOrig = p->pScan;
77560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxStatement *pStmtOrig = p->pStatement;
77570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
77580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zStmt = zSql;
7759b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
77600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( p->bRun ) return SQLITE_MISUSE;
7761b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
77620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  while( rc==SQLITE_OK && zStmt && zStmt[0] ){
77630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_stmt *pStmt = 0;
77640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = sqlite3_prepare_v2(p->dbv, zStmt, -1, &pStmt, &zStmt);
77650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( rc==SQLITE_OK ){
77660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( pStmt ){
77670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        IdxStatement *pNew;
77680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        const char *z = sqlite3_sql(pStmt);
77690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        int n = STRLEN(z);
77700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        pNew = (IdxStatement*)idxMalloc(&rc, sizeof(IdxStatement) + n+1);
77710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( rc==SQLITE_OK ){
77720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          pNew->zSql = (char*)&pNew[1];
77730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          memcpy(pNew->zSql, z, n+1);
77740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          pNew->pNext = p->pStatement;
77750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( p->pStatement ) pNew->iId = p->pStatement->iId+1;
77760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          p->pStatement = pNew;
7777b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        }
77780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_finalize(pStmt);
7779b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      }
77800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
77810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      idxDatabaseError(p->dbv, pzErr);
7782b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }
7783b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }
77840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
77850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc!=SQLITE_OK ){
77860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    idxScanFree(p->pScan, pScanOrig);
77870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    idxStatementFree(p->pStatement, pStmtOrig);
77880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    p->pScan = pScanOrig;
77890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    p->pStatement = pStmtOrig;
77900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
77910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
77920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
77930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
77940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
77950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovint sqlite3_expert_analyze(sqlite3expert *p, char **pzErr){
77960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;
77970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxHashEntry *pEntry;
77980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
77990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* Do trigger processing to collect any extra IdxScan structures */
78000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = idxProcessTriggers(p, pzErr);
78010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
78020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* Create candidate indexes within the in-memory database file */
78030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
78040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = idxCreateCandidates(p);
78050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
78060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
78070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* Generate the stat1 data */
78080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
78090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = idxPopulateStat1(p, pzErr);
78100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
78110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
78120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* Formulate the EXPERT_REPORT_CANDIDATES text */
78130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(pEntry=p->hIdx.pFirst; pEntry; pEntry=pEntry->pNext){
78140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    p->zCandidates = idxAppendText(&rc, p->zCandidates,
78150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "%s;%s%s\n", pEntry->zVal,
78160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        pEntry->zVal2 ? " -- stat1: " : "", pEntry->zVal2
78170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    );
78180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
78190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
78200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* Figure out which of the candidate indexes are preferred by the query
78210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ** planner and report the results to the user.  */
78220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
78230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = idxFindIndexes(p, pzErr);
78240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
78250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
78260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
78270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    p->bRun = 1;
78280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
78290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
78300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
78310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
78320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
78330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Return the total number of statements that have been added to this
78340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** sqlite3expert using sqlite3_expert_sql().
78350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
78360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovint sqlite3_expert_count(sqlite3expert *p){
78370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nRet = 0;
78380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( p->pStatement ) nRet = p->pStatement->iId+1;
78390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return nRet;
78400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
78410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
78420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
78430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Return a component of the report.
78440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
78450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovconst char *sqlite3_expert_report(sqlite3expert *p, int iStmt, int eReport){
78460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zRet = 0;
78470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  IdxStatement *pStmt;
78480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
78490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( p->bRun==0 ) return 0;
78500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(pStmt=p->pStatement; pStmt && pStmt->iId!=iStmt; pStmt=pStmt->pNext);
78510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  switch( eReport ){
78520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case EXPERT_REPORT_SQL:
78530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( pStmt ) zRet = pStmt->zSql;
78540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
78550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case EXPERT_REPORT_INDEXES:
78560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( pStmt ) zRet = pStmt->zIdx;
78570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
78580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case EXPERT_REPORT_PLAN:
78590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( pStmt ) zRet = pStmt->zEQP;
78600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
78610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case EXPERT_REPORT_CANDIDATES:
78620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zRet = p->zCandidates;
78630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
78640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
78650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return zRet;
7866b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis}
78670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
78680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
78690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Free an sqlite3expert object.
78700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
78710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovvoid sqlite3_expert_destroy(sqlite3expert *p){
78720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( p ){
78730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_close(p->dbm);
78740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_close(p->dbv);
78750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    idxScanFree(p->pScan, 0);
78760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    idxStatementFree(p->pStatement, 0);
78770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    idxTableFree(p->pTable);
78780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    idxWriteFree(p->pWrite);
78790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    idxHashClear(&p->hIdx);
78800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(p->zCandidates);
78810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(p);
78820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
78830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
78840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
78850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif /* ifndef SQLITE_OMIT_VIRTUAL_TABLE */
78860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
78870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/************************* End ../ext/expert/sqlite3expert.c ********************/
78887790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
788960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#if defined(SQLITE_ENABLE_SESSION)
789060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis/*
789160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** State information for a single open session
789260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis*/
789360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidistypedef struct OpenSession OpenSession;
789460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidisstruct OpenSession {
789560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  char *zName;             /* Symbolic name for this session */
789660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  int nFilter;             /* Number of xFilter rejection GLOB patterns */
789760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  char **azFilter;         /* Array of xFilter rejection GLOB patterns */
789860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  sqlite3_session *p;      /* The open session */
789960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis};
790060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#endif
790160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
79023fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich/*
790360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** Shell output mode information from before ".explain on",
79043fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich** saved so that it can be restored by ".explain off"
79053fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich*/
79063fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichtypedef struct SavedModeInfo SavedModeInfo;
79073fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichstruct SavedModeInfo {
79083fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  int valid;          /* Is there legit data in here? */
79093fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  int mode;           /* Mode prior to ".explain on" */
79103fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  int showHeader;     /* The ".header" setting prior to ".explain on" */
79113fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  int colWidth[100];  /* Column widths prior to ".explain on" */
79127790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project};
79137790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
79140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct ExpertInfo ExpertInfo;
79150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct ExpertInfo {
79160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3expert *pExpert;
79170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int bVerbose;
79180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
79190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
79207790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
79213fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich** State information about the database connection is contained in an
79223fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich** instance of the following structure.
79237790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
79243fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichtypedef struct ShellState ShellState;
79253fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichstruct ShellState {
7926a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  sqlite3 *db;           /* The database */
79270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 autoExplain;        /* Automatically turn on .explain mode */
79280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 autoEQP;            /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
79290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 statsOn;            /* True to display memory stats before each finalize */
79300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 scanstatsOn;        /* True to display scan stats before each finalize */
79310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 openMode;           /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
79320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 doXdgOpen;          /* Invoke start/open/xdg-open in output_reset() */
79331c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  int outCount;          /* Revert to stdout when reaching zero */
79347790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  int cnt;               /* Number of records displayed so far */
79357790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  FILE *out;             /* Write results here */
79368fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  FILE *traceOut;        /* Output for sqlite3_trace() */
793790ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  int nErr;              /* Number of errors seen */
79387790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  int mode;              /* An output mode setting */
79390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int modePrior;         /* Saved mode */
794060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  int cMode;             /* temporary output mode for the current query */
794160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  int normalMode;        /* Output mode before ".explain on" */
79427790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  int writableSchema;    /* True if PRAGMA writable_schema=ON */
79437790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  int showHeader;        /* True to show column names in List or Column mode */
794408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  int nCheck;            /* Number of ".check" commands run */
79453fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  unsigned shellFlgs;    /* Various flags */
79467790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  char *zDestTable;      /* Name of destination table when MODE_Insert */
79470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zTempFile;       /* Temporary file that might need deleting */
794808f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  char zTestcase[30];    /* Name of current test case */
79493fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  char colSeparator[20]; /* Column separator character for several modes */
79503fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  char rowSeparator[20]; /* Row separator character for MODE_Ascii */
79510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char colSepPrior[20];  /* Saved column separator */
79520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char rowSepPrior[20];  /* Saved row separator */
79537790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  int colWidth[100];     /* Requested width of each column when in column mode*/
79547790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  int actualWidth[100];  /* Actual width of each column */
79553fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  char nullValue[20];    /* The text to print when a NULL comes back from
79567790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project                         ** the database */
79577790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  char outfile[FILENAME_MAX]; /* Filename for *out */
79587790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  const char *zDbFilename;    /* name of the database file */
79598fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  char *zFreeOnClose;         /* Filename to free when closing */
796090ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  const char *zVfs;           /* Name of VFS to use */
7961a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  sqlite3_stmt *pStmt;   /* Current statement if any. */
7962aae12b8a5af3a1ac77382b067d9ebb350fbd0644Vasu Nori  FILE *pLog;            /* Write log output here */
79638fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int *aiIndent;         /* Array of indents used in MODE_Explain */
79648fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int nIndent;           /* Size of array aiIndent[] */
79658fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int iIndent;           /* Index of current op in aiIndent[] */
796660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#if defined(SQLITE_ENABLE_SESSION)
796760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  int nSession;             /* Number of active sessions */
796860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  OpenSession aSession[4];  /* Array of sessions.  [0] is in focus. */
796960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#endif
79700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ExpertInfo expert;        /* Valid if previous command was ".expert OPT..." */
79717790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project};
79727790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
79730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
79740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* Allowed values for ShellState.autoEQP
79750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
79760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define AUTOEQP_off      0
79770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define AUTOEQP_on       1
79780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define AUTOEQP_trigger  2
79790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define AUTOEQP_full     3
79800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
79810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* Allowed values for ShellState.openMode
79820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
79830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define SHELL_OPEN_UNSPEC     0      /* No open-mode specified */
79840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define SHELL_OPEN_NORMAL     1      /* Normal database file */
79850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define SHELL_OPEN_APPENDVFS  2      /* Use appendvfs */
79860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define SHELL_OPEN_ZIPFILE    3      /* Use the zipfile virtual table */
79870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
79887790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
79893fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich** These are the allowed shellFlgs values
79903fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich*/
79910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define SHFLG_Pagecache      0x00000001 /* The --pagecache option is used */
79920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define SHFLG_Lookaside      0x00000002 /* Lookaside memory is used */
79930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define SHFLG_Backslash      0x00000004 /* The --backslash option is used */
79940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define SHFLG_PreserveRowid  0x00000008 /* .dump preserves rowid values */
79950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define SHFLG_Newlines       0x00000010 /* .dump --newline flag */
7996b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis#define SHFLG_CountChanges   0x00000020 /* .changes setting */
7997b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis#define SHFLG_Echo           0x00000040 /* .echo or --echo setting */
7998b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
7999b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis/*
8000b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** Macros for testing and setting shellFlgs
8001b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis*/
8002b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis#define ShellHasFlag(P,X)    (((P)->shellFlgs & (X))!=0)
8003b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis#define ShellSetFlag(P,X)    ((P)->shellFlgs|=(X))
8004b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis#define ShellClearFlag(P,X)  ((P)->shellFlgs&=(~(X)))
80053fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
80063fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich/*
80077790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** These are the allowed modes.
80087790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
80097790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#define MODE_Line     0  /* One column per line.  Blank line between records */
80107790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#define MODE_Column   1  /* One record per line in neat columns */
80117790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#define MODE_List     2  /* One record per line with a separator */
80127790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#define MODE_Semi     3  /* Same as MODE_List but append ";" to each line */
80137790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#define MODE_Html     4  /* Generate an XHTML table */
80147790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#define MODE_Insert   5  /* Generate SQL "insert" statements */
8015e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani#define MODE_Quote    6  /* Quote values as for SQL */
8016e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani#define MODE_Tcl      7  /* Generate ANSI-C or TCL quoted elements */
8017e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani#define MODE_Csv      8  /* Quote strings, numbers are plain */
8018e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani#define MODE_Explain  9  /* Like MODE_Column, but do not truncate data */
8019e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani#define MODE_Ascii   10  /* Use ASCII unit and record separators (0x1F/0x1E) */
8020e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani#define MODE_Pretty  11  /* Pretty-print schemas */
80217790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
80227790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Projectstatic const char *modeDescr[] = {
80237790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  "line",
80247790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  "column",
80257790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  "list",
80267790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  "semi",
80277790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  "html",
80287790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  "insert",
8029e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  "quote",
80307790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  "tcl",
80317790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  "csv",
80327790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  "explain",
80333fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  "ascii",
803460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  "prettyprint",
80357790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project};
80367790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
80377790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
80383fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich** These are the column/row/line separators used by the various
80393fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich** import/export modes.
80403fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich*/
80413fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#define SEP_Column    "|"
80423fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#define SEP_Row       "\n"
80433fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#define SEP_Tab       "\t"
80443fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#define SEP_Space     " "
80453fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#define SEP_Comma     ","
80463fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#define SEP_CrLf      "\r\n"
80473fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#define SEP_Unit      "\x1F"
80483fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#define SEP_Record    "\x1E"
80493fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
80503fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich/*
80510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** A callback for the sqlite3_log() interface.
80520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
80530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void shellLog(void *pArg, int iErrCode, const char *zMsg){
80540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ShellState *p = (ShellState*)pArg;
80550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( p->pLog==0 ) return;
80560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
80570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  fflush(p->pLog);
80580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
80590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
80600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
80610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** SQL function:  shell_putsnl(X)
80620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
80630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Write the text X to the screen (or whatever output is being directed)
80640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** adding a newline at the end, and then return X.
80650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
80660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void shellPutsFunc(
80670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_context *pCtx,
80680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nVal,
80690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_value **apVal
80700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
80710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ShellState *p = (ShellState*)sqlite3_user_data(pCtx);
80720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  (void)nVal;
80730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0]));
80740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_result_value(pCtx, apVal[0]);
80750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
80760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
80770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
80780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** SQL function:   edit(VALUE)
80790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**                 edit(VALUE,EDITOR)
80800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
80810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** These steps:
80820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
80830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     (1) Write VALUE into a temporary file.
80840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     (2) Run program EDITOR on that temporary file.
80850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     (3) Read the temporary file back and return its content as the result.
80860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**     (4) Delete the temporary file
80870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
80880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** If the EDITOR argument is omitted, use the value in the VISUAL
80890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** environment variable.  If still there is no EDITOR, through an error.
80900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
80910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Also throw an error if the EDITOR program returns a non-zero exit code.
80927790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
80930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void editFunc(
80940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_context *context,
80950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int argc,
80960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_value **argv
80970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
80980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zEditor;
80990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zTempFile = 0;
81000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *db;
81010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zCmd = 0;
81020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int bBin;
81030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;
81040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  FILE *f = 0;
81050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_int64 sz;
81060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_int64 x;
81070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  unsigned char *p = 0;
81080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
81090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( argc==2 ){
81100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zEditor = (const char*)sqlite3_value_text(argv[1]);
81110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
81120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zEditor = getenv("VISUAL");
81130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
81140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( zEditor==0 ){
81150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_result_error(context, "no editor for edit()", -1);
81160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return;
81170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
81180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
81190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_result_error(context, "NULL input to edit()", -1);
81200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return;
81210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
81220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  db = sqlite3_context_db_handle(context);
81230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zTempFile = 0;
81240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_file_control(db, 0, SQLITE_FCNTL_TEMPFILENAME, &zTempFile);
81250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( zTempFile==0 ){
81260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_uint64 r = 0;
81270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_randomness(sizeof(r), &r);
81280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zTempFile = sqlite3_mprintf("temp%llx", r);
81290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( zTempFile==0 ){
81300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_result_error_nomem(context);
81310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      return;
81320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
81330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
81340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  bBin = sqlite3_value_type(argv[0])==SQLITE_BLOB;
81350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  f = fopen(zTempFile, bBin ? "wb" : "w");
81360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( f==0 ){
81370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_result_error(context, "edit() cannot open temp file", -1);
81380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    goto edit_func_end;
81390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
81400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sz = sqlite3_value_bytes(argv[0]);
81410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( bBin ){
81420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    x = fwrite(sqlite3_value_blob(argv[0]), 1, sz, f);
81430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
81440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    x = fwrite(sqlite3_value_text(argv[0]), 1, sz, f);
81450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
81460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  fclose(f);
81470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  f = 0;
81480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( x!=sz ){
81490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_result_error(context, "edit() could not write the whole file", -1);
81500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    goto edit_func_end;
81510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
81520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zCmd = sqlite3_mprintf("%s \"%s\"", zEditor, zTempFile);
81530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( zCmd==0 ){
81540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_result_error_nomem(context);
81550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    goto edit_func_end;
81560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
81570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = system(zCmd);
81580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(zCmd);
81590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc ){
81600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_result_error(context, "EDITOR returned non-zero", -1);
81610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    goto edit_func_end;
81620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
81630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  f = fopen(zTempFile, bBin ? "rb" : "r");
81640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( f==0 ){
81650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_result_error(context,
81660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      "edit() cannot reopen temp file after edit", -1);
81670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    goto edit_func_end;
81680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
81690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  fseek(f, 0, SEEK_END);
81700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sz = ftell(f);
81710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rewind(f);
81720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  p = sqlite3_malloc64( sz+(bBin==0) );
81730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( p==0 ){
81740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_result_error_nomem(context);
81750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    goto edit_func_end;
81760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
81770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( bBin ){
81780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    x = fread(p, 1, sz, f);
81790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
81800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    x = fread(p, 1, sz, f);
81810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    p[sz] = 0;
81820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
81830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  fclose(f);
81840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  f = 0;
81850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( x!=sz ){
81860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_result_error(context, "could not read back the whole file", -1);
81870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    goto edit_func_end;
81880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
81890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( bBin ){
81900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_result_blob(context, p, sz, sqlite3_free);
81910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
81920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_result_text(context, (const char*)p, sz, sqlite3_free);
81930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
81940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  p = 0;
81950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
81960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovedit_func_end:
81970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( f ) fclose(f);
81980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  unlink(zTempFile);
81990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(zTempFile);
82000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(p);
82010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
8202a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori
8203a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori/*
82040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Save or restore the current output mode
8205aae12b8a5af3a1ac77382b067d9ebb350fbd0644Vasu Nori*/
82060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void outputModePush(ShellState *p){
82070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  p->modePrior = p->mode;
82080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator));
82090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator));
82100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
82110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void outputModePop(ShellState *p){
82120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  p->mode = p->modePrior;
82130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator));
82140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator));
8215aae12b8a5af3a1ac77382b067d9ebb350fbd0644Vasu Nori}
8216aae12b8a5af3a1ac77382b067d9ebb350fbd0644Vasu Nori
8217aae12b8a5af3a1ac77382b067d9ebb350fbd0644Vasu Nori/*
8218a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori** Output the given string as a hex-encoded blob (eg. X'1234' )
8219a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori*/
8220a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Noristatic void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
8221a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  int i;
8222a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  char *zBlob = (char *)pBlob;
822360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  raw_printf(out,"X'");
822460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  for(i=0; i<nBlob; i++){ raw_printf(out,"%02x",zBlob[i]&0xff); }
822560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  raw_printf(out,"'");
8226a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori}
82277790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
82287790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
8229b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis** Find a string that is not found anywhere in z[].  Return a pointer
8230b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis** to that string.
8231b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis**
8232b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis** Try to use zA and zB first.  If both of those are already found in z[]
8233b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis** then make up some string and store it in the buffer zBuf.
8234b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis*/
8235b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidisstatic const char *unused_string(
8236b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  const char *z,                    /* Result must not appear anywhere in z */
8237b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  const char *zA, const char *zB,   /* Try these first */
8238b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  char *zBuf                        /* Space to store a generated string */
8239b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis){
8240b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  unsigned i = 0;
8241b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  if( strstr(z, zA)==0 ) return zA;
8242b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  if( strstr(z, zB)==0 ) return zB;
8243b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  do{
8244b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
8245b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  }while( strstr(z,zBuf)!=0 );
8246b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  return zBuf;
8247b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis}
8248b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis
8249b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis/*
82507790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** Output the given string as a quoted string using SQL quoting conventions.
8251b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis**
8252b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis** See also: output_quoted_escaped_string()
82537790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
82547790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Projectstatic void output_quoted_string(FILE *out, const char *z){
82557790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  int i;
8256b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  char c;
825760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  setBinaryMode(out, 1);
8258b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  for(i=0; (c = z[i])!=0 && c!='\''; i++){}
8259df94a5ddeff8b445868ed01f841d7c279b93395fAlex Naidis  if( c==0 ){
8260df94a5ddeff8b445868ed01f841d7c279b93395fAlex Naidis    utf8_printf(out,"'%s'",z);
8261df94a5ddeff8b445868ed01f841d7c279b93395fAlex Naidis  }else{
8262b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    raw_printf(out, "'");
8263df94a5ddeff8b445868ed01f841d7c279b93395fAlex Naidis    while( *z ){
8264b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      for(i=0; (c = z[i])!=0 && c!='\''; i++){}
8265df94a5ddeff8b445868ed01f841d7c279b93395fAlex Naidis      if( c=='\'' ) i++;
8266df94a5ddeff8b445868ed01f841d7c279b93395fAlex Naidis      if( i ){
8267df94a5ddeff8b445868ed01f841d7c279b93395fAlex Naidis        utf8_printf(out, "%.*s", i, z);
8268df94a5ddeff8b445868ed01f841d7c279b93395fAlex Naidis        z += i;
8269df94a5ddeff8b445868ed01f841d7c279b93395fAlex Naidis      }
8270df94a5ddeff8b445868ed01f841d7c279b93395fAlex Naidis      if( c=='\'' ){
8271b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        raw_printf(out, "'");
8272df94a5ddeff8b445868ed01f841d7c279b93395fAlex Naidis        continue;
8273b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      }
8274b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      if( c==0 ){
8275b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis        break;
8276b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      }
8277b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      z++;
8278b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    }
8279b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    raw_printf(out, "'");
8280b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  }
8281b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  setTextMode(out, 1);
8282b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis}
8283b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis
8284b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis/*
8285b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis** Output the given string as a quoted string using SQL quoting conventions.
8286b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis** Additionallly , escape the "\n" and "\r" characters so that they do not
8287b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis** get corrupted by end-of-line translation facilities in some operating
8288b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis** systems.
8289b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis**
8290b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis** This is like output_quoted_string() but with the addition of the \r\n
8291b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis** escape mechanism.
8292b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis*/
8293b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidisstatic void output_quoted_escaped_string(FILE *out, const char *z){
8294b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  int i;
8295b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  char c;
8296b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  setBinaryMode(out, 1);
8297b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
8298b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  if( c==0 ){
8299b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    utf8_printf(out,"'%s'",z);
8300b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  }else{
8301b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    const char *zNL = 0;
8302b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    const char *zCR = 0;
8303b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    int nNL = 0;
8304b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    int nCR = 0;
8305b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    char zBuf1[20], zBuf2[20];
8306b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    for(i=0; z[i]; i++){
8307b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      if( z[i]=='\n' ) nNL++;
8308b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      if( z[i]=='\r' ) nCR++;
8309b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    }
8310b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    if( nNL ){
8311b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      raw_printf(out, "replace(");
8312b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      zNL = unused_string(z, "\\n", "\\012", zBuf1);
8313b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    }
8314b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    if( nCR ){
8315b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      raw_printf(out, "replace(");
8316b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      zCR = unused_string(z, "\\r", "\\015", zBuf2);
8317b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    }
8318b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    raw_printf(out, "'");
8319b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    while( *z ){
8320b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
8321b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      if( c=='\'' ) i++;
8322b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      if( i ){
8323b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis        utf8_printf(out, "%.*s", i, z);
8324b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis        z += i;
8325b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      }
8326b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      if( c=='\'' ){
8327474de9dc715b92c3c3d546da70d69fa3c2bd56b5Nick Kralevich        raw_printf(out, "'");
8328b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis        continue;
8329474de9dc715b92c3c3d546da70d69fa3c2bd56b5Nick Kralevich      }
8330b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      if( c==0 ){
83317790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        break;
83327790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
8333b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      z++;
8334b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      if( c=='\n' ){
8335b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis        raw_printf(out, "%s", zNL);
8336b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis        continue;
8337b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      }
8338b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      raw_printf(out, "%s", zCR);
8339b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    }
8340b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    raw_printf(out, "'");
8341b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    if( nCR ){
8342b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      raw_printf(out, ",'%s',char(13))", zCR);
8343b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    }
8344b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    if( nNL ){
8345b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      raw_printf(out, ",'%s',char(10))", zNL);
83467790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
83477790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
834860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  setTextMode(out, 1);
83497790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
83507790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
83517790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
83527790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** Output the given string as a quoted according to C or TCL quoting rules.
83537790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
83547790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Projectstatic void output_c_string(FILE *out, const char *z){
83557790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  unsigned int c;
83567790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  fputc('"', out);
83577790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  while( (c = *(z++))!=0 ){
83587790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( c=='\\' ){
83597790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      fputc(c, out);
83607790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      fputc(c, out);
83618fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }else if( c=='"' ){
83628fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      fputc('\\', out);
83638fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      fputc('"', out);
83647790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else if( c=='\t' ){
83657790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      fputc('\\', out);
83667790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      fputc('t', out);
83677790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else if( c=='\n' ){
83687790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      fputc('\\', out);
83697790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      fputc('n', out);
83707790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else if( c=='\r' ){
83717790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      fputc('\\', out);
83727790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      fputc('r', out);
83738fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }else if( !isprint(c&0xff) ){
837460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(out, "\\%03o", c&0xff);
83757790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else{
83767790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      fputc(c, out);
83777790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
83787790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
83797790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  fputc('"', out);
83807790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
83817790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
83827790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
83837790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** Output the given string with characters that are special to
83847790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** HTML escaped.
83857790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
83867790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Projectstatic void output_html_string(FILE *out, const char *z){
83877790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  int i;
83888fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( z==0 ) z = "";
83897790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  while( *z ){
839060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    for(i=0;   z[i]
839160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            && z[i]!='<'
839260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            && z[i]!='&'
839360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            && z[i]!='>'
839460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            && z[i]!='\"'
8395a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori            && z[i]!='\'';
8396a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori        i++){}
83977790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( i>0 ){
839860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(out,"%.*s",i,z);
83997790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
84007790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( z[i]=='<' ){
840160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(out,"&lt;");
84027790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else if( z[i]=='&' ){
840360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(out,"&amp;");
8404a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }else if( z[i]=='>' ){
840560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(out,"&gt;");
8406a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }else if( z[i]=='\"' ){
840760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(out,"&quot;");
8408a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }else if( z[i]=='\'' ){
840960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(out,"&#39;");
84107790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else{
84117790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      break;
84127790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
84137790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    z += i + 1;
84147790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
84157790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
84167790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
84177790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
84187790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** If a field contains any character identified by a 1 in the following
84197790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** array, then the string must be quoted for CSV.
84207790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
84217790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Projectstatic const char needCsvQuote[] = {
842260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
842360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
842460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  1, 0, 1, 0, 0, 0, 0, 1,   0, 0, 0, 0, 0, 0, 0, 0,
842560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
842660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
842760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
842860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
842960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 1,
843060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
843160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
843260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
843360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
843460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
843560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
843660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
843760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
84387790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project};
84397790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
84407790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
84413fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich** Output a single term of CSV.  Actually, p->colSeparator is used for
84423fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich** the separator, which may or may not be a comma.  p->nullValue is
84439bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown** the null value.  Strings are quoted if necessary.  The separator
84449bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown** is only issued if bSep is true.
84457790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
84463fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichstatic void output_csv(ShellState *p, const char *z, int bSep){
84477790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  FILE *out = p->out;
84487790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if( z==0 ){
844960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(out,"%s",p->nullValue);
84507790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else{
84517790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    int i;
84523fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    int nSep = strlen30(p->colSeparator);
84537790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    for(i=0; z[i]; i++){
845460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( needCsvQuote[((unsigned char*)z)[i]]
845560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis         || (z[i]==p->colSeparator[0] &&
84563fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich             (nSep==1 || memcmp(z, p->colSeparator, nSep)==0)) ){
84577790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        i = 0;
84587790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        break;
84597790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
84607790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
84617790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( i==0 ){
84620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      char *zQuoted = sqlite3_mprintf("\"%w\"", z);
84630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      utf8_printf(out, "%s", zQuoted);
84640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_free(zQuoted);
84657790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else{
846660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(out, "%s", z);
84677790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
84687790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
84697790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if( bSep ){
847060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(p->out, "%s", p->colSeparator);
84717790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
84727790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
84737790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
84747790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
84757790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** This routine runs when the user presses Ctrl-C
84767790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
84777790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Projectstatic void interrupt_handler(int NotUsed){
8478a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  UNUSED_PARAMETER(NotUsed);
84791c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  seenInterrupt++;
84801c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( seenInterrupt>2 ) exit(1);
84813a6c79f802fabdb94367177310663397420e319fNick Kralevich  if( globalDb ) sqlite3_interrupt(globalDb);
84827790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
84830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
84840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
84850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
84860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This routine runs for console events (e.g. Ctrl-C) on Win32
84870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
84880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic BOOL WINAPI ConsoleCtrlHandler(
84890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  DWORD dwCtrlType /* One of the CTRL_*_EVENT constants */
84900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
84910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( dwCtrlType==CTRL_C_EVENT ){
84920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    interrupt_handler(0);
84930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return TRUE;
84940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
84950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return FALSE;
84960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
84977790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#endif
84987790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
849908f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis#ifndef SQLITE_OMIT_AUTHORIZATION
85007790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
850160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** When the ".auth ON" is set, the following authorizer callback is
850260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** invoked.  It always returns SQLITE_OK.
850360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis*/
850460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidisstatic int shellAuth(
850560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  void *pClientData,
850660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  int op,
850760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  const char *zA1,
850860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  const char *zA2,
850960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  const char *zA3,
851060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  const char *zA4
851160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis){
851260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  ShellState *p = (ShellState*)pClientData;
851360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  static const char *azAction[] = { 0,
851460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis     "CREATE_INDEX",         "CREATE_TABLE",         "CREATE_TEMP_INDEX",
851560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis     "CREATE_TEMP_TABLE",    "CREATE_TEMP_TRIGGER",  "CREATE_TEMP_VIEW",
851660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis     "CREATE_TRIGGER",       "CREATE_VIEW",          "DELETE",
851760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis     "DROP_INDEX",           "DROP_TABLE",           "DROP_TEMP_INDEX",
851860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis     "DROP_TEMP_TABLE",      "DROP_TEMP_TRIGGER",    "DROP_TEMP_VIEW",
851960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis     "DROP_TRIGGER",         "DROP_VIEW",            "INSERT",
852060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis     "PRAGMA",               "READ",                 "SELECT",
852160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis     "TRANSACTION",          "UPDATE",               "ATTACH",
852260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis     "DETACH",               "ALTER_TABLE",          "REINDEX",
852360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis     "ANALYZE",              "CREATE_VTABLE",        "DROP_VTABLE",
852460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis     "FUNCTION",             "SAVEPOINT",            "RECURSIVE"
852560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  };
852660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  int i;
852760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  const char *az[4];
852860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  az[0] = zA1;
852960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  az[1] = zA2;
853060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  az[2] = zA3;
853160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  az[3] = zA4;
853208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  utf8_printf(p->out, "authorizer: %s", azAction[op]);
853360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  for(i=0; i<4; i++){
853460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    raw_printf(p->out, " ");
853560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    if( az[i] ){
853660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      output_c_string(p->out, az[i]);
853760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }else{
853860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(p->out, "NULL");
853960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }
854060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  }
854160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  raw_printf(p->out, "\n");
854260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  return SQLITE_OK;
854360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis}
854408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis#endif
854508f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis
8546e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani/*
8547e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani** Print a schema statement.  Part of MODE_Semi and MODE_Pretty output.
8548e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani**
8549e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani** This routine converts some CREATE TABLE statements for shadow tables
8550e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
8551e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani*/
8552e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefanistatic void printSchemaLine(FILE *out, const char *z, const char *zTail){
8553e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
8554e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
8555e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  }else{
8556e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    utf8_printf(out, "%s%s", z, zTail);
8557e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  }
8558e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani}
8559e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefanistatic void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){
8560e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  char c = z[n];
8561e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  z[n] = 0;
8562e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  printSchemaLine(out, z, zTail);
8563e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  z[n] = c;
8564e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani}
856560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
856660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis/*
85670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Return true if string z[] has nothing but whitespace and comments to the
85680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** end of the first line.
85690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
85700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int wsToEol(const char *z){
85710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int i;
85720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(i=0; z[i]; i++){
85730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( z[i]=='\n' ) return 1;
85740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( IsSpace(z[i]) ) continue;
85750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( z[i]=='-' && z[i+1]=='-' ) return 1;
85760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return 0;
85770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
85780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return 1;
85790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
85800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
85810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
85820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
8583a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori** This is the callback routine that the shell
85847790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** invokes for each row of a query result.
85857790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
85863fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichstatic int shell_callback(
85873fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  void *pArg,
85883fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  int nArg,        /* Number of result columns */
85893fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  char **azArg,    /* Text of each result column */
85903fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  char **azCol,    /* Column names */
85913fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  int *aiType      /* Column types */
85923fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich){
85937790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  int i;
85943fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  ShellState *p = (ShellState*)pArg;
8595a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori
85960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( azArg==0 ) return 0;
859760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  switch( p->cMode ){
85987790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    case MODE_Line: {
85997790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      int w = 5;
86007790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      if( azArg==0 ) break;
86017790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      for(i=0; i<nArg; i++){
8602a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori        int len = strlen30(azCol[i] ? azCol[i] : "");
86037790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        if( len>w ) w = len;
86047790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
860560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator);
86067790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      for(i=0; i<nArg; i++){
860760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(p->out,"%*s = %s%s", w, azCol[i],
86083fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich                azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
86097790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
86107790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      break;
86117790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
86127790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    case MODE_Explain:
86137790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    case MODE_Column: {
861460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      static const int aExplainWidths[] = {4, 13, 4, 4, 4, 13, 2, 13};
861560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      const int *colWidth;
861660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      int showHdr;
861760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      char *rowSep;
861860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( p->cMode==MODE_Column ){
861960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        colWidth = p->colWidth;
862060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        showHdr = p->showHeader;
862160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        rowSep = p->rowSeparator;
862260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }else{
862360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        colWidth = aExplainWidths;
862460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        showHdr = 1;
862560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        rowSep = SEP_Row;
862660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }
86277790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      if( p->cnt++==0 ){
86287790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        for(i=0; i<nArg; i++){
86297790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project          int w, n;
86307790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project          if( i<ArraySize(p->colWidth) ){
863160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            w = colWidth[i];
86327790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project          }else{
86337790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project            w = 0;
86347790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project          }
86358fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich          if( w==0 ){
86360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            w = strlenChar(azCol[i] ? azCol[i] : "");
86377790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project            if( w<10 ) w = 10;
86380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            n = strlenChar(azArg && azArg[i] ? azArg[i] : p->nullValue);
86397790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project            if( w<n ) w = n;
86407790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project          }
86417790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project          if( i<ArraySize(p->actualWidth) ){
86427790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project            p->actualWidth[i] = w;
86437790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project          }
864460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          if( showHdr ){
8645b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis            utf8_width_print(p->out, w, azCol[i]);
8646b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis            utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : "  ");
86477790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project          }
86487790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        }
864960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        if( showHdr ){
86507790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project          for(i=0; i<nArg; i++){
86517790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project            int w;
86527790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project            if( i<ArraySize(p->actualWidth) ){
86537790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project               w = p->actualWidth[i];
86548fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich               if( w<0 ) w = -w;
86557790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project            }else{
86567790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project               w = 10;
86577790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project            }
865860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            utf8_printf(p->out,"%-*.*s%s",w,w,
865960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis                   "----------------------------------------------------------"
86607790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project                   "----------------------------------------------------------",
866160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis                    i==nArg-1 ? rowSep : "  ");
86627790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project          }
86637790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        }
86647790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
86657790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      if( azArg==0 ) break;
86667790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      for(i=0; i<nArg; i++){
86677790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        int w;
86687790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        if( i<ArraySize(p->actualWidth) ){
86697790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project           w = p->actualWidth[i];
86707790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        }else{
86717790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project           w = 10;
86727790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        }
86730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( p->cMode==MODE_Explain && azArg[i] && strlenChar(azArg[i])>w ){
86740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          w = strlenChar(azArg[i]);
86757790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        }
86768fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        if( i==1 && p->aiIndent && p->pStmt ){
86778fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich          if( p->iIndent<p->nIndent ){
867860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
86798fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich          }
86808fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich          p->iIndent++;
86818fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        }
8682b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis        utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue);
8683b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis        utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : "  ");
86847790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
86857790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      break;
86867790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
868760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    case MODE_Semi: {   /* .schema and .fullschema output */
8688e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      printSchemaLine(p->out, azArg[0], ";\n");
868960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      break;
869060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }
869160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    case MODE_Pretty: {  /* .schema and .fullschema with --indent */
869260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      char *z;
869360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      int j;
869460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      int nParen = 0;
869560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      char cEnd = 0;
869660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      char c;
869760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      int nLine = 0;
869860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      assert( nArg==1 );
869960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( azArg[0]==0 ) break;
870060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0
870160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis       || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0
870260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      ){
870360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(p->out, "%s;\n", azArg[0]);
870460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        break;
870560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }
870660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      z = sqlite3_mprintf("%s", azArg[0]);
870760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      j = 0;
870860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      for(i=0; IsSpace(z[i]); i++){}
870960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      for(; (c = z[i])!=0; i++){
871060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        if( IsSpace(c) ){
87110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( z[j-1]=='\r' ) z[j-1] = '\n';
871260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue;
871360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){
871460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          j--;
871560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        }
871660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        z[j++] = c;
871760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }
871860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      while( j>0 && IsSpace(z[j-1]) ){ j--; }
871960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      z[j] = 0;
872060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( strlen30(z)>=79 ){
87210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        for(i=j=0; (c = z[i])!=0; i++){  /* Copy changes from z[i] back to z[j] */
872260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          if( c==cEnd ){
872360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            cEnd = 0;
872460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          }else if( c=='"' || c=='\'' || c=='`' ){
872560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            cEnd = c;
872660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          }else if( c=='[' ){
872760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            cEnd = ']';
87280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }else if( c=='-' && z[i+1]=='-' ){
87290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            cEnd = '\n';
873060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          }else if( c=='(' ){
873160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            nParen++;
873260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          }else if( c==')' ){
873360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            nParen--;
873460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            if( nLine>0 && nParen==0 && j>0 ){
8735e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani              printSchemaLineN(p->out, z, j, "\n");
873660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis              j = 0;
873760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            }
873860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          }
873960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          z[j++] = c;
87400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( nParen==1 && cEnd==0
87410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov           && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1)))
87420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          ){
874360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            if( c=='\n' ) j--;
8744e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani            printSchemaLineN(p->out, z, j, "\n  ");
874560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            j = 0;
874660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            nLine++;
874760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            while( IsSpace(z[i+1]) ){ i++; }
874860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          }
874960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        }
875060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        z[j] = 0;
875160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }
8752e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      printSchemaLine(p->out, z, ";\n");
875360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      sqlite3_free(z);
875460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      break;
875560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }
87567790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    case MODE_List: {
87577790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      if( p->cnt++==0 && p->showHeader ){
87587790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        for(i=0; i<nArg; i++){
875960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          utf8_printf(p->out,"%s%s",azCol[i],
87603fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich                  i==nArg-1 ? p->rowSeparator : p->colSeparator);
87617790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        }
87627790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
87637790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      if( azArg==0 ) break;
87647790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      for(i=0; i<nArg; i++){
87657790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        char *z = azArg[i];
87663fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        if( z==0 ) z = p->nullValue;
876760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(p->out, "%s", z);
87687790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        if( i<nArg-1 ){
876960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          utf8_printf(p->out, "%s", p->colSeparator);
87707790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        }else{
877160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          utf8_printf(p->out, "%s", p->rowSeparator);
87727790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        }
87737790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
87747790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      break;
87757790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
87767790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    case MODE_Html: {
87777790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      if( p->cnt++==0 && p->showHeader ){
877860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        raw_printf(p->out,"<TR>");
87797790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        for(i=0; i<nArg; i++){
878060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          raw_printf(p->out,"<TH>");
8781a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori          output_html_string(p->out, azCol[i]);
878260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          raw_printf(p->out,"</TH>\n");
87837790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        }
878460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        raw_printf(p->out,"</TR>\n");
87857790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
87867790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      if( azArg==0 ) break;
878760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(p->out,"<TR>");
87887790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      for(i=0; i<nArg; i++){
878960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        raw_printf(p->out,"<TD>");
87903fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
879160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        raw_printf(p->out,"</TD>\n");
87927790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
879360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(p->out,"</TR>\n");
87947790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      break;
87957790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
87967790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    case MODE_Tcl: {
87977790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      if( p->cnt++==0 && p->showHeader ){
87987790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        for(i=0; i<nArg; i++){
87997790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project          output_c_string(p->out,azCol[i] ? azCol[i] : "");
880060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
88017790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        }
880260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(p->out, "%s", p->rowSeparator);
88037790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
88047790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      if( azArg==0 ) break;
88057790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      for(i=0; i<nArg; i++){
88063fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
880760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
88087790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
880960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(p->out, "%s", p->rowSeparator);
88107790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      break;
88117790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
88127790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    case MODE_Csv: {
881360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      setBinaryMode(p->out, 1);
88147790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      if( p->cnt++==0 && p->showHeader ){
88157790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        for(i=0; i<nArg; i++){
88167790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project          output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
88177790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        }
881860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(p->out, "%s", p->rowSeparator);
88197790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
88203fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      if( nArg>0 ){
88219bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown        for(i=0; i<nArg; i++){
88229bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown          output_csv(p, azArg[i], i<nArg-1);
88239bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown        }
882460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(p->out, "%s", p->rowSeparator);
88257790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
882660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      setTextMode(p->out, 1);
88277790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      break;
88287790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
88297790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    case MODE_Insert: {
88307790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      if( azArg==0 ) break;
8831b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
8832b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      if( p->showHeader ){
8833b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis        raw_printf(p->out,"(");
8834b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis        for(i=0; i<nArg; i++){
8835b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis          if( i>0 ) raw_printf(p->out, ",");
8836b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis          if( quoteChar(azCol[i]) ){
8837b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis            char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
8838b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis            utf8_printf(p->out, "%s", z);
8839b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis            sqlite3_free(z);
8840b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis          }else{
8841b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis            raw_printf(p->out, "%s", azCol[i]);
8842e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani          }
8843e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani        }
8844b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis        raw_printf(p->out,")");
8845b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      }
8846b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      p->cnt++;
8847b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      for(i=0; i<nArg; i++){
8848b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis        raw_printf(p->out, i>0 ? "," : " VALUES(");
8849b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis        if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
8850b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis          utf8_printf(p->out,"NULL");
8851b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis        }else if( aiType && aiType[i]==SQLITE_TEXT ){
88520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( ShellHasFlag(p, SHFLG_Newlines) ){
88530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            output_quoted_string(p->out, azArg[i]);
88540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }else{
88550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            output_quoted_escaped_string(p->out, azArg[i]);
88560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
8857b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis        }else if( aiType && aiType[i]==SQLITE_INTEGER ){
8858b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis          utf8_printf(p->out,"%s", azArg[i]);
8859b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis        }else if( aiType && aiType[i]==SQLITE_FLOAT ){
8860b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis          char z[50];
8861b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis          double r = sqlite3_column_double(p->pStmt, i);
8862b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis          sqlite3_snprintf(50,z,"%!.20g", r);
8863b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis          raw_printf(p->out, "%s", z);
8864b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis        }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
8865b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis          const void *pBlob = sqlite3_column_blob(p->pStmt, i);
8866b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis          int nBlob = sqlite3_column_bytes(p->pStmt, i);
8867b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis          output_hex_blob(p->out, pBlob, nBlob);
8868b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis        }else if( isNumber(azArg[i], 0) ){
8869b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis          utf8_printf(p->out,"%s", azArg[i]);
88700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }else if( ShellHasFlag(p, SHFLG_Newlines) ){
88710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          output_quoted_string(p->out, azArg[i]);
8872b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis        }else{
8873b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis          output_quoted_escaped_string(p->out, azArg[i]);
8874b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis        }
8875b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      }
8876b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      raw_printf(p->out,");\n");
8877b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      break;
8878b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    }
8879b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    case MODE_Quote: {
8880b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      if( azArg==0 ) break;
8881b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      if( p->cnt==0 && p->showHeader ){
88823a6c79f802fabdb94367177310663397420e319fNick Kralevich        for(i=0; i<nArg; i++){
8883e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani          if( i>0 ) raw_printf(p->out, ",");
8884e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani          output_quoted_string(p->out, azCol[i]);
88853a6c79f802fabdb94367177310663397420e319fNick Kralevich        }
8886e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani        raw_printf(p->out,"\n");
88873a6c79f802fabdb94367177310663397420e319fNick Kralevich      }
8888e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      p->cnt++;
88897790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      for(i=0; i<nArg; i++){
8890b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis        if( i>0 ) raw_printf(p->out, ",");
8891a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori        if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
8892b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis          utf8_printf(p->out,"NULL");
8893a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori        }else if( aiType && aiType[i]==SQLITE_TEXT ){
8894a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori          output_quoted_string(p->out, azArg[i]);
8895b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        }else if( aiType && aiType[i]==SQLITE_INTEGER ){
8896b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis          utf8_printf(p->out,"%s", azArg[i]);
8897b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        }else if( aiType && aiType[i]==SQLITE_FLOAT ){
8898b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          char z[50];
8899b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          double r = sqlite3_column_double(p->pStmt, i);
8900b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          sqlite3_snprintf(50,z,"%!.20g", r);
8901b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis          raw_printf(p->out, "%s", z);
8902a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori        }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
8903a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori          const void *pBlob = sqlite3_column_blob(p->pStmt, i);
8904a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori          int nBlob = sqlite3_column_bytes(p->pStmt, i);
8905a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori          output_hex_blob(p->out, pBlob, nBlob);
89067790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        }else if( isNumber(azArg[i], 0) ){
8907b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis          utf8_printf(p->out,"%s", azArg[i]);
89087790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        }else{
89097790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project          output_quoted_string(p->out, azArg[i]);
89107790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        }
89117790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
8912b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis      raw_printf(p->out,"\n");
89137790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      break;
89147790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
89153fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    case MODE_Ascii: {
89163fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      if( p->cnt++==0 && p->showHeader ){
89173fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        for(i=0; i<nArg; i++){
891860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
891960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : "");
89203fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        }
892160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(p->out, "%s", p->rowSeparator);
89223fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      }
89233fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      if( azArg==0 ) break;
89243fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      for(i=0; i<nArg; i++){
892560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
892660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
89273fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      }
892860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(p->out, "%s", p->rowSeparator);
89293fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      break;
89303fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    }
89317790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
89327790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  return 0;
89337790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
89347790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
89357790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
8936a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori** This is the callback routine that the SQLite library
8937a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori** invokes for each row of a query result.
8938a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori*/
8939a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Noristatic int callback(void *pArg, int nArg, char **azArg, char **azCol){
8940a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  /* since we don't have type info, call the shell_callback with a NULL value */
8941a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  return shell_callback(pArg, nArg, azArg, azCol, NULL);
8942a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori}
8943a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori
8944a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori/*
8945b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** This is the callback routine from sqlite3_exec() that appends all
8946b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** output onto the end of a ShellText object.
8947b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis*/
8948b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidisstatic int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){
8949b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  ShellText *p = (ShellText*)pArg;
8950b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  int i;
8951b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  UNUSED_PARAMETER(az);
89520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( azArg==0 ) return 0;
8953b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  if( p->n ) appendText(p, "|", 0);
8954b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  for(i=0; i<nArg; i++){
8955b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    if( i ) appendText(p, ",", 0);
8956b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    if( azArg[i] ) appendText(p, azArg[i], 0);
8957b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }
8958b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  return 0;
8959b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis}
8960b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
8961b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis/*
8962b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** Generate an appropriate SELFTEST table in the main database.
8963b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis*/
8964b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidisstatic void createSelftestTable(ShellState *p){
8965b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  char *zErrMsg = 0;
8966b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  sqlite3_exec(p->db,
8967b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "SAVEPOINT selftest_init;\n"
8968b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "CREATE TABLE IF NOT EXISTS selftest(\n"
8969b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "  tno INTEGER PRIMARY KEY,\n"   /* Test number */
8970b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "  op TEXT,\n"                   /* Operator:  memo run */
8971b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "  cmd TEXT,\n"                  /* Command text */
8972b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "  ans TEXT\n"                   /* Desired answer */
8973b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    ");"
8974b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "CREATE TEMP TABLE [_shell$self](op,cmd,ans);\n"
8975b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "INSERT INTO [_shell$self](rowid,op,cmd)\n"
8976b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "  VALUES(coalesce((SELECT (max(tno)+100)/10 FROM selftest),10),\n"
8977b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "         'memo','Tests generated by --init');\n"
8978b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "INSERT INTO [_shell$self]\n"
8979b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "  SELECT 'run',\n"
8980b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "    'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql "
8981b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis                                 "FROM sqlite_master ORDER BY 2'',224))',\n"
8982b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "    hex(sha3_query('SELECT type,name,tbl_name,sql "
8983b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis                          "FROM sqlite_master ORDER BY 2',224));\n"
8984b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "INSERT INTO [_shell$self]\n"
8985b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "  SELECT 'run',"
8986b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "    'SELECT hex(sha3_query(''SELECT * FROM \"' ||"
8987b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "        printf('%w',name) || '\" NOT INDEXED'',224))',\n"
8988b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "    hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n"
8989b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "  FROM (\n"
8990b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "    SELECT name FROM sqlite_master\n"
8991b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "     WHERE type='table'\n"
8992b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "       AND name<>'selftest'\n"
8993b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "       AND coalesce(rootpage,0)>0\n"
8994b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "  )\n"
8995b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    " ORDER BY name;\n"
8996b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "INSERT INTO [_shell$self]\n"
8997b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "  VALUES('run','PRAGMA integrity_check','ok');\n"
8998b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "INSERT INTO selftest(tno,op,cmd,ans)"
8999b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "  SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n"
9000b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    "DROP TABLE [_shell$self];"
9001b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    ,0,0,&zErrMsg);
9002b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  if( zErrMsg ){
9003b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    utf8_printf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg);
9004b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    sqlite3_free(zErrMsg);
9005b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }
9006b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0);
9007b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis}
9008b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
9009b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
9010b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis/*
90113fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich** Set the destination table field of the ShellState structure to
90127790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** the name of the table given.  Escape any quote characters in the
90137790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** table name.
90147790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
90153fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichstatic void set_table_name(ShellState *p, const char *zName){
90167790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  int i, n;
90170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char cQuote;
90187790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  char *z;
90197790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
90207790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if( p->zDestTable ){
90217790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    free(p->zDestTable);
90227790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    p->zDestTable = 0;
90237790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
90247790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if( zName==0 ) return;
9025b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  cQuote = quoteChar(zName);
9026b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  n = strlen30(zName);
90270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( cQuote ) n += n+2;
90287790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  z = p->zDestTable = malloc( n+1 );
90297790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if( z==0 ){
903060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    raw_printf(stderr,"Error: out of memory\n");
90317790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    exit(1);
90327790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
90337790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  n = 0;
9034b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  if( cQuote ) z[n++] = cQuote;
90357790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  for(i=0; zName[i]; i++){
90367790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    z[n++] = zName[i];
9037b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    if( zName[i]==cQuote ) z[n++] = cQuote;
90387790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
9039b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  if( cQuote ) z[n++] = cQuote;
90407790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  z[n] = 0;
90417790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
90427790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
90437790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
90447790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
9045c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown** Execute a query statement that will generate SQL output.  Print
9046c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown** the result columns, comma-separated, on a line and then add a
9047c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown** semicolon terminator to the end of that line.
90487790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project**
9049c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown** If the number of columns is 1 and that column contains text "--"
905060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** then write the semicolon on a separate line.  That way, if a
9051c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown** "--" comment occurs at the end of the statement, the comment
9052c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown** won't consume the semicolon terminator.
90537790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
9054a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Noristatic int run_table_dump_query(
90553fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  ShellState *p,           /* Query context */
905690ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  const char *zSelect,     /* SELECT statement to extract content */
905790ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  const char *zFirstRow    /* Print before first row, if not NULL */
9058a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori){
90597790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  sqlite3_stmt *pSelect;
90607790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  int rc;
9061c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown  int nResult;
9062c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown  int i;
9063c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown  const char *z;
90648fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
90657790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if( rc!=SQLITE_OK || !pSelect ){
906660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
906760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis                sqlite3_errmsg(p->db));
90688fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
90697790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    return rc;
90707790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
90717790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  rc = sqlite3_step(pSelect);
9072c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown  nResult = sqlite3_column_count(pSelect);
90737790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  while( rc==SQLITE_ROW ){
9074a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    if( zFirstRow ){
907560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(p->out, "%s", zFirstRow);
9076a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      zFirstRow = 0;
9077a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }
9078c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown    z = (const char*)sqlite3_column_text(pSelect, 0);
907960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(p->out, "%s", z);
908060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    for(i=1; i<nResult; i++){
908160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i));
9082c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown    }
9083c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown    if( z==0 ) z = "";
9084c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown    while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
9085c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown    if( z[0] ){
908660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(p->out, "\n;\n");
9087c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown    }else{
908860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(p->out, ";\n");
908960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }
90907790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    rc = sqlite3_step(pSelect);
90917790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
909290ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  rc = sqlite3_finalize(pSelect);
909390ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  if( rc!=SQLITE_OK ){
909460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
909560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis                sqlite3_errmsg(p->db));
90968fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
909790ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  }
909890ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  return rc;
90997790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
91007790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
9101a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori/*
9102a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori** Allocate space and save off current error string.
9103a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori*/
9104a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Noristatic char *save_err_msg(
9105a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  sqlite3 *db            /* Database to query */
9106a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori){
9107a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  int nErrMsg = 1+strlen30(sqlite3_errmsg(db));
91083a6c79f802fabdb94367177310663397420e319fNick Kralevich  char *zErrMsg = sqlite3_malloc64(nErrMsg);
9109a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  if( zErrMsg ){
9110a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg);
9111a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  }
9112a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  return zErrMsg;
9113a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori}
9114a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori
911560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#ifdef __linux__
911660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis/*
911760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** Attempt to display I/O stats on Linux using /proc/PID/io
911860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis*/
911960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidisstatic void displayLinuxIoStats(FILE *out){
912060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  FILE *in;
912160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  char z[200];
912260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
912360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  in = fopen(z, "rb");
912460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  if( in==0 ) return;
912560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  while( fgets(z, sizeof(z), in)!=0 ){
912660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    static const struct {
912760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      const char *zPattern;
912860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      const char *zDesc;
912960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    } aTrans[] = {
913060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      { "rchar: ",                  "Bytes received by read():" },
913160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      { "wchar: ",                  "Bytes sent to write():"    },
913260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      { "syscr: ",                  "Read() system calls:"      },
913360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      { "syscw: ",                  "Write() system calls:"     },
913460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      { "read_bytes: ",             "Bytes read from storage:"  },
913560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      { "write_bytes: ",            "Bytes written to storage:" },
913660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      { "cancelled_write_bytes: ",  "Cancelled write bytes:"    },
913760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    };
913860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    int i;
913960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    for(i=0; i<ArraySize(aTrans); i++){
91400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int n = strlen30(aTrans[i].zPattern);
914160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( strncmp(aTrans[i].zPattern, z, n)==0 ){
914208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis        utf8_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
914360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        break;
914460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }
914560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }
914660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  }
914760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  fclose(in);
914860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis}
914960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#endif
915060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
9151b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis/*
9152b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** Display a single line of status using 64-bit values.
9153b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis*/
9154b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidisstatic void displayStatLine(
9155b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  ShellState *p,            /* The shell context */
9156b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  char *zLabel,             /* Label for this one line */
9157b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  char *zFormat,            /* Format for the result */
9158b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  int iStatusCtrl,          /* Which status to display */
9159b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  int bReset                /* True to reset the stats */
9160b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis){
9161b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  sqlite3_int64 iCur = -1;
9162b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  sqlite3_int64 iHiwtr = -1;
9163b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  int i, nPercent;
9164b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  char zLine[200];
9165b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  sqlite3_status64(iStatusCtrl, &iCur, &iHiwtr, bReset);
9166b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  for(i=0, nPercent=0; zFormat[i]; i++){
9167b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    if( zFormat[i]=='%' ) nPercent++;
9168b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }
9169b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  if( nPercent>1 ){
9170b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iCur, iHiwtr);
9171b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }else{
9172b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr);
9173b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }
9174b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  raw_printf(p->out, "%-36s %s\n", zLabel, zLine);
9175b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis}
917660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
9177a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori/*
9178de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori** Display memory stats.
9179de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori*/
9180de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Noristatic int display_stats(
9181de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori  sqlite3 *db,                /* Database to query */
91823fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  ShellState *pArg,           /* Pointer to ShellState */
9183de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori  int bReset                  /* True to reset the stats */
9184de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori){
9185de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori  int iCur;
9186de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori  int iHiwtr;
9187de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori
9188de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori  if( pArg && pArg->out ){
9189b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    displayStatLine(pArg, "Memory Used:",
9190b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis       "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset);
9191b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    displayStatLine(pArg, "Number of Outstanding Allocations:",
9192b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis       "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset);
91933fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    if( pArg->shellFlgs & SHFLG_Pagecache ){
9194b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      displayStatLine(pArg, "Number of Pcache Pages Used:",
9195b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis         "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset);
91963fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    }
9197b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    displayStatLine(pArg, "Number of Pcache Overflow Bytes:",
9198b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis       "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
9199b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    displayStatLine(pArg, "Largest Allocation:",
9200b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis       "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
9201b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    displayStatLine(pArg, "Largest Pcache Allocation:",
9202b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis       "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
9203de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori#ifdef YYTRACKMAXSTACKDEPTH
9204b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    displayStatLine(pArg, "Deepest Parser Stack:",
9205b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis       "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
9206de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori#endif
9207de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori  }
9208de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori
9209de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori  if( pArg && pArg->out && db ){
92103fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    if( pArg->shellFlgs & SHFLG_Lookaside ){
92113fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      iHiwtr = iCur = -1;
92123fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
92133fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich                        &iCur, &iHiwtr, bReset);
921460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(pArg->out,
921560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis              "Lookaside Slots Used:                %d (max %d)\n",
92163fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich              iCur, iHiwtr);
92173fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT,
92183fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich                        &iCur, &iHiwtr, bReset);
921960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(pArg->out, "Successful lookaside attempts:       %d\n",
922060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis              iHiwtr);
92213fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
92223fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich                        &iCur, &iHiwtr, bReset);
922360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(pArg->out, "Lookaside failures due to size:      %d\n",
922460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis              iHiwtr);
92253fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
92263fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich                        &iCur, &iHiwtr, bReset);
922760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(pArg->out, "Lookaside failures due to OOM:       %d\n",
922860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis              iHiwtr);
92293fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    }
9230de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori    iHiwtr = iCur = -1;
9231de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
923260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    raw_printf(pArg->out, "Pager Heap Usage:                    %d bytes\n",
923360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            iCur);
92343fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    iHiwtr = iCur = -1;
923590ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
923660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    raw_printf(pArg->out, "Page cache hits:                     %d\n", iCur);
923790ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    iHiwtr = iCur = -1;
923890ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
923960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    raw_printf(pArg->out, "Page cache misses:                   %d\n", iCur);
9240de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori    iHiwtr = iCur = -1;
92418fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
924260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    raw_printf(pArg->out, "Page cache writes:                   %d\n", iCur);
92438fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    iHiwtr = iCur = -1;
9244de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori    sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
924560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    raw_printf(pArg->out, "Schema Heap Usage:                   %d bytes\n",
924660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            iCur);
9247de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori    iHiwtr = iCur = -1;
9248de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori    sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
924960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    raw_printf(pArg->out, "Statement Heap/Lookaside Usage:      %d bytes\n",
925060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            iCur);
9251de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori  }
9252de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori
9253de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori  if( pArg && pArg->out && db && pArg->pStmt ){
92543fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
92553fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich                               bReset);
925660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    raw_printf(pArg->out, "Fullscan Steps:                      %d\n", iCur);
9257de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
925860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    raw_printf(pArg->out, "Sort Operations:                     %d\n", iCur);
92593fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
926060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    raw_printf(pArg->out, "Autoindex Inserts:                   %d\n", iCur);
92618fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
926260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    raw_printf(pArg->out, "Virtual Machine Steps:               %d\n", iCur);
9263de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori  }
9264de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori
926560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#ifdef __linux__
926660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  displayLinuxIoStats(pArg->out);
926760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#endif
926860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
9269253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich  /* Do not remove this machine readable comment: extra-stats-output-here */
9270253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich
9271de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori  return 0;
9272de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori}
9273de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori
9274de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori/*
92753fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich** Display scan stats.
92763fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich*/
92773fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichstatic void display_scanstats(
92783fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  sqlite3 *db,                    /* Database to query */
92793fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  ShellState *pArg                /* Pointer to ShellState */
92803fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich){
9281253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
9282253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich  UNUSED_PARAMETER(db);
9283253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich  UNUSED_PARAMETER(pArg);
9284253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich#else
92853fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  int i, k, n, mx;
928660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  raw_printf(pArg->out, "-------- scanstats --------\n");
92873fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  mx = 0;
92883fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  for(k=0; k<=mx; k++){
92893fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    double rEstLoop = 1.0;
92903fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    for(i=n=0; 1; i++){
92913fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_stmt *p = pArg->pStmt;
92923fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_int64 nLoop, nVisit;
92933fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      double rEst;
92943fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      int iSid;
92953fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      const char *zExplain;
92963fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      if( sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop) ){
92973fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        break;
92983fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      }
92993fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid);
93003fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      if( iSid>mx ) mx = iSid;
93013fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      if( iSid!=k ) continue;
93023fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      if( n==0 ){
93033fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        rEstLoop = (double)nLoop;
930460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        if( k>0 ) raw_printf(pArg->out, "-------- subquery %d -------\n", k);
93053fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      }
93063fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      n++;
93073fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
93083fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst);
93093fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
931060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain);
93113fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      rEstLoop *= rEst;
931260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(pArg->out,
93133fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich          "         nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n",
93143fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich          nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst
93153fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      );
93163fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    }
93173fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  }
931860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  raw_printf(pArg->out, "---------------------------\n");
93193fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#endif
93203fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich}
93213fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
93223fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich/*
93238fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** Parameter azArray points to a zero-terminated array of strings. zStr
93248fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** points to a single nul-terminated string. Return non-zero if zStr
93258fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** is equal, according to strcmp(), to any of the strings in the array.
93268fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** Otherwise, return zero.
93278fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich*/
93288fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevichstatic int str_in_array(const char *zStr, const char **azArray){
93298fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int i;
93308fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  for(i=0; azArray[i]; i++){
93318fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( 0==strcmp(zStr, azArray[i]) ) return 1;
93328fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }
93338fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  return 0;
93348fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich}
93358fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
93368fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich/*
93378fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** If compiled statement pSql appears to be an EXPLAIN statement, allocate
93383fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich** and populate the ShellState.aiIndent[] array with the number of
933960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** spaces each opcode should be indented before it is output.
93408fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich**
93418fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** The indenting rules are:
93428fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich**
93438fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich**     * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
93448fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich**       all opcodes that occur between the p2 jump destination and the opcode
93458fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich**       itself by 2 spaces.
93468fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich**
93478fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich**     * For each "Goto", if the jump destination is earlier in the program
93488fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich**       and ends on one of:
93498fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich**          Yield  SeekGt  SeekLt  RowSetRead  Rewind
93508fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich**       or if the P1 parameter is one instead of zero,
93518fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich**       then indent all opcodes between the earlier instruction
93528fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich**       and "Goto" by 2 spaces.
93538fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich*/
93543fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichstatic void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
93558fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  const char *zSql;               /* The text of the SQL statement */
93568fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  const char *z;                  /* Used to check if this is an EXPLAIN */
93578fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int *abYield = 0;               /* True if op is an OP_Yield */
93588fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int nAlloc = 0;                 /* Allocated size of p->aiIndent[], abYield */
93598fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int iOp;                        /* Index of operation in p->aiIndent[] */
93608fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
93611c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext",
93621c7cea379348522163370244e8fbbff8a136b7faNick Kralevich                           "NextIfOpen", "PrevIfOpen", 0 };
93633fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
93643fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich                            "Rewind", 0 };
93658fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  const char *azGoto[] = { "Goto", 0 };
93668fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
93678fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  /* Try to figure out if this is really an EXPLAIN statement. If this
93688fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  ** cannot be verified, return early.  */
936960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  if( sqlite3_column_count(pSql)!=8 ){
937060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    p->cMode = p->mode;
937160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    return;
937260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  }
93738fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  zSql = sqlite3_sql(pSql);
93748fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( zSql==0 ) return;
93758fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++);
937660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  if( sqlite3_strnicmp(z, "explain", 7) ){
937760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    p->cMode = p->mode;
937860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    return;
937960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  }
93808fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
93818fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){
93828fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    int i;
93838fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    int iAddr = sqlite3_column_int(pSql, 0);
93848fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    const char *zOp = (const char*)sqlite3_column_text(pSql, 1);
93858fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
93868fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    /* Set p2 to the P2 field of the current opcode. Then, assuming that
93878fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    ** p2 is an instruction address, set variable p2op to the index of that
93888fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    ** instruction in the aiIndent[] array. p2 and p2op may be different if
93898fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    ** the current instruction is part of a sub-program generated by an
93908fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    ** SQL trigger or foreign key.  */
93918fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    int p2 = sqlite3_column_int(pSql, 3);
93928fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    int p2op = (p2 + (iOp-iAddr));
93938fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
93948fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    /* Grow the p->aiIndent array as required */
93958fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( iOp>=nAlloc ){
939660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( iOp==0 ){
939760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        /* Do further verfication that this is explain output.  Abort if
939860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        ** it is not */
939960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        static const char *explainCols[] = {
940060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis           "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" };
940160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        int jj;
940260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        for(jj=0; jj<ArraySize(explainCols); jj++){
940360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          if( strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){
940460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            p->cMode = p->mode;
940560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            sqlite3_reset(pSql);
940660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            return;
940760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          }
940860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        }
940960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }
94108fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      nAlloc += 100;
94113a6c79f802fabdb94367177310663397420e319fNick Kralevich      p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
94123a6c79f802fabdb94367177310663397420e319fNick Kralevich      abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
94138fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
94148fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    abYield[iOp] = str_in_array(zOp, azYield);
94158fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    p->aiIndent[iOp] = 0;
94168fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    p->nIndent = iOp+1;
94178fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
94188fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( str_in_array(zOp, azNext) ){
94198fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
94208fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
94218fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( str_in_array(zOp, azGoto) && p2op<p->nIndent
94228fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich     && (abYield[p2op] || sqlite3_column_int(pSql, 2))
94238fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    ){
942460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
94258fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
94268fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }
94278fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
94288fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  p->iIndent = 0;
94298fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  sqlite3_free(abYield);
94308fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  sqlite3_reset(pSql);
94318fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich}
94328fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
94338fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich/*
94348fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** Free the array allocated by explain_data_prepare().
94358fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich*/
94363fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichstatic void explain_data_delete(ShellState *p){
94378fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  sqlite3_free(p->aiIndent);
94388fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  p->aiIndent = 0;
94398fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  p->nIndent = 0;
94408fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  p->iIndent = 0;
94418fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich}
94428fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
94438fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich/*
944460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** Disable and restore .wheretrace and .selecttrace settings.
944560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis*/
944660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
944760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidisextern int sqlite3SelectTrace;
944860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidisstatic int savedSelectTrace;
944960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#endif
945060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
945160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidisextern int sqlite3WhereTrace;
945260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidisstatic int savedWhereTrace;
945360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#endif
945460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidisstatic void disable_debug_trace_modes(void){
945560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
945660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  savedSelectTrace = sqlite3SelectTrace;
945760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  sqlite3SelectTrace = 0;
945860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#endif
945960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
946060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  savedWhereTrace = sqlite3WhereTrace;
946160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  sqlite3WhereTrace = 0;
946260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#endif
946360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis}
946460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidisstatic void restore_debug_trace_modes(void){
946560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
946660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  sqlite3SelectTrace = savedSelectTrace;
946760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#endif
946860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
946960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  sqlite3WhereTrace = savedWhereTrace;
947060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#endif
947160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis}
947260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
947360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis/*
947460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** Run a prepared statement
947560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis*/
947660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidisstatic void exec_prepared_stmt(
947760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  ShellState *pArg,                                /* Pointer to ShellState */
947860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  sqlite3_stmt *pStmt,                             /* Statment to run */
947960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  int (*xCallback)(void*,int,char**,char**,int*)   /* Callback function */
948060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis){
948160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  int rc;
948260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
948360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  /* perform the first step.  this will tell us if we
948460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  ** have a result set or not and how wide it is.
948560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  */
948660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  rc = sqlite3_step(pStmt);
948760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  /* if we have a result set... */
948860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  if( SQLITE_ROW == rc ){
948960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    /* if we have a callback... */
949060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    if( xCallback ){
949160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      /* allocate space for col name ptr, value ptr, and type */
949260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      int nCol = sqlite3_column_count(pStmt);
949360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
949460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( !pData ){
949560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        rc = SQLITE_NOMEM;
949660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }else{
949760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        char **azCols = (char **)pData;      /* Names of result columns */
949860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        char **azVals = &azCols[nCol];       /* Results */
949960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        int *aiTypes = (int *)&azVals[nCol]; /* Result types */
950060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        int i, x;
950160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        assert(sizeof(int) <= sizeof(char *));
950260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        /* save off ptrs to column names */
950360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        for(i=0; i<nCol; i++){
950460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          azCols[i] = (char *)sqlite3_column_name(pStmt, i);
950560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        }
950660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        do{
950760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          /* extract the data and data types */
950860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          for(i=0; i<nCol; i++){
950960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            aiTypes[i] = x = sqlite3_column_type(pStmt, i);
951060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){
951160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis              azVals[i] = "";
951260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            }else{
951360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis              azVals[i] = (char*)sqlite3_column_text(pStmt, i);
951460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            }
951560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
951660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis              rc = SQLITE_NOMEM;
951760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis              break; /* from for */
951860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            }
951960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          } /* end for */
952060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
952160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          /* if data and types extracted successfully... */
952260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          if( SQLITE_ROW == rc ){
952360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            /* call the supplied callback with the result row data */
952460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            if( xCallback(pArg, nCol, azVals, azCols, aiTypes) ){
952560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis              rc = SQLITE_ABORT;
952660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            }else{
952760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis              rc = sqlite3_step(pStmt);
952860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            }
952960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          }
953060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        } while( SQLITE_ROW == rc );
953160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        sqlite3_free(pData);
953260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }
953360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }else{
953460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      do{
953560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        rc = sqlite3_step(pStmt);
953660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      } while( rc == SQLITE_ROW );
953760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }
953860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  }
953960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis}
954060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
95410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifndef SQLITE_OMIT_VIRTUALTABLE
95420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
95430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This function is called to process SQL if the previous shell command
95440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** was ".expert". It passes the SQL in the second argument directly to
95450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** the sqlite3expert object.
95460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
95470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
95480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** code. In this case, (*pzErr) may be set to point to a buffer containing
95490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** an English language error message. It is the responsibility of the
95500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** caller to eventually free this buffer using sqlite3_free().
95510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
95520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int expertHandleSQL(
95530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ShellState *pState,
95540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zSql,
95550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErr
95560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
95570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( pState->expert.pExpert );
95580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( pzErr==0 || *pzErr==0 );
95590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return sqlite3_expert_sql(pState->expert.pExpert, zSql, pzErr);
95600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
95610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
95620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
95630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This function is called either to silently clean up the object
95640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** created by the ".expert" command (if bCancel==1), or to generate a
95650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** report from it and then clean it up (if bCancel==0).
95660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
95670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
95680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** code. In this case, (*pzErr) may be set to point to a buffer containing
95690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** an English language error message. It is the responsibility of the
95700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** caller to eventually free this buffer using sqlite3_free().
95710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
95720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int expertFinish(
95730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ShellState *pState,
95740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int bCancel,
95750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzErr
95760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
95770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
95780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3expert *p = pState->expert.pExpert;
95790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( p );
95800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( bCancel || pzErr==0 || *pzErr==0 );
95810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( bCancel==0 ){
95820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    FILE *out = pState->out;
95830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int bVerbose = pState->expert.bVerbose;
95840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
95850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = sqlite3_expert_analyze(p, pzErr);
95860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( rc==SQLITE_OK ){
95870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int nQuery = sqlite3_expert_count(p);
95880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int i;
95890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
95900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( bVerbose ){
95910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES);
95920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        raw_printf(out, "-- Candidates -----------------------------\n");
95930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        raw_printf(out, "%s\n", zCand);
95940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
95950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      for(i=0; i<nQuery; i++){
95960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL);
95970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        const char *zIdx = sqlite3_expert_report(p, i, EXPERT_REPORT_INDEXES);
95980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN);
95990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( zIdx==0 ) zIdx = "(no new indexes)\n";
96000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( bVerbose ){
96010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          raw_printf(out, "-- Query %d --------------------------------\n",i+1);
96020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          raw_printf(out, "%s\n\n", zSql);
96030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
96040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        raw_printf(out, "%s\n", zIdx);
96050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        raw_printf(out, "%s\n", zEQP);
96060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
96070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
96080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
96090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_expert_destroy(p);
96100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  pState->expert.pExpert = 0;
96110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
96120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
96130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
96140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
96150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Implementation of ".expert" dot command.
96160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
96170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int expertDotCommand(
96180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ShellState *pState,             /* Current shell tool state */
96190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **azArg,                   /* Array of arguments passed to dot command */
96200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nArg                        /* Number of entries in azArg[] */
96210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
96220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
96230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zErr = 0;
96240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int i;
96250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int iSample = 0;
96260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
96270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  assert( pState->expert.pExpert==0 );
96280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  memset(&pState->expert, 0, sizeof(ExpertInfo));
96290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
96300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(i=1; rc==SQLITE_OK && i<nArg; i++){
96310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    char *z = azArg[i];
96320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int n;
96330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( z[0]=='-' && z[1]=='-' ) z++;
96340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    n = strlen30(z);
96350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( n>=2 && 0==strncmp(z, "-verbose", n) ){
96360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pState->expert.bVerbose = 1;
96370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
96380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    else if( n>=2 && 0==strncmp(z, "-sample", n) ){
96390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( i==(nArg-1) ){
96400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        raw_printf(stderr, "option requires an argument: %s\n", z);
96410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        rc = SQLITE_ERROR;
96420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else{
96430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        iSample = (int)integerValue(azArg[++i]);
96440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( iSample<0 || iSample>100 ){
96450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          raw_printf(stderr, "value out of range: %s\n", azArg[i]);
96460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          rc = SQLITE_ERROR;
96470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
96480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
96490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
96500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    else{
96510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      raw_printf(stderr, "unknown option: %s\n", z);
96520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = SQLITE_ERROR;
96530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
96540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
96550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
96560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
96570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr);
96580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pState->expert.pExpert==0 ){
96590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr);
96600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = SQLITE_ERROR;
96610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
96620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_expert_config(
96630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample
96640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      );
96650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
96660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
96670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
96680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
96690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
96700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
96710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
967260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis/*
967360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** Execute a statement or set of statements.  Print
967460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** any result rows/columns depending on the current mode
9675a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori** set via the supplied callback.
9676a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori**
967760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** This is very similar to SQLite's built-in sqlite3_exec()
967860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** function except it takes a slightly different callback
9679a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori** and callback data argument.
9680a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori*/
9681a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Noristatic int shell_exec(
96823fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  sqlite3 *db,                              /* An open database */
96833fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  const char *zSql,                         /* SQL to be evaluated */
9684a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  int (*xCallback)(void*,int,char**,char**,int*),   /* Callback function */
96853fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich                                            /* (not the same as sqlite3_exec) */
96863fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  ShellState *pArg,                         /* Pointer to ShellState */
96873fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  char **pzErrMsg                           /* Error msg written here */
9688a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori){
9689a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  sqlite3_stmt *pStmt = NULL;     /* Statement to execute. */
9690a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  int rc = SQLITE_OK;             /* Return Code */
969190ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  int rc2;
9692a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  const char *zLeftover;          /* Tail of unprocessed SQL */
9693a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori
9694a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  if( pzErrMsg ){
9695a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    *pzErrMsg = NULL;
9696a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  }
9697a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori
96980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifndef SQLITE_OMIT_VIRTUALTABLE
96990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pArg->expert.pExpert ){
97000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = expertHandleSQL(pArg, zSql, pzErrMsg);
97010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg);
97020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
97030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
97040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
9705a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  while( zSql[0] && (SQLITE_OK == rc) ){
970660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    static const char *zStmtSql;
9707a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
9708a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    if( SQLITE_OK != rc ){
9709a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      if( pzErrMsg ){
9710a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori        *pzErrMsg = save_err_msg(db);
9711a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      }
9712a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }else{
9713a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      if( !pStmt ){
9714a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori        /* this happens for a comment or white-space */
9715a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori        zSql = zLeftover;
971690ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown        while( IsSpace(zSql[0]) ) zSql++;
9717a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori        continue;
9718a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      }
971960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      zStmtSql = sqlite3_sql(pStmt);
9720e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      if( zStmtSql==0 ) zStmtSql = "";
972160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      while( IsSpace(zStmtSql[0]) ) zStmtSql++;
9722a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori
9723de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori      /* save off the prepared statment handle and reset row count */
9724de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori      if( pArg ){
9725de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori        pArg->pStmt = pStmt;
9726de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori        pArg->cnt = 0;
9727de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori      }
9728de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori
972971504cf29d6d55df7d2aac17ecb160f7e5470553Vasu Nori      /* echo the sql statement if echo on */
9730b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){
973160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
973271504cf29d6d55df7d2aac17ecb160f7e5470553Vasu Nori      }
973371504cf29d6d55df7d2aac17ecb160f7e5470553Vasu Nori
97348fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      /* Show the EXPLAIN QUERY PLAN if .eqp is on */
973560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( pArg && pArg->autoEQP && sqlite3_strlike("EXPLAIN%",zStmtSql,0)!=0 ){
97368fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        sqlite3_stmt *pExplain;
973760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        char *zEQP;
97380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        int triggerEQP = 0;
973960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        disable_debug_trace_modes();
97400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
97410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( pArg->autoEQP>=AUTOEQP_trigger ){
97420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
97430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
974460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
97458fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
97468fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        if( rc==SQLITE_OK ){
97478fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich          while( sqlite3_step(pExplain)==SQLITE_ROW ){
974860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            raw_printf(pArg->out,"--EQP-- %d,",sqlite3_column_int(pExplain, 0));
974960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            raw_printf(pArg->out,"%d,", sqlite3_column_int(pExplain, 1));
975060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            raw_printf(pArg->out,"%d,", sqlite3_column_int(pExplain, 2));
975160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            utf8_printf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3));
97528fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich          }
97538fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        }
97548fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        sqlite3_finalize(pExplain);
97558fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        sqlite3_free(zEQP);
97560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( pArg->autoEQP>=AUTOEQP_full ){
975760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          /* Also do an EXPLAIN for ".eqp full" mode */
975860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql);
975960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
976060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          if( rc==SQLITE_OK ){
976160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            pArg->cMode = MODE_Explain;
976260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            explain_data_prepare(pArg, pExplain);
976360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            exec_prepared_stmt(pArg, pExplain, xCallback);
976460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            explain_data_delete(pArg);
976560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          }
976660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          sqlite3_finalize(pExplain);
976760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          sqlite3_free(zEQP);
976860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        }
97690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, triggerEQP, 0);
977060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        restore_debug_trace_modes();
97718fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }
97728fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
977360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( pArg ){
977460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        pArg->cMode = pArg->mode;
977560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        if( pArg->autoExplain
977660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis         && sqlite3_column_count(pStmt)==8
977760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis         && sqlite3_strlike("EXPLAIN%", zStmtSql,0)==0
977860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        ){
977960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          pArg->cMode = MODE_Explain;
978060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        }
97818fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
978260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        /* If the shell is currently in ".explain" mode, gather the extra
978360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        ** data required to add indents to the output.*/
978460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        if( pArg->cMode==MODE_Explain ){
978560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          explain_data_prepare(pArg, pStmt);
9786a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori        }
9787a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      }
9788a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori
978960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      exec_prepared_stmt(pArg, pStmt, xCallback);
97908fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      explain_data_delete(pArg);
97918fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
9792de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori      /* print usage stats if stats on */
9793de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori      if( pArg && pArg->statsOn ){
9794de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori        display_stats(db, pArg, 0);
9795de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori      }
9796de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori
97973fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      /* print loop-counters if required */
97983fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      if( pArg && pArg->scanstatsOn ){
97993fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        display_scanstats(db, pArg);
98003fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      }
98013fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
980260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      /* Finalize the statement just executed. If this fails, save a
9803a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      ** copy of the error message. Otherwise, set zSql to point to the
9804a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      ** next statement to execute. */
980590ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      rc2 = sqlite3_finalize(pStmt);
980690ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      if( rc!=SQLITE_NOMEM ) rc = rc2;
9807a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      if( rc==SQLITE_OK ){
9808a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori        zSql = zLeftover;
980990ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown        while( IsSpace(zSql[0]) ) zSql++;
9810a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      }else if( pzErrMsg ){
9811a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori        *pzErrMsg = save_err_msg(db);
9812a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      }
9813de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori
9814de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori      /* clear saved stmt handle */
9815de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori      if( pArg ){
9816de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori        pArg->pStmt = NULL;
9817de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori      }
9818a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }
9819a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  } /* end while */
9820a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori
9821a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  return rc;
9822a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori}
9823a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori
9824b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis/*
9825b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** Release memory previously allocated by tableColumnList().
9826b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis*/
9827b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidisstatic void freeColumnList(char **azCol){
9828b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  int i;
9829b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  for(i=1; azCol[i]; i++){
9830b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    sqlite3_free(azCol[i]);
9831b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }
9832b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  /* azCol[0] is a static string */
9833b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  sqlite3_free(azCol);
9834b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis}
9835b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
9836b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis/*
9837b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** Return a list of pointers to strings which are the names of all
9838b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** columns in table zTab.   The memory to hold the names is dynamically
9839b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** allocated and must be released by the caller using a subsequent call
9840b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** to freeColumnList().
9841b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis**
9842b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** The azCol[0] entry is usually NULL.  However, if zTab contains a rowid
9843b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** value that needs to be preserved, then azCol[0] is filled in with the
9844b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** name of the rowid column.
9845b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis**
9846b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** The first regular column in the table is azCol[1].  The list is terminated
9847b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** by an entry with azCol[i]==0.
9848b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis*/
9849b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidisstatic char **tableColumnList(ShellState *p, const char *zTab){
9850b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  char **azCol = 0;
9851b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  sqlite3_stmt *pStmt;
9852b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  char *zSql;
9853b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  int nCol = 0;
9854b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  int nAlloc = 0;
9855b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  int nPK = 0;       /* Number of PRIMARY KEY columns seen */
9856b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  int isIPK = 0;     /* True if one PRIMARY KEY column of type INTEGER */
9857b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid);
9858b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  int rc;
9859b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
9860b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
9861b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9862b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  sqlite3_free(zSql);
9863b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  if( rc ) return 0;
9864b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  while( sqlite3_step(pStmt)==SQLITE_ROW ){
9865b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    if( nCol>=nAlloc-2 ){
9866b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      nAlloc = nAlloc*2 + nCol + 10;
9867b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
9868b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      if( azCol==0 ){
9869b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        raw_printf(stderr, "Error: out of memory\n");
9870b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        exit(1);
9871b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      }
9872b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }
9873b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
9874b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    if( sqlite3_column_int(pStmt, 5) ){
9875b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      nPK++;
9876b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      if( nPK==1
9877b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis       && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
98780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                          "INTEGER")==0
9879b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      ){
9880b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        isIPK = 1;
9881b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      }else{
9882b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        isIPK = 0;
9883b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      }
9884b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }
9885b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }
9886b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  sqlite3_finalize(pStmt);
98870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( azCol==0 ) return 0;
9888b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  azCol[0] = 0;
9889b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  azCol[nCol+1] = 0;
9890b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
9891b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  /* The decision of whether or not a rowid really needs to be preserved
9892b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  ** is tricky.  We never need to preserve a rowid for a WITHOUT ROWID table
9893b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  ** or a table with an INTEGER PRIMARY KEY.  We are unable to preserve
9894b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  ** rowids on tables where the rowid is inaccessible because there are other
9895b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  ** columns in the table named "rowid", "_rowid_", and "oid".
9896b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  */
9897b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  if( preserveRowid && isIPK ){
9898b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    /* If a single PRIMARY KEY column with type INTEGER was seen, then it
9899b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    ** might be an alise for the ROWID.  But it might also be a WITHOUT ROWID
9900b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    ** table or a INTEGER PRIMARY KEY DESC column, neither of which are
9901b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    ** ROWID aliases.  To distinguish these cases, check to see if
9902b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    ** there is a "pk" entry in "PRAGMA index_list".  There will be
9903b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
9904b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    */
9905b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
9906b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis                           " WHERE origin='pk'", zTab);
9907b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
9908b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    sqlite3_free(zSql);
9909b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    if( rc ){
9910b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      freeColumnList(azCol);
9911b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      return 0;
9912b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }
9913b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    rc = sqlite3_step(pStmt);
9914b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    sqlite3_finalize(pStmt);
9915b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    preserveRowid = rc==SQLITE_ROW;
9916b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }
9917b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  if( preserveRowid ){
9918b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    /* Only preserve the rowid if we can find a name to use for the
9919b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    ** rowid */
9920b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    static char *azRowid[] = { "rowid", "_rowid_", "oid" };
9921b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    int i, j;
9922b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    for(j=0; j<3; j++){
9923b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      for(i=1; i<=nCol; i++){
9924b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break;
9925b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      }
9926b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      if( i>nCol ){
9927b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        /* At this point, we know that azRowid[j] is not the name of any
9928b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        ** ordinary column in the table.  Verify that azRowid[j] is a valid
9929b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        ** name for the rowid before adding it to azCol[0].  WITHOUT ROWID
9930b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        ** tables will fail this last check */
9931b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0);
9932b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        if( rc==SQLITE_OK ) azCol[0] = azRowid[j];
9933b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        break;
9934b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      }
9935b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }
9936b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }
9937b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  return azCol;
9938b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis}
9939b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
9940b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis/*
9941b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** Toggle the reverse_unordered_selects setting.
9942b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis*/
9943b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidisstatic void toggleSelectOrder(sqlite3 *db){
9944b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  sqlite3_stmt *pStmt = 0;
9945b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  int iSetting = 0;
9946b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  char zStmt[100];
9947b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  sqlite3_prepare_v2(db, "PRAGMA reverse_unordered_selects", -1, &pStmt, 0);
9948b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  if( sqlite3_step(pStmt)==SQLITE_ROW ){
9949b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    iSetting = sqlite3_column_int(pStmt, 0);
9950b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }
9951b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  sqlite3_finalize(pStmt);
9952b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  sqlite3_snprintf(sizeof(zStmt), zStmt,
9953b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis       "PRAGMA reverse_unordered_selects(%d)", !iSetting);
9954b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  sqlite3_exec(db, zStmt, 0, 0, 0);
9955b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis}
99567790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
99577790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
99587790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** This is a different callback routine used for dumping the database.
99597790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** Each row received by this callback consists of a table name,
99607790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** the table type ("index" or "table") and SQL to create the table.
99617790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** This routine should print text sufficient to recreate the table.
99627790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
9963b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidisstatic int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
99647790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  int rc;
99657790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  const char *zTable;
99667790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  const char *zType;
99677790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  const char *zSql;
99683fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  ShellState *p = (ShellState *)pArg;
99697790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
9970b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  UNUSED_PARAMETER(azNotUsed);
99710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( nArg!=3 || azArg==0 ) return 0;
99727790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  zTable = azArg[0];
99737790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  zType = azArg[1];
99747790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  zSql = azArg[2];
997560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
99767790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if( strcmp(zTable, "sqlite_sequence")==0 ){
9977b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
99788fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
997960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    raw_printf(p->out, "ANALYZE sqlite_master;\n");
99807790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else if( strncmp(zTable, "sqlite_", 7)==0 ){
99817790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    return 0;
99827790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
99837790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    char *zIns;
99847790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( !p->writableSchema ){
998560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
99867790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      p->writableSchema = 1;
99877790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
99887790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    zIns = sqlite3_mprintf(
99897790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project       "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"
99907790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project       "VALUES('table','%q','%q',0,'%q');",
99917790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project       zTable, zTable, zSql);
999260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(p->out, "%s\n", zIns);
99937790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    sqlite3_free(zIns);
99947790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    return 0;
99957790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else{
9996e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    printSchemaLine(p->out, zSql, ";\n");
99977790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
99987790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
99997790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if( strcmp(zType, "table")==0 ){
10000b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    ShellText sSelect;
10001b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    ShellText sTable;
10002b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    char **azCol;
10003b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    int i;
10004b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    char *savedDestTable;
10005b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    int savedMode;
10006b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
10007b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    azCol = tableColumnList(p, zTable);
10008b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    if( azCol==0 ){
10009b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      p->nErr++;
10010b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      return 0;
100117790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
100127790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
100138fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    /* Always quote the table name, even if it appears to be pure ascii,
100148fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    ** in case it is a keyword. Ex:  INSERT INTO "table" ... */
10015b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    initText(&sTable);
10016b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    appendText(&sTable, zTable, quoteChar(zTable));
10017b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    /* If preserving the rowid, add a column list after the table name.
10018b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    ** In other words:  "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)"
10019b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    ** instead of the usual "INSERT INTO tab VALUES(...)".
10020b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    */
10021b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    if( azCol[0] ){
10022b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      appendText(&sTable, "(", 0);
10023b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      appendText(&sTable, azCol[0], 0);
10024b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      for(i=1; azCol[i]; i++){
10025b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        appendText(&sTable, ",", 0);
10026b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        appendText(&sTable, azCol[i], quoteChar(azCol[i]));
100277790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
10028b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      appendText(&sTable, ")", 0);
100297790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
100307790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
10031b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    /* Build an appropriate SELECT statement */
10032b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    initText(&sSelect);
10033b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    appendText(&sSelect, "SELECT ", 0);
10034b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    if( azCol[0] ){
10035b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      appendText(&sSelect, azCol[0], 0);
10036b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      appendText(&sSelect, ",", 0);
100377790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
10038b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    for(i=1; azCol[i]; i++){
10039b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      appendText(&sSelect, azCol[i], quoteChar(azCol[i]));
10040b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      if( azCol[i+1] ){
10041b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        appendText(&sSelect, ",", 0);
10042b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      }
10043b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }
10044b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    freeColumnList(azCol);
10045b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    appendText(&sSelect, " FROM ", 0);
10046b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    appendText(&sSelect, zTable, quoteChar(zTable));
10047b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
10048b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    savedDestTable = p->zDestTable;
10049b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    savedMode = p->mode;
10050b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    p->zDestTable = sTable.z;
10051b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    p->mode = p->cMode = MODE_Insert;
10052b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    rc = shell_exec(p->db, sSelect.z, shell_callback, p, 0);
10053b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    if( (rc&0xff)==SQLITE_CORRUPT ){
10054b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
10055b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      toggleSelectOrder(p->db);
10056b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      shell_exec(p->db, sSelect.z, shell_callback, p, 0);
10057b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      toggleSelectOrder(p->db);
10058b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }
10059b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    p->zDestTable = savedDestTable;
10060b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    p->mode = savedMode;
10061b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    freeText(&sTable);
10062b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    freeText(&sSelect);
10063b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    if( rc ) p->nErr++;
100647790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
100657790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  return 0;
100667790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
100677790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
100687790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
100697790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** Run zQuery.  Use dump_callback() as the callback routine so that
100707790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** the contents of the query are output as SQL statements.
100717790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project**
100727790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** If we get a SQLITE_CORRUPT error, rerun the query after appending
100737790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** "ORDER BY rowid DESC" to the end.
100747790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
100757790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Projectstatic int run_schema_dump_query(
1007660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  ShellState *p,
1007790ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  const char *zQuery
100787790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project){
100797790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  int rc;
1008090ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  char *zErr = 0;
1008190ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
100827790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if( rc==SQLITE_CORRUPT ){
100837790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    char *zQ2;
10084a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    int len = strlen30(zQuery);
1008560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
1008690ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    if( zErr ){
1008760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(p->out, "/****** %s ******/\n", zErr);
1008890ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      sqlite3_free(zErr);
1008990ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      zErr = 0;
1009090ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    }
100917790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    zQ2 = malloc( len+100 );
100927790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( zQ2==0 ) return rc;
100938fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery);
1009490ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
1009590ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    if( rc ){
1009660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(p->out, "/****** ERROR: %s ******/\n", zErr);
1009790ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    }else{
1009890ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      rc = SQLITE_CORRUPT;
1009990ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    }
1010090ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    sqlite3_free(zErr);
101017790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    free(zQ2);
101027790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
101037790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  return rc;
101047790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
101057790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
101067790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
101077790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** Text of a help message
101087790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
101097790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Projectstatic char zHelp[] =
101100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
101110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ".archive ...           Manage SQL archives: \".archive --help\" for details\n"
101120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
1011308f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis#ifndef SQLITE_OMIT_AUTHORIZATION
1011460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  ".auth ON|OFF           Show authorizer callbacks\n"
1011508f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis#endif
10116a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  ".backup ?DB? FILE      Backup DB (default \"main\") to FILE\n"
101171c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  ".bail on|off           Stop after hitting an error.  Default OFF\n"
101183a6c79f802fabdb94367177310663397420e319fNick Kralevich  ".binary on|off         Turn binary output on or off.  Default OFF\n"
101190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ".cd DIRECTORY          Change the working directory to DIRECTORY\n"
1012060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  ".changes on|off        Show number of rows changed by SQL\n"
1012108f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  ".check GLOB            Fail if output since .testcase does not match\n"
101228fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  ".clone NEWDB           Clone data into NEWDB from the existing database\n"
101237790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  ".databases             List names and files of attached databases\n"
101243fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  ".dbinfo ?DB?           Show status information about the database\n"
101257790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  ".dump ?TABLE? ...      Dump the database in an SQL text format\n"
10126a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  "                         If TABLE specified, only dump tables matching\n"
10127a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  "                         LIKE pattern TABLE.\n"
101281c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  ".echo on|off           Turn command echo on or off\n"
1012960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  ".eqp on|off|full       Enable or disable automatic EXPLAIN QUERY PLAN\n"
101300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ".excel                 Display the output of next command in a spreadsheet\n"
101317790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  ".exit                  Exit this program\n"
101320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ".expert                EXPERIMENTAL. Suggest indexes for specified queries\n"
101330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* Because explain mode comes on automatically now, the ".explain" mode
101340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** is removed from the help screen.  It is still supported for legacy, however */
101350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic\n"*/
1013660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  ".fullschema ?--indent? Show schema and the content of sqlite_stat tables\n"
101371c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  ".headers on|off        Turn display of headers on or off\n"
101387790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  ".help                  Show this message\n"
101397790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  ".import FILE TABLE     Import data from FILE into TABLE\n"
10140e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani#ifndef SQLITE_OMIT_TEST_CONTROL
10141e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  ".imposter INDEX TABLE  Create imposter table TABLE on index INDEX\n"
10142e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani#endif
101433fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  ".indexes ?TABLE?       Show names of all indexes\n"
101443fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  "                         If TABLE specified, only show indexes for tables\n"
10145a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  "                         matching LIKE pattern TABLE.\n"
101467790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#ifdef SQLITE_ENABLE_IOTRACE
101477790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  ".iotrace FILE          Enable I/O diagnostic logging to FILE\n"
101487790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#endif
101493a6c79f802fabdb94367177310663397420e319fNick Kralevich  ".limit ?LIMIT? ?VAL?   Display or change the value of an SQLITE_LIMIT\n"
10150e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  ".lint OPTIONS          Report potential schema issues. Options:\n"
10151e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  "                         fkey-indexes     Find missing foreign key indexes\n"
101527790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#ifndef SQLITE_OMIT_LOAD_EXTENSION
101537790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  ".load FILE ?ENTRY?     Load an extension library\n"
101547790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#endif
10155aae12b8a5af3a1ac77382b067d9ebb350fbd0644Vasu Nori  ".log FILE|off          Turn logging on or off.  FILE can be stderr/stdout\n"
101567790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  ".mode MODE ?TABLE?     Set output mode where MODE is one of:\n"
101573fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  "                         ascii    Columns/rows delimited by 0x1F and 0x1E\n"
101587790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  "                         csv      Comma-separated values\n"
101597790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  "                         column   Left-aligned columns.  (See .width)\n"
101607790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  "                         html     HTML <table> code\n"
101617790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  "                         insert   SQL insert statements for TABLE\n"
101627790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  "                         line     One value per line\n"
10163b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  "                         list     Values delimited by \"|\"\n"
10164e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  "                         quote    Escape answers as for SQL\n"
101657790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  "                         tabs     Tab-separated values\n"
101667790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  "                         tcl      TCL list elements\n"
101678fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  ".nullvalue STRING      Use STRING in place of NULL values\n"
101680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ".once (-e|-x|FILE)     Output for the next SQL command only to FILE\n"
101690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  "                         or invoke system text editor (-e) or spreadsheet (-x)\n"
101700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  "                         on the output.\n"
101710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE\n"
101720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  "                         The --new option starts with an empty file\n"
101730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ".output ?FILE?         Send output to FILE or stdout\n"
101748fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  ".print STRING...       Print literal STRING\n"
101757790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  ".prompt MAIN CONTINUE  Replace the standard prompts\n"
101767790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  ".quit                  Exit this program\n"
101777790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  ".read FILENAME         Execute SQL in FILENAME\n"
10178a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  ".restore ?DB? FILE     Restore content of DB (default \"main\") from FILE\n"
101798fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  ".save FILE             Write in-memory database into FILE\n"
101803fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  ".scanstats on|off      Turn sqlite3_stmt_scanstatus() metrics on or off\n"
1018160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  ".schema ?PATTERN?      Show the CREATE statements matching PATTERN\n"
1018260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  "                          Add --indent for pretty-printing\n"
10183b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  ".selftest ?--init?     Run tests defined in the SELFTEST table\n"
101843fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  ".separator COL ?ROW?   Change the column separator and optionally the row\n"
101853fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  "                         separator for both the output mode and .import\n"
1018660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#if defined(SQLITE_ENABLE_SESSION)
1018760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  ".session CMD ...       Create or control sessions\n"
1018860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#endif
10189b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  ".sha3sum ?OPTIONS...?  Compute a SHA3 hash of database content\n"
101901c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  ".shell CMD ARGS...     Run CMD ARGS... in a system shell\n"
101917790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  ".show                  Show the current values for various settings\n"
1019260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  ".stats ?on|off?        Show stats or turn stats on or off\n"
101931c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  ".system CMD ARGS...    Run CMD ARGS... in a system shell\n"
10194a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  ".tables ?TABLE?        List names of tables\n"
10195a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  "                         If TABLE specified, only list tables matching\n"
10196a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  "                         LIKE pattern TABLE.\n"
1019708f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  ".testcase NAME         Begin redirecting output to 'testcase-out.txt'\n"
101987790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  ".timeout MS            Try opening locked tables for MS milliseconds\n"
101991c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  ".timer on|off          Turn SQL timer on or off\n"
102008fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  ".trace FILE|off        Output each SQL statement as it is run\n"
1020160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  ".vfsinfo ?AUX?         Information about the top-level VFS\n"
1020260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  ".vfslist               List all available VFSes\n"
1020390ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  ".vfsname ?AUX?         Print the name of the VFS stack\n"
10204a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  ".width NUM1 NUM2 ...   Set column widths for \"column\" mode\n"
102051c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  "                         Negative values right-justify\n"
102067790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project;
102077790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
1020860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#if defined(SQLITE_ENABLE_SESSION)
1020960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis/*
1021060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** Print help information for the ".sessions" command
1021160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis*/
1021260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidisvoid session_help(ShellState *p){
1021360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  raw_printf(p->out,
1021460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    ".session ?NAME? SUBCOMMAND ?ARGS...?\n"
1021560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    "If ?NAME? is omitted, the first defined session is used.\n"
1021660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    "Subcommands:\n"
1021760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    "   attach TABLE             Attach TABLE\n"
1021860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    "   changeset FILE           Write a changeset into FILE\n"
1021960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    "   close                    Close one session\n"
1022060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    "   enable ?BOOLEAN?         Set or query the enable bit\n"
1022160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    "   filter GLOB...           Reject tables matching GLOBs\n"
1022260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    "   indirect ?BOOLEAN?       Mark or query the indirect status\n"
1022360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    "   isempty                  Query whether the session is empty\n"
1022460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    "   list                     List currently open session names\n"
1022560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    "   open DB NAME             Open a new session on DB\n"
1022660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    "   patchset FILE            Write a patchset into FILE\n"
1022760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  );
1022860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis}
1022960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#endif
1023060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
1023160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
102327790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/* Forward reference */
102333fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichstatic int process_input(ShellState *p, FILE *in);
1023408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis
1023508f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis/*
10236e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani** Read the content of file zName into memory obtained from sqlite3_malloc64()
102370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** and return a pointer to the buffer. The caller is responsible for freeing
102380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** the memory.
10239e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani**
10240e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes
10241e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani** read.
1024208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis**
10243e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani** For convenience, a nul-terminator byte is always appended to the data read
10244e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani** from the file before the buffer is returned. This byte is not included in
10245e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani** the final value of (*pnByte), if applicable.
10246e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani**
10247e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani** NULL is returned if any error is encountered. The final value of *pnByte
10248e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani** is undefined in this case.
1024908f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis*/
10250e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefanistatic char *readFile(const char *zName, int *pnByte){
1025108f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  FILE *in = fopen(zName, "rb");
1025208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  long nIn;
1025308f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  size_t nRead;
1025408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  char *pBuf;
1025508f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  if( in==0 ) return 0;
1025608f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  fseek(in, 0, SEEK_END);
1025708f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  nIn = ftell(in);
1025808f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  rewind(in);
1025908f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  pBuf = sqlite3_malloc64( nIn+1 );
1026008f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  if( pBuf==0 ) return 0;
1026108f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  nRead = fread(pBuf, nIn, 1, in);
1026208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  fclose(in);
1026308f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  if( nRead!=1 ){
1026408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    sqlite3_free(pBuf);
1026508f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    return 0;
1026608f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  }
1026708f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  pBuf[nIn] = 0;
10268e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  if( pnByte ) *pnByte = nIn;
1026908f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  return pBuf;
1027008f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis}
1027108f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis
1027260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#if defined(SQLITE_ENABLE_SESSION)
1027360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis/*
1027460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** Close a single OpenSession object and release all of its associated
1027560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** resources.
1027660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis*/
1027760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidisstatic void session_close(OpenSession *pSession){
1027860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  int i;
1027960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  sqlite3session_delete(pSession->p);
1028060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  sqlite3_free(pSession->zName);
1028160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  for(i=0; i<pSession->nFilter; i++){
1028260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    sqlite3_free(pSession->azFilter[i]);
1028360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  }
1028460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  sqlite3_free(pSession->azFilter);
1028560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  memset(pSession, 0, sizeof(OpenSession));
1028660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis}
1028760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#endif
1028860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
1028960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis/*
1029060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** Close all OpenSession objects and release all associated resources.
1029160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis*/
1029260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#if defined(SQLITE_ENABLE_SESSION)
1029360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidisstatic void session_close_all(ShellState *p){
1029460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  int i;
1029560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  for(i=0; i<p->nSession; i++){
1029660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    session_close(&p->aSession[i]);
1029760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  }
1029860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  p->nSession = 0;
1029960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis}
1030060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#else
1030160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis# define session_close_all(X)
1030260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#endif
1030360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
1030460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis/*
1030560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** Implementation of the xFilter function for an open session.  Omit
1030660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** any tables named by ".session filter" but let all other table through.
1030760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis*/
1030860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#if defined(SQLITE_ENABLE_SESSION)
1030960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidisstatic int session_filter(void *pCtx, const char *zTab){
1031060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  OpenSession *pSession = (OpenSession*)pCtx;
1031160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  int i;
1031260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  for(i=0; i<pSession->nFilter; i++){
1031360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0;
1031460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  }
1031560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  return 1;
1031660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis}
1031760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#endif
1031860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
103197790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
103200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Try to deduce the type of file for zName based on its content.  Return
103210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** one of the SHELL_OPEN_* constants.
103220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
103230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int deduceDatabaseType(const char *zName){
103240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  FILE *f = fopen(zName, "rb");
103250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  size_t n;
103260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SHELL_OPEN_UNSPEC;
103270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char zBuf[100];
103280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( f==0 ) return SHELL_OPEN_NORMAL;
103290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  fseek(f, -25, SEEK_END);
103300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  n = fread(zBuf, 25, 1, f);
103310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){
103320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = SHELL_OPEN_APPENDVFS;
103330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
103340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    fseek(f, -22, SEEK_END);
103350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    n = fread(zBuf, 22, 1, f);
103360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( n==1 && zBuf[0]==0x50 && zBuf[1]==0x4b && zBuf[2]==0x05
103370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov       && zBuf[3]==0x06 ){
103380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = SHELL_OPEN_ZIPFILE;
103390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
103400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
103410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  fclose(f);
103420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
103430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
103440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
103450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
103467790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** Make sure the database is open.  If it is not, then open it.  If
103477790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** the database fails to open, print an error message and exit.
103487790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
103493fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichstatic void open_db(ShellState *p, int keepAlive){
103507790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if( p->db==0 ){
103518fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    sqlite3_initialize();
103520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( p->openMode==SHELL_OPEN_UNSPEC && access(p->zDbFilename,0)==0 ){
103530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      p->openMode = deduceDatabaseType(p->zDbFilename);
103540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
103550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    switch( p->openMode ){
103560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      case SHELL_OPEN_APPENDVFS: {
103570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_open_v2(p->zDbFilename, &p->db,
103580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov           SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, "apndvfs");
103590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        break;
103600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
103610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      case SHELL_OPEN_ZIPFILE: {
103620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_open(":memory:", &p->db);
103630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        break;
103640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
103650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      case SHELL_OPEN_UNSPEC:
103660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      case SHELL_OPEN_NORMAL: {
103670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_open(p->zDbFilename, &p->db);
103680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        break;
103690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
103700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
103713a6c79f802fabdb94367177310663397420e319fNick Kralevich    globalDb = p->db;
103723a6c79f802fabdb94367177310663397420e319fNick Kralevich    if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
1037360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
103743a6c79f802fabdb94367177310663397420e319fNick Kralevich          p->zDbFilename, sqlite3_errmsg(p->db));
103758fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      if( keepAlive ) return;
103767790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      exit(1);
103777790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
103787790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#ifndef SQLITE_OMIT_LOAD_EXTENSION
103797790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    sqlite3_enable_load_extension(p->db, 1);
103807790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#endif
103810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_fileio_init(p->db, 0, 0);
103820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_shathree_init(p->db, 0, 0);
103830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_completion_init(p->db, 0, 0);
103840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifdef SQLITE_HAVE_ZLIB
103850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_zipfile_init(p->db, 0, 0);
103860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_sqlar_init(p->db, 0, 0);
103870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
103880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
103890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                            shellAddSchemaName, 0, 0);
103900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
103910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                            shellModuleSchema, 0, 0);
103920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
103930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                            shellPutsFunc, 0, 0);
103940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
103950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                            editFunc, 0, 0);
103960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
103970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                            editFunc, 0, 0);
103989bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown
10399c296bf9f8755fadd4e87c76f0a66d9e626c51b55Vasu Nori    // Begin Android Add
10400c296bf9f8755fadd4e87c76f0a66d9e626c51b55Vasu Nori    #ifndef NO_ANDROID_FUNCS
1040155536230a14a7c199bbe41a83893c7d82e0c0a24Neil Fuller        InitializeIcuOrDie();
104023a6c79f802fabdb94367177310663397420e319fNick Kralevich        int err = register_localized_collators(p->db, "en_US", 0);
10403c296bf9f8755fadd4e87c76f0a66d9e626c51b55Vasu Nori        if (err != SQLITE_OK) {
10404c296bf9f8755fadd4e87c76f0a66d9e626c51b55Vasu Nori          fprintf(stderr, "register_localized_collators() failed\n");
10405c296bf9f8755fadd4e87c76f0a66d9e626c51b55Vasu Nori          exit(1);
10406c296bf9f8755fadd4e87c76f0a66d9e626c51b55Vasu Nori        }
104073a6c79f802fabdb94367177310663397420e319fNick Kralevich        err = register_android_functions(p->db, 0);
10408c296bf9f8755fadd4e87c76f0a66d9e626c51b55Vasu Nori        if (err != SQLITE_OK) {
10409c296bf9f8755fadd4e87c76f0a66d9e626c51b55Vasu Nori          fprintf(stderr, "register_android_functions() failed\n");
10410c296bf9f8755fadd4e87c76f0a66d9e626c51b55Vasu Nori          exit(1);
10411c296bf9f8755fadd4e87c76f0a66d9e626c51b55Vasu Nori        }
10412c296bf9f8755fadd4e87c76f0a66d9e626c51b55Vasu Nori    #endif
10413c296bf9f8755fadd4e87c76f0a66d9e626c51b55Vasu Nori    // End Android Add
104140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
104150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( p->openMode==SHELL_OPEN_ZIPFILE ){
104160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      char *zSql = sqlite3_mprintf(
104170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov         "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", p->zDbFilename);
104180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_exec(p->db, zSql, 0, 0, 0);
104190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_free(zSql);
104200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
104210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
104220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
104230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
104240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if HAVE_READLINE || HAVE_EDITLINE
104250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
104260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Readline completion callbacks
104270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
104280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic char *readline_completion_generator(const char *text, int state){
104290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  static sqlite3_stmt *pStmt = 0;
104300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zRet;
104310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( state==0 ){
104320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    char *zSql;
104330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_finalize(pStmt);
104340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
104350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                           "  FROM completion(%Q) ORDER BY 1", text);
104360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
104370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(zSql);
104380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
104390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( sqlite3_step(pStmt)==SQLITE_ROW ){
104400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zRet = strdup((const char*)sqlite3_column_text(pStmt, 0));
104410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
104420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_finalize(pStmt);
104430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    pStmt = 0;
104440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zRet = 0;
104450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
104460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return zRet;
104470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
104480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic char **readline_completion(const char *zText, int iStart, int iEnd){
104490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rl_attempted_completion_over = 1;
104500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rl_completion_matches(zText, readline_completion_generator);
104510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
104520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
104530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#elif HAVE_LINENOISE
104540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
104550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Linenoise completion callback
104560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
104570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void linenoise_completion(const char *zLine, linenoiseCompletions *lc){
104580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nLine = strlen30(zLine);
104590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int i, iStart;
104600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_stmt *pStmt = 0;
104610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zSql;
104620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char zBuf[1000];
104630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
104640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( nLine>sizeof(zBuf)-30 ) return;
104650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( zLine[0]=='.' ) return;
104660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
104670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( i==nLine-1 ) return;
104680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  iStart = i+1;
104690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  memcpy(zBuf, zLine, iStart);
104700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
104710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                         "  FROM completion(%Q,%Q) ORDER BY 1",
104720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                         &zLine[iStart], zLine);
104730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
104740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(zSql);
104750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */
104760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  while( sqlite3_step(pStmt)==SQLITE_ROW ){
104770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0);
104780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int nCompletion = sqlite3_column_bytes(pStmt, 0);
104790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( iStart+nCompletion < sizeof(zBuf)-1 ){
104800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      memcpy(zBuf+iStart, zCompletion, nCompletion+1);
104810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      linenoiseAddCompletion(lc, zBuf);
104820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
104837790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
104840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_finalize(pStmt);
104857790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
104860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
104877790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
104887790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
104897790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** Do C-language style dequoting.
104907790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project**
104913a6c79f802fabdb94367177310663397420e319fNick Kralevich**    \a    -> alarm
104923a6c79f802fabdb94367177310663397420e319fNick Kralevich**    \b    -> backspace
104937790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project**    \t    -> tab
104947790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project**    \n    -> newline
104953a6c79f802fabdb94367177310663397420e319fNick Kralevich**    \v    -> vertical tab
104963a6c79f802fabdb94367177310663397420e319fNick Kralevich**    \f    -> form feed
104977790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project**    \r    -> carriage return
104983a6c79f802fabdb94367177310663397420e319fNick Kralevich**    \s    -> space
104998fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich**    \"    -> "
105003a6c79f802fabdb94367177310663397420e319fNick Kralevich**    \'    -> '
105017790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project**    \\    -> backslash
105023a6c79f802fabdb94367177310663397420e319fNick Kralevich**    \NNN  -> ascii character NNN in octal
105037790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
105047790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Projectstatic void resolve_backslashes(char *z){
10505a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  int i, j;
10506a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  char c;
105071c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  while( *z && *z!='\\' ) z++;
105087790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  for(i=j=0; (c = z[i])!=0; i++, j++){
105093a6c79f802fabdb94367177310663397420e319fNick Kralevich    if( c=='\\' && z[i+1]!=0 ){
105107790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      c = z[++i];
105113a6c79f802fabdb94367177310663397420e319fNick Kralevich      if( c=='a' ){
105123a6c79f802fabdb94367177310663397420e319fNick Kralevich        c = '\a';
105133a6c79f802fabdb94367177310663397420e319fNick Kralevich      }else if( c=='b' ){
105143a6c79f802fabdb94367177310663397420e319fNick Kralevich        c = '\b';
105157790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }else if( c=='t' ){
105167790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        c = '\t';
105173a6c79f802fabdb94367177310663397420e319fNick Kralevich      }else if( c=='n' ){
105183a6c79f802fabdb94367177310663397420e319fNick Kralevich        c = '\n';
105193a6c79f802fabdb94367177310663397420e319fNick Kralevich      }else if( c=='v' ){
105203a6c79f802fabdb94367177310663397420e319fNick Kralevich        c = '\v';
105213a6c79f802fabdb94367177310663397420e319fNick Kralevich      }else if( c=='f' ){
105223a6c79f802fabdb94367177310663397420e319fNick Kralevich        c = '\f';
105237790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }else if( c=='r' ){
105247790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        c = '\r';
105253a6c79f802fabdb94367177310663397420e319fNick Kralevich      }else if( c=='"' ){
105263a6c79f802fabdb94367177310663397420e319fNick Kralevich        c = '"';
105273a6c79f802fabdb94367177310663397420e319fNick Kralevich      }else if( c=='\'' ){
105283a6c79f802fabdb94367177310663397420e319fNick Kralevich        c = '\'';
105298fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }else if( c=='\\' ){
105308fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        c = '\\';
105317790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }else if( c>='0' && c<='7' ){
105327790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        c -= '0';
105337790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        if( z[i+1]>='0' && z[i+1]<='7' ){
105347790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project          i++;
105357790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project          c = (c<<3) + z[i] - '0';
105367790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project          if( z[i+1]>='0' && z[i+1]<='7' ){
105377790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project            i++;
105387790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project            c = (c<<3) + z[i] - '0';
105390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
105400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
105410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
105428fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
105430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    z[j] = c;
105448fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }
105450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( j<i ) z[j] = 0;
105468fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich}
105478fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
105488fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich/*
105498fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** Interpret zArg as either an integer or a boolean value.  Return 1 or 0
105508fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** for TRUE and FALSE.  Return the integer value if appropriate.
105517790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
10552b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidisstatic int booleanValue(const char *zArg){
105538fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int i;
105548fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( zArg[0]=='0' && zArg[1]=='x' ){
105558fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    for(i=2; hexDigitValue(zArg[i])>=0; i++){}
105568fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }else{
105578fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){}
105588fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }
105598fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff);
105608fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
105618fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    return 1;
105627790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
105638fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
105648fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    return 0;
105657790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
1056660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
105678fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich          zArg);
105688fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  return 0;
105698fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich}
105708fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
105718fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich/*
10572b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis** Set or clear a shell flag according to a boolean value.
10573b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis*/
10574b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidisstatic void setOrClearFlag(ShellState *p, unsigned mFlag, const char *zArg){
10575b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  if( booleanValue(zArg) ){
10576b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    ShellSetFlag(p, mFlag);
10577b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }else{
10578b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    ShellClearFlag(p, mFlag);
10579b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }
10580b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis}
10581b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
10582b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis/*
105838fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** Close an output file, assuming it is not stderr or stdout
105848fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich*/
105858fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevichstatic void output_file_close(FILE *f){
105868fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( f && f!=stdout && f!=stderr ) fclose(f);
105878fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich}
105888fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
105898fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich/*
105908fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** Try to open an output file.   The names "stdout" and "stderr" are
1059160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** recognized and do the right thing.  NULL is returned if the output
105928fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** filename is "off".
105938fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich*/
105940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic FILE *output_file_open(const char *zFile, int bTextMode){
105958fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  FILE *f;
105968fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( strcmp(zFile,"stdout")==0 ){
105978fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    f = stdout;
105988fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }else if( strcmp(zFile, "stderr")==0 ){
105998fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    f = stderr;
106008fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }else if( strcmp(zFile, "off")==0 ){
106018fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    f = 0;
106028fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }else{
106030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    f = fopen(zFile, bTextMode ? "w" : "wb");
106048fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( f==0 ){
1060560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
106068fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
106078fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }
106088fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  return f;
106098fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich}
106108fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
10611e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani#if !defined(SQLITE_UNTESTABLE)
10612e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
106138fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich/*
106148fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** A routine for handling output from sqlite3_trace().
106158fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich*/
1061674bd39cb46f3e9465fe069b650f40ffd8298a538Alex Naidisstatic int sql_trace_callback(
1061774bd39cb46f3e9465fe069b650f40ffd8298a538Alex Naidis  unsigned mType,
1061874bd39cb46f3e9465fe069b650f40ffd8298a538Alex Naidis  void *pArg,
1061974bd39cb46f3e9465fe069b650f40ffd8298a538Alex Naidis  void *pP,
1062074bd39cb46f3e9465fe069b650f40ffd8298a538Alex Naidis  void *pX
1062174bd39cb46f3e9465fe069b650f40ffd8298a538Alex Naidis){
106228fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  FILE *f = (FILE*)pArg;
1062374bd39cb46f3e9465fe069b650f40ffd8298a538Alex Naidis  UNUSED_PARAMETER(mType);
1062474bd39cb46f3e9465fe069b650f40ffd8298a538Alex Naidis  UNUSED_PARAMETER(pP);
106253fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  if( f ){
1062674bd39cb46f3e9465fe069b650f40ffd8298a538Alex Naidis    const char *z = (const char*)pX;
106270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int i = strlen30(z);
106283fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    while( i>0 && z[i-1]==';' ){ i--; }
1062960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(f, "%.*s;\n", i, z);
106303fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  }
1063174bd39cb46f3e9465fe069b650f40ffd8298a538Alex Naidis  return 0;
106328fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich}
10633e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani#endif
10634e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani#endif
106358fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
106368fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich/*
106378fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** A no-op routine that runs with the ".breakpoint" doc-command.  This is
106388fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** a useful spot to set a debugger breakpoint.
106398fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich*/
106408fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevichstatic void test_breakpoint(void){
106418fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  static int nCall = 0;
106428fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  nCall++;
106438fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich}
106448fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
106458fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich/*
106463fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich** An object used to read a CSV and other files for import.
106478fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich*/
106483fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichtypedef struct ImportCtx ImportCtx;
106493fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichstruct ImportCtx {
106508fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  const char *zFile;  /* Name of the input file */
106518fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  FILE *in;           /* Read the CSV text from this input stream */
106528fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  char *z;            /* Accumulated text for a field */
106538fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int n;              /* Number of bytes in z */
106548fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int nAlloc;         /* Space allocated for z[] */
106558fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int nLine;          /* Current line number */
106560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int bNotFirst;      /* True if one or more bytes already read */
106578fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int cTerm;          /* Character that terminated the most recent field */
106583fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  int cColSep;        /* The column separator character.  (Usually ",") */
106593fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  int cRowSep;        /* The row separator character.  (Usually "\n") */
106608fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich};
106618fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
106628fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich/* Append a single byte to z[] */
106633fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichstatic void import_append_char(ImportCtx *p, int c){
106648fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( p->n+1>=p->nAlloc ){
106658fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    p->nAlloc += p->nAlloc + 100;
106663a6c79f802fabdb94367177310663397420e319fNick Kralevich    p->z = sqlite3_realloc64(p->z, p->nAlloc);
106678fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( p->z==0 ){
1066860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "out of memory\n");
106698fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      exit(1);
106708fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
106718fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }
106728fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  p->z[p->n++] = (char)c;
106738fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich}
106748fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
106758fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich/* Read a single field of CSV text.  Compatible with rfc4180 and extended
106768fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** with the option of having a separator other than ",".
106778fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich**
106788fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich**   +  Input comes from p->in.
106798fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich**   +  Store results in p->z of length p->n.  Space to hold p->z comes
106803a6c79f802fabdb94367177310663397420e319fNick Kralevich**      from sqlite3_malloc64().
106813fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich**   +  Use p->cSep as the column separator.  The default is ",".
106823fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich**   +  Use p->rSep as the row separator.  The default is "\n".
106838fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich**   +  Keep track of the line number in p->nLine.
106848fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich**   +  Store the character that terminates the field in p->cTerm.  Store
106858fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich**      EOF on end-of-file.
106868fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich**   +  Report syntax errors on stderr
106878fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich*/
106883fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichstatic char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
106893fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  int c;
106903fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  int cSep = p->cColSep;
106913fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  int rSep = p->cRowSep;
106928fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  p->n = 0;
106938fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  c = fgetc(p->in);
106948fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( c==EOF || seenInterrupt ){
106958fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    p->cTerm = EOF;
106968fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    return 0;
106978fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }
106988fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( c=='"' ){
106993fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    int pc, ppc;
107008fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    int startLine = p->nLine;
107018fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    int cQuote = c;
107028fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    pc = ppc = 0;
107038fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    while( 1 ){
107048fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      c = fgetc(p->in);
107053fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      if( c==rSep ) p->nLine++;
107068fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      if( c==cQuote ){
107078fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        if( pc==cQuote ){
107088fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich          pc = 0;
107098fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich          continue;
107108fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        }
107118fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }
107128fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      if( (c==cSep && pc==cQuote)
107133fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich       || (c==rSep && pc==cQuote)
107143fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich       || (c==rSep && pc=='\r' && ppc==cQuote)
107158fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich       || (c==EOF && pc==cQuote)
107168fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      ){
107178fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        do{ p->n--; }while( p->z[p->n]!=cQuote );
107188fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        p->cTerm = c;
107198fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        break;
107208fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }
107218fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      if( pc==cQuote && c!='\r' ){
1072260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(stderr, "%s:%d: unescaped %c character\n",
107238fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich                p->zFile, p->nLine, cQuote);
107248fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }
107258fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      if( c==EOF ){
1072660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n",
107278fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich                p->zFile, startLine, cQuote);
107283fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        p->cTerm = c;
107298fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        break;
107308fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }
107313fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      import_append_char(p, c);
107328fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      ppc = pc;
107338fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      pc = c;
107348fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
107358fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }else{
107360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    /* If this is the first field being parsed and it begins with the
107370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ** UTF-8 BOM  (0xEF BB BF) then skip the BOM */
107380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( (c&0xff)==0xef && p->bNotFirst==0 ){
107390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      import_append_char(p, c);
107400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      c = fgetc(p->in);
107410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( (c&0xff)==0xbb ){
107420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        import_append_char(p, c);
107430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        c = fgetc(p->in);
107440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( (c&0xff)==0xbf ){
107450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          p->bNotFirst = 1;
107460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          p->n = 0;
107470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          return csv_read_one_field(p);
107480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
107490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
107500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
107513fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    while( c!=EOF && c!=cSep && c!=rSep ){
107523fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      import_append_char(p, c);
107538fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      c = fgetc(p->in);
107548fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
107553fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    if( c==rSep ){
107568fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      p->nLine++;
107578fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
107588fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
107598fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    p->cTerm = c;
107608fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }
107618fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( p->z ) p->z[p->n] = 0;
107620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  p->bNotFirst = 1;
107638fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  return p->z;
107648fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich}
107658fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
107663fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich/* Read a single field of ASCII delimited text.
107673fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich**
107683fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich**   +  Input comes from p->in.
107693fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich**   +  Store results in p->z of length p->n.  Space to hold p->z comes
107703a6c79f802fabdb94367177310663397420e319fNick Kralevich**      from sqlite3_malloc64().
107713fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich**   +  Use p->cSep as the column separator.  The default is "\x1F".
107723fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich**   +  Use p->rSep as the row separator.  The default is "\x1E".
107733fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich**   +  Keep track of the row number in p->nLine.
107743fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich**   +  Store the character that terminates the field in p->cTerm.  Store
107753fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich**      EOF on end-of-file.
107763fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich**   +  Report syntax errors on stderr
107773fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich*/
107783fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichstatic char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
107793fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  int c;
107803fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  int cSep = p->cColSep;
107813fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  int rSep = p->cRowSep;
107823fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  p->n = 0;
107833fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  c = fgetc(p->in);
107843fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  if( c==EOF || seenInterrupt ){
107853fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    p->cTerm = EOF;
107863fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    return 0;
107873fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  }
107883fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  while( c!=EOF && c!=cSep && c!=rSep ){
107893fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    import_append_char(p, c);
107903fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    c = fgetc(p->in);
107913fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  }
107923fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  if( c==rSep ){
107933fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    p->nLine++;
107943fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  }
107953fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  p->cTerm = c;
107963fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  if( p->z ) p->z[p->n] = 0;
107973fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  return p->z;
107983fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich}
107993fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
108008fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich/*
108018fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** Try to transfer data for table zTable.  If an error is seen while
108028fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** moving forward, try to go backwards.  The backwards movement won't
108038fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** work for WITHOUT ROWID tables.
108048fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich*/
108058fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevichstatic void tryToCloneData(
108063fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  ShellState *p,
108078fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  sqlite3 *newDb,
108088fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  const char *zTable
108098fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich){
1081060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  sqlite3_stmt *pQuery = 0;
108118fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  sqlite3_stmt *pInsert = 0;
108128fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  char *zQuery = 0;
108138fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  char *zInsert = 0;
108148fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int rc;
108158fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int i, j, n;
108160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nTable = strlen30(zTable);
108178fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int k = 0;
108188fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int cnt = 0;
108198fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  const int spinRate = 10000;
108208fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
108218fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
108228fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
108238fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( rc ){
1082460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(stderr, "Error %d: %s on [%s]\n",
108258fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich            sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
108268fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich            zQuery);
108278fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    goto end_data_xfer;
108288fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }
108298fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  n = sqlite3_column_count(pQuery);
108303a6c79f802fabdb94367177310663397420e319fNick Kralevich  zInsert = sqlite3_malloc64(200 + nTable + n*3);
108318fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( zInsert==0 ){
1083260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    raw_printf(stderr, "out of memory\n");
108338fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    goto end_data_xfer;
108348fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }
108358fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  sqlite3_snprintf(200+nTable,zInsert,
108368fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich                   "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
108370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  i = strlen30(zInsert);
108388fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  for(j=1; j<n; j++){
108398fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    memcpy(zInsert+i, ",?", 2);
108408fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    i += 2;
108418fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }
108428fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  memcpy(zInsert+i, ");", 3);
108438fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
108448fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( rc ){
1084560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(stderr, "Error %d: %s on [%s]\n",
108468fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich            sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
108478fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich            zQuery);
108488fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    goto end_data_xfer;
108498fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }
108508fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  for(k=0; k<2; k++){
108518fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
108528fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      for(i=0; i<n; i++){
108538fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        switch( sqlite3_column_type(pQuery, i) ){
108548fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich          case SQLITE_NULL: {
108558fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich            sqlite3_bind_null(pInsert, i+1);
108568fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich            break;
108578fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich          }
108588fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich          case SQLITE_INTEGER: {
108598fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich            sqlite3_bind_int64(pInsert, i+1, sqlite3_column_int64(pQuery,i));
108608fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich            break;
108618fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich          }
108628fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich          case SQLITE_FLOAT: {
108638fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich            sqlite3_bind_double(pInsert, i+1, sqlite3_column_double(pQuery,i));
108648fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich            break;
108658fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich          }
108668fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich          case SQLITE_TEXT: {
108678fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich            sqlite3_bind_text(pInsert, i+1,
108688fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich                             (const char*)sqlite3_column_text(pQuery,i),
108698fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich                             -1, SQLITE_STATIC);
108708fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich            break;
108718fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich          }
108728fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich          case SQLITE_BLOB: {
108738fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich            sqlite3_bind_blob(pInsert, i+1, sqlite3_column_blob(pQuery,i),
108748fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich                                            sqlite3_column_bytes(pQuery,i),
108758fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich                                            SQLITE_STATIC);
108768fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich            break;
108778fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich          }
108788fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        }
108798fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      } /* End for */
108808fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      rc = sqlite3_step(pInsert);
108818fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
1088260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
108838fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich                        sqlite3_errmsg(newDb));
108848fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }
108858fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      sqlite3_reset(pInsert);
108868fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      cnt++;
108878fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      if( (cnt%spinRate)==0 ){
108888fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        printf("%c\b", "|/-\\"[(cnt/spinRate)%4]);
108898fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        fflush(stdout);
108908fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }
108918fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    } /* End while */
108928fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( rc==SQLITE_DONE ) break;
108938fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    sqlite3_finalize(pQuery);
108948fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    sqlite3_free(zQuery);
108958fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
108968fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich                             zTable);
108978fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
108988fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( rc ){
1089960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
109008fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      break;
109018fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
109028fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  } /* End for(k=0...) */
109038fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
109048fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevichend_data_xfer:
109058fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  sqlite3_finalize(pQuery);
109068fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  sqlite3_finalize(pInsert);
109078fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  sqlite3_free(zQuery);
109088fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  sqlite3_free(zInsert);
109098fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich}
109108fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
109118fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
109128fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich/*
109138fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** Try to transfer all rows of the schema that match zWhere.  For
109148fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** each row, invoke xForEach() on the object defined by that row.
109158fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** If an error is encountered while moving forward through the
109168fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** sqlite_master table, try again moving backwards.
109178fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich*/
109188fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevichstatic void tryToCloneSchema(
109193fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  ShellState *p,
109208fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  sqlite3 *newDb,
109218fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  const char *zWhere,
109223fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  void (*xForEach)(ShellState*,sqlite3*,const char*)
109238fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich){
109248fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  sqlite3_stmt *pQuery = 0;
109258fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  char *zQuery = 0;
109268fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int rc;
109278fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  const unsigned char *zName;
109288fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  const unsigned char *zSql;
109298fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  char *zErrMsg = 0;
109308fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
109318fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
109328fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich                           " WHERE %s", zWhere);
109338fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
109348fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( rc ){
1093560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
109368fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich                    sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
109378fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich                    zQuery);
109388fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    goto end_schema_xfer;
109398fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }
109408fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
109418fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    zName = sqlite3_column_text(pQuery, 0);
109428fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    zSql = sqlite3_column_text(pQuery, 1);
109438fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    printf("%s... ", zName); fflush(stdout);
109448fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
109458fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( zErrMsg ){
1094660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
109478fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      sqlite3_free(zErrMsg);
109488fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      zErrMsg = 0;
109498fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
109508fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( xForEach ){
109518fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      xForEach(p, newDb, (const char*)zName);
109528fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
109538fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    printf("done\n");
109548fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }
109558fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( rc!=SQLITE_DONE ){
109568fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    sqlite3_finalize(pQuery);
109578fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    sqlite3_free(zQuery);
109588fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
109598fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich                             " WHERE %s ORDER BY rowid DESC", zWhere);
109608fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
109618fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( rc ){
1096260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
109638fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich                      sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
109648fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich                      zQuery);
109658fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      goto end_schema_xfer;
109668fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
109678fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
109688fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      zName = sqlite3_column_text(pQuery, 0);
109698fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      zSql = sqlite3_column_text(pQuery, 1);
109708fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      printf("%s... ", zName); fflush(stdout);
109718fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
109728fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      if( zErrMsg ){
1097360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
109748fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        sqlite3_free(zErrMsg);
109758fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        zErrMsg = 0;
109768fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }
109778fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      if( xForEach ){
109788fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        xForEach(p, newDb, (const char*)zName);
109798fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }
109808fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      printf("done\n");
109818fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
109828fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }
109838fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevichend_schema_xfer:
109848fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  sqlite3_finalize(pQuery);
109858fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  sqlite3_free(zQuery);
109868fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich}
109878fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
109888fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich/*
109898fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** Open a new database file named "zNewDb".  Try to recover as much information
109908fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** as possible out of the main database (which might be corrupt) and write it
109918fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** into zNewDb.
109928fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich*/
109933fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichstatic void tryToClone(ShellState *p, const char *zNewDb){
109948fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int rc;
109958fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  sqlite3 *newDb = 0;
109968fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( access(zNewDb,0)==0 ){
1099760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(stderr, "File \"%s\" already exists.\n", zNewDb);
109988fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    return;
109998fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }
110008fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  rc = sqlite3_open(zNewDb, &newDb);
110018fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( rc ){
1100260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(stderr, "Cannot create output database: %s\n",
110038fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich            sqlite3_errmsg(newDb));
110048fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }else{
110051c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
110068fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
110078fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
110088fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    tryToCloneSchema(p, newDb, "type!='table'", 0);
110098fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
110101c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
110118fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }
110128fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  sqlite3_close(newDb);
110137790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
110147790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
110157790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
110160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Change the output file back to stdout.
110170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
110180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** If the p->doXdgOpen flag is set, that means the output was being
110190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** redirected to a temporary file named by p->zTempFile.  In that case,
110200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** launch start/open/xdg-open on that temporary file.
110211c7cea379348522163370244e8fbbff8a136b7faNick Kralevich*/
110223fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichstatic void output_reset(ShellState *p){
110231c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( p->outfile[0]=='|' ){
110243fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#ifndef SQLITE_OMIT_POPEN
110251c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    pclose(p->out);
110263fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#endif
110271c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  }else{
110281c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    output_file_close(p->out);
110290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( p->doXdgOpen ){
110300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      const char *zXdgOpenCmd =
110310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if defined(_WIN32)
110320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      "start";
110330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#elif defined(__APPLE__)
110340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      "open";
110350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#else
110360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      "xdg-open";
110370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
110380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      char *zCmd;
110390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
110400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( system(zCmd) ){
110410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        utf8_printf(stderr, "Failed: [%s]\n", zCmd);
110420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
110430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_free(zCmd);
110440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      outputModePop(p);
110450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      p->doXdgOpen = 0;
110460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
110471c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  }
110481c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  p->outfile[0] = 0;
110491c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  p->out = stdout;
110501c7cea379348522163370244e8fbbff8a136b7faNick Kralevich}
110511c7cea379348522163370244e8fbbff8a136b7faNick Kralevich
110521c7cea379348522163370244e8fbbff8a136b7faNick Kralevich/*
110533fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich** Run an SQL command and return the single integer result.
110543fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich*/
110553fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichstatic int db_int(ShellState *p, const char *zSql){
110563fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  sqlite3_stmt *pStmt;
110573fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  int res = 0;
110583fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
110593fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
110603fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    res = sqlite3_column_int(pStmt,0);
110613fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  }
110623fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  sqlite3_finalize(pStmt);
110633fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  return res;
110643fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich}
110653fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
110663fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich/*
110673fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich** Convert a 2-byte or 4-byte big-endian integer into a native integer
110683fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich*/
1106974bd39cb46f3e9465fe069b650f40ffd8298a538Alex Naidisstatic unsigned int get2byteInt(unsigned char *a){
110703fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  return (a[0]<<8) + a[1];
110713fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich}
1107274bd39cb46f3e9465fe069b650f40ffd8298a538Alex Naidisstatic unsigned int get4byteInt(unsigned char *a){
110733fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
110743fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich}
110753fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
110763fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich/*
110773fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich** Implementation of the ".info" command.
110783fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich**
110793fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich** Return 1 on error, 2 to exit, and 0 otherwise.
110803fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich*/
110813fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichstatic int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
110823fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  static const struct { const char *zName; int ofst; } aField[] = {
110833fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich     { "file change counter:",  24  },
110843fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich     { "database page count:",  28  },
110853fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich     { "freelist page count:",  36  },
110863fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich     { "schema cookie:",        40  },
110873fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich     { "schema format:",        44  },
110883fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich     { "default cache size:",   48  },
110893fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich     { "autovacuum top root:",  52  },
110903fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich     { "incremental vacuum:",   64  },
110913fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich     { "text encoding:",        56  },
110923fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich     { "user version:",         60  },
110933fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich     { "application id:",       68  },
110943fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich     { "software version:",     96  },
110953fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  };
110963fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  static const struct { const char *zName; const char *zSql; } aQuery[] = {
110973fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich     { "number of tables:",
110983fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich       "SELECT count(*) FROM %s WHERE type='table'" },
110993fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich     { "number of indexes:",
111003fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich       "SELECT count(*) FROM %s WHERE type='index'" },
111013fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich     { "number of triggers:",
111023fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich       "SELECT count(*) FROM %s WHERE type='trigger'" },
111033fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich     { "number of views:",
111043fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich       "SELECT count(*) FROM %s WHERE type='view'" },
111053fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich     { "schema size:",
111063fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich       "SELECT total(length(sql)) FROM %s" },
111073fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  };
111083fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  int i;
111093fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  char *zSchemaTab;
111103fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  char *zDb = nArg>=2 ? azArg[1] : "main";
111110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_stmt *pStmt = 0;
111123fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  unsigned char aHdr[100];
111133fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  open_db(p, 0);
111143fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  if( p->db==0 ) return 1;
111150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_prepare_v2(p->db,"SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
111160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                     -1, &pStmt, 0);
111170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
111180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( sqlite3_step(pStmt)==SQLITE_ROW
111190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov   && sqlite3_column_bytes(pStmt,0)>100
111200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ){
111210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100);
111220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_finalize(pStmt);
111230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
1112460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    raw_printf(stderr, "unable to read database header\n");
111250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_finalize(pStmt);
111263fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    return 1;
111273fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  }
111283fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  i = get2byteInt(aHdr+16);
111293fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  if( i==1 ) i = 65536;
1113060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  utf8_printf(p->out, "%-20s %d\n", "database page size:", i);
1113160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
1113260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
1113360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
11134253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich  for(i=0; i<ArraySize(aField); i++){
111353fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    int ofst = aField[i].ofst;
111363fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    unsigned int val = get4byteInt(aHdr + ofst);
1113760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(p->out, "%-20s %u", aField[i].zName, val);
111383fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    switch( ofst ){
111393fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      case 56: {
1114060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        if( val==1 ) raw_printf(p->out, " (utf8)");
1114160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        if( val==2 ) raw_printf(p->out, " (utf16le)");
1114260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        if( val==3 ) raw_printf(p->out, " (utf16be)");
111433fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      }
111443fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    }
1114560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    raw_printf(p->out, "\n");
111463fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  }
111473fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  if( zDb==0 ){
111483fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    zSchemaTab = sqlite3_mprintf("main.sqlite_master");
111493fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  }else if( strcmp(zDb,"temp")==0 ){
111503fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_master");
111513fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  }else{
111523fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_master", zDb);
111533fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  }
11154253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich  for(i=0; i<ArraySize(aQuery); i++){
111553fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
111563fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    int val = db_int(p, zSql);
111573fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    sqlite3_free(zSql);
1115860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
111593fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  }
111603fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  sqlite3_free(zSchemaTab);
111613fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  return 0;
111623fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich}
111633fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
11164253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich/*
11165253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich** Print the current sqlite3_errmsg() value to stderr and return 1.
11166253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich*/
11167253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevichstatic int shellDatabaseError(sqlite3 *db){
11168253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich  const char *zErr = sqlite3_errmsg(db);
1116960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  utf8_printf(stderr, "Error: %s\n", zErr);
11170253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich  return 1;
11171253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich}
11172253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich
11173253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich/*
11174253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich** Print an out-of-memory message to stderr and return 1.
11175253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich*/
11176253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevichstatic int shellNomemError(void){
1117760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  raw_printf(stderr, "Error: out of memory\n");
11178253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich  return 1;
11179253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich}
111803fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
111813fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich/*
1118208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis** Compare the pattern in zGlob[] against the text in z[].  Return TRUE
1118308f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis** if they match and FALSE (0) if they do not match.
1118408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis**
1118508f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis** Globbing rules:
1118608f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis**
1118708f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis**      '*'       Matches any sequence of zero or more characters.
1118808f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis**
1118908f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis**      '?'       Matches exactly one character.
1119008f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis**
1119108f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis**     [...]      Matches one character from the enclosed list of
1119208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis**                characters.
1119308f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis**
1119408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis**     [^...]     Matches one character not in the enclosed list.
1119508f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis**
1119608f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis**      '#'       Matches any sequence of one or more digits with an
1119708f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis**                optional + or - sign in front
1119808f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis**
1119908f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis**      ' '       Any span of whitespace matches any other span of
1120008f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis**                whitespace.
1120108f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis**
1120208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis** Extra whitespace at the end of z[] is ignored.
1120308f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis*/
1120408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidisstatic int testcase_glob(const char *zGlob, const char *z){
1120508f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  int c, c2;
1120608f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  int invert;
1120708f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  int seen;
1120808f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis
1120908f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  while( (c = (*(zGlob++)))!=0 ){
1121008f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    if( IsSpace(c) ){
1121108f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      if( !IsSpace(*z) ) return 0;
1121208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      while( IsSpace(*zGlob) ) zGlob++;
1121308f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      while( IsSpace(*z) ) z++;
1121408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    }else if( c=='*' ){
1121508f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      while( (c=(*(zGlob++))) == '*' || c=='?' ){
1121608f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis        if( c=='?' && (*(z++))==0 ) return 0;
1121708f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      }
1121808f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      if( c==0 ){
1121908f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis        return 1;
1122008f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      }else if( c=='[' ){
1122108f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis        while( *z && testcase_glob(zGlob-1,z)==0 ){
1122208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis          z++;
1122308f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis        }
1122408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis        return (*z)!=0;
1122508f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      }
1122608f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      while( (c2 = (*(z++)))!=0 ){
1122708f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis        while( c2!=c ){
1122808f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis          c2 = *(z++);
1122908f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis          if( c2==0 ) return 0;
1123008f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis        }
1123108f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis        if( testcase_glob(zGlob,z) ) return 1;
1123208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      }
1123308f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      return 0;
1123408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    }else if( c=='?' ){
1123508f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      if( (*(z++))==0 ) return 0;
1123608f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    }else if( c=='[' ){
1123708f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      int prior_c = 0;
1123808f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      seen = 0;
1123908f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      invert = 0;
1124008f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      c = *(z++);
1124108f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      if( c==0 ) return 0;
1124208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      c2 = *(zGlob++);
1124308f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      if( c2=='^' ){
1124408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis        invert = 1;
1124508f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis        c2 = *(zGlob++);
1124608f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      }
1124708f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      if( c2==']' ){
1124808f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis        if( c==']' ) seen = 1;
1124908f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis        c2 = *(zGlob++);
1125008f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      }
1125108f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      while( c2 && c2!=']' ){
1125208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis        if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){
1125308f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis          c2 = *(zGlob++);
1125408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis          if( c>=prior_c && c<=c2 ) seen = 1;
1125508f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis          prior_c = 0;
1125608f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis        }else{
1125708f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis          if( c==c2 ){
1125808f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis            seen = 1;
1125908f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis          }
1126008f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis          prior_c = c2;
1126108f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis        }
1126208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis        c2 = *(zGlob++);
1126308f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      }
1126408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      if( c2==0 || (seen ^ invert)==0 ) return 0;
1126508f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    }else if( c=='#' ){
1126608f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      if( (z[0]=='-' || z[0]=='+') && IsDigit(z[1]) ) z++;
1126708f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      if( !IsDigit(z[0]) ) return 0;
1126808f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      z++;
1126908f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      while( IsDigit(z[0]) ){ z++; }
1127008f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    }else{
1127108f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      if( c!=(*(z++)) ) return 0;
1127208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    }
1127308f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  }
1127408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  while( IsSpace(*z) ){ z++; }
1127508f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  return *z==0;
1127608f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis}
1127708f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis
1127808f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis
1127908f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis/*
1128060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** Compare the string as a command-line option with either one or two
1128160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis** initial "-" characters.
1128260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis*/
1128360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidisstatic int optionMatch(const char *zStr, const char *zOpt){
1128460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  if( zStr[0]!='-' ) return 0;
1128560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  zStr++;
1128660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  if( zStr[0]=='-' ) zStr++;
1128760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  return strcmp(zStr, zOpt)==0;
1128860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis}
1128960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
1129060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis/*
1129108f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis** Delete a file.
1129208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis*/
1129308f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidisint shellDeleteFile(const char *zFilename){
1129408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  int rc;
1129508f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis#ifdef _WIN32
1129608f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  wchar_t *z = sqlite3_win32_utf8_to_unicode(zFilename);
1129708f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  rc = _wunlink(z);
1129808f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  sqlite3_free(z);
1129908f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis#else
1130008f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  rc = unlink(zFilename);
1130108f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis#endif
1130208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  return rc;
1130308f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis}
1130408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis
113050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
113060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Try to delete the temporary file (if there is one) and free the
113070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** memory used to hold the name of the temp file.
113080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
113090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void clearTempFile(ShellState *p){
113100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( p->zTempFile==0 ) return;
113110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( p->doXdgOpen ) return;
113120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( shellDeleteFile(p->zTempFile) ) return;
113130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(p->zTempFile);
113140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  p->zTempFile = 0;
113150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
113160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
113170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
113180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Create a new temp file name with the given suffix.
113190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
113200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void newTempFile(ShellState *p, const char *zSuffix){
113210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  clearTempFile(p);
113220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(p->zTempFile);
113230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  p->zTempFile = 0;
113240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( p->db ){
113250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile);
113260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
113270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( p->zTempFile==0 ){
113280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_uint64 r;
113290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_randomness(sizeof(r), &r);
113300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    p->zTempFile = sqlite3_mprintf("temp%llx.%s", r, zSuffix);
113310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
113320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);
113330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
113340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( p->zTempFile==0 ){
113350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    raw_printf(stderr, "out of memory\n");
113360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    exit(1);
113370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
113380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
113390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
11340e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani
11341e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani/*
11342e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani** The implementation of SQL scalar function fkey_collate_clause(), used
11343e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani** by the ".lint fkey-indexes" command. This scalar function is always
11344e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani** called with four arguments - the parent table name, the parent column name,
11345e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani** the child table name and the child column name.
11346e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani**
11347e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani**   fkey_collate_clause('parent-tab', 'parent-col', 'child-tab', 'child-col')
11348e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani**
11349e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani** If either of the named tables or columns do not exist, this function
113500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** returns an empty string. An empty string is also returned if both tables
11351e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani** and columns exist but have the same default collation sequence. Or,
11352e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani** if both exist but the default collation sequences are different, this
11353e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani** function returns the string " COLLATE <parent-collation>", where
11354e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani** <parent-collation> is the default collation sequence of the parent column.
11355e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani*/
11356e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefanistatic void shellFkeyCollateClause(
113570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_context *pCtx,
113580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nVal,
11359e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  sqlite3_value **apVal
11360e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani){
11361e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  sqlite3 *db = sqlite3_context_db_handle(pCtx);
11362e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  const char *zParent;
11363e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  const char *zParentCol;
11364e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  const char *zParentSeq;
11365e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  const char *zChild;
11366e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  const char *zChildCol;
11367e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  const char *zChildSeq = 0;  /* Initialize to avoid false-positive warning */
11368e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  int rc;
113690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
11370e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  assert( nVal==4 );
11371e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  zParent = (const char*)sqlite3_value_text(apVal[0]);
11372e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  zParentCol = (const char*)sqlite3_value_text(apVal[1]);
11373e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  zChild = (const char*)sqlite3_value_text(apVal[2]);
11374e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  zChildCol = (const char*)sqlite3_value_text(apVal[3]);
11375e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani
11376e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC);
11377e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  rc = sqlite3_table_column_metadata(
11378e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      db, "main", zParent, zParentCol, 0, &zParentSeq, 0, 0, 0
11379e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  );
11380e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  if( rc==SQLITE_OK ){
11381e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    rc = sqlite3_table_column_metadata(
11382e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani        db, "main", zChild, zChildCol, 0, &zChildSeq, 0, 0, 0
11383e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    );
11384e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  }
11385e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani
11386e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  if( rc==SQLITE_OK && sqlite3_stricmp(zParentSeq, zChildSeq) ){
11387e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    char *z = sqlite3_mprintf(" COLLATE %s", zParentSeq);
11388e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
11389e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    sqlite3_free(z);
11390e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  }
11391e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani}
11392e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani
11393e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani
11394e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani/*
11395e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani** The implementation of dot-command ".lint fkey-indexes".
11396e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani*/
11397e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefanistatic int lintFkeyIndexes(
11398e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  ShellState *pState,             /* Current shell tool state */
11399e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  char **azArg,                   /* Array of arguments passed to dot command */
11400e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  int nArg                        /* Number of entries in azArg[] */
11401e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani){
11402e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  sqlite3 *db = pState->db;       /* Database handle to query "main" db of */
11403e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  FILE *out = pState->out;        /* Stream to write non-error output to */
11404e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  int bVerbose = 0;               /* If -verbose is present */
11405e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  int bGroupByParent = 0;         /* If -groupbyparent is present */
11406e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  int i;                          /* To iterate through azArg[] */
11407e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  const char *zIndent = "";       /* How much to indent CREATE INDEX by */
11408e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  int rc;                         /* Return code */
11409e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  sqlite3_stmt *pSql = 0;         /* Compiled version of SQL statement below */
11410e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani
11411e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  /*
11412e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  ** This SELECT statement returns one row for each foreign key constraint
11413e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  ** in the schema of the main database. The column values are:
11414e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  **
11415e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  ** 0. The text of an SQL statement similar to:
11416e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  **
114170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  **      "EXPLAIN QUERY PLAN SELECT 1 FROM child_table WHERE child_key=?"
11418e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  **
114190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  **    This SELECT is similar to the one that the foreign keys implementation
114200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  **    needs to run internally on child tables. If there is an index that can
11421e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  **    be used to optimize this query, then it can also be used by the FK
11422e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  **    implementation to optimize DELETE or UPDATE statements on the parent
11423e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  **    table.
11424e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  **
11425e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  ** 1. A GLOB pattern suitable for sqlite3_strglob(). If the plan output by
11426e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  **    the EXPLAIN QUERY PLAN command matches this pattern, then the schema
11427e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  **    contains an index that can be used to optimize the query.
11428e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  **
11429e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  ** 2. Human readable text that describes the child table and columns. e.g.
11430e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  **
11431e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  **       "child_table(child_key1, child_key2)"
11432e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  **
11433e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  ** 3. Human readable text that describes the parent table and columns. e.g.
11434e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  **
11435e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  **       "parent_table(parent_key1, parent_key2)"
11436e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  **
11437e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  ** 4. A full CREATE INDEX statement for an index that could be used to
11438e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  **    optimize DELETE or UPDATE statements on the parent table. e.g.
11439e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  **
11440e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  **       "CREATE INDEX child_table_child_key ON child_table(child_key)"
11441e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  **
11442e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  ** 5. The name of the parent table.
11443e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  **
11444e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  ** These six values are used by the C logic below to generate the report.
11445e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  */
11446e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  const char *zSql =
11447e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  "SELECT "
114480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "     'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '"
11449e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    "  || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
11450b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    "  || fkey_collate_clause("
11451b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    "       f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
11452e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    ", "
11453e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    "     'SEARCH TABLE ' || s.name || ' USING COVERING INDEX*('"
11454e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    "  || group_concat('*=?', ' AND ') || ')'"
11455e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    ", "
11456e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    "     s.name  || '(' || group_concat(f.[from],  ', ') || ')'"
11457e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    ", "
11458b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    "     f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'"
11459e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    ", "
11460e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    "     'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))"
11461e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    "  || ' ON ' || quote(s.name) || '('"
11462e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    "  || group_concat(quote(f.[from]) ||"
11463b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    "        fkey_collate_clause("
11464b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    "          f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')"
11465e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    "  || ');'"
11466e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    ", "
11467e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    "     f.[table] "
11468e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    "FROM sqlite_master AS s, pragma_foreign_key_list(s.name) AS f "
11469b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) "
11470e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    "GROUP BY s.name, f.id "
11471e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
11472e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  ;
11473b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis  const char *zGlobIPK = "SEARCH TABLE * USING INTEGER PRIMARY KEY (rowid=?)";
11474e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani
11475e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  for(i=2; i<nArg; i++){
114760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int n = strlen30(azArg[i]);
11477e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){
11478e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      bVerbose = 1;
11479e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    }
11480e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){
11481e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      bGroupByParent = 1;
11482e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      zIndent = "    ";
11483e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    }
11484e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    else{
11485e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n",
11486e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani          azArg[0], azArg[1]
11487e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      );
11488e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      return SQLITE_ERROR;
11489e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    }
11490e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  }
114910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
11492e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  /* Register the fkey_collate_clause() SQL function */
11493e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8,
11494e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      0, shellFkeyCollateClause, 0, 0
11495e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  );
11496e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani
11497e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani
11498e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  if( rc==SQLITE_OK ){
11499e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0);
11500e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  }
11501e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  if( rc==SQLITE_OK ){
11502e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    sqlite3_bind_int(pSql, 1, bGroupByParent);
11503e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  }
11504e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani
11505e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  if( rc==SQLITE_OK ){
11506e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    int rc2;
11507e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    char *zPrev = 0;
11508e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    while( SQLITE_ROW==sqlite3_step(pSql) ){
11509e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      int res = -1;
11510e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      sqlite3_stmt *pExplain = 0;
11511e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      const char *zEQP = (const char*)sqlite3_column_text(pSql, 0);
11512e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      const char *zGlob = (const char*)sqlite3_column_text(pSql, 1);
11513e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      const char *zFrom = (const char*)sqlite3_column_text(pSql, 2);
11514e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      const char *zTarget = (const char*)sqlite3_column_text(pSql, 3);
11515e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      const char *zCI = (const char*)sqlite3_column_text(pSql, 4);
11516e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      const char *zParent = (const char*)sqlite3_column_text(pSql, 5);
11517e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani
115180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
115190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( rc!=SQLITE_OK ) break;
115200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( SQLITE_ROW==sqlite3_step(pExplain) ){
115210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3);
115220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        res = (
115230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov              0==sqlite3_strglob(zGlob, zPlan)
115240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov           || 0==sqlite3_strglob(zGlobIPK, zPlan)
115250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        );
115260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
115270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = sqlite3_finalize(pExplain);
115280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( rc!=SQLITE_OK ) break;
115290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
115300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( res<0 ){
115310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        raw_printf(stderr, "Error: internal error");
115320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        break;
115330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else{
115340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( bGroupByParent
115350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        && (bVerbose || res==0)
115360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        && (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
115370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        ){
115380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          raw_printf(out, "-- Parent table %s\n", zParent);
115390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          sqlite3_free(zPrev);
115400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          zPrev = sqlite3_mprintf("%s", zParent);
115410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
115420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
115430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( res==0 ){
115440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget);
115450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }else if( bVerbose ){
115460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n",
115470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov              zIndent, zFrom, zTarget
115480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          );
115490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
115500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
115510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
115520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(zPrev);
115530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
115540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( rc!=SQLITE_OK ){
115550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
115560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
115570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
115580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc2 = sqlite3_finalize(pSql);
115590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( rc==SQLITE_OK && rc2!=SQLITE_OK ){
115600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = rc2;
115610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
115620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
115630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
115640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
115650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
115660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
115670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
115680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
115690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
115700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
115710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Implementation of ".lint" dot command.
115720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
115730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int lintDotCommand(
115740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ShellState *pState,             /* Current shell tool state */
115750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **azArg,                   /* Array of arguments passed to dot command */
115760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nArg                        /* Number of entries in azArg[] */
115770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
115780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int n;
115790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  n = (nArg>=2 ? strlen30(azArg[1]) : 0);
115800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage;
115810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return lintFkeyIndexes(pState, azArg, nArg);
115820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
115830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov usage:
115840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]);
115850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  raw_printf(stderr, "Where sub-commands are:\n");
115860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  raw_printf(stderr, "    fkey-indexes\n");
115870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_ERROR;
115880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
115890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
115900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
115910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*********************************************************************************
115920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The ".archive" or ".ar" command.
115930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
115940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void shellPrepare(
115950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *db,
115960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int *pRc,
115970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zSql,
115980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_stmt **ppStmt
115990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
116000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  *ppStmt = 0;
116010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( *pRc==SQLITE_OK ){
116020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
116030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( rc!=SQLITE_OK ){
116040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      raw_printf(stderr, "sql error: %s (%d)\n",
116050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          sqlite3_errmsg(db), sqlite3_errcode(db)
116060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      );
116070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      *pRc = rc;
116080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
116090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
116100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
116110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
116120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void shellPreparePrintf(
116130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *db,
116140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int *pRc,
116150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_stmt **ppStmt,
116160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zFmt,
116170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ...
116180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
116190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  *ppStmt = 0;
116200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( *pRc==SQLITE_OK ){
116210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    va_list ap;
116220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    char *z;
116230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    va_start(ap, zFmt);
116240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    z = sqlite3_vmprintf(zFmt, ap);
116250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( z==0 ){
116260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      *pRc = SQLITE_NOMEM;
116270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
116280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      shellPrepare(db, pRc, z, ppStmt);
116290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_free(z);
116300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
116310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
116320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
116330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
116340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void shellFinalize(
116350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int *pRc,
116360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_stmt *pStmt
116370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
116380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pStmt ){
116390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3 *db = sqlite3_db_handle(pStmt);
116400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int rc = sqlite3_finalize(pStmt);
116410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( *pRc==SQLITE_OK ){
116420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( rc!=SQLITE_OK ){
116430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
116440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
116450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      *pRc = rc;
116460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
116470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
116480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
116490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
116500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void shellReset(
116510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int *pRc,
116520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_stmt *pStmt
116530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
116540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = sqlite3_reset(pStmt);
116550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( *pRc==SQLITE_OK ){
116560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( rc!=SQLITE_OK ){
116570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3 *db = sqlite3_db_handle(pStmt);
116580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
116590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
116600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    *pRc = rc;
116610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
116620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
116630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
116640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Structure representing a single ".ar" command.
116650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
116660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovtypedef struct ArCommand ArCommand;
116670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstruct ArCommand {
116680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 eCmd;                        /* An AR_CMD_* value */
116690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 bVerbose;                    /* True if --verbose */
116700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 bZip;                        /* True if the archive is a ZIP */
116710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 bDryRun;                     /* True if --dry-run */
116720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  u8 bAppend;                     /* True if --append */
116730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nArg;                       /* Number of command arguments */
116740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zSrcTable;                /* "sqlar", "zipfile($file)" or "zip" */
116750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zFile;              /* --file argument, or NULL */
116760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zDir;               /* --directory argument, or NULL */
116770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **azArg;                   /* Array of command arguments */
116780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ShellState *p;                  /* Shell state */
116790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3 *db;                    /* Database containing the archive */
116800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov};
116810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
116820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
116830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Print a usage message for the .ar command to stderr and return SQLITE_ERROR.
116840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
116850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int arUsage(FILE *f){
116860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  raw_printf(f,
116870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov"\n"
116880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov"Usage: .ar [OPTION...] [FILE...]\n"
116890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov"The .ar command manages sqlar archives.\n"
116900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov"\n"
116910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov"Examples:\n"
116920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov"  .ar -cf archive.sar foo bar    # Create archive.sar from files foo and bar\n"
116930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov"  .ar -tf archive.sar            # List members of archive.sar\n"
116940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov"  .ar -xvf archive.sar           # Verbosely extract files from archive.sar\n"
116950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov"\n"
116960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov"Each command line must feature exactly one command option:\n"
116970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov"  -c, --create               Create a new archive\n"
116980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov"  -u, --update               Update or add files to an existing archive\n"
116990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov"  -t, --list                 List contents of archive\n"
117000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov"  -x, --extract              Extract files from archive\n"
117010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov"\n"
117020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov"And zero or more optional options:\n"
117030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov"  -v, --verbose              Print each filename as it is processed\n"
117040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov"  -f FILE, --file FILE       Operate on archive FILE (default is current db)\n"
117050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov"  -a FILE, --append FILE     Operate on FILE opened using the apndvfs VFS\n"
117060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov"  -C DIR, --directory DIR    Change to directory DIR to read/extract files\n"
117070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov"  -n, --dryrun               Show the SQL that would have occurred\n"
117080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov"\n"
117090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov"See also: http://sqlite.org/cli.html#sqlar_archive_support\n"
117100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov"\n"
117110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov);
117120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_ERROR;
117130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
117140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
117150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
117160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Print an error message for the .ar command to stderr and return
117170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** SQLITE_ERROR.
117180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
117190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int arErrorMsg(const char *zFmt, ...){
117200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  va_list ap;
117210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *z;
117220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  va_start(ap, zFmt);
117230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  z = sqlite3_vmprintf(zFmt, ap);
117240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  va_end(ap);
117250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  raw_printf(stderr, "Error: %s (try \".ar --help\")\n", z);
117260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(z);
117270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_ERROR;
117280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
117290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
117300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
117310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Values for ArCommand.eCmd.
117320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
117330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define AR_CMD_CREATE       1
117340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define AR_CMD_EXTRACT      2
117350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define AR_CMD_LIST         3
117360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define AR_CMD_UPDATE       4
117370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define AR_CMD_HELP         5
117380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
117390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
117400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Other (non-command) switches.
117410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
117420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define AR_SWITCH_VERBOSE     6
117430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define AR_SWITCH_FILE        7
117440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define AR_SWITCH_DIRECTORY   8
117450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define AR_SWITCH_APPEND      9
117460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define AR_SWITCH_DRYRUN     10
117470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
117480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
117490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  switch( eSwitch ){
117500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case AR_CMD_CREATE:
117510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case AR_CMD_EXTRACT:
117520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case AR_CMD_LIST:
117530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case AR_CMD_UPDATE:
117540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case AR_CMD_HELP:
117550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( pAr->eCmd ){
117560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        return arErrorMsg("multiple command options");
117570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
117580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pAr->eCmd = eSwitch;
117590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
117600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
117610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case AR_SWITCH_DRYRUN:
117620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pAr->bDryRun = 1;
117630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
117640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case AR_SWITCH_VERBOSE:
117650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pAr->bVerbose = 1;
117660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
117670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case AR_SWITCH_APPEND:
117680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pAr->bAppend = 1;
117690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      /* Fall thru into --file */
117700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case AR_SWITCH_FILE:
117710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pAr->zFile = zArg;
117720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
117730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    case AR_SWITCH_DIRECTORY:
117740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pAr->zDir = zArg;
117750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      break;
117760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
117770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
117780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
117790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
117800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
117810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
117820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Parse the command line for an ".ar" command. The results are written into
117830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** structure (*pAr). SQLITE_OK is returned if the command line is parsed
117840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** successfully, otherwise an error message is written to stderr and
117850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** SQLITE_ERROR returned.
117860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
117870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int arParseCommand(
117880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **azArg,                   /* Array of arguments passed to dot command */
117890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nArg,                       /* Number of entries in azArg[] */
117900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ArCommand *pAr                  /* Populate this object */
117910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
117920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  struct ArSwitch {
117930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const char *zLong;
117940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    char cShort;
117950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    u8 eSwitch;
117960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    u8 bArg;
117970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  } aSwitch[] = {
117980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    { "create",    'c', AR_CMD_CREATE,       0 },
117990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    { "extract",   'x', AR_CMD_EXTRACT,      0 },
118000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    { "list",      't', AR_CMD_LIST,         0 },
118010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    { "update",    'u', AR_CMD_UPDATE,       0 },
118020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    { "help",      'h', AR_CMD_HELP,         0 },
118030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    { "verbose",   'v', AR_SWITCH_VERBOSE,   0 },
118040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    { "file",      'f', AR_SWITCH_FILE,      1 },
118050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    { "append",    'a', AR_SWITCH_APPEND,    1 },
118060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    { "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
118070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    { "dryrun",    'n', AR_SWITCH_DRYRUN,    0 },
118080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  };
118090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
118100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  struct ArSwitch *pEnd = &aSwitch[nSwitch];
118110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
118120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( nArg<=1 ){
118130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    return arUsage(stderr);
118140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
118150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    char *z = azArg[1];
118160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    memset(pAr, 0, sizeof(ArCommand));
118170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
118180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( z[0]!='-' ){
118190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      /* Traditional style [tar] invocation */
118200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int i;
118210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int iArg = 2;
118220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      for(i=0; z[i]; i++){
118230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        const char *zArg = 0;
118240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        struct ArSwitch *pOpt;
118250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
118260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( z[i]==pOpt->cShort ) break;
118270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
118280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( pOpt==pEnd ){
118290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          return arErrorMsg("unrecognized option: %c", z[i]);
118300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
118310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( pOpt->bArg ){
118320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( iArg>=nArg ){
118330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            return arErrorMsg("option requires an argument: %c",z[i]);
118340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
118350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          zArg = azArg[iArg++];
118360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
118370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
118380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
118390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      pAr->nArg = nArg-iArg;
118400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( pAr->nArg>0 ){
118410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        pAr->azArg = &azArg[iArg];
118420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
118430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
118440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      /* Non-traditional invocation */
118450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int iArg;
118460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      for(iArg=1; iArg<nArg; iArg++){
118470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        int n;
118480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        z = azArg[iArg];
118490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( z[0]!='-' ){
118500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          /* All remaining command line words are command arguments. */
118510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          pAr->azArg = &azArg[iArg];
118520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          pAr->nArg = nArg-iArg;
118530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          break;
118540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
118550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        n = strlen30(z);
118560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
118570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( z[1]!='-' ){
118580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          int i;
118590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          /* One or more short options */
118600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          for(i=1; i<n; i++){
118610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            const char *zArg = 0;
118620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            struct ArSwitch *pOpt;
118630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
118640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov              if( z[i]==pOpt->cShort ) break;
118650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            }
118660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            if( pOpt==pEnd ){
118670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov              return arErrorMsg("unrecognized option: %c\n", z[i]);
118680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            }
118690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            if( pOpt->bArg ){
118700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov              if( i<(n-1) ){
118710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                zArg = &z[i+1];
118720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                i = n;
118730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov              }else{
118740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                if( iArg>=(nArg-1) ){
118750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                  return arErrorMsg("option requires an argument: %c\n",z[i]);
118760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                }
118770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                zArg = azArg[++iArg];
118780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov              }
118790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            }
118800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
118810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
118820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }else if( z[2]=='\0' ){
118830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          /* A -- option, indicating that all remaining command line words
118840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          ** are command arguments.  */
118850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          pAr->azArg = &azArg[iArg+1];
118860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          pAr->nArg = nArg-iArg-1;
118870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          break;
118880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }else{
118890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          /* A long option */
118900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          const char *zArg = 0;             /* Argument for option, if any */
118910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          struct ArSwitch *pMatch = 0;      /* Matching option */
118920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          struct ArSwitch *pOpt;            /* Iterator */
118930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
118940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            const char *zLong = pOpt->zLong;
118950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            if( (n-2)<=strlen30(zLong) && 0==memcmp(&z[2], zLong, n-2) ){
118960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov              if( pMatch ){
118970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                return arErrorMsg("ambiguous option: %s",z);
118980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov              }else{
118990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                pMatch = pOpt;
119000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov              }
119010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            }
119020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
119030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
119040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( pMatch==0 ){
119050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            return arErrorMsg("unrecognized option: %s", z);
119060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
119070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( pMatch->bArg ){
119080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            if( iArg>=(nArg-1) ){
119090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov              return arErrorMsg("option requires an argument: %s", z);
119100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            }
119110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            zArg = azArg[++iArg];
119120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
119130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR;
119140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
119150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
119160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
119170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
119180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
119190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return SQLITE_OK;
119200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
119210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
119220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
119230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This function assumes that all arguments within the ArCommand.azArg[]
119240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** array refer to archive members, as for the --extract or --list commands.
119250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** It checks that each of them are present. If any specified file is not
119260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** present in the archive, an error is printed to stderr and an error
119270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** code returned. Otherwise, if all specified arguments are present in
119280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** the archive, SQLITE_OK is returned.
119290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
119300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This function strips any trailing '/' characters from each argument.
119310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** This is consistent with the way the [tar] command seems to work on
119320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Linux.
119330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
119340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int arCheckEntries(ArCommand *pAr){
119350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
119360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pAr->nArg ){
119370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int i, j;
119380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_stmt *pTest = 0;
119390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
119400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    shellPreparePrintf(pAr->db, &rc, &pTest,
119410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        "SELECT name FROM %s WHERE name=$name",
119420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        pAr->zSrcTable
119430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    );
119440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    j = sqlite3_bind_parameter_index(pTest, "$name");
119450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
119460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      char *z = pAr->azArg[i];
119470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int n = strlen30(z);
119480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int bOk = 0;
119490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      while( n>0 && z[n-1]=='/' ) n--;
119500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      z[n] = '\0';
119510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC);
119520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( SQLITE_ROW==sqlite3_step(pTest) ){
119530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        bOk = 1;
119540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
119550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      shellReset(&rc, pTest);
119560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( rc==SQLITE_OK && bOk==0 ){
119570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        utf8_printf(stderr, "not found in archive: %s\n", z);
119580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        rc = SQLITE_ERROR;
119590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
119600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
119610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    shellFinalize(&rc, pTest);
119620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
119630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
119640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
119650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
119660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
119670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Format a WHERE clause that can be used against the "sqlar" table to
119680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** identify all archive members that match the command arguments held
119690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning.
119700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The caller is responsible for eventually calling sqlite3_free() on
119710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** any non-NULL (*pzWhere) value.
119720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
119730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic void arWhereClause(
119740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int *pRc,
119750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ArCommand *pAr,
119760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char **pzWhere                  /* OUT: New WHERE clause */
119770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
119780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zWhere = 0;
119790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( *pRc==SQLITE_OK ){
119800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pAr->nArg==0 ){
119810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zWhere = sqlite3_mprintf("1");
119820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
119830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int i;
119840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      const char *zSep = "";
119850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      for(i=0; i<pAr->nArg; i++){
119860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        const char *z = pAr->azArg[i];
119870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        zWhere = sqlite3_mprintf(
119880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          "%z%s name = '%q' OR substr(name,1,%d) = '%q/'",
119890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          zWhere, zSep, z, strlen30(z)+1, z
119900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        );
119910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( zWhere==0 ){
119920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          *pRc = SQLITE_NOMEM;
119930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          break;
119940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
119950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        zSep = " OR ";
119960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
119970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
119980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
119990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  *pzWhere = zWhere;
120000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
120010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
120020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
120030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Implementation of .ar "lisT" command.
120040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
120050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int arListCommand(ArCommand *pAr){
120060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zSql = "SELECT %s FROM %s WHERE %s";
120070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *azCols[] = {
120080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "name",
120090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name"
120100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  };
120110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
120120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zWhere = 0;
120130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_stmt *pSql = 0;
120140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;
120150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
120160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = arCheckEntries(pAr);
120170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  arWhereClause(&rc, pAr, &zWhere);
120180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
120190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
120200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                     pAr->zSrcTable, zWhere);
120210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pAr->bDryRun ){
120220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
120230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
120240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
120250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( pAr->bVerbose ){
120260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        utf8_printf(pAr->p->out, "%s % 10d  %s  %s\n",
120270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            sqlite3_column_text(pSql, 0),
120280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            sqlite3_column_int(pSql, 1),
120290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            sqlite3_column_text(pSql, 2),
120300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            sqlite3_column_text(pSql, 3)
120310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        );
120320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else{
120330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
120340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
120350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
120360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
120370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  shellFinalize(&rc, pSql);
120380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
120390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
120400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
120410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
120420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
120430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Implementation of .ar "eXtract" command.
120440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
120450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int arExtractCommand(ArCommand *pAr){
120460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zSql1 =
120470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "SELECT "
120480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    " ($dir || name),"
120490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    " writefile(($dir || name), %s, mode, mtime) "
120500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)";
120510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
120520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *azExtraArg[] = {
120530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "sqlar_uncompress(data, sz)",
120540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    "data"
120550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  };
120560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
120570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_stmt *pSql = 0;
120580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc = SQLITE_OK;
120590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zDir = 0;
120600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  char *zWhere = 0;
120610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int i, j;
120620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
120630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* If arguments are specified, check that they actually exist within
120640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ** the archive before proceeding. And formulate a WHERE clause to
120650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ** match them.  */
120660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = arCheckEntries(pAr);
120670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  arWhereClause(&rc, pAr, &zWhere);
120680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
120690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
120700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( pAr->zDir ){
120710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zDir = sqlite3_mprintf("%s/", pAr->zDir);
120720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
120730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zDir = sqlite3_mprintf("");
120740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
120750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( zDir==0 ) rc = SQLITE_NOMEM;
120760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
120770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
120780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  shellPreparePrintf(pAr->db, &rc, &pSql, zSql1,
120790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere
120800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  );
12081e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani
120820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
120830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    j = sqlite3_bind_parameter_index(pSql, "$dir");
120840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
120850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
120860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    /* Run the SELECT statement twice. The first time, writefile() is called
120870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ** for all archive members that should be extracted. The second time,
120880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ** only for the directories. This is because the timestamps for
120890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ** extracted directories must be reset after they are populated (as
120900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ** populating them changes the timestamp).  */
120910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    for(i=0; i<2; i++){
120920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      j = sqlite3_bind_parameter_index(pSql, "$dirOnly");
120930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_bind_int(pSql, j, i);
120940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( pAr->bDryRun ){
120950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
12096e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      }else{
120970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
120980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( i==0 && pAr->bVerbose ){
120990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
121000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
12101e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani        }
12102e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      }
121030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      shellReset(&rc, pSql);
12104e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    }
121050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    shellFinalize(&rc, pSql);
121060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
12107e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani
121080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(zDir);
121090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(zWhere);
121100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
121110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
12112e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani
121130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
121140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Run the SQL statement in zSql.  Or if doing a --dryrun, merely print it out.
121150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
121160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int arExecSql(ArCommand *pAr, const char *zSql){
121170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;
121180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( pAr->bDryRun ){
121190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    utf8_printf(pAr->p->out, "%s\n", zSql);
121200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = SQLITE_OK;
12121e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  }else{
121220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    char *zErr = 0;
121230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
121240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( zErr ){
121250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      utf8_printf(stdout, "ERROR: %s\n", zErr);
121260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_free(zErr);
121270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
12128e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  }
121290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
121300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov}
121310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
121320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
121330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/*
121340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Implementation of .ar "create" and "update" commands.
121350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
121360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Create the "sqlar" table in the database if it does not already exist.
121370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Then add each file in the azFile[] array to the archive. Directories
121380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** are added recursively. If argument bVerbose is non-zero, a message is
121390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** printed on stdout for each file archived.
121400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**
121410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** The create command is the same as update, except that it drops
121420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** any existing "sqlar" table before beginning.
121430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov*/
121440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int arCreateOrUpdateCommand(
121450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ArCommand *pAr,                 /* Command arguments and options */
121460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int bUpdate                     /* true for a --create.  false for --update */
121470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov){
121480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zCreate =
121490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      "CREATE TABLE IF NOT EXISTS sqlar(\n"
121500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      "  name TEXT PRIMARY KEY,  -- name of the file\n"
121510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      "  mode INT,               -- access permissions\n"
121520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      "  mtime INT,              -- last modification time\n"
121530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      "  sz INT,                 -- original file size\n"
121540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      "  data BLOB               -- compressed content\n"
121550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      ")";
121560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zDrop = "DROP TABLE IF EXISTS sqlar";
121570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  const char *zInsertFmt =
121580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov     "REPLACE INTO sqlar(name,mode,mtime,sz,data)\n"
121590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov     "  SELECT\n"
121600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov     "    %s,\n"
121610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov     "    mode,\n"
121620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov     "    mtime,\n"
121630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov     "    CASE substr(lsmode(mode),1,1)\n"
121640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov     "      WHEN '-' THEN length(data)\n"
121650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov     "      WHEN 'd' THEN 0\n"
121660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov     "      ELSE -1 END,\n"
121670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov     "    CASE WHEN lsmode(mode) LIKE 'd%%' THEN NULL else data END\n"
121680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov     "  FROM fsdir(%Q,%Q)\n"
121690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov     "  WHERE lsmode(mode) NOT LIKE '?%%';";
121700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int i;                          /* For iterating through azFile[] */
121710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;                         /* Return code */
12172e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani
121730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = arExecSql(pAr, "SAVEPOINT ar;");
121740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc!=SQLITE_OK ) return rc;
121750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( bUpdate==0 ){
121760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = arExecSql(pAr, zDrop);
121770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( rc!=SQLITE_OK ) return rc;
121780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
121790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = arExecSql(pAr, zCreate);
121800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
121810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    char *zSql = sqlite3_mprintf(zInsertFmt,
121820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        pAr->bVerbose ? "shell_putsnl(name)" : "name",
121830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        pAr->azArg[i], pAr->zDir);
121840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = arExecSql(pAr, zSql);
121850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_free(zSql);
121860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
121870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc!=SQLITE_OK ){
121880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    arExecSql(pAr, "ROLLBACK TO ar; RELEASE ar;");
121890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else{
121900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = arExecSql(pAr, "RELEASE ar;");
121910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
12192e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  return rc;
12193e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani}
12194e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani
12195e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani/*
121960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov** Implementation of ".ar" dot command.
12197e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani*/
121980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovstatic int arDotCommand(
12199e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  ShellState *pState,             /* Current shell tool state */
12200e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  char **azArg,                   /* Array of arguments passed to dot command */
12201e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  int nArg                        /* Number of entries in azArg[] */
12202e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani){
122030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ArCommand cmd;
122040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  int rc;
122050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  memset(&cmd, 0, sizeof(cmd));
122060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  rc = arParseCommand(azArg, nArg, &cmd);
122070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( rc==SQLITE_OK ){
122080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int eDbType = SHELL_OPEN_UNSPEC;
122090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    cmd.p = pState;
122100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    cmd.db = pState->db;
122110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( cmd.zFile ){
122120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      eDbType = deduceDatabaseType(cmd.zFile);
122130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
122140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      eDbType = pState->openMode;
122150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
122160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( eDbType==SHELL_OPEN_ZIPFILE ){
122170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( cmd.zFile==0 ){
122180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        cmd.zSrcTable = sqlite3_mprintf("zip");
122190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else{
122200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile);
122210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
122220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_UPDATE ){
122230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        utf8_printf(stderr, "zip archives are read-only\n");
122240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        rc = SQLITE_ERROR;
122250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        goto end_ar_command;
122260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
122270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      cmd.bZip = 1;
122280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else if( cmd.zFile ){
122290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int flags;
122300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
122310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_UPDATE ){
122320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
122330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else{
122340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        flags = SQLITE_OPEN_READONLY;
122350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
122360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      cmd.db = 0;
122370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( cmd.bDryRun ){
122380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile,
122390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov             eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
122400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
122410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags,
122420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov             eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0);
122430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( rc!=SQLITE_OK ){
122440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        utf8_printf(stderr, "cannot open file: %s (%s)\n",
122450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            cmd.zFile, sqlite3_errmsg(cmd.db)
122460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        );
122470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        goto end_ar_command;
122480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
122490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_fileio_init(cmd.db, 0, 0);
122500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifdef SQLITE_HAVE_ZLIB
122510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_sqlar_init(cmd.db, 0, 0);
122520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
122530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p,
122540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                              shellPutsFunc, 0, 0);
12255e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani
122560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
122570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( cmd.zSrcTable==0 ){
122580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( cmd.eCmd!=AR_CMD_CREATE
122590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov       && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
122600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      ){
122610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        utf8_printf(stderr, "database does not contain an 'sqlar' table\n");
122620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        rc = SQLITE_ERROR;
122630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        goto end_ar_command;
122640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
122650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      cmd.zSrcTable = sqlite3_mprintf("sqlar");
122660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
122670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
122680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    switch( cmd.eCmd ){
122690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      case AR_CMD_CREATE:
122700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        rc = arCreateOrUpdateCommand(&cmd, 0);
122710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        break;
122720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
122730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      case AR_CMD_EXTRACT:
122740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        rc = arExtractCommand(&cmd);
122750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        break;
122760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
122770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      case AR_CMD_LIST:
122780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        rc = arListCommand(&cmd);
122790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        break;
122800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
122810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      case AR_CMD_HELP:
122820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        arUsage(pState->out);
122830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        break;
122840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
122850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      default:
122860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        assert( cmd.eCmd==AR_CMD_UPDATE );
122870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        rc = arCreateOrUpdateCommand(&cmd, 1);
122880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        break;
122890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
122900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
122910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolovend_ar_command:
122920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( cmd.db!=pState->db ){
122930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_close(cmd.db);
122940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
122950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_free(cmd.zSrcTable);
122960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
122970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  return rc;
12298e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani}
122990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov/* End of the ".archive" or ".ar" command logic
123000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov**********************************************************************************/
123010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
12302e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani
12303e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani
1230408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis/*
123057790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** If an input line begins with "." then invoke this routine to
123067790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** process that line.
123077790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project**
123087790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** Return 1 on error, 2 to exit, and 0 otherwise.
123097790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
123103fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichstatic int do_meta_command(char *zLine, ShellState *p){
123113a6c79f802fabdb94367177310663397420e319fNick Kralevich  int h = 1;
123127790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  int nArg = 0;
123137790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  int n, c;
123147790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  int rc = 0;
123157790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  char *azArg[50];
123167790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
123170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifndef SQLITE_OMIT_VIRTUALTABLE
123180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( p->expert.pExpert ){
123190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    expertFinish(p, 1, 0);
123200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }
123210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
123220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
123237790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  /* Parse the input line into tokens.
123247790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  */
123253a6c79f802fabdb94367177310663397420e319fNick Kralevich  while( zLine[h] && nArg<ArraySize(azArg) ){
123263a6c79f802fabdb94367177310663397420e319fNick Kralevich    while( IsSpace(zLine[h]) ){ h++; }
123273a6c79f802fabdb94367177310663397420e319fNick Kralevich    if( zLine[h]==0 ) break;
123283a6c79f802fabdb94367177310663397420e319fNick Kralevich    if( zLine[h]=='\'' || zLine[h]=='"' ){
123293a6c79f802fabdb94367177310663397420e319fNick Kralevich      int delim = zLine[h++];
123303a6c79f802fabdb94367177310663397420e319fNick Kralevich      azArg[nArg++] = &zLine[h];
1233160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      while( zLine[h] && zLine[h]!=delim ){
123323a6c79f802fabdb94367177310663397420e319fNick Kralevich        if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
1233360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        h++;
123348fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }
123353a6c79f802fabdb94367177310663397420e319fNick Kralevich      if( zLine[h]==delim ){
123363a6c79f802fabdb94367177310663397420e319fNick Kralevich        zLine[h++] = 0;
123377790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
123387790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
123397790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else{
123403a6c79f802fabdb94367177310663397420e319fNick Kralevich      azArg[nArg++] = &zLine[h];
123413a6c79f802fabdb94367177310663397420e319fNick Kralevich      while( zLine[h] && !IsSpace(zLine[h]) ){ h++; }
123423a6c79f802fabdb94367177310663397420e319fNick Kralevich      if( zLine[h] ) zLine[h++] = 0;
123437790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      resolve_backslashes(azArg[nArg-1]);
123447790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
123457790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
123467790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
123477790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  /* Process the input line.
123487790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  */
12349a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  if( nArg==0 ) return 0; /* no tokens, no error */
12350a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  n = strlen30(azArg[0]);
123517790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  c = azArg[0][0];
123520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  clearTempFile(p);
1235360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
1235408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis#ifndef SQLITE_OMIT_AUTHORIZATION
1235560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){
1235660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    if( nArg!=2 ){
1235760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Usage: .auth ON|OFF\n");
1235860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      rc = 1;
1235960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      goto meta_command_exit;
1236060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }
1236160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    open_db(p, 0);
1236260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    if( booleanValue(azArg[1]) ){
1236360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      sqlite3_set_authorizer(p->db, shellAuth, p);
1236460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }else{
1236560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      sqlite3_set_authorizer(p->db, 0, 0);
1236660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }
1236760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  }else
1236808f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis#endif
1236960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
123700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
123710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){
123720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    open_db(p, 0);
123730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = arDotCommand(p, azArg, nArg);
123740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else
123750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
123760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
123778fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
123788fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich   || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
123798fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  ){
123808fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    const char *zDestFile = 0;
123818fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    const char *zDb = 0;
12382a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    sqlite3 *pDest;
12383a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    sqlite3_backup *pBackup;
123848fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    int j;
123858fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    for(j=1; j<nArg; j++){
123868fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      const char *z = azArg[j];
123878fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      if( z[0]=='-' ){
123888fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        while( z[0]=='-' ) z++;
123898fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        /* No options to process at this time */
123908fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        {
1239160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
123928fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich          return 1;
123938fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        }
123948fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }else if( zDestFile==0 ){
123958fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        zDestFile = azArg[j];
123968fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }else if( zDb==0 ){
123978fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        zDb = zDestFile;
123988fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        zDestFile = azArg[j];
123998fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }else{
1240060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        raw_printf(stderr, "too many arguments to .backup\n");
124018fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        return 1;
124028fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }
124038fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
124048fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( zDestFile==0 ){
1240560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "missing FILENAME argument on .backup\n");
124068fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      return 1;
12407a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }
124088fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( zDb==0 ) zDb = "main";
12409a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    rc = sqlite3_open(zDestFile, &pDest);
12410a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    if( rc!=SQLITE_OK ){
1241160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
12412a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      sqlite3_close(pDest);
12413a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      return 1;
12414a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }
124158fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    open_db(p, 0);
12416a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
12417a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    if( pBackup==0 ){
1241860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
12419a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      sqlite3_close(pDest);
12420a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      return 1;
12421a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }
12422a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    while(  (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
12423a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    sqlite3_backup_finish(pBackup);
12424a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    if( rc==SQLITE_DONE ){
12425a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      rc = 0;
12426a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }else{
1242760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
12428a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      rc = 1;
12429a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }
12430a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    sqlite3_close(pDest);
12431a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  }else
12432a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori
124331c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
124341c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    if( nArg==2 ){
124351c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      bail_on_error = booleanValue(azArg[1]);
124361c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }else{
1243760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Usage: .bail on|off\n");
124381c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      rc = 1;
124391c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }
124407790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else
124417790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
124423a6c79f802fabdb94367177310663397420e319fNick Kralevich  if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
124433a6c79f802fabdb94367177310663397420e319fNick Kralevich    if( nArg==2 ){
124443a6c79f802fabdb94367177310663397420e319fNick Kralevich      if( booleanValue(azArg[1]) ){
1244560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        setBinaryMode(p->out, 1);
124463a6c79f802fabdb94367177310663397420e319fNick Kralevich      }else{
1244760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        setTextMode(p->out, 1);
124483a6c79f802fabdb94367177310663397420e319fNick Kralevich      }
124493a6c79f802fabdb94367177310663397420e319fNick Kralevich    }else{
1245060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Usage: .binary on|off\n");
124513a6c79f802fabdb94367177310663397420e319fNick Kralevich      rc = 1;
124523a6c79f802fabdb94367177310663397420e319fNick Kralevich    }
124533a6c79f802fabdb94367177310663397420e319fNick Kralevich  }else
124543a6c79f802fabdb94367177310663397420e319fNick Kralevich
124550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( c=='c' && strcmp(azArg[0],"cd")==0 ){
124560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( nArg==2 ){
124570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if defined(_WIN32) || defined(WIN32)
124580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
124590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = !SetCurrentDirectoryW(z);
124600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_free(z);
124610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#else
124620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = chdir(azArg[1]);
124630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
124640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( rc ){
124650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]);
124660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        rc = 1;
124670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
124680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
124690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      raw_printf(stderr, "Usage: .cd DIRECTORY\n");
124700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = 1;
124710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
124720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else
124730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
124748fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  /* The undocumented ".breakpoint" command causes a call to the no-op
124758fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  ** routine named test_breakpoint().
124768fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  */
124778fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
124788fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    test_breakpoint();
124798fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }else
124808fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
1248160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
1248260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    if( nArg==2 ){
12483b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
1248460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }else{
1248560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Usage: .changes on|off\n");
1248660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      rc = 1;
1248760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }
1248860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  }else
1248960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
1249008f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  /* Cancel output redirection, if it is currently set (by .testcase)
1249108f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  ** Then read the content of the testcase-out.txt file and compare against
1249208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  ** azArg[1].  If there are differences, report an error and exit.
1249308f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  */
1249408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  if( c=='c' && n>=3 && strncmp(azArg[0], "check", n)==0 ){
1249508f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    char *zRes = 0;
1249608f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    output_reset(p);
1249708f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    if( nArg!=2 ){
1249808f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      raw_printf(stderr, "Usage: .check GLOB-PATTERN\n");
1249908f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      rc = 2;
12500e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
1250108f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      raw_printf(stderr, "Error: cannot read 'testcase-out.txt'\n");
1250208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      rc = 2;
1250308f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    }else if( testcase_glob(azArg[1],zRes)==0 ){
1250408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      utf8_printf(stderr,
1250508f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis                 "testcase-%s FAILED\n Expected: [%s]\n      Got: [%s]\n",
1250608f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis                 p->zTestcase, azArg[1], zRes);
125070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = 1;
1250808f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    }else{
1250908f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase);
1251008f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      p->nCheck++;
1251108f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    }
1251208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    sqlite3_free(zRes);
1251308f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  }else
1251408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis
125151c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
125161c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    if( nArg==2 ){
125171c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      tryToClone(p, azArg[1]);
125181c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }else{
1251960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Usage: .clone FILENAME\n");
125201c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      rc = 1;
125211c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }
125228fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }else
125238fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
125241c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
125253fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    ShellState data;
125267790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    char *zErrMsg = 0;
125278fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    open_db(p, 0);
125287790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    memcpy(&data, p, sizeof(data));
12529e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    data.showHeader = 0;
12530e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    data.cMode = data.mode = MODE_List;
12531e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    sqlite3_snprintf(sizeof(data.colSeparator),data.colSeparator,": ");
125327790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    data.cnt = 0;
12533e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    sqlite3_exec(p->db, "SELECT name, file FROM pragma_database_list",
12534e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani                 callback, &data, &zErrMsg);
125357790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( zErrMsg ){
1253660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(stderr,"Error: %s\n", zErrMsg);
125377790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      sqlite3_free(zErrMsg);
12538a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      rc = 1;
125397790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
125407790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else
125417790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
125423fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  if( c=='d' && strncmp(azArg[0], "dbinfo", n)==0 ){
125433fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    rc = shell_dbinfo_command(p, nArg, azArg);
125443fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  }else
125453fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
125461c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
12547b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    const char *zLike = 0;
12548b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    int i;
12549b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    int savedShowHeader = p->showHeader;
125500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ShellClearFlag(p, SHFLG_PreserveRowid|SHFLG_Newlines);
12551b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    for(i=1; i<nArg; i++){
12552b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      if( azArg[i][0]=='-' ){
12553b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        const char *z = azArg[i]+1;
12554b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        if( z[0]=='-' ) z++;
12555b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        if( strcmp(z,"preserve-rowids")==0 ){
12556b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis#ifdef SQLITE_OMIT_VIRTUALTABLE
12557b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          raw_printf(stderr, "The --preserve-rowids option is not compatible"
12558b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis                             " with SQLITE_OMIT_VIRTUALTABLE\n");
12559b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          rc = 1;
12560b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          goto meta_command_exit;
12561b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis#else
12562b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          ShellSetFlag(p, SHFLG_PreserveRowid);
12563b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis#endif
12564b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        }else
125650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( strcmp(z,"newlines")==0 ){
125660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          ShellSetFlag(p, SHFLG_Newlines);
125670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }else
12568b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        {
12569b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
12570b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          rc = 1;
12571b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          goto meta_command_exit;
12572b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        }
12573b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      }else if( zLike ){
125740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        raw_printf(stderr, "Usage: .dump ?--preserve-rowids? "
125750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                           "?--newlines? ?LIKE-PATTERN?\n");
12576b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        rc = 1;
12577b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        goto meta_command_exit;
12578b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      }else{
12579b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        zLike = azArg[i];
12580b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      }
12581b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }
125828fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    open_db(p, 0);
12583a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    /* When playing back a "dump", the content might appear in an order
12584a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    ** which causes immediate foreign key constraints to be violated.
12585a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    ** So disable foreign-key constraint enforcement to prevent problems. */
1258660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
1258760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    raw_printf(p->out, "BEGIN TRANSACTION;\n");
125887790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    p->writableSchema = 0;
12589b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    p->showHeader = 0;
12590b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    /* Set writable_schema=ON since doing so forces SQLite to initialize
12591b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    ** as much of the schema as it can even if the sqlite_master table is
12592b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    ** corrupt. */
1259390ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
1259490ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    p->nErr = 0;
12595b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    if( zLike==0 ){
1259660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      run_schema_dump_query(p,
125977790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        "SELECT name, type, sql FROM sqlite_master "
1259890ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown        "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'"
12599a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      );
1260060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      run_schema_dump_query(p,
12601a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori        "SELECT name, type, sql FROM sqlite_master "
1260290ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown        "WHERE name=='sqlite_sequence'"
126037790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      );
1260490ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      run_table_dump_query(p,
126057790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        "SELECT sql FROM sqlite_master "
12606a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori        "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0
126077790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      );
126087790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else{
12609b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      char *zSql;
12610b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      zSql = sqlite3_mprintf(
12611b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        "SELECT name, type, sql FROM sqlite_master "
12612b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        "WHERE tbl_name LIKE %Q AND type=='table'"
12613b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        "  AND sql NOT NULL", zLike);
12614b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      run_schema_dump_query(p,zSql);
12615b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      sqlite3_free(zSql);
12616b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      zSql = sqlite3_mprintf(
12617b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        "SELECT sql FROM sqlite_master "
12618b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        "WHERE sql NOT NULL"
12619b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        "  AND type IN ('index','trigger','view')"
12620b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        "  AND tbl_name LIKE %Q", zLike);
12621b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      run_table_dump_query(p, zSql, 0);
12622b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      sqlite3_free(zSql);
126237790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
126247790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( p->writableSchema ){
1262560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
126267790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      p->writableSchema = 0;
126277790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
1262890ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
1262990ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
1263060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    raw_printf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n");
12631b94ea7b498a753b88afce0b6c54ce0f08095f03eAlex Naidis    p->showHeader = savedShowHeader;
126327790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else
126337790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
126341c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
126351c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    if( nArg==2 ){
12636b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      setOrClearFlag(p, SHFLG_Echo, azArg[1]);
126371c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }else{
1263860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Usage: .echo on|off\n");
126391c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      rc = 1;
126401c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }
126417790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else
126427790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
126431c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
126441c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    if( nArg==2 ){
1264560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( strcmp(azArg[1],"full")==0 ){
126460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        p->autoEQP = AUTOEQP_full;
126470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else if( strcmp(azArg[1],"trigger")==0 ){
126480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        p->autoEQP = AUTOEQP_trigger;
1264960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }else{
1265060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        p->autoEQP = booleanValue(azArg[1]);
1265160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }
126521c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }else{
126530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      raw_printf(stderr, "Usage: .eqp off|on|trigger|full\n");
126541c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      rc = 1;
1265560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }
126568fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }else
126578fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
126588fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
126598fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
126607790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    rc = 2;
126617790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else
126627790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
126630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  /* The ".explain" command is automatic now.  It is largely pointless.  It
126640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  ** retained purely for backwards compatibility */
126651c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
1266660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    int val = 1;
1266760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    if( nArg>=2 ){
1266860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( strcmp(azArg[1],"auto")==0 ){
1266960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        val = 99;
1267060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }else{
1267160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        val =  booleanValue(azArg[1]);
126727790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
1267360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }
1267460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    if( val==1 && p->mode!=MODE_Explain ){
1267560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      p->normalMode = p->mode;
126767790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      p->mode = MODE_Explain;
1267760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      p->autoExplain = 0;
1267860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }else if( val==0 ){
1267960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( p->mode==MODE_Explain ) p->mode = p->normalMode;
1268060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      p->autoExplain = 0;
1268160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }else if( val==99 ){
1268260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( p->mode==MODE_Explain ) p->mode = p->normalMode;
1268360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      p->autoExplain = 1;
126847790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
126857790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else
126867790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
126870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifndef SQLITE_OMIT_VIRTUALTABLE
126880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){
126890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    open_db(p, 0);
126900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    expertDotCommand(p, azArg, nArg);
126910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  }else
126920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
126930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
126949bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown  if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
126953fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    ShellState data;
126969bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown    char *zErrMsg = 0;
126979bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown    int doStats = 0;
1269860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    memcpy(&data, p, sizeof(data));
1269960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    data.showHeader = 0;
1270060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    data.cMode = data.mode = MODE_Semi;
1270160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    if( nArg==2 && optionMatch(azArg[1], "indent") ){
1270260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      data.cMode = data.mode = MODE_Pretty;
1270360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      nArg = 1;
1270460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }
127059bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown    if( nArg!=1 ){
1270660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Usage: .fullschema ?--indent?\n");
127079bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown      rc = 1;
127089bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown      goto meta_command_exit;
127099bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown    }
127109bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown    open_db(p, 0);
127119bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown    rc = sqlite3_exec(p->db,
127129bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown       "SELECT sql FROM"
127139bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown       "  (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
127149bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown       "     FROM sqlite_master UNION ALL"
127159bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown       "   SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) "
127163fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich       "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
127179bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown       "ORDER BY rowid",
127189bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown       callback, &data, &zErrMsg
127199bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown    );
127209bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown    if( rc==SQLITE_OK ){
127219bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown      sqlite3_stmt *pStmt;
127229bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown      rc = sqlite3_prepare_v2(p->db,
127239bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown               "SELECT rowid FROM sqlite_master"
127249bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown               " WHERE name GLOB 'sqlite_stat[134]'",
127259bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown               -1, &pStmt, 0);
127269bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown      doStats = sqlite3_step(pStmt)==SQLITE_ROW;
127279bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown      sqlite3_finalize(pStmt);
127289bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown    }
127299bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown    if( doStats==0 ){
1273060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(p->out, "/* No STAT tables available */\n");
127319bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown    }else{
1273260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(p->out, "ANALYZE sqlite_master;\n");
127339bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown      sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_master'",
127349bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown                   callback, &data, &zErrMsg);
1273560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      data.cMode = data.mode = MODE_Insert;
127369bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown      data.zDestTable = "sqlite_stat1";
127379bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown      shell_exec(p->db, "SELECT * FROM sqlite_stat1",
127389bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown                 shell_callback, &data,&zErrMsg);
127399bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown      data.zDestTable = "sqlite_stat3";
127409bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown      shell_exec(p->db, "SELECT * FROM sqlite_stat3",
127419bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown                 shell_callback, &data,&zErrMsg);
127429bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown      data.zDestTable = "sqlite_stat4";
127439bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown      shell_exec(p->db, "SELECT * FROM sqlite_stat4",
127449bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown                 shell_callback, &data, &zErrMsg);
1274560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(p->out, "ANALYZE sqlite_master;\n");
127469bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown    }
127479bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown  }else
127489bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown
127491c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
127501c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    if( nArg==2 ){
127511c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      p->showHeader = booleanValue(azArg[1]);
127521c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }else{
1275360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Usage: .headers on|off\n");
127541c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      rc = 1;
127551c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }
127567790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else
127577790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
127587790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
1275960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(p->out, "%s", zHelp);
127607790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else
127617790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
127621c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
127631c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    char *zTable;               /* Insert data into this table */
127641c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    char *zFile;                /* Name of file to extra content from */
12765a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    sqlite3_stmt *pStmt = NULL; /* A statement */
127667790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    int nCol;                   /* Number of columns in the table */
127677790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    int nByte;                  /* Number of bytes in an SQL string */
127687790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    int i, j;                   /* Loop counters */
127698fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    int needCommit;             /* True to COMMIT or ROLLBACK at end */
127703fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    int nSep;                   /* Number of bytes in p->colSeparator[] */
127717790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    char *zSql;                 /* An SQL statement */
127723fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    ImportCtx sCtx;             /* Reader context */
127733fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
127743fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    int (SQLITE_CDECL *xCloser)(FILE*);      /* Func to close file */
127757790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
127761c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    if( nArg!=3 ){
1277760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Usage: .import FILE TABLE\n");
127781c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      goto meta_command_exit;
127791c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }
127801c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    zFile = azArg[1];
127811c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    zTable = azArg[2];
127828fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    seenInterrupt = 0;
127833fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    memset(&sCtx, 0, sizeof(sCtx));
127848fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    open_db(p, 0);
127853fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    nSep = strlen30(p->colSeparator);
127867790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( nSep==0 ){
1278760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr,
1278860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis                 "Error: non-null column separator required for import\n");
12789a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      return 1;
127907790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
127918fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( nSep>1 ){
1279260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Error: multi-character column separators not allowed"
127938fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich                      " for import\n");
127948fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      return 1;
127958fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
127963fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    nSep = strlen30(p->rowSeparator);
127973fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    if( nSep==0 ){
1279860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Error: non-null row separator required for import\n");
127993fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      return 1;
128003fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    }
128013fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator, SEP_CrLf)==0 ){
128023fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      /* When importing CSV (only), if the row separator is set to the
128033fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      ** default output row separator, change it to the default input
128043fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      ** row separator.  This avoids having to maintain different input
128053fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      ** and output row separators. */
128063fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
128073fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      nSep = strlen30(p->rowSeparator);
128083fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    }
128093fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    if( nSep>1 ){
1281060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Error: multi-character row separators not allowed"
128113fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich                      " for import\n");
128123fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      return 1;
128133fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    }
128143fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    sCtx.zFile = zFile;
128153fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    sCtx.nLine = 1;
128163fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    if( sCtx.zFile[0]=='|' ){
128173fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#ifdef SQLITE_OMIT_POPEN
1281860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Error: pipes are not supported in this OS\n");
128193fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      return 1;
128203fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#else
128213fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sCtx.in = popen(sCtx.zFile+1, "r");
128223fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sCtx.zFile = "<pipe>";
128238fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      xCloser = pclose;
128243fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#endif
128258fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }else{
128263fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sCtx.in = fopen(sCtx.zFile, "rb");
128278fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      xCloser = fclose;
128288fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
128293fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    if( p->mode==MODE_Ascii ){
128303fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      xRead = ascii_read_one_field;
128313fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    }else{
128323fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      xRead = csv_read_one_field;
128333fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    }
128343fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    if( sCtx.in==0 ){
1283560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
128368fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      return 1;
128378fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
128383fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    sCtx.cColSep = p->colSeparator[0];
128393fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    sCtx.cRowSep = p->rowSeparator[0];
1284090ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    zSql = sqlite3_mprintf("SELECT * FROM %s", zTable);
12841a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    if( zSql==0 ){
1284260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Error: out of memory\n");
128433fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      xCloser(sCtx.in);
12844a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      return 1;
12845a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }
12846a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    nByte = strlen30(zSql);
128478fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
128483fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    import_append_char(&sCtx, 0);    /* To ensure sCtx.z is allocated */
128493a6c79f802fabdb94367177310663397420e319fNick Kralevich    if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
128508fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
128518fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      char cSep = '(';
128523fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      while( xRead(&sCtx) ){
1285360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        zCreate = sqlite3_mprintf("%z%c\n  \"%w\" TEXT", zCreate, cSep, sCtx.z);
128548fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        cSep = ',';
128553fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        if( sCtx.cTerm!=sCtx.cColSep ) break;
128568fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }
128578fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      if( cSep=='(' ){
128588fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        sqlite3_free(zCreate);
128593fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        sqlite3_free(sCtx.z);
128603fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        xCloser(sCtx.in);
1286160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
128628fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        return 1;
128638fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }
128648fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      zCreate = sqlite3_mprintf("%z\n)", zCreate);
128658fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
128668fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      sqlite3_free(zCreate);
128678fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      if( rc ){
1286860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable,
128693a6c79f802fabdb94367177310663397420e319fNick Kralevich                sqlite3_errmsg(p->db));
128703fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        sqlite3_free(sCtx.z);
128713fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        xCloser(sCtx.in);
128728fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        return 1;
128738fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }
128748fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
128758fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
128767790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    sqlite3_free(zSql);
128777790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( rc ){
12878a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      if (pStmt) sqlite3_finalize(pStmt);
1287960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
128803fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      xCloser(sCtx.in);
12881a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      return 1;
128827790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
12883a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    nCol = sqlite3_column_count(pStmt);
128847790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    sqlite3_finalize(pStmt);
12885a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    pStmt = 0;
12886a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    if( nCol==0 ) return 0; /* no columns, no error */
128873a6c79f802fabdb94367177310663397420e319fNick Kralevich    zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
12888a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    if( zSql==0 ){
1288960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Error: out of memory\n");
128903fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      xCloser(sCtx.in);
12891a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      return 1;
12892a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }
128938fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
12894a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    j = strlen30(zSql);
128957790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    for(i=1; i<nCol; i++){
128967790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      zSql[j++] = ',';
128977790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      zSql[j++] = '?';
128987790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
128997790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    zSql[j++] = ')';
129007790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    zSql[j] = 0;
129018fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
129028fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    sqlite3_free(zSql);
129037790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( rc ){
1290460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
12905a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      if (pStmt) sqlite3_finalize(pStmt);
129063fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      xCloser(sCtx.in);
129077790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      return 1;
129087790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
129093a6c79f802fabdb94367177310663397420e319fNick Kralevich    needCommit = sqlite3_get_autocommit(p->db);
129103a6c79f802fabdb94367177310663397420e319fNick Kralevich    if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
129118fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    do{
129123fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      int startLine = sCtx.nLine;
129138fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      for(i=0; i<nCol; i++){
129143fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        char *z = xRead(&sCtx);
129153fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        /*
129163fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        ** Did we reach end-of-file before finding any columns?
129173fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        ** If so, stop instead of NULL filling the remaining columns.
129183fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        */
129198fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        if( z==0 && i==0 ) break;
129203fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        /*
129213fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        ** Did we reach end-of-file OR end-of-line before finding any
129223fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        ** columns in ASCII mode?  If so, stop instead of NULL filling
129233fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        ** the remaining columns.
129243fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        */
129253fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        if( p->mode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break;
129268fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
129273fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
1292860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
129298fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich                          "filling the rest with NULL\n",
129303fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich                          sCtx.zFile, startLine, nCol, i+1);
129313fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich          i += 2;
129329bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown          while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
129337790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        }
129347790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
129353fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      if( sCtx.cTerm==sCtx.cColSep ){
129368fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        do{
129373fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich          xRead(&sCtx);
129388fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich          i++;
129393fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        }while( sCtx.cTerm==sCtx.cColSep );
1294060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
129418fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich                        "extras ignored\n",
129423fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich                        sCtx.zFile, startLine, nCol, i);
129438fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }
129448fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      if( i>=nCol ){
129458fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        sqlite3_step(pStmt);
129468fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        rc = sqlite3_reset(pStmt);
129478fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        if( rc!=SQLITE_OK ){
1294860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
1294960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis                      startLine, sqlite3_errmsg(p->db));
12950c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown        }
129517790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
129523fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    }while( sCtx.cTerm!=EOF );
129538fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
129543fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    xCloser(sCtx.in);
129553fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    sqlite3_free(sCtx.z);
129567790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    sqlite3_finalize(pStmt);
129573a6c79f802fabdb94367177310663397420e319fNick Kralevich    if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
129587790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else
129597790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
12960e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani#ifndef SQLITE_UNTESTABLE
12961e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){
12962e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    char *zSql;
12963e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    char *zCollist = 0;
12964e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    sqlite3_stmt *pStmt;
12965e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    int tnum = 0;
12966e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    int i;
12967e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    if( nArg!=3 ){
12968e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n");
129691c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      rc = 1;
129701c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      goto meta_command_exit;
12971a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }
12972e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    open_db(p, 0);
12973e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    zSql = sqlite3_mprintf("SELECT rootpage FROM sqlite_master"
12974e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani                           " WHERE name='%q' AND type='index'", azArg[1]);
12975e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
12976e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    sqlite3_free(zSql);
12977e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    if( sqlite3_step(pStmt)==SQLITE_ROW ){
12978e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      tnum = sqlite3_column_int(pStmt, 0);
12979e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    }
12980e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    sqlite3_finalize(pStmt);
12981e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    if( tnum==0 ){
12982e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
12983a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      rc = 1;
12984e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      goto meta_command_exit;
12985e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    }
12986e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);
12987e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
12988e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    sqlite3_free(zSql);
12989e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    i = 0;
12990e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    while( sqlite3_step(pStmt)==SQLITE_ROW ){
12991e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      char zLabel[20];
12992e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      const char *zCol = (const char*)sqlite3_column_text(pStmt,2);
12993e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      i++;
12994e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      if( zCol==0 ){
12995e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani        if( sqlite3_column_int(pStmt,1)==-1 ){
12996e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani          zCol = "_ROWID_";
12997e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani        }else{
12998e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani          sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i);
12999e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani          zCol = zLabel;
13000e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani        }
13001e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      }
13002e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      if( zCollist==0 ){
13003e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani        zCollist = sqlite3_mprintf("\"%w\"", zCol);
13004e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      }else{
13005e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani        zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol);
13006e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      }
13007e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    }
13008e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    sqlite3_finalize(pStmt);
13009e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    zSql = sqlite3_mprintf(
13010e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani          "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%s))WITHOUT ROWID",
13011e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani          azArg[2], zCollist, zCollist);
13012e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    sqlite3_free(zCollist);
13013e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
13014e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    if( rc==SQLITE_OK ){
13015e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
13016e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
13017e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      if( rc ){
13018e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani        utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
13019e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      }else{
13020e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani        utf8_printf(stdout, "%s;\n", zSql);
13021e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani        raw_printf(stdout,
13022e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani           "WARNING: writing to an imposter table will corrupt the index!\n"
13023e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani        );
13024e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      }
13025e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    }else{
13026e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
13027a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      rc = 1;
130287790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
13029e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    sqlite3_free(zSql);
130307790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else
13031e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani#endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */
130327790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
130337790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#ifdef SQLITE_ENABLE_IOTRACE
130347790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
130353fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
130367790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( iotrace && iotrace!=stdout ) fclose(iotrace);
130377790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    iotrace = 0;
130387790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( nArg<2 ){
130397790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      sqlite3IoTrace = 0;
130407790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else if( strcmp(azArg[1], "-")==0 ){
130417790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      sqlite3IoTrace = iotracePrintf;
130427790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      iotrace = stdout;
130437790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else{
130447790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      iotrace = fopen(azArg[1], "w");
130457790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      if( iotrace==0 ){
1304660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
130477790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        sqlite3IoTrace = 0;
13048a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori        rc = 1;
130497790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }else{
130507790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        sqlite3IoTrace = iotracePrintf;
130517790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
130527790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
130537790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else
130547790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#endif
13055e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani
130563a6c79f802fabdb94367177310663397420e319fNick Kralevich  if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){
130573a6c79f802fabdb94367177310663397420e319fNick Kralevich    static const struct {
130583a6c79f802fabdb94367177310663397420e319fNick Kralevich       const char *zLimitName;   /* Name of a limit */
130593a6c79f802fabdb94367177310663397420e319fNick Kralevich       int limitCode;            /* Integer code for that limit */
130603a6c79f802fabdb94367177310663397420e319fNick Kralevich    } aLimit[] = {
130613a6c79f802fabdb94367177310663397420e319fNick Kralevich      { "length",                SQLITE_LIMIT_LENGTH                    },
130623a6c79f802fabdb94367177310663397420e319fNick Kralevich      { "sql_length",            SQLITE_LIMIT_SQL_LENGTH                },
130633a6c79f802fabdb94367177310663397420e319fNick Kralevich      { "column",                SQLITE_LIMIT_COLUMN                    },
130643a6c79f802fabdb94367177310663397420e319fNick Kralevich      { "expr_depth",            SQLITE_LIMIT_EXPR_DEPTH                },
130653a6c79f802fabdb94367177310663397420e319fNick Kralevich      { "compound_select",       SQLITE_LIMIT_COMPOUND_SELECT           },
130663a6c79f802fabdb94367177310663397420e319fNick Kralevich      { "vdbe_op",               SQLITE_LIMIT_VDBE_OP                   },
130673a6c79f802fabdb94367177310663397420e319fNick Kralevich      { "function_arg",          SQLITE_LIMIT_FUNCTION_ARG              },
130683a6c79f802fabdb94367177310663397420e319fNick Kralevich      { "attached",              SQLITE_LIMIT_ATTACHED                  },
130693a6c79f802fabdb94367177310663397420e319fNick Kralevich      { "like_pattern_length",   SQLITE_LIMIT_LIKE_PATTERN_LENGTH       },
130703a6c79f802fabdb94367177310663397420e319fNick Kralevich      { "variable_number",       SQLITE_LIMIT_VARIABLE_NUMBER           },
130713a6c79f802fabdb94367177310663397420e319fNick Kralevich      { "trigger_depth",         SQLITE_LIMIT_TRIGGER_DEPTH             },
130723a6c79f802fabdb94367177310663397420e319fNick Kralevich      { "worker_threads",        SQLITE_LIMIT_WORKER_THREADS            },
130733a6c79f802fabdb94367177310663397420e319fNick Kralevich    };
130743a6c79f802fabdb94367177310663397420e319fNick Kralevich    int i, n2;
130753a6c79f802fabdb94367177310663397420e319fNick Kralevich    open_db(p, 0);
130763a6c79f802fabdb94367177310663397420e319fNick Kralevich    if( nArg==1 ){
13077253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich      for(i=0; i<ArraySize(aLimit); i++){
1307860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        printf("%20s %d\n", aLimit[i].zLimitName,
130793a6c79f802fabdb94367177310663397420e319fNick Kralevich               sqlite3_limit(p->db, aLimit[i].limitCode, -1));
130803a6c79f802fabdb94367177310663397420e319fNick Kralevich      }
130813a6c79f802fabdb94367177310663397420e319fNick Kralevich    }else if( nArg>3 ){
1308260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
130833a6c79f802fabdb94367177310663397420e319fNick Kralevich      rc = 1;
130843a6c79f802fabdb94367177310663397420e319fNick Kralevich      goto meta_command_exit;
130853a6c79f802fabdb94367177310663397420e319fNick Kralevich    }else{
130863a6c79f802fabdb94367177310663397420e319fNick Kralevich      int iLimit = -1;
130873a6c79f802fabdb94367177310663397420e319fNick Kralevich      n2 = strlen30(azArg[1]);
13088253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich      for(i=0; i<ArraySize(aLimit); i++){
130893a6c79f802fabdb94367177310663397420e319fNick Kralevich        if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
130903a6c79f802fabdb94367177310663397420e319fNick Kralevich          if( iLimit<0 ){
130913a6c79f802fabdb94367177310663397420e319fNick Kralevich            iLimit = i;
130923a6c79f802fabdb94367177310663397420e319fNick Kralevich          }else{
1309360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            utf8_printf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
130943a6c79f802fabdb94367177310663397420e319fNick Kralevich            rc = 1;
130953a6c79f802fabdb94367177310663397420e319fNick Kralevich            goto meta_command_exit;
130963a6c79f802fabdb94367177310663397420e319fNick Kralevich          }
130973a6c79f802fabdb94367177310663397420e319fNick Kralevich        }
130983a6c79f802fabdb94367177310663397420e319fNick Kralevich      }
130993a6c79f802fabdb94367177310663397420e319fNick Kralevich      if( iLimit<0 ){
1310060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(stderr, "unknown limit: \"%s\"\n"
131013a6c79f802fabdb94367177310663397420e319fNick Kralevich                        "enter \".limits\" with no arguments for a list.\n",
131023a6c79f802fabdb94367177310663397420e319fNick Kralevich                         azArg[1]);
131033a6c79f802fabdb94367177310663397420e319fNick Kralevich        rc = 1;
131043a6c79f802fabdb94367177310663397420e319fNick Kralevich        goto meta_command_exit;
131053a6c79f802fabdb94367177310663397420e319fNick Kralevich      }
131063a6c79f802fabdb94367177310663397420e319fNick Kralevich      if( nArg==3 ){
13107693f9c610b18f09ffe4aaa8f583362481c9e1532Nick Kralevich        sqlite3_limit(p->db, aLimit[iLimit].limitCode,
13108693f9c610b18f09ffe4aaa8f583362481c9e1532Nick Kralevich                      (int)integerValue(azArg[2]));
131093a6c79f802fabdb94367177310663397420e319fNick Kralevich      }
131103a6c79f802fabdb94367177310663397420e319fNick Kralevich      printf("%20s %d\n", aLimit[iLimit].zLimitName,
131113a6c79f802fabdb94367177310663397420e319fNick Kralevich             sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
131123a6c79f802fabdb94367177310663397420e319fNick Kralevich    }
131133a6c79f802fabdb94367177310663397420e319fNick Kralevich  }else
131147790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
13115e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  if( c=='l' && n>2 && strncmp(azArg[0], "lint", n)==0 ){
13116e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    open_db(p, 0);
13117e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    lintDotCommand(p, azArg, nArg);
13118e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  }else
13119e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani
131207790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#ifndef SQLITE_OMIT_LOAD_EXTENSION
131211c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
131227790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    const char *zFile, *zProc;
131237790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    char *zErrMsg = 0;
131241c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    if( nArg<2 ){
1312560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
131261c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      rc = 1;
131271c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      goto meta_command_exit;
131281c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }
131297790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    zFile = azArg[1];
131307790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    zProc = nArg>=3 ? azArg[2] : 0;
131318fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    open_db(p, 0);
131327790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
131337790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( rc!=SQLITE_OK ){
1313460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(stderr, "Error: %s\n", zErrMsg);
131357790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      sqlite3_free(zErrMsg);
131367790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      rc = 1;
131377790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
131387790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else
131397790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#endif
131407790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
131411c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
131421c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    if( nArg!=2 ){
1314360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Usage: .log FILENAME\n");
131441c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      rc = 1;
131451c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }else{
131461c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      const char *zFile = azArg[1];
131471c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      output_file_close(p->pLog);
131480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      p->pLog = output_file_open(zFile, 0);
131491c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }
13150aae12b8a5af3a1ac77382b067d9ebb350fbd0644Vasu Nori  }else
13151aae12b8a5af3a1ac77382b067d9ebb350fbd0644Vasu Nori
131521c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){
131531c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    const char *zMode = nArg>=2 ? azArg[1] : "";
131540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int n2 = strlen30(zMode);
131551c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    int c2 = zMode[0];
131561c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){
131577790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      p->mode = MODE_Line;
131584b7ed9600a8a9a52e622980c609aab9038bdf6b4Alex Naidis      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
131591c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){
131607790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      p->mode = MODE_Column;
131614b7ed9600a8a9a52e622980c609aab9038bdf6b4Alex Naidis      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
131621c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){
131637790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      p->mode = MODE_List;
131644b7ed9600a8a9a52e622980c609aab9038bdf6b4Alex Naidis      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column);
131654b7ed9600a8a9a52e622980c609aab9038bdf6b4Alex Naidis      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
131661c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){
131677790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      p->mode = MODE_Html;
131681c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){
131697790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      p->mode = MODE_Tcl;
131703fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space);
131714b7ed9600a8a9a52e622980c609aab9038bdf6b4Alex Naidis      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
131721c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
131737790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      p->mode = MODE_Csv;
131743fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
131753fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
131761c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
131777790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      p->mode = MODE_List;
131783fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
131791c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
131807790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      p->mode = MODE_Insert;
131811c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      set_table_name(p, nArg>=3 ? azArg[2] : "table");
13182e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){
13183e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      p->mode = MODE_Quote;
131843fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
131853fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      p->mode = MODE_Ascii;
131863fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
131873fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
131880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else if( nArg==1 ){
131890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
131900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else{
1319160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Error: mode should be one of: "
13192e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani         "ascii column csv html insert line list quote tabs tcl\n");
13193a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      rc = 1;
13194a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }
1319560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    p->cMode = p->mode;
13196a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  }else
13197a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori
131981c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
131991c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    if( nArg==2 ){
132003fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
132013fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich                       "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
132021c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }else{
1320360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Usage: .nullvalue STRING\n");
13204a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      rc = 1;
132057790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
132067790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else
132077790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
132088fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
1320908f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    char *zNewFilename;  /* Name of the database file to open */
1321008f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    int iName = 1;       /* Index in azArg[] of the filename */
1321108f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    int newFlag = 0;     /* True to delete file before opening */
1321208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    /* Close the existing database */
1321308f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    session_close_all(p);
1321408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    sqlite3_close(p->db);
132158fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    p->db = 0;
13216b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    p->zDbFilename = 0;
1321708f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    sqlite3_free(p->zFreeOnClose);
1321808f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    p->zFreeOnClose = 0;
132190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    p->openMode = SHELL_OPEN_UNSPEC;
1322008f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    /* Check for command-line arguments */
1322108f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    for(iName=1; iName<nArg && azArg[iName][0]=='-'; iName++){
1322208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      const char *z = azArg[iName];
1322308f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      if( optionMatch(z,"new") ){
1322408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis        newFlag = 1;
132250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifdef SQLITE_HAVE_ZIP
132260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else if( optionMatch(z, "zip") ){
132270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        p->openMode = SHELL_OPEN_ZIPFILE;
132280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
132290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else if( optionMatch(z, "append") ){
132300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        p->openMode = SHELL_OPEN_APPENDVFS;
1323108f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      }else if( z[0]=='-' ){
1323208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis        utf8_printf(stderr, "unknown option: %s\n", z);
1323308f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis        rc = 1;
1323408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis        goto meta_command_exit;
1323508f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      }
1323608f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    }
1323708f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    /* If a filename is specified, try to open it first */
1323808f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    zNewFilename = nArg>iName ? sqlite3_mprintf("%s", azArg[iName]) : 0;
1323908f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    if( zNewFilename ){
1324008f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      if( newFlag ) shellDeleteFile(zNewFilename);
1324108f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      p->zDbFilename = zNewFilename;
1324208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      open_db(p, 1);
1324308f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      if( p->db==0 ){
1324408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis        utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
1324508f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis        sqlite3_free(zNewFilename);
1324608f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      }else{
1324708f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis        p->zFreeOnClose = zNewFilename;
1324808f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      }
1324908f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    }
1325008f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    if( p->db==0 ){
1325108f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      /* As a fall-back open a TEMP database */
1325208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      p->zDbFilename = 0;
1325308f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      open_db(p, 0);
132548fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
132558fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }else
132568fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
132570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( (c=='o'
132580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0))
132590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov   || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0)
132601c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  ){
132611c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    const char *zFile = nArg>=2 ? azArg[1] : "stdout";
132620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int bTxtMode = 0;
132630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( azArg[0][0]=='e' ){
132640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      /* Transform the ".excel" command into ".once -x" */
132650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      nArg = 2;
132660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      azArg[0] = "once";
132670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zFile = azArg[1] = "-x";
132680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      n = 4;
132690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
132701c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    if( nArg>2 ){
132710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      utf8_printf(stderr, "Usage: .%s [-e|-x|FILE]\n", azArg[0]);
132721c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      rc = 1;
132731c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      goto meta_command_exit;
132741c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }
132751c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    if( n>1 && strncmp(azArg[0], "once", n)==0 ){
132761c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      if( nArg<2 ){
132770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        raw_printf(stderr, "Usage: .once (-e|-x|FILE)\n");
132781c7cea379348522163370244e8fbbff8a136b7faNick Kralevich        rc = 1;
132791c7cea379348522163370244e8fbbff8a136b7faNick Kralevich        goto meta_command_exit;
132801c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      }
132811c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      p->outCount = 2;
132828fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }else{
132831c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      p->outCount = 0;
132847790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
132851c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    output_reset(p);
132860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( zFile[0]=='-' && zFile[1]=='-' ) zFile++;
132870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( strcmp(zFile, "-e")==0 || strcmp(zFile, "-x")==0 ){
132880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      p->doXdgOpen = 1;
132890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      outputModePush(p);
132900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( zFile[1]=='x' ){
132910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        newTempFile(p, "csv");
132920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        p->mode = MODE_Csv;
132930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
132940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
132950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else{
132960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        newTempFile(p, "txt");
132970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        bTxtMode = 1;
132980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
132990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zFile = p->zTempFile;
133000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
133011c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    if( zFile[0]=='|' ){
133023fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#ifdef SQLITE_OMIT_POPEN
1330360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Error: pipes are not supported in this OS\n");
133043fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      rc = 1;
133053fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      p->out = stdout;
133063fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#else
133071c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      p->out = popen(zFile + 1, "w");
133088fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      if( p->out==0 ){
1330960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
133108fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        p->out = stdout;
133118fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        rc = 1;
133128fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }else{
133131c7cea379348522163370244e8fbbff8a136b7faNick Kralevich        sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
133148fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }
133153fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#endif
133167790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else{
133170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      p->out = output_file_open(zFile, bTxtMode);
133187790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      if( p->out==0 ){
133191c7cea379348522163370244e8fbbff8a136b7faNick Kralevich        if( strcmp(zFile,"off")!=0 ){
1332060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile);
133218fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        }
133227790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        p->out = stdout;
13323a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori        rc = 1;
133247790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      } else {
133251c7cea379348522163370244e8fbbff8a136b7faNick Kralevich        sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
133267790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
133277790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
133287790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else
133297790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
133308fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
133318fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    int i;
133328fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    for(i=1; i<nArg; i++){
1333360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( i>1 ) raw_printf(p->out, " ");
1333460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(p->out, "%s", azArg[i]);
133358fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
1333660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    raw_printf(p->out, "\n");
133378fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }else
133388fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
133391c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){
133407790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( nArg >= 2) {
133417790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
133427790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
133437790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( nArg >= 3) {
133447790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
133457790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
133467790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else
133477790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
133481c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
133497790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    rc = 2;
133507790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else
133517790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
133521c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
133531c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    FILE *alt;
133541c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    if( nArg!=2 ){
1335560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Usage: .read FILE\n");
133561c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      rc = 1;
133571c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      goto meta_command_exit;
133581c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }
133591c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    alt = fopen(azArg[1], "rb");
133607790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( alt==0 ){
1336160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
13362a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      rc = 1;
133637790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else{
13364a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      rc = process_input(p, alt);
133657790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      fclose(alt);
133667790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
133677790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else
133687790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
133691c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
13370a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    const char *zSrcFile;
13371a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    const char *zDb;
13372a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    sqlite3 *pSrc;
13373a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    sqlite3_backup *pBackup;
13374a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    int nTimeout = 0;
13375a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori
13376a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    if( nArg==2 ){
13377a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      zSrcFile = azArg[1];
13378a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      zDb = "main";
133791c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }else if( nArg==3 ){
13380a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      zSrcFile = azArg[2];
13381a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      zDb = azArg[1];
133821c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }else{
1338360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Usage: .restore ?DB? FILE\n");
133841c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      rc = 1;
133851c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      goto meta_command_exit;
13386a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }
13387a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    rc = sqlite3_open(zSrcFile, &pSrc);
13388a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    if( rc!=SQLITE_OK ){
1338960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
13390a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      sqlite3_close(pSrc);
13391a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      return 1;
13392a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }
133938fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    open_db(p, 0);
13394a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
13395a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    if( pBackup==0 ){
1339660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
13397a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      sqlite3_close(pSrc);
13398a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      return 1;
13399a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }
13400a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
13401a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori          || rc==SQLITE_BUSY  ){
13402a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      if( rc==SQLITE_BUSY ){
13403a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori        if( nTimeout++ >= 3 ) break;
13404a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori        sqlite3_sleep(100);
13405a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      }
13406a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }
13407a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    sqlite3_backup_finish(pBackup);
13408a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    if( rc==SQLITE_DONE ){
13409a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      rc = 0;
13410a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
1341160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Error: source database is busy\n");
13412a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      rc = 1;
13413a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }else{
1341460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
13415a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      rc = 1;
13416a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }
13417a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    sqlite3_close(pSrc);
13418a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  }else
13419a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori
134203fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
134213fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
134223fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    if( nArg==2 ){
134233fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      p->scanstatsOn = booleanValue(azArg[1]);
134243fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
1342560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
134263fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#endif
134273fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    }else{
1342860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Usage: .scanstats on|off\n");
134293fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      rc = 1;
134303fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    }
134313fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  }else
134323fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
134331c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
134340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ShellText sSelect;
134353fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    ShellState data;
134367790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    char *zErrMsg = 0;
134370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const char *zDiv = "(";
134380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const char *zName = 0;
134390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int iSchema = 0;
134400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int bDebug = 0;
134410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int ii;
134420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
134438fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    open_db(p, 0);
134447790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    memcpy(&data, p, sizeof(data));
134457790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    data.showHeader = 0;
1344660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    data.cMode = data.mode = MODE_Semi;
134470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    initText(&sSelect);
134480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    for(ii=1; ii<nArg; ii++){
134490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( optionMatch(azArg[ii],"indent") ){
134500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        data.cMode = data.mode = MODE_Pretty;
134510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else if( optionMatch(azArg[ii],"debug") ){
134520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        bDebug = 1;
134530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else if( zName==0 ){
134540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        zName = azArg[ii];
134550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else{
134560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n");
134570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        rc = 1;
134580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        goto meta_command_exit;
134590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
1346060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }
134610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( zName!=0 ){
134620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      int isMaster = sqlite3_strlike(zName, "sqlite_master", 0)==0;
134630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( isMaster || sqlite3_strlike(zName,"sqlite_temp_master",0)==0 ){
134647790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        char *new_argv[2], *new_colv[2];
134650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        new_argv[0] = sqlite3_mprintf(
134660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                      "CREATE TABLE %s (\n"
134677790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project                      "  type text,\n"
134687790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project                      "  name text,\n"
134697790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project                      "  tbl_name text,\n"
134707790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project                      "  rootpage integer,\n"
134717790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project                      "  sql text\n"
134720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                      ")", isMaster ? "sqlite_master" : "sqlite_temp_master");
134737790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        new_argv[1] = 0;
134747790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        new_colv[0] = "sql";
134757790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        new_colv[1] = 0;
134767790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        callback(&data, 1, new_argv, new_colv);
134770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_free(new_argv[0]);
134780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
134790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
134800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( zDiv ){
134810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_stmt *pStmt = 0;
134820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
134830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                              -1, &pStmt, 0);
134840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( rc ){
134850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
134860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_finalize(pStmt);
134870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        rc = 1;
134880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        goto meta_command_exit;
134890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
134900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      appendText(&sSelect, "SELECT sql FROM", 0);
134910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      iSchema = 0;
134920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      while( sqlite3_step(pStmt)==SQLITE_ROW ){
134930181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
134940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        char zScNum[30];
134950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
134960181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        appendText(&sSelect, zDiv, 0);
134970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        zDiv = " UNION ALL ";
134980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        appendText(&sSelect, "SELECT shell_add_schema(sql,", 0);
134990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( sqlite3_stricmp(zDb, "main")!=0 ){
135000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          appendText(&sSelect, zDb, '"');
135010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }else{
135020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          appendText(&sSelect, "NULL", 0);
135030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
135040181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        appendText(&sSelect, ",name) AS sql, type, tbl_name, name, rowid,", 0);
135050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        appendText(&sSelect, zScNum, 0);
135060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        appendText(&sSelect, " AS snum, ", 0);
135070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        appendText(&sSelect, zDb, '\'');
135080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        appendText(&sSelect, " AS sname FROM ", 0);
135090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        appendText(&sSelect, zDb, '"');
135100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        appendText(&sSelect, ".sqlite_master", 0);
135110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
135120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_finalize(pStmt);
135130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifdef SQLITE_INTROSPECTION_PRAGMAS
135140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( zName ){
135150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        appendText(&sSelect,
135160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov           " UNION ALL SELECT shell_module_schema(name),"
135170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov           " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list", 0);
135180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
135190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
135200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      appendText(&sSelect, ") WHERE ", 0);
135210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( zName ){
135220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        char *zQarg = sqlite3_mprintf("%Q", zName);
135230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( strchr(zName, '.') ){
135240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0);
135250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }else{
135260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          appendText(&sSelect, "lower(tbl_name)", 0);
135270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }
135280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        appendText(&sSelect, strchr(zName, '*') ? " GLOB " : " LIKE ", 0);
135290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        appendText(&sSelect, zQarg, 0);
135300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        appendText(&sSelect, " AND ", 0);
135310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_free(zQarg);
135320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
135330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      appendText(&sSelect, "type!='meta' AND sql IS NOT NULL"
135340181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                           " ORDER BY snum, rowid", 0);
135350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( bDebug ){
135360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
135377790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }else{
135380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
135397790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
135400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      freeText(&sSelect);
135417790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
135427790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( zErrMsg ){
1354360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(stderr,"Error: %s\n", zErrMsg);
135447790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      sqlite3_free(zErrMsg);
13545a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      rc = 1;
13546a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }else if( rc != SQLITE_OK ){
1354760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr,"Error: querying schema information\n");
13548a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      rc = 1;
13549a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }else{
13550a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      rc = 0;
135517790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
135527790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else
135537790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
135543fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
135553fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
13556b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    sqlite3SelectTrace = (int)integerValue(azArg[1]);
135573fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  }else
135583fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#endif
135593fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
1356060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#if defined(SQLITE_ENABLE_SESSION)
1356160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
1356260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    OpenSession *pSession = &p->aSession[0];
1356360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    char **azCmd = &azArg[1];
1356460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    int iSes = 0;
1356560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    int nCmd = nArg - 1;
1356660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    int i;
1356760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    if( nArg<=1 ) goto session_syntax_error;
1356860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    open_db(p, 0);
1356960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    if( nArg>=3 ){
1357060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      for(iSes=0; iSes<p->nSession; iSes++){
1357160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        if( strcmp(p->aSession[iSes].zName, azArg[1])==0 ) break;
1357260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }
1357360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( iSes<p->nSession ){
1357460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        pSession = &p->aSession[iSes];
1357560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        azCmd++;
1357660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        nCmd--;
1357760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }else{
1357860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        pSession = &p->aSession[0];
1357960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        iSes = 0;
1358060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }
1358160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }
1358260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
1358360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    /* .session attach TABLE
1358460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    ** Invoke the sqlite3session_attach() interface to attach a particular
1358560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    ** table so that it is never filtered.
1358660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    */
1358760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    if( strcmp(azCmd[0],"attach")==0 ){
1358860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( nCmd!=2 ) goto session_syntax_error;
1358960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( pSession->p==0 ){
1359060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        session_not_open:
1359160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        raw_printf(stderr, "ERROR: No sessions are open\n");
1359260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }else{
1359360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        rc = sqlite3session_attach(pSession->p, azCmd[1]);
1359460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        if( rc ){
1359560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc);
1359660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          rc = 0;
1359760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        }
1359860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }
1359960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }else
1360060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
1360160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    /* .session changeset FILE
1360260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    ** .session patchset FILE
1360360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    ** Write a changeset or patchset into a file.  The file is overwritten.
1360460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    */
1360560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){
1360660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      FILE *out = 0;
1360760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( nCmd!=2 ) goto session_syntax_error;
1360860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( pSession->p==0 ) goto session_not_open;
1360960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      out = fopen(azCmd[1], "wb");
1361060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( out==0 ){
1361160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n", azCmd[1]);
1361260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }else{
1361360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        int szChng;
1361460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        void *pChng;
1361560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        if( azCmd[0][0]=='c' ){
1361660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          rc = sqlite3session_changeset(pSession->p, &szChng, &pChng);
1361760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        }else{
1361860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);
1361960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        }
1362060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        if( rc ){
1362160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          printf("Error: error code %d\n", rc);
1362260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          rc = 0;
1362360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        }
1362460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        if( pChng
1362560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          && fwrite(pChng, szChng, 1, out)!=1 ){
1362660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n",
1362760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis                  szChng);
1362860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        }
1362960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        sqlite3_free(pChng);
1363060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        fclose(out);
1363160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }
1363260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }else
1363360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
1363460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    /* .session close
1363560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    ** Close the identified session
1363660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    */
1363760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    if( strcmp(azCmd[0], "close")==0 ){
1363860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( nCmd!=1 ) goto session_syntax_error;
1363960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( p->nSession ){
1364060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        session_close(pSession);
1364160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        p->aSession[iSes] = p->aSession[--p->nSession];
1364260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }
1364360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }else
1364460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
1364560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    /* .session enable ?BOOLEAN?
1364660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    ** Query or set the enable flag
1364760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    */
1364860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    if( strcmp(azCmd[0], "enable")==0 ){
1364960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      int ii;
1365060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( nCmd>2 ) goto session_syntax_error;
1365160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
1365260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( p->nSession ){
1365360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        ii = sqlite3session_enable(pSession->p, ii);
1365460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(p->out, "session %s enable flag = %d\n",
1365560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis                    pSession->zName, ii);
1365660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }
1365760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }else
1365860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
1365960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    /* .session filter GLOB ....
1366060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    ** Set a list of GLOB patterns of table names to be excluded.
1366160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    */
1366260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    if( strcmp(azCmd[0], "filter")==0 ){
1366360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      int ii, nByte;
1366460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( nCmd<2 ) goto session_syntax_error;
1366560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( p->nSession ){
1366660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        for(ii=0; ii<pSession->nFilter; ii++){
1366760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          sqlite3_free(pSession->azFilter[ii]);
1366860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        }
1366960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        sqlite3_free(pSession->azFilter);
1367060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
1367160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        pSession->azFilter = sqlite3_malloc( nByte );
1367260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        if( pSession->azFilter==0 ){
1367360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          raw_printf(stderr, "Error: out or memory\n");
1367460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          exit(1);
1367560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        }
1367660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        for(ii=1; ii<nCmd; ii++){
1367760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
1367860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        }
1367960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        pSession->nFilter = ii-1;
1368060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }
1368160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }else
1368260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
1368360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    /* .session indirect ?BOOLEAN?
1368460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    ** Query or set the indirect flag
1368560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    */
1368660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    if( strcmp(azCmd[0], "indirect")==0 ){
1368760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      int ii;
1368860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( nCmd>2 ) goto session_syntax_error;
1368960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
1369060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( p->nSession ){
1369160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        ii = sqlite3session_indirect(pSession->p, ii);
1369260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(p->out, "session %s indirect flag = %d\n",
1369360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis                    pSession->zName, ii);
1369460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }
1369560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }else
1369660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
1369760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    /* .session isempty
1369860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    ** Determine if the session is empty
1369960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    */
1370060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    if( strcmp(azCmd[0], "isempty")==0 ){
1370160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      int ii;
1370260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( nCmd!=1 ) goto session_syntax_error;
1370360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( p->nSession ){
1370460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        ii = sqlite3session_isempty(pSession->p);
1370560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(p->out, "session %s isempty flag = %d\n",
1370660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis                    pSession->zName, ii);
1370760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }
1370860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }else
1370960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
1371060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    /* .session list
1371160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    ** List all currently open sessions
1371260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    */
1371360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    if( strcmp(azCmd[0],"list")==0 ){
1371460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      for(i=0; i<p->nSession; i++){
1371560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(p->out, "%d %s\n", i, p->aSession[i].zName);
1371660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }
1371760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }else
1371860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
1371960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    /* .session open DB NAME
1372060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    ** Open a new session called NAME on the attached database DB.
1372160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    ** DB is normally "main".
1372260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    */
1372360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    if( strcmp(azCmd[0],"open")==0 ){
1372460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      char *zName;
1372560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( nCmd!=3 ) goto session_syntax_error;
1372660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      zName = azCmd[2];
1372760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( zName[0]==0 ) goto session_syntax_error;
1372860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      for(i=0; i<p->nSession; i++){
1372960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        if( strcmp(p->aSession[i].zName,zName)==0 ){
1373060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
1373160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          goto meta_command_exit;
1373260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        }
1373360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }
1373460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( p->nSession>=ArraySize(p->aSession) ){
1373560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(p->aSession));
1373660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        goto meta_command_exit;
1373760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }
1373860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      pSession = &p->aSession[p->nSession];
1373960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
1374060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( rc ){
1374160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        raw_printf(stderr, "Cannot open session: error code=%d\n", rc);
1374260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        rc = 0;
1374360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        goto meta_command_exit;
1374460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }
1374560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      pSession->nFilter = 0;
1374660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      sqlite3session_table_filter(pSession->p, session_filter, pSession);
1374760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      p->nSession++;
1374860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      pSession->zName = sqlite3_mprintf("%s", zName);
1374960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }else
1375060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    /* If no command name matches, show a syntax error */
1375160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    session_syntax_error:
1375260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    session_help(p);
1375360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  }else
1375460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#endif
137553fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
137568fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich#ifdef SQLITE_DEBUG
137578fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  /* Undocumented commands for internal testing.  Subject to change
137588fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  ** without notice. */
137598fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
137608fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
137618fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      int i, v;
137628fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      for(i=1; i<nArg; i++){
137638fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        v = booleanValue(azArg[i]);
1376460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
137658fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }
137668fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
137678fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( strncmp(azArg[0]+9, "integer", n-9)==0 ){
137688fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      int i; sqlite3_int64 v;
137698fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      for(i=1; i<nArg; i++){
137708fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        char zBuf[200];
137718fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        v = integerValue(azArg[i]);
137721c7cea379348522163370244e8fbbff8a136b7faNick Kralevich        sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
1377360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(p->out, "%s", zBuf);
137748fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }
137758fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
137768fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }else
137778fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich#endif
137788fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
13779b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){
13780b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    int bIsInit = 0;         /* True to initialize the SELFTEST table */
13781b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    int bVerbose = 0;        /* Verbose output */
13782b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    int bSelftestExists;     /* True if SELFTEST already exists */
137830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int i, k;                /* Loop counters */
13784b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    int nTest = 0;           /* Number of tests runs */
13785b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    int nErr = 0;            /* Number of errors seen */
13786b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    ShellText str;           /* Answer for a query */
137870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */
13788b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
13789b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    open_db(p,0);
13790b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    for(i=1; i<nArg; i++){
13791b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      const char *z = azArg[i];
13792b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      if( z[0]=='-' && z[1]=='-' ) z++;
13793b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      if( strcmp(z,"-init")==0 ){
13794b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        bIsInit = 1;
13795b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      }else
13796b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      if( strcmp(z,"-v")==0 ){
13797b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        bVerbose++;
13798b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      }else
13799b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      {
13800b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
13801b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis                    azArg[i], azArg[0]);
13802b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        raw_printf(stderr, "Should be one of: --init -v\n");
13803b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        rc = 1;
13804b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        goto meta_command_exit;
13805b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      }
13806b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }
13807b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    if( sqlite3_table_column_metadata(p->db,"main","selftest",0,0,0,0,0,0)
13808b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis           != SQLITE_OK ){
13809b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      bSelftestExists = 0;
13810b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }else{
13811b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      bSelftestExists = 1;
13812b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }
13813b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    if( bIsInit ){
13814b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      createSelftestTable(p);
13815b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      bSelftestExists = 1;
13816b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }
138170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    initText(&str);
138180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    appendText(&str, "x", 0);
138190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    for(k=bSelftestExists; k>=0; k--){
138200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( k==1 ){
138210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        rc = sqlite3_prepare_v2(p->db,
138220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno",
138230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            -1, &pStmt, 0);
138240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else{
138250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        rc = sqlite3_prepare_v2(p->db,
138260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          "VALUES(0,'memo','Missing SELFTEST table - default checks only',''),"
138270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          "      (1,'run','PRAGMA integrity_check','ok')",
138280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          -1, &pStmt, 0);
138290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
13830b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      if( rc ){
13831b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        raw_printf(stderr, "Error querying the selftest table\n");
13832b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        rc = 1;
138330181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        sqlite3_finalize(pStmt);
13834b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        goto meta_command_exit;
13835b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      }
138360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){
138370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        int tno = sqlite3_column_int(pStmt, 0);
138380181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        const char *zOp = (const char*)sqlite3_column_text(pStmt, 1);
138390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        const char *zSql = (const char*)sqlite3_column_text(pStmt, 2);
138400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        const char *zAns = (const char*)sqlite3_column_text(pStmt, 3);
138410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
138420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        k = 0;
138430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( bVerbose>0 ){
138440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          char *zQuote = sqlite3_mprintf("%q", zSql);
138450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          printf("%d: %s %s\n", tno, zOp, zSql);
138460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          sqlite3_free(zQuote);
13847b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        }
138480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( strcmp(zOp,"memo")==0 ){
138490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          utf8_printf(p->out, "%s\n", zSql);
138500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }else
138510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( strcmp(zOp,"run")==0 ){
138520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          char *zErrMsg = 0;
138530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          str.n = 0;
138540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          str.z[0] = 0;
138550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
138560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          nTest++;
138570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( bVerbose ){
138580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            utf8_printf(p->out, "Result: %s\n", str.z);
138590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
138600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( rc || zErrMsg ){
138610181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            nErr++;
138620181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            rc = 1;
138630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
138640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            sqlite3_free(zErrMsg);
138650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }else if( strcmp(zAns,str.z)!=0 ){
138660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            nErr++;
138670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            rc = 1;
138680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns);
138690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            utf8_printf(p->out, "%d:      Got: [%s]\n", tno, str.z);
138700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
138710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        }else
138720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        {
138730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          utf8_printf(stderr,
138740181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            "Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
13875b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          rc = 1;
138760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          break;
13877b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        }
138780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      } /* End loop over rows of content from SELFTEST */
138790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      sqlite3_finalize(pStmt);
138800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    } /* End loop over k */
13881b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    freeText(&str);
13882b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest);
13883b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }else
13884b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
138851c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
138869bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown    if( nArg<2 || nArg>3 ){
1388760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
138881c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      rc = 1;
138891c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }
138909bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown    if( nArg>=2 ){
138913fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator,
138923fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich                       "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]);
138939bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown    }
138949bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown    if( nArg>=3 ){
138953fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator,
138963fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich                       "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]);
138979bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown    }
138987790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else
138997790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
13900b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  if( c=='s' && n>=4 && strncmp(azArg[0],"sha3sum",n)==0 ){
13901b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    const char *zLike = 0;   /* Which table to checksum. 0 means everything */
13902b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    int i;                   /* Loop counter */
13903b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    int bSchema = 0;         /* Also hash the schema */
13904b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    int bSeparate = 0;       /* Hash each table separately */
13905b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    int iSize = 224;         /* Hash algorithm to use */
13906b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    int bDebug = 0;          /* Only show the query that would have run */
13907b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    sqlite3_stmt *pStmt;     /* For querying tables names */
13908b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    char *zSql;              /* SQL to be run */
13909b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    char *zSep;              /* Separator */
13910b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    ShellText sSql;          /* Complete SQL for the query to run the hash */
13911b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    ShellText sQuery;        /* Set of queries used to read all content */
13912b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    open_db(p, 0);
13913b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    for(i=1; i<nArg; i++){
13914b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      const char *z = azArg[i];
13915b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      if( z[0]=='-' ){
13916b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        z++;
13917b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        if( z[0]=='-' ) z++;
13918b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        if( strcmp(z,"schema")==0 ){
13919b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          bSchema = 1;
13920b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        }else
139210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0
139220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov         || strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0
13923b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        ){
13924b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          iSize = atoi(&z[5]);
13925b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        }else
13926b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        if( strcmp(z,"debug")==0 ){
13927b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          bDebug = 1;
13928b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        }else
13929b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        {
13930b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
13931b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis                      azArg[i], azArg[0]);
13932b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          raw_printf(stderr, "Should be one of: --schema"
13933b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis                             " --sha3-224 --sha3-255 --sha3-384 --sha3-512\n");
13934b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          rc = 1;
13935b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          goto meta_command_exit;
13936b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        }
13937b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      }else if( zLike ){
13938b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
13939b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        rc = 1;
13940b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        goto meta_command_exit;
13941b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      }else{
13942b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        zLike = z;
13943b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        bSeparate = 1;
13944b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        if( sqlite3_strlike("sqlite_%", zLike, 0)==0 ) bSchema = 1;
13945b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      }
13946b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }
13947b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    if( bSchema ){
13948b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      zSql = "SELECT lower(name) FROM sqlite_master"
13949b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis             " WHERE type='table' AND coalesce(rootpage,0)>1"
13950b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis             " UNION ALL SELECT 'sqlite_master'"
13951b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis             " ORDER BY 1 collate nocase";
13952b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }else{
13953b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      zSql = "SELECT lower(name) FROM sqlite_master"
13954b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis             " WHERE type='table' AND coalesce(rootpage,0)>1"
13955b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis             " AND name NOT LIKE 'sqlite_%'"
13956b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis             " ORDER BY 1 collate nocase";
13957b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }
13958b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
13959b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    initText(&sQuery);
13960b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    initText(&sSql);
13961b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0);
13962b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    zSep = "VALUES(";
13963b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    while( SQLITE_ROW==sqlite3_step(pStmt) ){
13964b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      const char *zTab = (const char*)sqlite3_column_text(pStmt,0);
13965b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue;
13966b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      if( strncmp(zTab, "sqlite_",7)!=0 ){
13967b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        appendText(&sQuery,"SELECT * FROM ", 0);
13968b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        appendText(&sQuery,zTab,'"');
13969b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        appendText(&sQuery," NOT INDEXED;", 0);
13970b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      }else if( strcmp(zTab, "sqlite_master")==0 ){
13971b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_master"
13972b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis                           " ORDER BY name;", 0);
13973b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      }else if( strcmp(zTab, "sqlite_sequence")==0 ){
13974b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence"
13975b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis                           " ORDER BY name;", 0);
13976b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      }else if( strcmp(zTab, "sqlite_stat1")==0 ){
13977b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1"
13978b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis                           " ORDER BY tbl,idx;", 0);
13979b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      }else if( strcmp(zTab, "sqlite_stat3")==0
13980b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis             || strcmp(zTab, "sqlite_stat4")==0 ){
13981b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        appendText(&sQuery, "SELECT * FROM ", 0);
13982b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        appendText(&sQuery, zTab, 0);
13983b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis        appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
13984b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      }
13985b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      appendText(&sSql, zSep, 0);
13986b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      appendText(&sSql, sQuery.z, '\'');
13987b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      sQuery.n = 0;
13988b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      appendText(&sSql, ",", 0);
13989b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      appendText(&sSql, zTab, '\'');
13990b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      zSep = "),(";
13991b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }
13992b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    sqlite3_finalize(pStmt);
13993b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    if( bSeparate ){
13994b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      zSql = sqlite3_mprintf(
13995b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          "%s))"
13996b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          " SELECT lower(hex(sha3_query(a,%d))) AS hash, b AS label"
13997b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          "   FROM [sha3sum$query]",
13998b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          sSql.z, iSize);
13999b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }else{
14000b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      zSql = sqlite3_mprintf(
14001b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          "%s))"
14002b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          " SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash"
14003b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          "   FROM [sha3sum$query]",
14004b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis          sSql.z, iSize);
14005b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }
14006b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    freeText(&sQuery);
14007b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    freeText(&sSql);
14008b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    if( bDebug ){
14009b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      utf8_printf(p->out, "%s\n", zSql);
14010b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }else{
14011b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      shell_exec(p->db, zSql, shell_callback, p, 0);
14012b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    }
14013b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    sqlite3_free(zSql);
14014b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }else
14015b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis
140161c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='s'
140171c7cea379348522163370244e8fbbff8a136b7faNick Kralevich   && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
140181c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  ){
140191c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    char *zCmd;
140209bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown    int i, x;
140211c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    if( nArg<2 ){
1402260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Usage: .system COMMAND\n");
140231c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      rc = 1;
140241c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      goto meta_command_exit;
140251c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }
140261c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
140271c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    for(i=2; i<nArg; i++){
140281c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
140291c7cea379348522163370244e8fbbff8a136b7faNick Kralevich                             zCmd, azArg[i]);
140301c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }
140319bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown    x = system(zCmd);
140321c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    sqlite3_free(zCmd);
1403360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    if( x ) raw_printf(stderr, "System command returns %d\n", x);
140341c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  }else
140351c7cea379348522163370244e8fbbff8a136b7faNick Kralevich
140361c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
140370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    static const char *azBool[] = { "off", "on", "trigger", "full"};
140381c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    int i;
140391c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    if( nArg!=1 ){
1404060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Usage: .show\n");
140411c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      rc = 1;
140421c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      goto meta_command_exit;
140431c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }
14044b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis    utf8_printf(p->out, "%12.12s: %s\n","echo",
14045b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis                                  azBool[ShellHasFlag(p, SHFLG_Echo)]);
1404660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
1404760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(p->out, "%12.12s: %s\n","explain",
1404860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis         p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
1404960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
1405060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
1405160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(p->out, "%12.12s: ", "nullvalue");
140523fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      output_c_string(p->out, p->nullValue);
1405360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(p->out, "\n");
1405460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(p->out,"%12.12s: %s\n","output",
14055a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori            strlen30(p->outfile) ? p->outfile : "stdout");
1405660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(p->out,"%12.12s: ", "colseparator");
140573fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      output_c_string(p->out, p->colSeparator);
1405860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(p->out, "\n");
1405960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(p->out,"%12.12s: ", "rowseparator");
140603fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      output_c_string(p->out, p->rowSeparator);
1406160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(p->out, "\n");
1406260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(p->out, "%12.12s: %s\n","stats", azBool[p->statsOn!=0]);
1406360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(p->out, "%12.12s: ", "width");
140647790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
1406560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(p->out, "%d ", p->colWidth[i]);
140667790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
1406760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    raw_printf(p->out, "\n");
1406808f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    utf8_printf(p->out, "%12.12s: %s\n", "filename",
1406908f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis                p->zDbFilename ? p->zDbFilename : "");
140707790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else
140717790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
140721c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
140731c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    if( nArg==2 ){
140741c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      p->statsOn = booleanValue(azArg[1]);
1407560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }else if( nArg==1 ){
1407660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      display_stats(p->db, p, 0);
140771c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }else{
1407860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Usage: .stats ?on|off?\n");
140791c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      rc = 1;
140801c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }
14081de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori  }else
14082de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori
14083e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  if( (c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0)
14084e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani   || (c=='i' && (strncmp(azArg[0], "indices", n)==0
14085e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani                 || strncmp(azArg[0], "indexes", n)==0) )
14086e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  ){
140878fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    sqlite3_stmt *pStmt;
140887790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    char **azResult;
140898fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    int nRow, nAlloc;
140908fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    int ii;
140910181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    ShellText s;
140920181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    initText(&s);
140938fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    open_db(p, 0);
140948fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
14095253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich    if( rc ) return shellDatabaseError(p->db);
14096253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich
140970181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( nArg>2 && c=='i' ){
14098e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      /* It is an historical accident that the .indexes command shows an error
14099e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      ** when called with the wrong number of arguments whereas the .tables
14100e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      ** command does not. */
14101e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
14102e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      rc = 1;
14103e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      goto meta_command_exit;
14104e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    }
141050181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
141068fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
141070181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( zDbName==0 ) continue;
141080181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( s.z && s.z[0] ) appendText(&s, " UNION ALL ", 0);
141090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( sqlite3_stricmp(zDbName, "main")==0 ){
141100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        appendText(&s, "SELECT name FROM ", 0);
141110181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else{
141120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        appendText(&s, "SELECT ", 0);
141130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        appendText(&s, zDbName, '\'');
141140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        appendText(&s, "||'.'||name FROM ", 0);
141150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
141160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      appendText(&s, zDbName, '"');
141170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      appendText(&s, ".sqlite_master ", 0);
14118e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      if( c=='t' ){
141190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        appendText(&s," WHERE type IN ('table','view')"
141200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                      "   AND name NOT LIKE 'sqlite_%'"
141210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                      "   AND name LIKE ?1", 0);
141228fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }else{
141230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        appendText(&s," WHERE type='index'"
141240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                      "   AND tbl_name LIKE ?1", 0);
141258fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }
141267790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
14127253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich    rc = sqlite3_finalize(pStmt);
141280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    appendText(&s, " ORDER BY 1", 0);
141290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0);
141300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    freeText(&s);
14131253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich    if( rc ) return shellDatabaseError(p->db);
14132253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich
14133253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich    /* Run the SQL statement prepared by the above block. Store the results
14134253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich    ** as an array of nul-terminated strings in azResult[].  */
141358fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    nRow = nAlloc = 0;
141368fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    azResult = 0;
141378fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( nArg>1 ){
141388fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT);
14139a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    }else{
141408fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
141418fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
141428fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    while( sqlite3_step(pStmt)==SQLITE_ROW ){
141438fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      if( nRow>=nAlloc ){
141448fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        char **azNew;
141453a6c79f802fabdb94367177310663397420e319fNick Kralevich        int n2 = nAlloc*2 + 10;
141463a6c79f802fabdb94367177310663397420e319fNick Kralevich        azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
141478fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        if( azNew==0 ){
14148253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich          rc = shellNomemError();
141498fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich          break;
141508fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        }
141513a6c79f802fabdb94367177310663397420e319fNick Kralevich        nAlloc = n2;
141528fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        azResult = azNew;
141538fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }
141548fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
14155253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich      if( 0==azResult[nRow] ){
14156253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich        rc = shellNomemError();
14157253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich        break;
14158253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich      }
14159253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich      nRow++;
14160253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich    }
14161253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich    if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
14162253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich      rc = shellDatabaseError(p->db);
141638fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
14164253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich
14165253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich    /* Pretty-print the contents of array azResult[] to the output */
14166253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich    if( rc==0 && nRow>0 ){
141677790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      int len, maxlen = 0;
141687790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      int i, j;
141697790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      int nPrintCol, nPrintRow;
141708fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      for(i=0; i<nRow; i++){
14171a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori        len = strlen30(azResult[i]);
141727790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        if( len>maxlen ) maxlen = len;
141737790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
141747790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      nPrintCol = 80/(maxlen+2);
141757790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      if( nPrintCol<1 ) nPrintCol = 1;
141767790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
141777790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      for(i=0; i<nPrintRow; i++){
141788fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        for(j=i; j<nRow; j+=nPrintRow){
141798fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich          char *zSp = j<nPrintRow ? "" : "  ";
1418060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          utf8_printf(p->out, "%s%-*s", zSp, maxlen,
1418160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis                      azResult[j] ? azResult[j]:"");
141827790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        }
1418360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        raw_printf(p->out, "\n");
141847790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
141857790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
14186253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich
141878fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
141888fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    sqlite3_free(azResult);
141897790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else
141907790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
1419108f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  /* Begin redirecting output to the file "testcase-out.txt" */
1419208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  if( c=='t' && strcmp(azArg[0],"testcase")==0 ){
1419308f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    output_reset(p);
141940181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    p->out = output_file_open("testcase-out.txt", 0);
1419508f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    if( p->out==0 ){
14196e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
1419708f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    }
1419808f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    if( nArg>=2 ){
1419908f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
1420008f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    }else{
1420108f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
1420208f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    }
1420308f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  }else
1420408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis
14205e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani#ifndef SQLITE_UNTESTABLE
142060181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
1420790ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    static const struct {
1420890ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown       const char *zCtrlName;   /* Name of a test-control option */
1420990ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown       int ctrlCode;            /* Integer code for that option */
142100181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov       const char *zUsage;      /* Usage notes */
1421190ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    } aCtrl[] = {
142120181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      { "always",             SQLITE_TESTCTRL_ALWAYS,        "BOOLEAN"            },
142130181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      { "assert",             SQLITE_TESTCTRL_ASSERT,        "BOOLEAN"            },
142140181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, ""          },*/
142150181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    /*{ "bitvec_test",        SQLITE_TESTCTRL_BITVEC_TEST,   ""                },*/
142160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      { "byteorder",          SQLITE_TESTCTRL_BYTEORDER,     ""                   },
142170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    /*{ "fault_install",      SQLITE_TESTCTRL_FAULT_INSTALL, ""                }, */
142180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      { "imposter",           SQLITE_TESTCTRL_IMPOSTER,   "SCHEMA ON/OFF ROOTPAGE"},
142190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifdef SQLITE_N_KEYWORD
142200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      { "iskeyword",          SQLITE_TESTCTRL_ISKEYWORD,     "IDENTIFIER"         },
142210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
142220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      { "localtime_fault",    SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN"           },
142230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      { "never_corrupt",      SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN"            },
142240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      { "optimizations",      SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK"       },
142250181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifdef YYCOVERAGE
142260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      { "parser_coverage",    SQLITE_TESTCTRL_PARSER_COVERAGE, ""                 },
142270181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
142280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      { "pending_byte",       SQLITE_TESTCTRL_PENDING_BYTE,  "OFFSET  "           },
142290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      { "prng_reset",         SQLITE_TESTCTRL_PRNG_RESET,    ""                   },
142300181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      { "prng_restore",       SQLITE_TESTCTRL_PRNG_RESTORE,  ""                   },
142310181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      { "prng_save",          SQLITE_TESTCTRL_PRNG_SAVE,     ""                   },
142320181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      { "reserve",            SQLITE_TESTCTRL_RESERVE,       "BYTES-OF-RESERVE"   },
1423390ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    };
1423490ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    int testctrl = -1;
142350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int iCtrl = -1;
142360181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int rc2 = 0;    /* 0: usage.  1: %d  2: %x  3: no-output */
142370181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    int isOk = 0;
142383a6c79f802fabdb94367177310663397420e319fNick Kralevich    int i, n2;
142390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    const char *zCmd = 0;
142400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
142418fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    open_db(p, 0);
142420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    zCmd = nArg>=2 ? azArg[1] : "help";
142430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
142440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    /* The argument can optionally begin with "-" or "--" */
142450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( zCmd[0]=='-' && zCmd[1] ){
142460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      zCmd++;
142470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
142480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
142490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
142500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    /* --help lists all test-controls */
142510181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( strcmp(zCmd,"help")==0 ){
142520181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      utf8_printf(p->out, "Available test-controls:\n");
142530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      for(i=0; i<ArraySize(aCtrl); i++){
142540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        utf8_printf(p->out, "  .testctrl %s %s\n",
142550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                    aCtrl[i].zCtrlName, aCtrl[i].zUsage);
142560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }
142570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = 1;
142580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      goto meta_command_exit;
142590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
1426090ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown
1426190ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    /* convert testctrl text option to value. allow any unique prefix
1426290ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    ** of the option name, or a numerical value. */
142630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    n2 = strlen30(zCmd);
14264253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich    for(i=0; i<ArraySize(aCtrl); i++){
142650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
1426690ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown        if( testctrl<0 ){
1426790ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown          testctrl = aCtrl[i].ctrlCode;
142680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          iCtrl = i;
1426990ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown        }else{
142700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          utf8_printf(stderr, "Error: ambiguous test-control: \"%s\"\n"
142710181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                              "Use \".testctrl --help\" for help\n", zCmd);
142720181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          rc = 1;
142730181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          goto meta_command_exit;
1427490ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown        }
1427590ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      }
1427690ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    }
142770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( testctrl<0 ){
142780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      utf8_printf(stderr,"Error: unknown test-control: %s\n"
142790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                         "Use \".testctrl --help\" for help\n", zCmd);
1428090ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    }else{
1428190ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      switch(testctrl){
1428290ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown
1428390ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown        /* sqlite3_test_control(int, db, int) */
1428490ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown        case SQLITE_TESTCTRL_OPTIMIZATIONS:
1428560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        case SQLITE_TESTCTRL_RESERVE:
1428690ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown          if( nArg==3 ){
1428760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            int opt = (int)strtol(azArg[2], 0, 0);
142883a6c79f802fabdb94367177310663397420e319fNick Kralevich            rc2 = sqlite3_test_control(testctrl, p->db, opt);
142890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            isOk = 3;
1429090ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown          }
1429190ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown          break;
1429290ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown
1429390ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown        /* sqlite3_test_control(int) */
142941c7cea379348522163370244e8fbbff8a136b7faNick Kralevich        case SQLITE_TESTCTRL_PRNG_SAVE:
142951c7cea379348522163370244e8fbbff8a136b7faNick Kralevich        case SQLITE_TESTCTRL_PRNG_RESTORE:
1429690ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown        case SQLITE_TESTCTRL_PRNG_RESET:
142971c7cea379348522163370244e8fbbff8a136b7faNick Kralevich        case SQLITE_TESTCTRL_BYTEORDER:
1429890ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown          if( nArg==2 ){
142993a6c79f802fabdb94367177310663397420e319fNick Kralevich            rc2 = sqlite3_test_control(testctrl);
143000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            isOk = testctrl==SQLITE_TESTCTRL_BYTEORDER ? 1 : 3;
1430190ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown          }
1430290ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown          break;
1430390ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown
1430490ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown        /* sqlite3_test_control(int, uint) */
1430560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        case SQLITE_TESTCTRL_PENDING_BYTE:
1430690ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown          if( nArg==3 ){
143078fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich            unsigned int opt = (unsigned int)integerValue(azArg[2]);
143083a6c79f802fabdb94367177310663397420e319fNick Kralevich            rc2 = sqlite3_test_control(testctrl, opt);
143090181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            isOk = 3;
1431090ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown          }
1431190ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown          break;
1431260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
1431390ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown        /* sqlite3_test_control(int, int) */
1431460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        case SQLITE_TESTCTRL_ASSERT:
1431560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        case SQLITE_TESTCTRL_ALWAYS:
143160181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( nArg==3 ){
143170181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            int opt = booleanValue(azArg[2]);
143180181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            rc2 = sqlite3_test_control(testctrl, opt);
143190181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            isOk = 1;
143200181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
143210181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          break;
143220181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov
143230181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        /* sqlite3_test_control(int, int) */
143240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        case SQLITE_TESTCTRL_LOCALTIME_FAULT:
1432560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        case SQLITE_TESTCTRL_NEVER_CORRUPT:
1432690ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown          if( nArg==3 ){
1432760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            int opt = booleanValue(azArg[2]);
143283a6c79f802fabdb94367177310663397420e319fNick Kralevich            rc2 = sqlite3_test_control(testctrl, opt);
143290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            isOk = 3;
1433090ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown          }
1433190ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown          break;
1433290ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown
1433390ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown        /* sqlite3_test_control(int, char *) */
1433490ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown#ifdef SQLITE_N_KEYWORD
1433560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        case SQLITE_TESTCTRL_ISKEYWORD:
1433690ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown          if( nArg==3 ){
1433760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            const char *opt = azArg[2];
143383a6c79f802fabdb94367177310663397420e319fNick Kralevich            rc2 = sqlite3_test_control(testctrl, opt);
143390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            isOk = 1;
1434090ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown          }
1434190ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown          break;
1434290ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown#endif
1434390ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown
143443fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        case SQLITE_TESTCTRL_IMPOSTER:
143453fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich          if( nArg==5 ){
1434660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis            rc2 = sqlite3_test_control(testctrl, p->db,
143473fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich                          azArg[2],
143483fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich                          integerValue(azArg[3]),
143493fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich                          integerValue(azArg[4]));
143500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            isOk = 3;
143513fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich          }
143523fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich          break;
143533fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
143540181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifdef YYCOVERAGE
143550181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        case SQLITE_TESTCTRL_PARSER_COVERAGE:
143560181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          if( nArg==2 ){
143570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            sqlite3_test_control(testctrl, p->out);
143580181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov            isOk = 3;
143590181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov          }
143600181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
1436190ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      }
1436290ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    }
143630181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    if( isOk==0 && iCtrl>=0 ){
143640181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd, aCtrl[iCtrl].zUsage);
143650181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = 1;
143660181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else if( isOk==1 ){
143670181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      raw_printf(p->out, "%d\n", rc2);
143680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else if( isOk==2 ){
143690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      raw_printf(p->out, "0x%08x\n", rc2);
143700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }
1437190ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  }else
14372b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis#endif /* !defined(SQLITE_UNTESTABLE) */
1437390ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown
143741c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
143758fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    open_db(p, 0);
143761c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
143777790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else
1437860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
143791c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){
143801c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    if( nArg==2 ){
143811c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      enableTimer = booleanValue(azArg[1]);
143821c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      if( enableTimer && !HAS_TIMER ){
1438360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        raw_printf(stderr, "Error: timer not available on this system.\n");
143841c7cea379348522163370244e8fbbff8a136b7faNick Kralevich        enableTimer = 0;
143851c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      }
143861c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }else{
1438760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Usage: .timer on|off\n");
143881c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      rc = 1;
143891c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }
143907790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else
1439160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
143921c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
143938fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    open_db(p, 0);
143941c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    if( nArg!=2 ){
1439560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Usage: .trace FILE|off\n");
143961c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      rc = 1;
143971c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      goto meta_command_exit;
143981c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    }
143993fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    output_file_close(p->traceOut);
144000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    p->traceOut = output_file_open(azArg[1], 0);
144018fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
144028fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( p->traceOut==0 ){
1440374bd39cb46f3e9465fe069b650f40ffd8298a538Alex Naidis      sqlite3_trace_v2(p->db, 0, 0, 0);
144048fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }else{
1440574bd39cb46f3e9465fe069b650f40ffd8298a538Alex Naidis      sqlite3_trace_v2(p->db, SQLITE_TRACE_STMT, sql_trace_callback,p->traceOut);
144068fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
144078fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich#endif
144088fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }else
144098fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
144103fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#if SQLITE_USER_AUTHENTICATION
144113fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
144123fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    if( nArg<2 ){
1441360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
144143fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      rc = 1;
144153fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      goto meta_command_exit;
144163fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    }
144173fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    open_db(p, 0);
144183fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    if( strcmp(azArg[1],"login")==0 ){
144193fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      if( nArg!=4 ){
1442060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        raw_printf(stderr, "Usage: .user login USER PASSWORD\n");
144213fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        rc = 1;
144223fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        goto meta_command_exit;
144233fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      }
144240181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3], strlen30(azArg[3]));
144253fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      if( rc ){
1442660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
144273fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        rc = 1;
144283fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      }
144293fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    }else if( strcmp(azArg[1],"add")==0 ){
144303fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      if( nArg!=5 ){
1443160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
144323fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        rc = 1;
144333fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        goto meta_command_exit;
144343fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      }
144350181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
144363fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich                            booleanValue(azArg[4]));
144373fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      if( rc ){
1443860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        raw_printf(stderr, "User-Add failed: %d\n", rc);
144393fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        rc = 1;
144403fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      }
144413fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    }else if( strcmp(azArg[1],"edit")==0 ){
144423fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      if( nArg!=5 ){
1444360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
144443fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        rc = 1;
144453fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        goto meta_command_exit;
144463fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      }
144470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
144483fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich                              booleanValue(azArg[4]));
144493fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      if( rc ){
1445060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        raw_printf(stderr, "User-Edit failed: %d\n", rc);
144513fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        rc = 1;
144523fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      }
144533fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    }else if( strcmp(azArg[1],"delete")==0 ){
144543fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      if( nArg!=3 ){
1445560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        raw_printf(stderr, "Usage: .user delete USER\n");
144563fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        rc = 1;
144573fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        goto meta_command_exit;
144583fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      }
144593fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      rc = sqlite3_user_delete(p->db, azArg[2]);
144603fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      if( rc ){
1446160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        raw_printf(stderr, "User-Delete failed: %d\n", rc);
144623fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        rc = 1;
144633fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      }
144643fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    }else{
1446560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n");
144663fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      rc = 1;
144673fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      goto meta_command_exit;
1446860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }
144693fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  }else
144703fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#endif /* SQLITE_USER_AUTHENTICATION */
144713fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
1447290ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
1447360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
1447490ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown        sqlite3_libversion(), sqlite3_sourceid());
144750181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if SQLITE_HAVE_ZLIB
144760181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    utf8_printf(p->out, "zlib version %s\n", zlibVersion());
144770181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
144780181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define CTIMEOPT_VAL_(opt) #opt
144790181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
144800181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if defined(__clang__) && defined(__clang_major__)
144810181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "."
144820181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                    CTIMEOPT_VAL(__clang_minor__) "."
144830181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov                    CTIMEOPT_VAL(__clang_patchlevel__) "\n");
144840181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#elif defined(_MSC_VER)
144850181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) "\n");
144860181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#elif defined(__GNUC__) && defined(__VERSION__)
144870181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    utf8_printf(p->out, "gcc-" __VERSION__ "\n");
144880181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
1448990ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  }else
1449090ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown
1449160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){
1449260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    const char *zDbName = nArg==2 ? azArg[1] : "main";
144934b7ed9600a8a9a52e622980c609aab9038bdf6b4Alex Naidis    sqlite3_vfs *pVfs = 0;
1449460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    if( p->db ){
1449560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
1449660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( pVfs ){
1449760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(p->out, "vfs.zName      = \"%s\"\n", pVfs->zName);
1449860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        raw_printf(p->out, "vfs.iVersion   = %d\n", pVfs->iVersion);
1449960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        raw_printf(p->out, "vfs.szOsFile   = %d\n", pVfs->szOsFile);
1450060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
1450160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }
1450260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }
1450360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  }else
1450460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
1450560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  if( c=='v' && strncmp(azArg[0], "vfslist", n)==0 ){
1450660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    sqlite3_vfs *pVfs;
1450760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    sqlite3_vfs *pCurrent = 0;
1450860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    if( p->db ){
1450960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent);
1451060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }
1451160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
1451260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(p->out, "vfs.zName      = \"%s\"%s\n", pVfs->zName,
1451360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis           pVfs==pCurrent ? "  <--- CURRENT" : "");
1451460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(p->out, "vfs.iVersion   = %d\n", pVfs->iVersion);
1451560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(p->out, "vfs.szOsFile   = %d\n", pVfs->szOsFile);
1451660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
1451760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( pVfs->pNext ){
1451860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        raw_printf(p->out, "-----------------------------------\n");
1451960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      }
1452060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }
1452160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  }else
1452260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
1452390ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
1452490ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    const char *zDbName = nArg==2 ? azArg[1] : "main";
1452590ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    char *zVfsName = 0;
1452690ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    if( p->db ){
1452790ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
1452890ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      if( zVfsName ){
1452960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(p->out, "%s\n", zVfsName);
1453090ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown        sqlite3_free(zVfsName);
1453190ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      }
1453290ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    }
1453390ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  }else
1453490ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown
145358fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
145368fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
145371c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    sqlite3WhereTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff;
145388fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }else
145398fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich#endif
145408fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
145411c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
145427790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    int j;
145437790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    assert( nArg<=ArraySize(azArg) );
145447790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
145458fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      p->colWidth[j-1] = (int)integerValue(azArg[j]);
145467790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
145477790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else
145487790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
145497790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  {
1455060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(stderr, "Error: unknown command or invalid arguments: "
145517790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      " \"%s\". Enter \".help\" for help\n", azArg[0]);
14552a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    rc = 1;
145537790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
145547790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
145551c7cea379348522163370244e8fbbff8a136b7faNick Kralevichmeta_command_exit:
145561c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  if( p->outCount ){
145571c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    p->outCount--;
145581c7cea379348522163370244e8fbbff8a136b7faNick Kralevich    if( p->outCount==0 ) output_reset(p);
145591c7cea379348522163370244e8fbbff8a136b7faNick Kralevich  }
145607790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  return rc;
145617790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
145627790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
145637790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
145647790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** Return TRUE if a semicolon occurs anywhere in the first N characters
145657790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** of string z[].
145667790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
145678fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevichstatic int line_contains_semicolon(const char *z, int N){
145687790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  int i;
145697790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  for(i=0; i<N; i++){  if( z[i]==';' ) return 1; }
145707790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  return 0;
145717790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
145727790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
145737790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
145747790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** Test to see if a line consists entirely of whitespace.
145757790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
145767790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Projectstatic int _all_whitespace(const char *z){
145777790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  for(; *z; z++){
1457890ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    if( IsSpace(z[0]) ) continue;
145797790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( *z=='/' && z[1]=='*' ){
145807790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      z += 2;
145817790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      while( *z && (*z!='*' || z[1]!='/') ){ z++; }
145827790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      if( *z==0 ) return 0;
145837790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      z++;
145847790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      continue;
145857790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
145867790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( *z=='-' && z[1]=='-' ){
145877790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      z += 2;
145887790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      while( *z && *z!='\n' ){ z++; }
145897790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      if( *z==0 ) return 1;
145907790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      continue;
145917790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
145927790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    return 0;
145937790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
145947790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  return 1;
145957790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
145967790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
145977790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
145987790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** Return TRUE if the line typed in is an SQL command terminator other
145997790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** than a semi-colon.  The SQL Server style "go" command is understood
146007790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** as is the Oracle "/".
146017790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
146028fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevichstatic int line_is_command_terminator(const char *zLine){
1460390ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  while( IsSpace(zLine[0]) ){ zLine++; };
14604a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ){
14605a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    return 1;  /* Oracle */
14606a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  }
1460790ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  if( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o'
146087790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project         && _all_whitespace(&zLine[2]) ){
146097790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    return 1;  /* SQL Server */
146107790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
146117790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  return 0;
146127790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
146137790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
146147790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
14615a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori** Return true if zSql is a complete SQL statement.  Return false if it
14616a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori** ends in the middle of a string literal or C-style comment.
14617a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori*/
146188fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevichstatic int line_is_complete(char *zSql, int nSql){
14619a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  int rc;
14620a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  if( zSql==0 ) return 1;
14621a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  zSql[nSql] = ';';
14622a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  zSql[nSql+1] = 0;
14623a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  rc = sqlite3_complete(zSql);
14624a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  zSql[nSql] = 0;
14625a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori  return rc;
14626a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori}
14627a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori
14628a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori/*
14629e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani** Run a single line of SQL
14630e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani*/
14631e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefanistatic int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
14632e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  int rc;
14633e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  char *zErrMsg = 0;
14634e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani
14635e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  open_db(p, 0);
14636b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
14637e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  BEGIN_TIMER;
14638e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg);
14639e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  END_TIMER;
14640e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  if( rc || zErrMsg ){
14641e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    char zPrefix[100];
14642e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    if( in!=0 || !stdin_is_interactive ){
14643e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      sqlite3_snprintf(sizeof(zPrefix), zPrefix,
14644e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani                       "Error: near line %d:", startline);
14645e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    }else{
14646e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:");
14647e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    }
14648e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    if( zErrMsg!=0 ){
14649e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg);
14650e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      sqlite3_free(zErrMsg);
14651e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      zErrMsg = 0;
14652e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    }else{
14653e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
14654e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    }
14655e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    return 1;
14656b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis  }else if( ShellHasFlag(p, SHFLG_CountChanges) ){
14657e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    raw_printf(p->out, "changes: %3d   total_changes: %d\n",
14658e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani            sqlite3_changes(p->db), sqlite3_total_changes(p->db));
14659e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  }
14660e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  return 0;
14661e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani}
14662e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani
14663e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani
14664e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani/*
146657790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** Read input from *in and process it.  If *in==0 then input
146667790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** is interactive - the user is typing it it.  Otherwise, input
146677790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** is coming from a file or device.  A prompt is issued and history
146687790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** is saved only if input is interactive.  An interrupt signal will
146697790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** cause this routine to exit immediately, unless input is interactive.
146707790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project**
146717790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** Return the number of errors.
146727790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
146733fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichstatic int process_input(ShellState *p, FILE *in){
146748fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  char *zLine = 0;          /* A single input line */
146758fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  char *zSql = 0;           /* Accumulated SQL text */
146768fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int nLine;                /* Length of current line */
146778fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int nSql = 0;             /* Bytes of zSql[] used */
146788fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int nAlloc = 0;           /* Allocated zSql[] space */
146798fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int nSqlPrior = 0;        /* Bytes of zSql[] used by prior line */
146808fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int rc;                   /* Error code */
146818fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int errCnt = 0;           /* Number of errors seen */
146828fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int lineno = 0;           /* Current line number */
146838fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int startline = 0;        /* Line number for start of current input */
146847790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
146857790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){
146867790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    fflush(p->out);
146878fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    zLine = one_input_line(in, zLine, nSql>0);
146887790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( zLine==0 ){
146898fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      /* End of input */
1469008f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      if( in==0 && stdin_is_interactive ) printf("\n");
146918fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      break;
146927790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
146937790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( seenInterrupt ){
146947790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      if( in!=0 ) break;
146957790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      seenInterrupt = 0;
146967790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
146977790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    lineno++;
146988fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( nSql==0 && _all_whitespace(zLine) ){
14699b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
147008fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      continue;
147018fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
147027790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( zLine && zLine[0]=='.' && nSql==0 ){
14703b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
147047790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      rc = do_meta_command(zLine, p);
14705a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      if( rc==2 ){ /* exit requested */
147067790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        break;
147077790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }else if( rc ){
147087790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        errCnt++;
147097790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
147107790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      continue;
147117790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
147128fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( line_is_command_terminator(zLine) && line_is_complete(zSql, nSql) ){
147137790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      memcpy(zLine,";",2);
147147790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
147158fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    nLine = strlen30(zLine);
147168fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( nSql+nLine+2>=nAlloc ){
147178fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      nAlloc = nSql+nLine+100;
147188fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      zSql = realloc(zSql, nAlloc);
147198fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      if( zSql==0 ){
1472060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        raw_printf(stderr, "Error: out of memory\n");
147218fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        exit(1);
147228fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }
147238fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
147247790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    nSqlPrior = nSql;
147258fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( nSql==0 ){
147267790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      int i;
1472790ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
147288fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      assert( nAlloc>0 && zSql!=0 );
147298fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      memcpy(zSql, zLine+i, nLine+1-i);
147308fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      startline = lineno;
147318fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      nSql = nLine-i;
147327790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else{
147337790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      zSql[nSql++] = '\n';
147348fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      memcpy(zSql+nSql, zLine, nLine+1);
147358fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      nSql += nLine;
147367790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
147378fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior)
147387790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project                && sqlite3_complete(zSql) ){
14739e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani      errCnt += runOneSqlLine(p, zSql, in, startline);
147408fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      nSql = 0;
147411c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      if( p->outCount ){
147421c7cea379348522163370244e8fbbff8a136b7faNick Kralevich        output_reset(p);
147431c7cea379348522163370244e8fbbff8a136b7faNick Kralevich        p->outCount = 0;
147440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      }else{
147450181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        clearTempFile(p);
147461c7cea379348522163370244e8fbbff8a136b7faNick Kralevich      }
147478fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }else if( nSql && _all_whitespace(zSql) ){
14748b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql);
147497790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      nSql = 0;
147507790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
147517790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
14752e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani  if( nSql && !_all_whitespace(zSql) ){
14753e7f3e808a8a09ccddbb17168c95fdd18e88ce974Luca Stefani    runOneSqlLine(p, zSql, in, startline);
147547790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
14755253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich  free(zSql);
147567790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  free(zLine);
147578fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  return errCnt>0;
147587790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
147597790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
147607790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
147617790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** Return a pathname which is the user's home directory.  A
147628fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** 0 return indicates an error of some kind.
147637790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
1476408f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidisstatic char *find_home_dir(int clearFlag){
147658fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  static char *home_dir = NULL;
1476608f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  if( clearFlag ){
1476708f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    free(home_dir);
1476808f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    home_dir = 0;
1476908f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    return 0;
1477008f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  }
147718fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( home_dir ) return home_dir;
147727790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
147733fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \
147743fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich     && !defined(__RTP__) && !defined(_WRS_KERNEL)
147758fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  {
147768fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    struct passwd *pwent;
147778fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    uid_t uid = getuid();
147788fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( (pwent=getpwuid(uid)) != NULL) {
147798fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      home_dir = pwent->pw_dir;
147808fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
147817790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
147827790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#endif
147837790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
147847790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#if defined(_WIN32_WCE)
147857790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv()
147867790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project   */
147878fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  home_dir = "/";
147887790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#else
147897790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
147908fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich#if defined(_WIN32) || defined(WIN32)
147917790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if (!home_dir) {
147927790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    home_dir = getenv("USERPROFILE");
147937790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
147947790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#endif
147957790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
147967790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if (!home_dir) {
147977790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    home_dir = getenv("HOME");
147987790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
147997790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
148008fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich#if defined(_WIN32) || defined(WIN32)
148017790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if (!home_dir) {
148027790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    char *zDrive, *zPath;
148037790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    int n;
148047790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    zDrive = getenv("HOMEDRIVE");
148057790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    zPath = getenv("HOMEPATH");
148067790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( zDrive && zPath ){
14807a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      n = strlen30(zDrive) + strlen30(zPath) + 1;
148087790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      home_dir = malloc( n );
148097790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      if( home_dir==0 ) return 0;
148107790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath);
148117790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      return home_dir;
148127790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
148137790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    home_dir = "c:\\";
148147790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
148157790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#endif
148167790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
148177790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#endif /* !_WIN32_WCE */
148187790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
148197790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if( home_dir ){
14820a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    int n = strlen30(home_dir) + 1;
148217790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    char *z = malloc( n );
148227790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( z ) memcpy(z, home_dir, n);
148237790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    home_dir = z;
148247790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
148257790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
148267790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  return home_dir;
148277790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
148287790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
148297790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
148307790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** Read input from the file given by sqliterc_override.  Or if that
148317790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** parameter is NULL, take input from ~/.sqliterc
14832a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori**
14833a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori** Returns the number of errors.
148347790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
148353fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichstatic void process_sqliterc(
148363fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  ShellState *p,                  /* Configuration data */
148377790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  const char *sqliterc_override   /* Name of config file. NULL to use default */
148387790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project){
148397790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  char *home_dir = NULL;
148407790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  const char *sqliterc = sqliterc_override;
148417790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  char *zBuf = 0;
148427790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  FILE *in = NULL;
148437790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
148447790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if (sqliterc == NULL) {
1484508f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis    home_dir = find_home_dir(0);
148467790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( home_dir==0 ){
1484760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "-- warning: cannot find home directory;"
148483fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich                      " cannot read ~/.sqliterc\n");
148493fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      return;
148507790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
148518fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    sqlite3_initialize();
148528fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
148538fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    sqliterc = zBuf;
148547790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
148557790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  in = fopen(sqliterc,"rb");
148567790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if( in ){
148577790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( stdin_is_interactive ){
1485860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
148597790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
148603fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    process_input(p,in);
148617790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    fclose(in);
148627790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
148638fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  sqlite3_free(zBuf);
148647790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
148657790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
148667790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
148677790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** Show available command line options
148687790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
1486960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidisstatic const char zOptions[] =
148703fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  "   -ascii               set output mode to 'ascii'\n"
148717790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  "   -bail                stop after hitting an error\n"
148727790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  "   -batch               force batch I/O\n"
148737790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  "   -column              set output mode to 'column'\n"
148748fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  "   -cmd COMMAND         run \"COMMAND\" before reading stdin\n"
148757790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  "   -csv                 set output mode to 'csv'\n"
14876c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown  "   -echo                print commands before execution\n"
148778fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  "   -init FILENAME       read/process named file\n"
14878c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown  "   -[no]header          turn headers on or off\n"
148798fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
148808fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  "   -heap SIZE           Size of heap for memsys3 or memsys5\n"
148818fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich#endif
14882c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown  "   -help                show this message\n"
148837790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  "   -html                set output mode to HTML\n"
14884c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown  "   -interactive         force interactive I/O\n"
148857790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  "   -line                set output mode to 'line'\n"
148867790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  "   -list                set output mode to 'list'\n"
148873fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  "   -lookaside SIZE N    use N entries of SZ bytes for lookaside memory\n"
148888fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  "   -mmap N              default mmap size set to N\n"
14889c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown#ifdef SQLITE_ENABLE_MULTIPLEX
14890c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown  "   -multiplex           enable the multiplexor VFS\n"
14891c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown#endif
148923fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  "   -newline SEP         set output row separator. Default: '\\n'\n"
148938fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  "   -nullvalue TEXT      set text string for NULL values. Default ''\n"
148943fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  "   -pagecache SIZE N    use N slots of SZ bytes each for page cache memory\n"
148950181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  "   -quote               set output mode to 'quote'\n"
148963fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  "   -separator SEP       set output column separator. Default: '|'\n"
14897de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori  "   -stats               print memory stats before each finalize\n"
148987790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  "   -version             show SQLite version\n"
1489990ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  "   -vfs NAME            use NAME as the default VFS\n"
1490090ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown#ifdef SQLITE_ENABLE_VFSTRACE
1490190ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  "   -vfstrace            enable tracing of all VFS calls\n"
1490290ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown#endif
149037790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project;
149047790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Projectstatic void usage(int showDetail){
1490560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  utf8_printf(stderr,
1490660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      "Usage: %s [OPTIONS] FILENAME [SQL]\n"
149077790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      "FILENAME is the name of an SQLite database. A new database is created\n"
149087790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      "if the file does not previously exist.\n", Argv0);
149097790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if( showDetail ){
1491060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(stderr, "OPTIONS include:\n%s", zOptions);
149117790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else{
1491260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    raw_printf(stderr, "Use the -help option for additional information\n");
149137790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
149147790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  exit(1);
149157790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
149167790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
149177790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project/*
149187790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project** Initialize the state information in data
149197790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project*/
149203fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichstatic void main_init(ShellState *data) {
149217790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  memset(data, 0, sizeof(*data));
1492260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  data->normalMode = data->cMode = data->mode = MODE_List;
1492360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  data->autoExplain = 1;
149243fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  memcpy(data->colSeparator,SEP_Column, 2);
149253fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  memcpy(data->rowSeparator,SEP_Row, 2);
149267790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  data->showHeader = 0;
149273fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  data->shellFlgs = SHFLG_Lookaside;
1492890ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  sqlite3_config(SQLITE_CONFIG_URI, 1);
14929aae12b8a5af3a1ac77382b067d9ebb350fbd0644Vasu Nori  sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
149303fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
149317790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
149327790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  sqlite3_snprintf(sizeof(continuePrompt), continuePrompt,"   ...> ");
149337790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
149347790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
149358fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich/*
149368fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** Output text to the console in a font that attracts extra attention.
149378fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich*/
149388fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich#ifdef _WIN32
149398fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevichstatic void printBold(const char *zText){
149408fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
149418fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
149428fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
149438fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  SetConsoleTextAttribute(out,
149448fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich         FOREGROUND_RED|FOREGROUND_INTENSITY
149458fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  );
149468fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  printf("%s", zText);
149478fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
149488fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich}
149498fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich#else
149508fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevichstatic void printBold(const char *zText){
149518fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  printf("\033[1m%s\033[0m", zText);
149528fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich}
149538fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich#endif
149548fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
149558fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich/*
149568fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** Get the argument to an --option.  Throw an error and die if no argument
149578fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich** is available.
149588fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich*/
149598fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevichstatic char *cmdline_option_value(int argc, char **argv, int i){
149608fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( i==argc ){
1496160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(stderr, "%s: Error: missing argument to %s\n",
149628fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich            argv[0], argv[argc-1]);
149638fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    exit(1);
149648fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }
149658fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  return argv[i];
149668fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich}
149678fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich
1496860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#ifndef SQLITE_SHELL_IS_UTF8
1496960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#  if (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
1497060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#    define SQLITE_SHELL_IS_UTF8          (0)
1497160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#  else
1497260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#    define SQLITE_SHELL_IS_UTF8          (1)
1497360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#  endif
1497460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#endif
1497560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
1497660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#if SQLITE_SHELL_IS_UTF8
149773fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevichint SQLITE_CDECL main(int argc, char **argv){
1497860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#else
1497960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidisint SQLITE_CDECL wmain(int argc, wchar_t **wargv){
1498060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  char **argv;
1498160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#endif
149827790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  char *zErrMsg = 0;
149833fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  ShellState data;
149847790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  const char *zInitFile = 0;
149857790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  int i;
149867790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  int rc = 0;
149878fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  int warnInmemoryDb = 0;
149883fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  int readStdin = 1;
149893fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  int nCmd = 0;
149903fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  char **azCmd = 0;
149917790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
1499260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  setBinaryMode(stdin, 0);
1499360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
1499460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  stdin_is_interactive = isatty(0);
1499560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  stdout_is_console = isatty(1);
1499660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis
149978fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich#if USE_SYSTEM_SQLITE+0!=1
149980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
1499960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
1500090ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown            sqlite3_sourceid(), SQLITE_SOURCE_ID);
1500190ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    exit(1);
1500290ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  }
150038fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich#endif
150047790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  main_init(&data);
1500560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#if !SQLITE_SHELL_IS_UTF8
1500660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  sqlite3_initialize();
1500760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  argv = sqlite3_malloc64(sizeof(argv[0])*argc);
1500860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  if( argv==0 ){
1500960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    raw_printf(stderr, "out of memory\n");
1501060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    exit(1);
1501160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  }
1501260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  for(i=0; i<argc; i++){
1501360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    argv[i] = sqlite3_win32_unicode_to_utf8(wargv[i]);
1501460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    if( argv[i]==0 ){
1501560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr, "out of memory\n");
1501660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      exit(1);
1501760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }
1501860fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  }
1501960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#endif
1502060fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  assert( argc>=1 && argv && argv[0] );
1502160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  Argv0 = argv[0];
150227790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
150237790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  /* Make sure we have a valid signal handler early, before anything
150247790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  ** else is done.
150257790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  */
150267790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#ifdef SIGINT
150277790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  signal(SIGINT, interrupt_handler);
150280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
150290181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
150307790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#endif
150317790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
150323fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#ifdef SQLITE_SHELL_DBNAME_PROC
150333fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  {
150343fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name
150353fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    ** of a C-function that will provide the name of the database file.  Use
150363fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    ** this compile-time option to embed this shell program in larger
150373fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    ** applications. */
150383fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    extern void SQLITE_SHELL_DBNAME_PROC(const char**);
150393fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    SQLITE_SHELL_DBNAME_PROC(&data.zDbFilename);
150403fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    warnInmemoryDb = 0;
150413fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  }
150423fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich#endif
150433fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich
150447790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  /* Do an initial pass through the command-line argument to locate
150457790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  ** the name of the database file, the name of the initialization file,
1504690ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown  ** the size of the alternative malloc heap,
150477790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  ** and the first command to execute.
150487790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  */
150498fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  for(i=1; i<argc; i++){
150507790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    char *z;
150517790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    z = argv[i];
150528fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( z[0]!='-' ){
150538fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      if( data.zDbFilename==0 ){
150548fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        data.zDbFilename = z;
150553fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      }else{
150563fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        /* Excesss arguments are interpreted as SQL (or dot-commands) and
150573fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        ** mean that nothing is read from stdin */
150583fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        readStdin = 0;
150593fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        nCmd++;
150603fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
150613fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        if( azCmd==0 ){
1506260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          raw_printf(stderr, "out of memory\n");
150633fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich          exit(1);
150643fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        }
150653fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        azCmd[nCmd-1] = z;
150668fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }
150678fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }
15068c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown    if( z[1]=='-' ) z++;
15069c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown    if( strcmp(z,"-separator")==0
15070c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown     || strcmp(z,"-nullvalue")==0
150719bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown     || strcmp(z,"-newline")==0
15072c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown     || strcmp(z,"-cmd")==0
15073c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown    ){
150748fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      (void)cmdline_option_value(argc, argv, ++i);
15075c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown    }else if( strcmp(z,"-init")==0 ){
150768fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      zInitFile = cmdline_option_value(argc, argv, ++i);
15077c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown    }else if( strcmp(z,"-batch")==0 ){
150788fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      /* Need to check for batch mode here to so we can avoid printing
1507960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      ** informational messages (like from process_sqliterc) before
150808fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      ** we do the actual processing of arguments later in a second pass.
150818fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      */
15082a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      stdin_is_interactive = 0;
15083c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown    }else if( strcmp(z,"-heap")==0 ){
1508490ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
1508590ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      const char *zSize;
1508690ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      sqlite3_int64 szHeap;
1508790ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown
150888fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      zSize = cmdline_option_value(argc, argv, ++i);
150898fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      szHeap = integerValue(zSize);
1509090ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
1509190ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
1509274bd39cb46f3e9465fe069b650f40ffd8298a538Alex Naidis#else
1509374bd39cb46f3e9465fe069b650f40ffd8298a538Alex Naidis      (void)cmdline_option_value(argc, argv, ++i);
1509490ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown#endif
150953fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    }else if( strcmp(z,"-pagecache")==0 ){
150963fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      int n, sz;
150973fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
150983fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      if( sz>70000 ) sz = 70000;
1509960fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      if( sz<0 ) sz = 0;
151003fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      n = (int)integerValue(cmdline_option_value(argc,argv,++i));
1510160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      sqlite3_config(SQLITE_CONFIG_PAGECACHE,
1510260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis                    (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
151033fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      data.shellFlgs |= SHFLG_Pagecache;
151043fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    }else if( strcmp(z,"-lookaside")==0 ){
151053fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      int n, sz;
151063fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
151073fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      if( sz<0 ) sz = 0;
151083fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      n = (int)integerValue(cmdline_option_value(argc,argv,++i));
151093fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      if( n<0 ) n = 0;
151103fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n);
151113fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside;
1511290ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown#ifdef SQLITE_ENABLE_VFSTRACE
15113c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown    }else if( strcmp(z,"-vfstrace")==0 ){
1511490ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      extern int vfstrace_register(
1511590ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown         const char *zTraceName,
1511690ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown         const char *zOldVfsName,
1511790ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown         int (*xOut)(const char*,void*),
1511890ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown         void *pOutArg,
1511990ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown         int makeDefault
1512090ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      );
1512190ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
1512290ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown#endif
1512390ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown#ifdef SQLITE_ENABLE_MULTIPLEX
15124c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown    }else if( strcmp(z,"-multiplex")==0 ){
1512590ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      extern int sqlite3_multiple_initialize(const char*,int);
1512690ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      sqlite3_multiplex_initialize(0, 1);
1512790ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown#endif
151288fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }else if( strcmp(z,"-mmap")==0 ){
151298fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
151308fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz);
15131c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown    }else if( strcmp(z,"-vfs")==0 ){
151328fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      sqlite3_vfs *pVfs = sqlite3_vfs_find(cmdline_option_value(argc,argv,++i));
1513390ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      if( pVfs ){
1513490ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown        sqlite3_vfs_register(pVfs, 1);
1513590ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      }else{
1513660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis        utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);
1513790ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown        exit(1);
1513890ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      }
151390181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifdef SQLITE_HAVE_ZIP
151400181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else if( strcmp(z,"-zip")==0 ){
151410181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      data.openMode = SHELL_OPEN_ZIPFILE;
151420181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
151430181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else if( strcmp(z,"-append")==0 ){
151440181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      data.openMode = SHELL_OPEN_APPENDVFS;
151457790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
151467790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
151478fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  if( data.zDbFilename==0 ){
151487790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#ifndef SQLITE_OMIT_MEMORYDB
151497790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    data.zDbFilename = ":memory:";
151508fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    warnInmemoryDb = argc==1;
151517790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#else
1515260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
15153a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori    return 1;
151547790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project#endif
151558fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  }
151568fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  data.out = stdout;
151570181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  sqlite3_appendvfs_init(0,0,0);
151587790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
151597790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  /* Go ahead and open the database file if it already exists.  If the
151607790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  ** file does not exist, delay opening it.  This prevents empty database
151617790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  ** files from being created if a user mistypes the database name argument
151627790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  ** to the sqlite command-line tool.
151637790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  */
151647790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  if( access(data.zDbFilename, 0)==0 ){
151658fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    open_db(&data, 0);
151667790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
151677790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
151687790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  /* Process the initialization file if there is one.  If no -init option
151697790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  ** is given on the command line, look for a file named ~/.sqliterc and
151707790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  ** try to process it.
151717790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  */
151723fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  process_sqliterc(&data,zInitFile);
151737790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
151747790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  /* Make a second pass through the command-line argument and set
151757790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  ** options.  This second pass is delayed until after the initialization
151767790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  ** file is processed so that the command-line arguments will override
151777790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  ** settings in the initialization file.
151787790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  */
151798fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich  for(i=1; i<argc; i++){
151807790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    char *z = argv[i];
151818fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    if( z[0]!='-' ) continue;
151827790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( z[1]=='-' ){ z++; }
151837790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( strcmp(z,"-init")==0 ){
151847790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      i++;
151857790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else if( strcmp(z,"-html")==0 ){
151867790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      data.mode = MODE_Html;
151877790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else if( strcmp(z,"-list")==0 ){
151887790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      data.mode = MODE_List;
151890181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else if( strcmp(z,"-quote")==0 ){
151900181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      data.mode = MODE_Quote;
151917790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else if( strcmp(z,"-line")==0 ){
151927790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      data.mode = MODE_Line;
151937790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else if( strcmp(z,"-column")==0 ){
151947790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      data.mode = MODE_Column;
151957790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else if( strcmp(z,"-csv")==0 ){
151967790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      data.mode = MODE_Csv;
151973fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      memcpy(data.colSeparator,",",2);
151980181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#ifdef SQLITE_HAVE_ZIP
151990181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else if( strcmp(z,"-zip")==0 ){
152000181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      data.openMode = SHELL_OPEN_ZIPFILE;
152010181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
152020181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov    }else if( strcmp(z,"-append")==0 ){
152030181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      data.openMode = SHELL_OPEN_APPENDVFS;
152043fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    }else if( strcmp(z,"-ascii")==0 ){
152053fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      data.mode = MODE_Ascii;
152063fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
152073fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich                       SEP_Unit);
152083fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
152093fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich                       SEP_Record);
152107790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else if( strcmp(z,"-separator")==0 ){
152113fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
152128fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich                       "%s",cmdline_option_value(argc,argv,++i));
152139bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown    }else if( strcmp(z,"-newline")==0 ){
152143fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
152159bee60b0fc0b60d4ae9e7533e0e6b7beca5f37fcJeff Brown                       "%s",cmdline_option_value(argc,argv,++i));
152167790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else if( strcmp(z,"-nullvalue")==0 ){
152173fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      sqlite3_snprintf(sizeof(data.nullValue), data.nullValue,
152188fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich                       "%s",cmdline_option_value(argc,argv,++i));
152197790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else if( strcmp(z,"-header")==0 ){
152207790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      data.showHeader = 1;
152217790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else if( strcmp(z,"-noheader")==0 ){
152227790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      data.showHeader = 0;
152237790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else if( strcmp(z,"-echo")==0 ){
15224b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      ShellSetFlag(&data, SHFLG_Echo);
152258fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }else if( strcmp(z,"-eqp")==0 ){
152260181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      data.autoEQP = AUTOEQP_on;
1522760fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    }else if( strcmp(z,"-eqpfull")==0 ){
152280181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      data.autoEQP = AUTOEQP_full;
15229de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori    }else if( strcmp(z,"-stats")==0 ){
15230de2b3240539802d409a25760d5cec9d4ebfd6686Vasu Nori      data.statsOn = 1;
152313fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    }else if( strcmp(z,"-scanstats")==0 ){
152323fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      data.scanstatsOn = 1;
152333a6c79f802fabdb94367177310663397420e319fNick Kralevich    }else if( strcmp(z,"-backslash")==0 ){
152343a6c79f802fabdb94367177310663397420e319fNick Kralevich      /* Undocumented command-line option: -backslash
152353a6c79f802fabdb94367177310663397420e319fNick Kralevich      ** Causes C-style backslash escapes to be evaluated in SQL statements
152363a6c79f802fabdb94367177310663397420e319fNick Kralevich      ** prior to sending the SQL into SQLite.  Useful for injecting
152373a6c79f802fabdb94367177310663397420e319fNick Kralevich      ** crazy bytes in the middle of SQL statements for testing and debugging.
152383a6c79f802fabdb94367177310663397420e319fNick Kralevich      */
15239b86c0cf2300ba27af03e33f64a4c73be84a4c8a2Alex Naidis      ShellSetFlag(&data, SHFLG_Backslash);
152407790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else if( strcmp(z,"-bail")==0 ){
152417790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      bail_on_error = 1;
152427790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else if( strcmp(z,"-version")==0 ){
1524390ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
152447790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      return 0;
152457790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else if( strcmp(z,"-interactive")==0 ){
152467790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      stdin_is_interactive = 1;
152477790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else if( strcmp(z,"-batch")==0 ){
152487790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      stdin_is_interactive = 0;
1524990ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    }else if( strcmp(z,"-heap")==0 ){
1525090ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      i++;
152513fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    }else if( strcmp(z,"-pagecache")==0 ){
152523fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      i+=2;
152533fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    }else if( strcmp(z,"-lookaside")==0 ){
152543fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      i+=2;
152558fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich    }else if( strcmp(z,"-mmap")==0 ){
152568fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      i++;
1525790ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    }else if( strcmp(z,"-vfs")==0 ){
1525890ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      i++;
1525990ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown#ifdef SQLITE_ENABLE_VFSTRACE
1526090ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    }else if( strcmp(z,"-vfstrace")==0 ){
1526190ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      i++;
1526290ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown#endif
1526390ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown#ifdef SQLITE_ENABLE_MULTIPLEX
1526490ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    }else if( strcmp(z,"-multiplex")==0 ){
1526590ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown      i++;
1526690ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown#endif
15267c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown    }else if( strcmp(z,"-help")==0 ){
152687790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      usage(1);
15269c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown    }else if( strcmp(z,"-cmd")==0 ){
152703fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      /* Run commands that follow -cmd first and separately from commands
152713fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      ** that simply appear on the command-line.  This seems goofy.  It would
152723fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      ** be better if all commands ran in the order that they appear.  But
152733fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      ** we retain the goofy behavior for historical compatibility. */
15274c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown      if( i==argc-1 ) break;
152758fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      z = cmdline_option_value(argc,argv,++i);
15276c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown      if( z[0]=='.' ){
15277c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown        rc = do_meta_command(z, &data);
152788fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        if( rc && bail_on_error ) return rc==2 ? 0 : rc;
15279c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown      }else{
152808fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        open_db(&data, 0);
15281c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown        rc = shell_exec(data.db, z, shell_callback, &data, &zErrMsg);
15282c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown        if( zErrMsg!=0 ){
1528360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          utf8_printf(stderr,"Error: %s\n", zErrMsg);
15284c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown          if( bail_on_error ) return rc!=0 ? rc : 1;
15285c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown        }else if( rc!=0 ){
1528660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
15287c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown          if( bail_on_error ) return rc;
15288c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown        }
15289c82acac4e67711e8d9289b572d334298aeb5d806Jeff Brown      }
152907790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else{
1529160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
1529260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis      raw_printf(stderr,"Use -help for a list of options.\n");
152937790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      return 1;
152947790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
1529560fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    data.cMode = data.mode;
152967790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
152977790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project
152983fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich  if( !readStdin ){
152993fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    /* Run all arguments that do not begin with '-' as if they were separate
153003fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    ** command-line inputs, except for the argToSkip argument which contains
153013fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    ** the database filename.
153027790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    */
153033fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    for(i=0; i<nCmd; i++){
153043fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      if( azCmd[i][0]=='.' ){
153053fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        rc = do_meta_command(azCmd[i], &data);
153063fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        if( rc ) return rc==2 ? 0 : rc;
153073fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich      }else{
153083fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        open_db(&data, 0);
153093fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        rc = shell_exec(data.db, azCmd[i], shell_callback, &data, &zErrMsg);
153103fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        if( zErrMsg!=0 ){
1531160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          utf8_printf(stderr,"Error: %s\n", zErrMsg);
153123fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich          return rc!=0 ? rc : 1;
153133fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        }else if( rc!=0 ){
1531460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis          utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
153153fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich          return rc;
153163fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        }
153177790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
153187790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
153193fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich    free(azCmd);
153207790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }else{
153217790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    /* Run commands received from standard input
153227790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    */
153237790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    if( stdin_is_interactive ){
153247790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      char *zHome;
153257790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      char *zHistory = 0;
153267790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      int nHistory;
153277790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      printf(
1532890ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown        "SQLite version %s %.19s\n" /*extra-version-info*/
153298fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        "Enter \".help\" for usage hints.\n",
1533090ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown        sqlite3_libversion(), sqlite3_sourceid()
153317790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      );
153328fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      if( warnInmemoryDb ){
153338fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        printf("Connected to a ");
153348fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        printBold("transient in-memory database");
153358fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich        printf(".\nUse \".open FILENAME\" to reopen on a "
153368fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich               "persistent database.\n");
153378fecf56c625b5691ee3381e107ccbe1ff42398b1Nick Kralevich      }
1533808f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis      zHome = find_home_dir(0);
15339a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori      if( zHome ){
15340a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori        nHistory = strlen30(zHome) + 20;
15341a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori        if( (zHistory = malloc(nHistory))!=0 ){
15342a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori          sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
15343a4356a0ea71404ae414a07eafd7b95b91cc88c8cVasu Nori        }
153447790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
15345253ed64ded244ef3d8a7226efb812e7989bc8026Nick Kralevich      if( zHistory ){ shell_read_history(zHistory); }
153460181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#if HAVE_READLINE || HAVE_EDITLINE
153470181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      rl_attempted_completion_function = readline_completion;
153480181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#elif HAVE_LINENOISE
153490181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov      linenoiseSetCompletionCallback(linenoise_completion);
153500181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov#endif
153517790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      rc = process_input(&data, 0);
153527790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      if( zHistory ){
153530181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov        shell_stifle_history(2000);
153543fcd43a0f1ef02756029e12af3cb9ba9faa13364Nick Kralevich        shell_write_history(zHistory);
153557790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project        free(zHistory);
153567790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      }
153577790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }else{
153587790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project      rc = process_input(&data, stdin);
153597790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project    }
153607790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
153617790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  set_table_name(&data, 0);
1536271504cf29d6d55df7d2aac17ecb160f7e5470553Vasu Nori  if( data.db ){
1536360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis    session_close_all(&data);
1536490ed05d921d6ed7f12012d9786d53f57fafee51aJeff Brown    sqlite3_close(data.db);
153657790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  }
1536660fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  sqlite3_free(data.zFreeOnClose);
1536708f78cbf3cb8295a3b9e0be36b6778051ba4add6Alex Naidis  find_home_dir(1);
153680181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  output_reset(&data);
153690181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  data.doXdgOpen = 0;
153700181ec2d7e84e3aa37130674021fb0b822732c7cFyodor Kupolov  clearTempFile(&data);
1537160fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#if !SQLITE_SHELL_IS_UTF8
1537260fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  for(i=0; i<argc; i++) sqlite3_free(argv[i]);
1537360fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis  sqlite3_free(argv);
1537460fa6fd5623cb0939ef089b799adeb068389218fAlex Naidis#endif
153757790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project  return rc;
153767790ef5367fe6731048c3e3a1c067f94b321cb4dThe Android Open Source Project}
15377