#ifndef SQLITE3SHX_H
#define SQLITE3SHX_H
#include "sqlite3ext.h"
#include "obj_interfaces.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Convey data to, from and/or between I/O handlers and meta-commands. */
typedef struct {
/* A semi-transient holder of arbitrary data used during operations
* not interrupted by meta-command invocations. Any not-null pointer
* left after a meta-command has completed is, by contract, to be
* freeable using sqlite3_free(). It is otherwise unconstrained.
*/
void *pvHandlerData;
/* The user's currently open and primary DB connection */
sqlite3 *db;
/* The DB connection used for shell's dynamical data */
sqlite3 *dbShell;
/* Output stream to which shell's text output to be written */
FILE *pCurrentOutputStream;
/* Number of lines written during a query result output */
int resultCount;
/* Whether to exit as command completes.
* 0 => no exit
* ~0 => a non-error (0) exit
* other => exit with process exit code other
* For embedded shell, "exit" means "return from REPL".
*/
int shellExit;
/* Whether to show column names for certain output modes */
int showHeader;
/* Column separator character for some modes */
char *zFieldSeparator;
/* Row separator character for some modes (MODE_Ascii) */
char *zRecordSeparator;
/* Row set prefix for some modes */
char *zRecordLead;
/* Row set suffix for some modes */
char *zRecordTrail;
/* Text to represent a NULL in external data formats */
char *zNullValue;
/* Number of column widths presently desired or tracked */
int numWidths; /* known allocation count of next 2 members */
/* The column widths last specified via .width command */
int *pWantWidths;
/* The column widths last observed in query results */
int *pHaveWidths;
} ShellExState;
/* The shell's state, shared among meta-command implementations.
* The ShellStateX object includes a private partition whose content
* and usage are opaque to shell extensions compiled separately
* from the shell.c core. (As defined here, it is wholly opaque.)
*/
typedef struct ShellStateX {
ShellExState sxs; /* sizeof(ShellExState) will never shrink. */
struct ShellState *pSS; /* The offset of this member is NOT STABLE. */
} ShellStateX;
/* This function pointer has the same signature as the sqlite3_X_init()
* function that is called as SQLite3 completes loading an extension.
*/
typedef int (*ExtensionId)
(sqlite3 *, char **, const struct sqlite3_api_routines *);
/*****************
* See "Shell Extensions, Programming" for purposes and usage of the following
* interfaces supporting extended meta-commands and import and output modes.
*/
/* An object implementing below interface is registered with the
* shell to make new or overriding meta-commands available to it.
*/
INTERFACE_BEGIN( MetaCommand );
PURE_VMETHOD(const char *, name, MetaCommand, 0,());
PURE_VMETHOD(const char *, help, MetaCommand, 1,(int more));
PURE_VMETHOD(struct {unsigned minArgs; unsigned maxArgs;},
argsRange, MetaCommand, 0,());
PURE_VMETHOD(int, execute, MetaCommand,
4,(ShellStateX *, char **pzErrMsg, int nArgs, char *azArgs[]));
INTERFACE_END( MetaCommand );
/* Define error codes to be returned either by a meta-command during
* its own checking or by the dispatcher for bad argument counts.
*/
#define SHELL_INVALID_ARGS SQLITE_MISUSE
#define SHELL_FORBIDDEN_OP 0x7ffe /* Action disallowed under --safe.*/
/* An object implementing below interface is registered with the
* shell to make new or overriding output modes available to it.
*/
INTERFACE_BEGIN( OutModeHandler );
PURE_VMETHOD(const char *, name, OutModeHandler, 0,());
PURE_VMETHOD(const char *, help, OutModeHandler, 1,(int more));
PURE_VMETHOD(int, openResultsOutStream, OutModeHandler,
5,( ShellExState *pSES, char **pzErr,
int numArgs, char *azArgs[], const char * zName ));
PURE_VMETHOD(int, prependResultsOut, OutModeHandler,
3,( ShellExState *pSES, char **pzErr, sqlite3_stmt *pStmt ));
PURE_VMETHOD(int, rowResultsOut, OutModeHandler,
3,( ShellExState *pSES, char **pzErr, sqlite3_stmt *pStmt ));
PURE_VMETHOD(int, appendResultsOut, OutModeHandler,
3,( ShellExState *pSES, char **pzErr, sqlite3_stmt *pStmt ));
PURE_VMETHOD(void, closeResultsOutStream, OutModeHandler,
2,( ShellExState *pSES, char **pzErr ));
INTERFACE_END( OutModeHandlerVtable );
/* An object implementing below interface is registered with the
* shell to make new or overriding data importers available to it.
*/
INTERFACE_BEGIN( ImportHandler );
PURE_VMETHOD(const char *, name, ImportHandler, 0,());
PURE_VMETHOD(const char *, help, ImportHandler, 1,( int more ));
PURE_VMETHOD(int, openDataInStream, ImportHandler,
5,( ShellExState *pSES, char **pzErr,
int numArgs, char *azArgs[], const char * zName ));
PURE_VMETHOD(int, prepareDataInput, ImportHandler,
3,( ShellExState *pSES, char **pzErr, sqlite3_stmt * *ppStmt ));
PURE_VMETHOD(int, rowDataInput, ImportHandler,
3,( ShellExState *pSES, char **pzErr, sqlite3_stmt *pStmt ));
PURE_VMETHOD(int, finishDataInput, ImportHandler,
3,( ShellExState *pSES, char **pzErr, sqlite3_stmt *pStmt ));
PURE_VMETHOD(void, closeDataInStream, ImportHandler,
2,( ShellExState *pSES, char **pzErr ));
INTERFACE_END( ImportHandlerVtable );
typedef struct {
int helperCount;
union ExtHelp {
struct {
void (*failIfSafeMode)(ShellStateX *p, const char *zErrMsg, ...);
} named ;
void (*nameless[2])(); /* Same as named but anonymous plus a sentinel. */
} helpers;
} ExtensionHelpers;
#define SHELLEXT_VALIDITY_MARK "ExtensibleShell"
typedef struct ShellExtensionLink {
char validityMark[16]; /* Preset to contain "ExtensibleShell\x00" */
char *zErrMsg; /* Extension puts error message here if any. */
int sizeOfThis; /* sizeof(struct ShellExtensionLink) */
const char *shellVersion; /* Preset to "3.??.??\x00" or similar */
/* An init "out" parameter, used as the loaded extension ID. Unless
* this is set within sqlite3_X_init() prior to register*() calls,
* the extension cannot be unloaded.
*/
ExtensionId eid;
/* Another init "out" parameter, a destructor for extension overall.
* Set to 0 on input and may be left so if no destructor is needed.
*/
void (*extensionDestruct)(void *);
/* Various shell extension helpers and feature registration functions
*/
ExtensionHelpers * pExtHelp;
union ShellExtensionAPI {
struct ShExtAPI {
/* Register a meta-command */
int (*registerMetaCommand)(ExtensionId eid, MetaCommand *pMC);
/* Register an output data display (or other disposition) mode */
int (*registerOutMode)(ExtensionId eid, OutModeHandler *pOMH);
/* Register an import variation from (various sources) for .import */
int (*registerImporter)(ExtensionId eid, ImportHandler *pIH);
/* Preset to 0 at extension load, a sentinel for expansion */
void (*pExtra)(void);
} named;
void (*pFunctions[4])(); /* 0-terminated sequence of function pointers */
} api;
} ShellExtensionLink;
/* Test whether a char ** references a ShellExtensionLink instance's
* validityMark, and if so return the instance's address, else return 0.
* This macro may be used by a shell extension's sqlite3_X_init() function
* to obtain a pointer to the ShellExtensionLink struct, derived from the
* error message pointer (pzErrMsg) passed as the 2nd argument. This enables
* the extension to incorporate its features into a running shell process.
*/
#define EXTENSION_LINKAGE_PTR(pzem) ( \
pzem != 0 && *pzem != 0 && strcmp(*pzem, SHELLEXT_VALIDITY_MARK) == 0 \
&& *pzem == (char *)pzem \
+ offsetof(ShellExtensionLink, validityMark) \
- offsetof(ShellExtensionLink, zErrMsg) ) \
? (ShellExtensionLink *) \
((char *)pzem-offsetof(ShellExtensionLink,zErrMsg)) \
: 0
/* String used with SQLite "Pointer Passing Interfaces" as a type marker.
* That API subset is used by the shell to pass its extension API to the
* sqlite3_X_init() function of extensions, via the DB parameter.
*/
#define SHELLEXT_API_POINTERS "shellext_api_pointers"
/* Pre-write a function to retrieve a ShellExtensionLink pointer from the
* shell's DB. This is an alternative to use of the EXTENSION_LINKAGE_PTR
* macro above. It takes some more code, replicated across extensions.
*/
#define DEFINE_SHDB_TO_SHEXT_API(func_name) \
static ShellExtensionLink * func_name(sqlite3 * db){ \
ShellExtensionLink *rv = 0; sqlite3_stmt *pStmt = 0; \
if( SQLITE_OK==sqlite3_prepare(db,"SELECT shext_pointer(0)",-1,&pStmt,0) \
&& SQLITE_ROW == sqlite3_step(pStmt) ) \
rv = (ShellExtensionLink *)sqlite3_value_pointer \
(sqlite3_column_value(pStmt, 0), SHELLEXT_API_POINTERS); \
sqlite3_finalize(pStmt); return rv; \
}
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* !defined(SQLITE3SHX_H) */