numerous fixes
This commit is contained in:
parent
8f5855b6b6
commit
bdd732cef7
23 changed files with 305 additions and 158 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -8,4 +8,4 @@ dist/config.hin
|
||||||
dist/configure
|
dist/configure
|
||||||
src/py/setup.py
|
src/py/setup.py
|
||||||
test/scr050/Makefile
|
test/scr050/Makefile
|
||||||
|
result-bin
|
||||||
|
|
2
README
2
README
|
@ -1,4 +1,4 @@
|
||||||
DBSQL 0.3.1: (October 19, 2023)
|
DBSQL 0.3.1: (October 21, 2023)
|
||||||
|
|
||||||
This is version 0.3.1 of DBSQL.
|
This is version 0.3.1 of DBSQL.
|
||||||
|
|
||||||
|
|
17
dist/Makefile.in
vendored
17
dist/Makefile.in
vendored
|
@ -125,8 +125,8 @@ C_FILES=\
|
||||||
$(srcdir)/os/os_jtime.c $(srcdir)/clib/memcmp.c \
|
$(srcdir)/os/os_jtime.c $(srcdir)/clib/memcmp.c \
|
||||||
$(srcdir)/clib/strcasecmp.c $(srcdir)/os/dbsql_alloc.c \
|
$(srcdir)/clib/strcasecmp.c $(srcdir)/os/dbsql_alloc.c \
|
||||||
$(srcdir)/common/str.c $(srcdir)/common/dbsql_atoi.c \
|
$(srcdir)/common/str.c $(srcdir)/common/dbsql_atoi.c \
|
||||||
$(srcdir)/common/dbsql_atof.c $(srcdir)/safety.c \
|
$(srcdir)/common/dbsql_atof.c $(srcdir)/common/dbsql_fop.c \
|
||||||
$(srcdir)/clib/strdup.c
|
$(srcdir)/safety.c $(srcdir)/clib/strdup.c
|
||||||
|
|
||||||
##################################################
|
##################################################
|
||||||
# Object and utility lists.
|
# Object and utility lists.
|
||||||
|
@ -137,9 +137,10 @@ C_OBJS= cg_attach@o@ cg_insert@o@ sql_tokenize@o@ cg_auth@o@ \
|
||||||
cg_pragma@o@ cg_where@o@ cg_trigger@o@ cg_build@o@ \
|
cg_pragma@o@ cg_where@o@ cg_trigger@o@ cg_build@o@ \
|
||||||
sql_fns@o@ random@o@ cg_update@o@ cg_delete@o@ hash@o@ \
|
sql_fns@o@ random@o@ cg_update@o@ cg_delete@o@ hash@o@ \
|
||||||
cg_expr@o@ opcodes@o@ sql_parser@o@ cg_vacuum@o@ \
|
cg_expr@o@ opcodes@o@ sql_parser@o@ cg_vacuum@o@ \
|
||||||
vdbe@o@ vdbe_method@o@ sm@o@ snprintf@o@ dbsql_err@o@ cg_select@o@ \
|
vdbe@o@ vdbe_method@o@ sm@o@ snprintf@o@ dbsql_err@o@ \
|
||||||
os_jtime@o@ memcmp@o@ dbsql_atof@o@ safety@o@ dbsql_atoi@o@ \
|
dbsql_fop@o@ cg_select@o@ os_jtime@o@ memcmp@o@ \
|
||||||
strcasecmp@o@ strdup@o@ dbsql_alloc@o@ str@o@
|
dbsql_atof@o@ safety@o@ dbsql_atoi@o@ strcasecmp@o@ \
|
||||||
|
strdup@o@ dbsql_alloc@o@ str@o@
|
||||||
|
|
||||||
LEMON_OBJS=\
|
LEMON_OBJS=\
|
||||||
lemon@o@
|
lemon@o@
|
||||||
|
@ -187,12 +188,12 @@ $(libdbsql): $(DEF_LIB)
|
||||||
$(ln) -s $(libdbsql_version) $@)
|
$(ln) -s $(libdbsql_version) $@)
|
||||||
|
|
||||||
# Real static C library.
|
# Real static C library.
|
||||||
$(libdbsql_version): dbsql_int.h sql_parser.h opcodes.h $(C_OBJS)
|
$(libdbsql_version): dbsql_int.h db_int.h sql_parser.h opcodes.h $(C_OBJS)
|
||||||
$(ar) cr $@ $(C_OBJS)
|
$(ar) cr $@ $(C_OBJS)
|
||||||
test ! -f $(ranlib) || $(ranlib) $@
|
test ! -f $(ranlib) || $(ranlib) $@
|
||||||
|
|
||||||
# Shared C library.
|
# Shared C library.
|
||||||
$(libso_target): dbsql_int.h sql_parser.h opcodes.h $(C_OBJS)
|
$(libso_target): dbsql_int.h db_int.h sql_parser.h opcodes.h $(C_OBJS)
|
||||||
$(SOLINK) $(SOFLAGS) $(LDFLAGS) -o $@ $(C_OBJS) $(LIBSO_LIBS)
|
$(SOLINK) $(SOFLAGS) $(LDFLAGS) -o $@ $(C_OBJS) $(LIBSO_LIBS)
|
||||||
|
|
||||||
##################################################
|
##################################################
|
||||||
|
@ -396,6 +397,8 @@ dbsql_atoi@o@: $(srcdir)/common/dbsql_atoi.c
|
||||||
$(CC) $(CFLAGS) $?
|
$(CC) $(CFLAGS) $?
|
||||||
dbsql_err@o@: $(srcdir)/common/dbsql_err.c
|
dbsql_err@o@: $(srcdir)/common/dbsql_err.c
|
||||||
$(CC) $(CFLAGS) $?
|
$(CC) $(CFLAGS) $?
|
||||||
|
dbsql_fop@o@: $(srcdir)/common/dbsql_fop.c
|
||||||
|
$(CC) $(CFLAGS) $?
|
||||||
str@o@: $(srcdir)/common/str.c
|
str@o@: $(srcdir)/common/str.c
|
||||||
$(CC) $(CFLAGS) $?
|
$(CC) $(CFLAGS) $?
|
||||||
hash@o@: $(srcdir)/common/hash.c
|
hash@o@: $(srcdir)/common/hash.c
|
||||||
|
|
20
dist/sqlconf
vendored
20
dist/sqlconf
vendored
|
@ -28,10 +28,19 @@ args="--enable-test $args"
|
||||||
args="--enable-tcl $args"
|
args="--enable-tcl $args"
|
||||||
#args="--enable-sqlite-compat $args"
|
#args="--enable-sqlite-compat $args"
|
||||||
args="--enable-soundex-sqlfn $args"
|
args="--enable-soundex-sqlfn $args"
|
||||||
args="--with-tcl=/nix/store/aqlscqccxp85w5zxrcmim7qf1i88xyli-tcl-8.5.19/lib $args"
|
#args="--with-tcl=/usr/lib/tcl-8.5.19/lib $args"
|
||||||
args="--with-berkeleydb=/nix/store/mlhib3c2ra8bj36vhxmwqhyxph8a8sgf-db-4.8.30 $args"
|
#args="--with-berkeleydb=/usr/local/db-4.8.30 $args"
|
||||||
#args="--with-db-uniquename=FOO $args"
|
#args="--with-db-uniquename=FOO $args"
|
||||||
#args="LD_TWOLEVEL_NAMESPACE=1 LIBTSO_LIBS=-ltcl8.4 $args" # Mac OS/X
|
|
||||||
|
# Mac OS/X enable:
|
||||||
|
#args="LD_TWOLEVEL_NAMESPACE=1 LIBTSO_LIBS=-ltcl8.4 $args"
|
||||||
|
|
||||||
|
# On NixOS enable:
|
||||||
|
CFLAGS=${NIX_CFLAGS_COMPILE}
|
||||||
|
LDLAGS=${NIX_LDFLAGS}
|
||||||
|
#args="--with-berkeleydb=$(pkg-config --variable=prefix db) $args"
|
||||||
|
args="--with-berkeleydb=/nix/store/mlhib3c2ra8bj36vhxmwqhyxph8a8sgf-db-4.8.30 $args"
|
||||||
|
args="--with-tcl=$(pkg-config --variable=libdir tcl) $args"
|
||||||
|
|
||||||
echo "env $cppflags $ldflags $libs ../dist/configure $args"
|
echo "env $cppflags $ldflags $libs ../dist/configure $args"
|
||||||
env $cppflags $ldflags $libs sh ../dist/configure -C $args
|
env $cppflags $ldflags $libs sh ../dist/configure -C $args
|
||||||
|
@ -57,3 +66,8 @@ rm -f tags
|
||||||
ln -s ../dist/tags tags
|
ln -s ../dist/tags tags
|
||||||
mkdir -p .libs && true
|
mkdir -p .libs && true
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
nix-build -E 'with import <nixpkgs> {}; enableDebugging db4'
|
||||||
|
gdb -ix .gdbinit --tui build_unix/.libs/dbsql
|
||||||
|
r --init ../tests/smoke.sql /tmp/dbsql
|
||||||
|
|
|
@ -49,6 +49,12 @@
|
||||||
configureFlags = [
|
configureFlags = [
|
||||||
"--host ${system}"
|
"--host ${system}"
|
||||||
];
|
];
|
||||||
|
buildInputs = [
|
||||||
|
(enableDebuging db4)
|
||||||
|
glibc.out
|
||||||
|
glibc.static
|
||||||
|
tcl-8_5
|
||||||
|
];
|
||||||
nativeBuildInputs = [ autoreconfHook ];
|
nativeBuildInputs = [ autoreconfHook ];
|
||||||
meta = {
|
meta = {
|
||||||
changelog = "https://git.burd.me/greg/dbsql/raw/branch/main/ChangeLog";
|
changelog = "https://git.burd.me/greg/dbsql/raw/branch/main/ChangeLog";
|
||||||
|
|
|
@ -1,25 +1,26 @@
|
||||||
{ pkgs ? import <nixpkgs> {} }:
|
{ pkgs ? import <nixpkgs> {} }:
|
||||||
|
|
||||||
pkgs.mkShell {
|
pkgs.mkShell {
|
||||||
# nativeBuildInputs is usually what you want -- tools you need to run
|
|
||||||
nativeBuildInputs = with pkgs.buildPackages; [
|
nativeBuildInputs = with pkgs.buildPackages; [
|
||||||
act
|
act
|
||||||
autoconf
|
autoconf
|
||||||
db4
|
|
||||||
ed
|
ed
|
||||||
gcc
|
gcc
|
||||||
gdb
|
gdb
|
||||||
gettext
|
gettext
|
||||||
libtool
|
libtool
|
||||||
m4
|
m4
|
||||||
|
pkg-config
|
||||||
perl
|
perl
|
||||||
ripgrep
|
ripgrep
|
||||||
tcl-8_5
|
|
||||||
];
|
];
|
||||||
|
|
||||||
buildInputs = with pkgs; [
|
buildInputs = with pkgs; [
|
||||||
|
# (enableDebuging db4)
|
||||||
|
db4
|
||||||
glibc.out
|
glibc.out
|
||||||
glibc.static
|
glibc.static
|
||||||
|
tcl-8_5
|
||||||
];
|
];
|
||||||
|
|
||||||
DOCKER_BUILDKIT = 1;
|
DOCKER_BUILDKIT = 1;
|
||||||
|
|
|
@ -1360,20 +1360,21 @@ dbsql_create_env(dbpp, dir, crypt, mode, flags)
|
||||||
return DBSQL_CANTOPEN;
|
return DBSQL_CANTOPEN;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (__os_exists(dbenv, dir, &dir_p) == 0) {
|
if (__dbsql_exists(NULL, dir, &dir_p) == 0) {
|
||||||
if (dir_p) {
|
if (dir_p) {
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
snprintf(buf, 1024, "%s%s%s", dir,
|
snprintf(buf, 1024, "%s%s%s", dir,
|
||||||
PATH_SEPARATOR, dir);
|
PATH_SEPARATOR, dir);
|
||||||
if (__os_exists(dbenv, buf, &dir_p) == 0)
|
if (__dbsql_exists(NULL, buf, &dir_p) == 0)
|
||||||
env_open_flags = DB_JOINENV;
|
env_open_flags = DB_JOINENV;
|
||||||
} else {
|
} else {
|
||||||
__dbsql_err(NULL,
|
__dbsql_err(NULL,
|
||||||
"Environment must be a directory.");
|
"Environment must be a directory.");
|
||||||
return DBSQL_INVALID_NAME;
|
return DBSQL_INVALID_NAME;
|
||||||
}
|
}
|
||||||
} else { /* TODO __db_omode("rwxrwxrwx"):mode) != 0) */
|
} else {
|
||||||
if (mkdir(dir, mode == 0 ? 0777 : mode) != 0)
|
mode = mode == 0 ? __dbsql_omode(NULL, "rwxrwxrwx") : mode;
|
||||||
|
if (__dbsql_mkdir(NULL, dir, mode) != 0)
|
||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,7 @@ __null_callback(not_used, n, a, b)
|
||||||
/*
|
/*
|
||||||
* __parse_exec --
|
* __parse_exec --
|
||||||
* This routine is called after a single SQL statement has been
|
* This routine is called after a single SQL statement has been
|
||||||
* parsed and we want to execute the VDBE code to implement
|
* parsed and we want to execute the VDBE code to implement
|
||||||
* that statement. Prior action routines should have already
|
* that statement. Prior action routines should have already
|
||||||
* constructed VDBE code to do the work of the SQL statement.
|
* constructed VDBE code to do the work of the SQL statement.
|
||||||
* This routine just has to execute the VDBE code.
|
* This routine just has to execute the VDBE code.
|
||||||
|
@ -163,7 +163,7 @@ __parse_exec(parser)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* __find_table --
|
* __find_table --
|
||||||
* Locate the in-memory structure that describes
|
* Locate the in-memory structure that describes
|
||||||
* a particular database table given the name
|
* a particular database table given the name
|
||||||
* of that table and (optionally) the name of the database
|
* of that table and (optionally) the name of the database
|
||||||
* containing the table. Return NULL if not found.
|
* containing the table. Return NULL if not found.
|
||||||
|
@ -199,7 +199,7 @@ __find_table(dbp, name, database)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* __locate_table --
|
* __locate_table --
|
||||||
* Locate the in-memory structure that describes
|
* Locate the in-memory structure that describes
|
||||||
* a particular database table given the name
|
* a particular database table given the name
|
||||||
* of that table and (optionally) the name of the database
|
* of that table and (optionally) the name of the database
|
||||||
* containing the table. Return NULL if not found.
|
* containing the table. Return NULL if not found.
|
||||||
|
@ -236,7 +236,7 @@ __locate_table(parser, name, database)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* __find_index --
|
* __find_index --
|
||||||
* Locate the in-memory structure that describes
|
* Locate the in-memory structure that describes
|
||||||
* a particular index given the name of that index
|
* a particular index given the name of that index
|
||||||
* and the name of the database that contains the index.
|
* and the name of the database that contains the index.
|
||||||
* Return NULL if not found.
|
* Return NULL if not found.
|
||||||
|
@ -433,7 +433,7 @@ __commit_internal_changes(dbp)
|
||||||
* This routine just deletes the data structure. It does not unlink
|
* This routine just deletes the data structure. It does not unlink
|
||||||
* the table data structure from the hash table. Nor does it remove
|
* the table data structure from the hash table. Nor does it remove
|
||||||
* foreign keys from the aFKey hash table. But it does destroy
|
* foreign keys from the aFKey hash table. But it does destroy
|
||||||
* memory structures of the indices and foreign keys associated with
|
* memory structures of the indices and foreign keys associated with
|
||||||
* the table.
|
* the table.
|
||||||
* Indices associated with the table are unlinked from the "db"
|
* Indices associated with the table are unlinked from the "db"
|
||||||
* data structure if db!=NULL. If db==NULL, indices attached to
|
* data structure if db!=NULL. If db==NULL, indices attached to
|
||||||
|
@ -466,7 +466,7 @@ __vdbe_delete_table(dbp, table)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Delete all foreign keys associated with this table. The keys
|
* Delete all foreign keys associated with this table. The keys
|
||||||
* should have already been unlinked from the dbp->aFKey hash table
|
* should have already been unlinked from the dbp->aFKey hash table
|
||||||
*/
|
*/
|
||||||
for (fkey = table->pFKey; fkey; fkey = next_fkey) {
|
for (fkey = table->pFKey; fkey; fkey = next_fkey) {
|
||||||
next_fkey = fkey->pNextFrom;
|
next_fkey = fkey->pNextFrom;
|
||||||
|
@ -548,7 +548,7 @@ __table_name_from_token(name)
|
||||||
/*
|
/*
|
||||||
* __open_master_table --
|
* __open_master_table --
|
||||||
* Generate code to open the appropriate master table. The table
|
* Generate code to open the appropriate master table. The table
|
||||||
* opened will be DBSQL_MASTER for persistent tables and
|
* opened will be DBSQL_MASTER for persistent tables and
|
||||||
* DBSQL_TEMP_MASTER for temporary tables. The table is opened
|
* DBSQL_TEMP_MASTER for temporary tables. The table is opened
|
||||||
* on cursor 0.
|
* on cursor 0.
|
||||||
*
|
*
|
||||||
|
@ -636,9 +636,9 @@ void __start_table(parser, start, name, temp, view)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
/*
|
||||||
* Before trying to create a temporary table, make sure the DB for
|
* Before trying to create a temporary table, make sure the DB for
|
||||||
* holding temporary tables is open.
|
* holding temporary tables is open.
|
||||||
*/
|
*/
|
||||||
|
@ -687,7 +687,7 @@ void __start_table(parser, start, name, temp, view)
|
||||||
if ((idx = __find_index(dbp, n, 0)) != 0 &&
|
if ((idx = __find_index(dbp, n, 0)) != 0 &&
|
||||||
(idx->iDb == 0 || !parser->initFlag)) {
|
(idx->iDb == 0 || !parser->initFlag)) {
|
||||||
__str_append(&parser->zErrMsg,
|
__str_append(&parser->zErrMsg,
|
||||||
"there is already an index named ",
|
"there is already an index named ",
|
||||||
n, (char*)0);
|
n, (char*)0);
|
||||||
__dbsql_free(dbp, n);
|
__dbsql_free(dbp, n);
|
||||||
parser->nErr++;
|
parser->nErr++;
|
||||||
|
@ -813,7 +813,7 @@ __add_not_null(parser, on_error)
|
||||||
* in 'type'.
|
* in 'type'.
|
||||||
*
|
*
|
||||||
* PUBLIC: void __add_column_type __P((parser_t *, token_t *, token_t *));
|
* PUBLIC: void __add_column_type __P((parser_t *, token_t *, token_t *));
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
__add_column_type(parser, first, last)
|
__add_column_type(parser, first, last)
|
||||||
parser_t *parser;
|
parser_t *parser;
|
||||||
|
@ -884,7 +884,7 @@ __add_default_value(parser, val, minus)
|
||||||
/*
|
/*
|
||||||
* __add_primary_key --
|
* __add_primary_key --
|
||||||
*
|
*
|
||||||
* Designate the PRIMARY KEY for the table. 'list' is a list of names
|
* Designate the PRIMARY KEY for the table. 'list' is a list of names
|
||||||
* of columns that form the primary key. If 'list' is NULL, then the
|
* of columns that form the primary key. If 'list' is NULL, then the
|
||||||
* most recently added column of the table is the primary key.
|
* most recently added column of the table is the primary key.
|
||||||
* A table can have at most one primary key. If the table already has
|
* A table can have at most one primary key. If the table already has
|
||||||
|
@ -1045,7 +1045,8 @@ __add_collate_type(parser, type)
|
||||||
*
|
*
|
||||||
* PUBLIC: void __change_schema_signature __P((DBSQL *, vdbe_t *));
|
* PUBLIC: void __change_schema_signature __P((DBSQL *, vdbe_t *));
|
||||||
*/
|
*/
|
||||||
void __change_schema_signature(dbp, v)
|
void
|
||||||
|
__change_schema_signature(dbp, v)
|
||||||
DBSQL *dbp;
|
DBSQL *dbp;
|
||||||
vdbe_t *v;
|
vdbe_t *v;
|
||||||
{
|
{
|
||||||
|
@ -1184,7 +1185,7 @@ __gen_create_table_stmt(table)
|
||||||
* recently changed, so the entry for this table already exists in
|
* recently changed, so the entry for this table already exists in
|
||||||
* the master table. We do not want to create it again.
|
* the master table. We do not want to create it again.
|
||||||
* If the 'select' argument is not NULL, it means that this routine
|
* If the 'select' argument is not NULL, it means that this routine
|
||||||
* was called to create a table generated from a
|
* was called to create a table generated from a
|
||||||
* "CREATE TABLE ... AS SELECT ..." statement. The column names of
|
* "CREATE TABLE ... AS SELECT ..." statement. The column names of
|
||||||
* the new table will match the result set of the SELECT.
|
* the new table will match the result set of the SELECT.
|
||||||
*
|
*
|
||||||
|
@ -1246,7 +1247,7 @@ __ending_create_table_paren(parser, end, select)
|
||||||
if (!parser->initFlag) {
|
if (!parser->initFlag) {
|
||||||
int n;
|
int n;
|
||||||
vdbe_t *v;
|
vdbe_t *v;
|
||||||
|
|
||||||
v = __parser_get_vdbe(parser);
|
v = __parser_get_vdbe(parser);
|
||||||
if (v == 0)
|
if (v == 0)
|
||||||
return;
|
return;
|
||||||
|
@ -1305,8 +1306,8 @@ __ending_create_table_paren(parser, end, select)
|
||||||
if (parser->explain == 0 && parser->nErr == 0) {
|
if (parser->explain == 0 && parser->nErr == 0) {
|
||||||
table_t *old;
|
table_t *old;
|
||||||
foreign_key_t *fkey;
|
foreign_key_t *fkey;
|
||||||
old = __hash_insert(&dbp->aDb[table->iDb].tblHash,
|
old = __hash_insert(&dbp->aDb[table->iDb].tblHash,
|
||||||
table->zName, strlen(table->zName) + 1, table);
|
table->zName, strlen(table->zName) + 1, table);
|
||||||
if (old) {
|
if (old) {
|
||||||
/* Malloc must have failed inside __hash_insert() */
|
/* Malloc must have failed inside __hash_insert() */
|
||||||
DBSQL_ASSERT(table == old);
|
DBSQL_ASSERT(table == old);
|
||||||
|
@ -1450,7 +1451,7 @@ __view_get_column_names(parser, table)
|
||||||
/*
|
/*
|
||||||
* If we get this far, it means we need to compute the table names.
|
* If we get this far, it means we need to compute the table names.
|
||||||
*/
|
*/
|
||||||
/* If nCol == 0, then 'table' must be a VIEW */
|
/* If nCol == 0, then 'table' must be a VIEW */
|
||||||
DBSQL_ASSERT(table->pSelect);
|
DBSQL_ASSERT(table->pSelect);
|
||||||
sel = table->pSelect;
|
sel = table->pSelect;
|
||||||
|
|
||||||
|
@ -1483,7 +1484,7 @@ __view_get_column_names(parser, table)
|
||||||
__select_unbind(sel);
|
__select_unbind(sel);
|
||||||
__expr_list_delete(sel->pEList);
|
__expr_list_delete(sel->pEList);
|
||||||
sel->pEList = elist;
|
sel->pEList = elist;
|
||||||
return nerr;
|
return nerr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1627,7 +1628,7 @@ __drop_table(parser, name, view)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (table->readOnly) {
|
if (table->readOnly) {
|
||||||
__str_append(&parser->zErrMsg, "table ", table->zName,
|
__str_append(&parser->zErrMsg, "table ", table->zName,
|
||||||
" may not be dropped", (char*)0);
|
" may not be dropped", (char*)0);
|
||||||
parser->nErr++;
|
parser->nErr++;
|
||||||
return;
|
return;
|
||||||
|
@ -1819,7 +1820,7 @@ void __create_foreign_key(parser, from_col, to, to_col, flags)
|
||||||
if (to_col && to_col->nId!=1 ){
|
if (to_col && to_col->nId!=1 ){
|
||||||
__str_nappend(&parser->zErrMsg,
|
__str_nappend(&parser->zErrMsg,
|
||||||
"foreign key on ", -1,
|
"foreign key on ", -1,
|
||||||
table->aCol[col].zName, -1,
|
table->aCol[col].zName, -1,
|
||||||
" should reference only one column "
|
" should reference only one column "
|
||||||
"of table ", -1, to->z, to->n, NULL);
|
"of table ", -1, to->z, to->n, NULL);
|
||||||
parser->nErr++;
|
parser->nErr++;
|
||||||
|
@ -1827,7 +1828,7 @@ void __create_foreign_key(parser, from_col, to, to_col, flags)
|
||||||
}
|
}
|
||||||
ncol = 1;
|
ncol = 1;
|
||||||
} else if (to_col && to_col->nId != from_col->nId) {
|
} else if (to_col && to_col->nId != from_col->nId) {
|
||||||
__str_append(&parser->zErrMsg,
|
__str_append(&parser->zErrMsg,
|
||||||
"number of columns in foreign key does not "
|
"number of columns in foreign key does not "
|
||||||
"match the number of columns in the referenced "
|
"match the number of columns in the referenced "
|
||||||
"table", (char*)0);
|
"table", (char*)0);
|
||||||
|
@ -1870,7 +1871,7 @@ void __create_foreign_key(parser, from_col, to, to_col, flags)
|
||||||
}
|
}
|
||||||
if (j >= table->nCol) {
|
if (j >= table->nCol) {
|
||||||
__str_append(&parser->zErrMsg,
|
__str_append(&parser->zErrMsg,
|
||||||
"unknown column \"",
|
"unknown column \"",
|
||||||
from_col->a[i].zName,
|
from_col->a[i].zName,
|
||||||
"\" in foreign key definition",
|
"\" in foreign key definition",
|
||||||
(char*)0);
|
(char*)0);
|
||||||
|
@ -1929,8 +1930,8 @@ __defer_foreign_key(parser, deferred)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* __creat_index --
|
* __create_index --
|
||||||
* Create a new index for an SQL table. 'index' is the name of the
|
* Create a new index for an SQL table. 'index' is the name of the
|
||||||
* index and pTable is the name of the table that is to be indexed.
|
* index and pTable is the name of the table that is to be indexed.
|
||||||
* Both will be NULL for a primary key or an index that is created
|
* Both will be NULL for a primary key or an index that is created
|
||||||
* to satisfy a UNIQUE constraint. If pTable and pIndex are NULL,
|
* to satisfy a UNIQUE constraint. If pTable and pIndex are NULL,
|
||||||
|
@ -1954,7 +1955,8 @@ __defer_foreign_key(parser, deferred)
|
||||||
* statement.
|
* statement.
|
||||||
* end The ")" that closes the CREATE INDEX statement.
|
* end The ")" that closes the CREATE INDEX statement.
|
||||||
*/
|
*/
|
||||||
void __create_index(parser, token, sltable, list, on_error, start, end)
|
void
|
||||||
|
__create_index(parser, token, sltable, list, on_error, start, end)
|
||||||
parser_t *parser;
|
parser_t *parser;
|
||||||
token_t *token;
|
token_t *token;
|
||||||
src_list_t *sltable;
|
src_list_t *sltable;
|
||||||
|
@ -1969,7 +1971,7 @@ void __create_index(parser, token, sltable, list, on_error, start, end)
|
||||||
int i, j;
|
int i, j;
|
||||||
token_t null_id; /* Fake token for an empty ID list */
|
token_t null_id; /* Fake token for an empty ID list */
|
||||||
ref_normalizer_ctx_t normctx; /* For assigning database
|
ref_normalizer_ctx_t normctx; /* For assigning database
|
||||||
names to sltable */
|
names to sltable */
|
||||||
int temp; /* True for a temporary index */
|
int temp; /* True for a temporary index */
|
||||||
DBSQL *dbp = parser->db;
|
DBSQL *dbp = parser->db;
|
||||||
|
|
||||||
|
@ -2002,7 +2004,7 @@ void __create_index(parser, token, sltable, list, on_error, start, end)
|
||||||
goto exit_create_index;
|
goto exit_create_index;
|
||||||
}
|
}
|
||||||
if (table->iDb >= 2 && parser->initFlag == 0) {
|
if (table->iDb >= 2 && parser->initFlag == 0) {
|
||||||
__str_append(&parser->zErrMsg, "table ", table->zName,
|
__str_append(&parser->zErrMsg, "table ", table->zName,
|
||||||
" may not have indices added", (char*)0);
|
" may not have indices added", (char*)0);
|
||||||
parser->nErr++;
|
parser->nErr++;
|
||||||
goto exit_create_index;
|
goto exit_create_index;
|
||||||
|
@ -2017,7 +2019,7 @@ void __create_index(parser, token, sltable, list, on_error, start, end)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the name of the index. Make sure there is not already another
|
* Find the name of the index. Make sure there is not already another
|
||||||
* index or table with the same name.
|
* index or table with the same name.
|
||||||
*
|
*
|
||||||
* Exception: If we are reading the names of permanent indices from
|
* Exception: If we are reading the names of permanent indices from
|
||||||
* the master table (because some other process changed the schema) and
|
* the master table (because some other process changed the schema) and
|
||||||
|
@ -2034,7 +2036,7 @@ void __create_index(parser, token, sltable, list, on_error, start, end)
|
||||||
if (name == 0)
|
if (name == 0)
|
||||||
goto exit_create_index;
|
goto exit_create_index;
|
||||||
if ((idx_same_name = __find_index(dbp, name, 0)) != 0) {
|
if ((idx_same_name = __find_index(dbp, name, 0)) != 0) {
|
||||||
__str_append(&parser->zErrMsg, "index ", name,
|
__str_append(&parser->zErrMsg, "index ", name,
|
||||||
" already exists", (char*)0);
|
" already exists", (char*)0);
|
||||||
parser->nErr++;
|
parser->nErr++;
|
||||||
goto exit_create_index;
|
goto exit_create_index;
|
||||||
|
@ -2098,8 +2100,8 @@ void __create_index(parser, token, sltable, list, on_error, start, end)
|
||||||
goto exit_create_index;
|
goto exit_create_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate the index structure.
|
* Allocate the index structure.
|
||||||
*/
|
*/
|
||||||
if (__dbsql_calloc(dbp, 1, sizeof(index_t) + (strlen(name) + 1) +
|
if (__dbsql_calloc(dbp, 1, sizeof(index_t) + (strlen(name) + 1) +
|
||||||
(sizeof(int) * list->nId), &index) == ENOMEM)
|
(sizeof(int) * list->nId), &index) == ENOMEM)
|
||||||
|
@ -2136,16 +2138,16 @@ void __create_index(parser, token, sltable, list, on_error, start, end)
|
||||||
index->aiColumn[i] = j;
|
index->aiColumn[i] = j;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Link the new index_t structure to its table and to the other
|
* Link the new index_t structure to its table and to the other
|
||||||
* in-memory database structures.
|
* in-memory database structures.
|
||||||
*/
|
*/
|
||||||
if (!parser->explain) {
|
if (!parser->explain) {
|
||||||
index_t *rindex;
|
index_t *rindex;
|
||||||
rindex = __hash_insert(&dbp->aDb[index->iDb].idxHash,
|
rindex = __hash_insert(&dbp->aDb[index->iDb].idxHash,
|
||||||
index->zName, strlen(index->zName) + 1, index);
|
index->zName, strlen(index->zName) + 1, index);
|
||||||
if (rindex) {
|
if (rindex) {
|
||||||
/* Malloc must have failed */
|
/* Malloc must have failed */
|
||||||
DBSQL_ASSERT(rindex == index);
|
DBSQL_ASSERT(rindex == index);
|
||||||
__dbsql_free(dbp, index);
|
__dbsql_free(dbp, index);
|
||||||
goto exit_create_index;
|
goto exit_create_index;
|
||||||
|
@ -2186,8 +2188,8 @@ void __create_index(parser, token, sltable, list, on_error, start, end)
|
||||||
* involves writing the index into the master table and
|
* involves writing the index into the master table and
|
||||||
* filling in the index with the current table contents.
|
* filling in the index with the current table contents.
|
||||||
*
|
*
|
||||||
* The initFlag is 0 when the user first enters a CREATE INDEX
|
* The initFlag is 0 when the user first enters a CREATE INDEX
|
||||||
* command. The initFlag is 1 when a database is opened and
|
* command. The initFlag is 1 when a database is opened and
|
||||||
* CREATE INDEX statements are read out of the master table.
|
* CREATE INDEX statements are read out of the master table.
|
||||||
* In the latter case the index already exists on disk, which
|
* In the latter case the index already exists on disk, which
|
||||||
* is why we don't want to recreate it.
|
* is why we don't want to recreate it.
|
||||||
|
@ -2281,7 +2283,7 @@ exit_create_index:
|
||||||
* This routine will drop an existing named index. This routine
|
* This routine will drop an existing named index. This routine
|
||||||
* implements the DROP INDEX statement.
|
* implements the DROP INDEX statement.
|
||||||
*
|
*
|
||||||
* PUBILC: __drop_index __P((parser_t *, src_list_t *));
|
* PUBLIC: void __drop_index __P((parser_t *, src_list_t *));
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
__drop_index(parser, name)
|
__drop_index(parser, name)
|
||||||
|
@ -2335,7 +2337,7 @@ __drop_index(parser, name)
|
||||||
v = __parser_get_vdbe(parser);
|
v = __parser_get_vdbe(parser);
|
||||||
if( v ){
|
if( v ){
|
||||||
static vdbe_op_t drop_index[] = {
|
static vdbe_op_t drop_index[] = {
|
||||||
{ OP_Rewind, 0, ADDR(9), 0},
|
{ OP_Rewind, 0, ADDR(9), 0},
|
||||||
{ OP_String, 0, 0, 0}, /* 1 */
|
{ OP_String, 0, 0, 0}, /* 1 */
|
||||||
{ OP_MemStore, 1, 1, 0},
|
{ OP_MemStore, 1, 1, 0},
|
||||||
{ OP_MemLoad, 1, 0, 0}, /* 3 */
|
{ OP_MemLoad, 1, 0, 0}, /* 3 */
|
||||||
|
@ -2494,7 +2496,7 @@ __src_list_append(list, table, database)
|
||||||
* __src_list_assign_cursors --
|
* __src_list_assign_cursors --
|
||||||
* Assign cursors to all tables in a src_list_t.
|
* Assign cursors to all tables in a src_list_t.
|
||||||
*
|
*
|
||||||
* __src_list_assign_cursors __P((parser_t *, src_list_t *));
|
* PUBLIC: void __src_list_assign_cursors __P((parser_t *, src_list_t *));
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
__src_list_assign_cursors(parser, list)
|
__src_list_assign_cursors(parser, list)
|
||||||
|
@ -2685,7 +2687,7 @@ __dbsql_txn_abort(parser)
|
||||||
if ((dbp->flags & DBSQL_InTrans) == 0) {
|
if ((dbp->flags & DBSQL_InTrans) == 0) {
|
||||||
__error_msg(parser,
|
__error_msg(parser,
|
||||||
"cannot rollback - no transaction is active");
|
"cannot rollback - no transaction is active");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
v = __parser_get_vdbe(parser);
|
v = __parser_get_vdbe(parser);
|
||||||
if (v) {
|
if (v) {
|
||||||
|
@ -2771,7 +2773,7 @@ __vdbe_prepare_write(parser, checkpoint, idb)
|
||||||
* the database. If a statement transaction was started, then emit
|
* the database. If a statement transaction was started, then emit
|
||||||
* an OP_Commit that will cause the changes to be committed to disk.
|
* an OP_Commit that will cause the changes to be committed to disk.
|
||||||
* Note that checkpoints are automatically committed at the end of
|
* Note that checkpoints are automatically committed at the end of
|
||||||
* a statement. Note also that there can be multiple calls to
|
* a statement. Note also that there can be multiple calls to
|
||||||
* __vdbe_prepare_write() but there should only be a single
|
* __vdbe_prepare_write() but there should only be a single
|
||||||
* call to __vdbe_conclude_write() at the conclusion of the statement.
|
* call to __vdbe_conclude_write() at the conclusion of the statement.
|
||||||
*
|
*
|
||||||
|
@ -2789,7 +2791,7 @@ __vdbe_conclude_write(parser)
|
||||||
if (v == 0)
|
if (v == 0)
|
||||||
return;
|
return;
|
||||||
if (dbp->flags & DBSQL_InTrans) {
|
if (dbp->flags & DBSQL_InTrans) {
|
||||||
/*
|
/*
|
||||||
* A BEGIN has executed. Do not commit until we see an
|
* A BEGIN has executed. Do not commit until we see an
|
||||||
* explicit COMMIT statement.
|
* explicit COMMIT statement.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -869,7 +869,7 @@ __code_trigger_program(parser, steplist, orconfin)
|
||||||
* pointing at a row containing values to be substituted for old.*
|
* pointing at a row containing values to be substituted for old.*
|
||||||
* expressions in the trigger program(s).
|
* expressions in the trigger program(s).
|
||||||
*
|
*
|
||||||
* PUBlIC: int __code_row_trigger __P(());
|
* PUBLIC: int __code_row_trigger __P(());
|
||||||
*
|
*
|
||||||
* parser Parser context
|
* parser Parser context
|
||||||
* op One of TK_UPDATE, TK_INSERT, TK_DELETE
|
* op One of TK_UPDATE, TK_INSERT, TK_DELETE
|
||||||
|
|
|
@ -18,8 +18,12 @@
|
||||||
* General Public License for more details.
|
* General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dbsql.h"
|
||||||
#include "dbsql_config.h"
|
#include "dbsql_config.h"
|
||||||
#include "dbsql_int.h"
|
#include "db_int.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* __dbsql_umalloc --
|
* __dbsql_umalloc --
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#include "dbsql_config.h"
|
#include "dbsql_config.h"
|
||||||
#include "dbsql_int.h"
|
#include "dbsql_int.h"
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* __dbsql_atof --
|
* __dbsql_atof --
|
||||||
* The string z[] is an ascii representation of a real number.
|
* The string z[] is an ascii representation of a real number.
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#include "dbsql_config.h"
|
#include "dbsql_config.h"
|
||||||
#include "dbsql_int.h"
|
#include "dbsql_int.h"
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* __dbsql_atoi --
|
* __dbsql_atoi --
|
||||||
* Return TRUE if 'str' is a 32-bit signed integer and write
|
* Return TRUE if 'str' is a 32-bit signed integer and write
|
||||||
|
|
|
@ -280,8 +280,8 @@ __dbsql_errcall(dbp, error, error_set, fmt, ap)
|
||||||
* are pretty rare anymore.
|
* are pretty rare anymore.
|
||||||
*/
|
*/
|
||||||
if ((size_t)(p - errbuf) > sizeof(errbuf)) {
|
if ((size_t)(p - errbuf) > sizeof(errbuf)) {
|
||||||
write(
|
IGNORE_RESULT(write(
|
||||||
STDERR_FILENO, OVERFLOW_ERROR, sizeof(OVERFLOW_ERROR) - 1);
|
STDERR_FILENO, OVERFLOW_ERROR, sizeof(OVERFLOW_ERROR) - 1));
|
||||||
abort();
|
abort();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
101
src/common/dbsql_fop.c
Normal file
101
src/common/dbsql_fop.c
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
/*-
|
||||||
|
* DBSQL - A SQL database engine.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007-2008 The DBSQL Group, Inc. - All rights reserved.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* There are special exceptions to the terms and conditions of the GPL as it
|
||||||
|
* is applied to this software. View the full text of the exception in file
|
||||||
|
* LICENSE_EXCEPTIONS in the directory of this software distribution.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dbsql_config.h"
|
||||||
|
#include "dbsql_int.h"
|
||||||
|
#include "db_int.h"
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* __dbsql_exists --
|
||||||
|
* Returns if file exists using the __os_exists call of DB.
|
||||||
|
*
|
||||||
|
* PUBLIC: int __dbsql_exists __P((DBSQL *, const char *, int *));
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
__dbsql_exists(dbp, path, isdirp)
|
||||||
|
DBSQL *dbp;
|
||||||
|
const char *path;
|
||||||
|
int *isdirp;
|
||||||
|
{
|
||||||
|
return (__os_exists((dbp ? dbp->dbenv : NULL), path, isdirp));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* __dbsql_mkdir --
|
||||||
|
* Create a directory using the __os_mkdir call of DB.
|
||||||
|
*
|
||||||
|
* PUBLIC: int __dbsql_mkdir __P((DBSQL *, const char *, int));
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
__dbsql_mkdir(dbp, path, mode)
|
||||||
|
DBSQL *dbp;
|
||||||
|
const char *path;
|
||||||
|
int mode;
|
||||||
|
{
|
||||||
|
return (__os_mkdir((dbp ? dbp->dbenv : NULL), path, mode));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* __dbsql_omode --
|
||||||
|
* Convert a file mode from a string to an int.
|
||||||
|
*
|
||||||
|
* PUBLIC: int __dbsql_omode __P((DBSQL *, const char *));
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
__dbsql_omode(dbp, mode)
|
||||||
|
DBSQL *dbp;
|
||||||
|
const char *mode;
|
||||||
|
{
|
||||||
|
u_int t;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
|
||||||
|
#define __SETMODE(offset, valid_ch, mask) { \
|
||||||
|
if (mode[offset] == (valid_ch)) \
|
||||||
|
t |= (mask); \
|
||||||
|
else if (mode[offset] != '-') \
|
||||||
|
goto format_err; \
|
||||||
|
}
|
||||||
|
t = 0;
|
||||||
|
__SETMODE(0, 'r', S_IRUSR);
|
||||||
|
__SETMODE(1, 'w', S_IWUSR);
|
||||||
|
__SETMODE(2, 'x', S_IXUSR);
|
||||||
|
__SETMODE(3, 'r', S_IRGRP);
|
||||||
|
__SETMODE(4, 'w', S_IWGRP);
|
||||||
|
__SETMODE(5, 'x', S_IXGRP);
|
||||||
|
__SETMODE(6, 'r', S_IROTH);
|
||||||
|
__SETMODE(7, 'w', S_IWOTH);
|
||||||
|
__SETMODE(8, 'x', S_IXOTH);
|
||||||
|
if (mode[9] != '\0' || t == 0) {
|
||||||
|
/*
|
||||||
|
* We disallow modes of 0 -- we use 0 to decide the application
|
||||||
|
* never configured intermediate directory permissions, and we
|
||||||
|
* shouldn't create intermediate directories. Besides, setting
|
||||||
|
* the permissions to 0 makes no sense.
|
||||||
|
*/
|
||||||
|
|
||||||
|
format_err: __dbsql_err(dbp, "illegal mode \"%s\"", mode);
|
||||||
|
return (EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
|
@ -95,6 +95,9 @@
|
||||||
#include "dbsql_config.h"
|
#include "dbsql_config.h"
|
||||||
#include "dbsql_int.h"
|
#include "dbsql_int.h"
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
|
||||||
unsigned char __str_upper_to_lower[] = {
|
unsigned char __str_upper_to_lower[] = {
|
||||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
|
||||||
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
|
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
|
||||||
|
@ -164,9 +167,9 @@ __str_append(result, fmt, va_alist)
|
||||||
/*
|
/*
|
||||||
* __str_nappend --
|
* __str_nappend --
|
||||||
* Works like __str_append, but each string is now followed by
|
* Works like __str_append, but each string is now followed by
|
||||||
* a length integer which specifies how much of the source string
|
* a length integer which specifies how much of the source string
|
||||||
* to copy (in bytes). -1 means use the whole string. The 1st
|
* to copy (in bytes). -1 means use the whole string. The 1st
|
||||||
* argument must either be NULL or point to memory obtained from
|
* argument must either be NULL or point to memory obtained from
|
||||||
* __dbsql_calloc().
|
* __dbsql_calloc().
|
||||||
*
|
*
|
||||||
* PUBLIC: void __str_nappend __P((char **, ...));
|
* PUBLIC: void __str_nappend __P((char **, ...));
|
||||||
|
@ -273,8 +276,8 @@ __str_urealloc(pz)
|
||||||
char *new;
|
char *new;
|
||||||
|
|
||||||
if (pz == 0 || *pz == NULL)
|
if (pz == 0 || *pz == NULL)
|
||||||
return;
|
return rc;
|
||||||
|
|
||||||
if (__dbsql_umalloc(NULL, strlen(*pz) + 1, &new) == ENOMEM) {
|
if (__dbsql_umalloc(NULL, strlen(*pz) + 1, &new) == ENOMEM) {
|
||||||
rc = ENOMEM;
|
rc = ENOMEM;
|
||||||
__dbsql_free(NULL, *pz);
|
__dbsql_free(NULL, *pz);
|
||||||
|
@ -394,7 +397,7 @@ static int __utf8_to_int(const unsigned char *z) {
|
||||||
* '?' Matches exactly one character.
|
* '?' Matches exactly one character.
|
||||||
*
|
*
|
||||||
* [...] Matches one character from the enclosed list of
|
* [...] Matches one character from the enclosed list of
|
||||||
* characters.
|
* characters.
|
||||||
*
|
*
|
||||||
* [^...] Matches one character not in the enclosed list.
|
* [^...] Matches one character not in the enclosed list.
|
||||||
*
|
*
|
||||||
|
@ -408,12 +411,12 @@ static int __utf8_to_int(const unsigned char *z) {
|
||||||
*
|
*
|
||||||
* Hints: to match '*' or '?', put them in "[]". Like this:
|
* Hints: to match '*' or '?', put them in "[]". Like this:
|
||||||
*
|
*
|
||||||
* abc[*]xyz Matches "abc*xyz" only
|
* abc[*]xyz Matches "abc*xyz" only
|
||||||
*
|
*
|
||||||
* PUBLIC: int __str_glob_cmp __P((const unsigned char *,
|
* PUBLIC: int __str_glob_cmp __P((const unsigned char *,
|
||||||
* PUBLIC: const unsigned char *));
|
* PUBLIC: const unsigned char *));
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
__str_glob_cmp(pattern, string)
|
__str_glob_cmp(pattern, string)
|
||||||
const unsigned char *pattern;
|
const unsigned char *pattern;
|
||||||
const unsigned char *string;
|
const unsigned char *string;
|
||||||
|
@ -526,7 +529,7 @@ __str_glob_cmp(pattern, string)
|
||||||
* PUBLIC: int __str_like_cmp __P((const unsigned char *,
|
* PUBLIC: int __str_like_cmp __P((const unsigned char *,
|
||||||
* PUBLIC: const unsigned char *));
|
* PUBLIC: const unsigned char *));
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
__str_like_cmp(pattern, string)
|
__str_like_cmp(pattern, string)
|
||||||
const unsigned char *pattern;
|
const unsigned char *pattern;
|
||||||
const unsigned char *string;
|
const unsigned char *string;
|
||||||
|
@ -588,10 +591,10 @@ __str_like_cmp(pattern, string)
|
||||||
* do not necessarily contain numbers. They could contain text.
|
* do not necessarily contain numbers. They could contain text.
|
||||||
*
|
*
|
||||||
* If the input strings both look like actual numbers then they
|
* If the input strings both look like actual numbers then they
|
||||||
* compare in numerical order. Numerical strings are always less
|
* compare in numerical order. Numerical strings are always less
|
||||||
* than non-numeric strings so if one input string looks like a
|
* than non-numeric strings so if one input string looks like a
|
||||||
* number and the other does not, then the one that looks like
|
* number and the other does not, then the one that looks like
|
||||||
* a number is the smaller. Non-numeric strings compare in
|
* a number is the smaller. Non-numeric strings compare in
|
||||||
* lexigraphical order (the same order as strcmp()).
|
* lexigraphical order (the same order as strcmp()).
|
||||||
*
|
*
|
||||||
* PUBLIC: int __str_numeric_cmp __P((const char *, const char *));
|
* PUBLIC: int __str_numeric_cmp __P((const char *, const char *));
|
||||||
|
@ -631,7 +634,7 @@ __str_numeric_cmp(left, right)
|
||||||
} else {
|
} else {
|
||||||
result = strcmp(left, right);
|
result = strcmp(left, right);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -704,7 +707,7 @@ __str_real_as_sortable(r, z)
|
||||||
* The digits must be chosen such at their ASCII codes are increasing.
|
* The digits must be chosen such at their ASCII codes are increasing.
|
||||||
* This means we can not use the traditional base-64 digit set.
|
* This means we can not use the traditional base-64 digit set.
|
||||||
*/
|
*/
|
||||||
static const char digit[] =
|
static const char digit[] =
|
||||||
"0123456789"
|
"0123456789"
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
"abcdefghijklmnopqrstuvwxyz"
|
"abcdefghijklmnopqrstuvwxyz"
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "dbsql_config.h"
|
#include "dbsql_config.h"
|
||||||
|
#include "dbsql_int.h"
|
||||||
#include "dbsql.h"
|
#include "dbsql.h"
|
||||||
|
|
||||||
#if !defined(_WIN32) && !defined(WIN32)
|
#if !defined(_WIN32) && !defined(WIN32)
|
||||||
|
@ -51,29 +52,29 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct globals {
|
struct globals {
|
||||||
/* The Berkeley DBSQL database manager. */
|
/* The Berkeley DBSQL database manager. */
|
||||||
DBSQL *dbp;
|
DBSQL *dbp;
|
||||||
|
|
||||||
/* The Berkeley DB database environment. */
|
/* The Berkeley DB database environment. */
|
||||||
DB_ENV *dbenv;
|
DB_ENV *dbenv;
|
||||||
|
|
||||||
/* Non-zero if an interrupt (Control-C) has been received. */
|
/* Non-zero if an interrupt (Control-C) has been received. */
|
||||||
int interrupted_p;
|
int interrupted_p;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is the name of our program. It is set in main(), used
|
* This is the name of our program. It is set in main(), used
|
||||||
* in a number of other places, mostly for error messages.
|
* in a number of other places, mostly for error messages.
|
||||||
*/
|
*/
|
||||||
char *progname;
|
char *progname;
|
||||||
|
|
||||||
/* An output stream for error messages, normally stdout. */
|
/* An output stream for error messages, normally stdout. */
|
||||||
FILE *errfp;
|
FILE *errfp;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prompt strings. Initialized in main. Settable using the
|
* Prompt strings. Initialized in main. Settable using the
|
||||||
* '.prompt [main] [continuation]' command.
|
* '.prompt [main] [continuation]' command.
|
||||||
*/
|
*/
|
||||||
char prompt[20]; /* First line prompt. default: "SQL> "*/
|
char prompt[20]; /* First line prompt. default: "SQL> "*/
|
||||||
char prompt2[20]; /* Continuation prompt. default: "...> " */
|
char prompt2[20]; /* Continuation prompt. default: "...> " */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -222,11 +223,6 @@ char *modeDescr[MODE_NUM_OF] = {
|
||||||
"insert"
|
"insert"
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* Number of elements in an array
|
|
||||||
*/
|
|
||||||
#define ARRAY_SIZE(X) (sizeof(X)/sizeof(X[0]))
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Output the given string as a quoted string using SQL quoting conventions.
|
* Output the given string as a quoted string using SQL quoting conventions.
|
||||||
*/
|
*/
|
||||||
|
@ -326,7 +322,7 @@ callback(arg, num_args, args, cols)
|
||||||
if (p->cnt++ > 0)
|
if (p->cnt++ > 0)
|
||||||
fprintf(p->out, "\n");
|
fprintf(p->out, "\n");
|
||||||
for (i = 0; i < num_args; i++) {
|
for (i = 0; i < num_args; i++) {
|
||||||
fprintf(p->out, "%*s = %s\n", w, cols[i],
|
fprintf(p->out, "%*s = %s\n", w, cols[i],
|
||||||
(args[i] ? args[i] : p->nullvalue));
|
(args[i] ? args[i] : p->nullvalue));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -368,7 +364,7 @@ callback(arg, num_args, args, cols)
|
||||||
w = 10;
|
w = 10;
|
||||||
}
|
}
|
||||||
fprintf(p->out, "%-*.*s%s", w, w,
|
fprintf(p->out, "%-*.*s%s", w, w,
|
||||||
"----------------------------------------------------------"
|
"----------------------------------------------------------"
|
||||||
"-----------------------------------",
|
"-----------------------------------",
|
||||||
(i == num_args - 1) ?
|
(i == num_args - 1) ?
|
||||||
"\n" : " ");
|
"\n" : " ");
|
||||||
|
@ -696,7 +692,7 @@ do_meta_command(line, p)
|
||||||
p->db->exec_printf(p->db,
|
p->db->exec_printf(p->db,
|
||||||
"SELECT name, type, sql FROM " MASTER_NAME " "
|
"SELECT name, type, sql FROM " MASTER_NAME " "
|
||||||
"WHERE tbl_name LIKE '%q' AND type!='meta' AND sql NOT NULL "
|
"WHERE tbl_name LIKE '%q' AND type!='meta' AND sql NOT NULL "
|
||||||
"ORDER BY substr(type,2,1), name",
|
"ORDER BY substr(type,2,1), name",
|
||||||
dump_callback, p,
|
dump_callback, p,
|
||||||
&err_msgs, args[i]);
|
&err_msgs, args[i]);
|
||||||
}
|
}
|
||||||
|
@ -1490,26 +1486,26 @@ main(argc, argv)
|
||||||
int
|
int
|
||||||
version_check()
|
version_check()
|
||||||
{
|
{
|
||||||
int v_major, v_minor, v_patch;
|
int v_major, v_minor, v_patch;
|
||||||
|
|
||||||
/* Make sure we're loaded with the right version of the DB library. */
|
/* Make sure we're loaded with the right version of the DB library. */
|
||||||
(void)dbsql_version(&v_major, &v_minor, &v_patch);
|
(void)dbsql_version(&v_major, &v_minor, &v_patch);
|
||||||
if (v_major != DBSQL_VERSION_MAJOR || v_minor != DBSQL_VERSION_MINOR) {
|
if (v_major != DBSQL_VERSION_MAJOR || v_minor != DBSQL_VERSION_MINOR) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%s: version %d.%d doesn't match library version %d.%d\n",
|
"%s: version %d.%d doesn't match library version %d.%d\n",
|
||||||
g.progname, DBSQL_VERSION_MAJOR, DBSQL_VERSION_MINOR,
|
g.progname, DBSQL_VERSION_MAJOR, DBSQL_VERSION_MINOR,
|
||||||
v_major, v_minor);
|
v_major, v_minor);
|
||||||
return (EXIT_FAILURE);
|
return (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure we're loaded with the right version of the DB library. */
|
/* Make sure we're loaded with the right version of the DB library. */
|
||||||
(void)db_version(&v_major, &v_minor, &v_patch);
|
(void)db_version(&v_major, &v_minor, &v_patch);
|
||||||
if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) {
|
if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%s: version %d.%d doesn't match library version %d.%d\n",
|
"%s: version %d.%d doesn't match library version %d.%d\n",
|
||||||
g.progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
|
g.progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
|
||||||
v_major, v_minor);
|
v_major, v_minor);
|
||||||
return (EXIT_FAILURE);
|
return (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dbsql_config.h"
|
#include "dbsql_config.h"
|
||||||
|
|
||||||
#include "dbsql_int.h"
|
#include "dbsql_int.h"
|
||||||
#include "tcl.h"
|
#include "tcl.h"
|
||||||
|
|
||||||
|
@ -42,9 +41,9 @@ static char main_loop[] =
|
||||||
"append line [gets stdin]\n"
|
"append line [gets stdin]\n"
|
||||||
"if {[info complete $line]} {\n"
|
"if {[info complete $line]} {\n"
|
||||||
"if {[catch {uplevel #0 $line} result]} {\n"
|
"if {[catch {uplevel #0 $line} result]} {\n"
|
||||||
"puts stderr \"Error: $result\"\n"
|
"puts stderr \"Error: $result\"\n"
|
||||||
"} elseif {$result!=\"\"} {\n"
|
"} elseif {$result!=\"\"} {\n"
|
||||||
"puts $result\n"
|
"puts $result\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"set line {}\n"
|
"set line {}\n"
|
||||||
"} else {\n"
|
"} else {\n"
|
||||||
|
|
|
@ -26,6 +26,9 @@ void __dbsql_err __P((const DBSQL *, const char *, ...)) __attribute__ ((__forma
|
||||||
void __dbsql_errcall __P((const DBSQL *, int, int, const char *, va_list));
|
void __dbsql_errcall __P((const DBSQL *, int, int, const char *, va_list));
|
||||||
void __dbsql_errfile __P((const DBSQL *, int, int, const char *, va_list));
|
void __dbsql_errfile __P((const DBSQL *, int, int, const char *, va_list));
|
||||||
void __error_msg __P((parser_t *, const char *, ...));
|
void __error_msg __P((parser_t *, const char *, ...));
|
||||||
|
int __dbsql_exists __P((DBSQL *, const char *, int *));
|
||||||
|
int __dbsql_mkdir __P((DBSQL *, const char *, int));
|
||||||
|
int __dbsql_omode __P((DBSQL *, const char *));
|
||||||
void __hash_init __P((hash_t *, int, int));
|
void __hash_init __P((hash_t *, int, int));
|
||||||
void __hash_clear __P((hash_t *));
|
void __hash_clear __P((hash_t *));
|
||||||
void *__hash_find __P((const hash_t *, const void *, int));
|
void *__hash_find __P((const hash_t *, const void *, int));
|
||||||
|
|
|
@ -32,21 +32,22 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void *__ua_memcpy__DB_UNIQUE_NAME__ __P((void *, const void *, size_t));
|
extern int __db_omode__DB_UNIQUE_NAME__ __P((const char *));
|
||||||
|
extern int __os_calloc__DB_UNIQUE_NAME__ __P((DB_ENV *, size_t, size_t, void *));
|
||||||
|
extern int __os_exists__DB_UNIQUE_NAME__ __P((DB_ENV *, const char *, int *));
|
||||||
extern int __os_get_errno__DB_UNIQUE_NAME__ __P((void));
|
extern int __os_get_errno__DB_UNIQUE_NAME__ __P((void));
|
||||||
|
extern int __os_id__DB_UNIQUE_NAME__ __P((DB_ENV *, pid_t *, db_threadid_t*));
|
||||||
|
extern int __os_malloc__DB_UNIQUE_NAME__ __P((DB_ENV *, size_t, void *));
|
||||||
|
extern int __os_mkdir__DB_UNIQUE_NAME__ __P((DB_ENV *, const char *, int));
|
||||||
|
extern int __os_realloc__DB_UNIQUE_NAME__ __P((DB_ENV *, size_t, void *));
|
||||||
|
extern int __os_strdup__DB_UNIQUE_NAME__ __P((DB_ENV *, const char *, void *));
|
||||||
|
extern int __os_umalloc__DB_UNIQUE_NAME__ __P((DB_ENV *, size_t, void *));
|
||||||
|
extern int __os_urealloc__DB_UNIQUE_NAME__ __P((DB_ENV *, size_t, void *));
|
||||||
|
extern void *__ua_memcpy__DB_UNIQUE_NAME__ __P((void *, const void *, size_t));
|
||||||
|
extern void __os_free__DB_UNIQUE_NAME__ __P((DB_ENV *, void *));
|
||||||
extern void __os_set_errno__DB_UNIQUE_NAME__ __P((int));
|
extern void __os_set_errno__DB_UNIQUE_NAME__ __P((int));
|
||||||
extern void __os_sleep__DB_UNIQUE_NAME__ __P((DB_ENV *, u_long, u_long));
|
extern void __os_sleep__DB_UNIQUE_NAME__ __P((DB_ENV *, u_long, u_long));
|
||||||
extern void __os_free__DB_UNIQUE_NAME__ __P((DB_ENV *, void *));
|
|
||||||
extern int __os_realloc__DB_UNIQUE_NAME__ __P((DB_ENV *, size_t, void *));
|
|
||||||
extern int __os_malloc__DB_UNIQUE_NAME__ __P((DB_ENV *, size_t, void *));
|
|
||||||
extern int __os_calloc__DB_UNIQUE_NAME__ __P((DB_ENV *, size_t, size_t, void *));
|
|
||||||
extern int __os_strdup__DB_UNIQUE_NAME__ __P((DB_ENV *, const char *, void *));
|
|
||||||
extern void __os_ufree__DB_UNIQUE_NAME__ __P((DB_ENV *, void *));
|
extern void __os_ufree__DB_UNIQUE_NAME__ __P((DB_ENV *, void *));
|
||||||
extern int __os_urealloc__DB_UNIQUE_NAME__ __P((DB_ENV *, size_t, void *));
|
|
||||||
extern int __os_umalloc__DB_UNIQUE_NAME__ __P((DB_ENV *, size_t, void *));
|
|
||||||
extern int __os_exists__DB_UNIQUE_NAME__ __P((const char *, int *));
|
|
||||||
extern int __db_omode__DB_UNIQUE_NAME__ __P((const char *));
|
|
||||||
extern int __os_id__DB_UNIQUE_NAME__ __P((DB_ENV *, pid_t *, db_threadid_t*));
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,8 +54,10 @@ void __add_idx_key_type __P((vdbe_t *, index_t *));
|
||||||
void __create_foreign_key __P((parser_t *, id_list_t *, token_t *, id_list_t *, int));
|
void __create_foreign_key __P((parser_t *, id_list_t *, token_t *, id_list_t *, int));
|
||||||
void __defer_foreign_key __P((parser_t *, int));
|
void __defer_foreign_key __P((parser_t *, int));
|
||||||
void __create_index __P((parser_t *, token_t *, src_list_t *, id_list_t *, int, token_t *, token_t *));
|
void __create_index __P((parser_t *, token_t *, src_list_t *, id_list_t *, int, token_t *, token_t *));
|
||||||
|
void __drop_index __P((parser_t *, src_list_t *));
|
||||||
id_list_t *__id_list_append __P((id_list_t *, token_t *));
|
id_list_t *__id_list_append __P((id_list_t *, token_t *));
|
||||||
src_list_t *__src_list_append __P((src_list_t *, token_t *, token_t *));
|
src_list_t *__src_list_append __P((src_list_t *, token_t *, token_t *));
|
||||||
|
void __src_list_assign_cursors __P((parser_t *, src_list_t *));
|
||||||
void __src_list_add_alias __P((src_list_t *, token_t *));
|
void __src_list_add_alias __P((src_list_t *, token_t *));
|
||||||
void __id_list_delete __P((id_list_t *));
|
void __id_list_delete __P((id_list_t *));
|
||||||
int __id_list_index __P((id_list_t *, const char *));
|
int __id_list_index __P((id_list_t *, const char *));
|
||||||
|
@ -119,6 +121,7 @@ void __vdbe_delete_trigger __P((trigger_t *));
|
||||||
void __drop_trigger __P((parser_t *, src_list_t *));
|
void __drop_trigger __P((parser_t *, src_list_t *));
|
||||||
void __drop_trigger_ptr __P((parser_t *, trigger_t *, int));
|
void __drop_trigger_ptr __P((parser_t *, trigger_t *, int));
|
||||||
int __triggers_exist __P((parser_t *, trigger_t *, int, int, int, expr_list_t *));
|
int __triggers_exist __P((parser_t *, trigger_t *, int, int, int, expr_list_t *));
|
||||||
|
int __code_row_trigger __P(());
|
||||||
void __update __P((parser_t *, src_list_t *, expr_list_t *, expr_t *, int));
|
void __update __P((parser_t *, src_list_t *, expr_list_t *, expr_t *, int));
|
||||||
void __vacuum __P((parser_t *, token_t *));
|
void __vacuum __P((parser_t *, token_t *));
|
||||||
int __execute_vacuum __P((char **, DBSQL *));
|
int __execute_vacuum __P((char **, DBSQL *));
|
||||||
|
@ -160,7 +163,7 @@ int __sm_get_format_version __P((sm_t *, u_int32_t *));
|
||||||
int __sm_set_schema_sig __P((sm_t *, u_int32_t));
|
int __sm_set_schema_sig __P((sm_t *, u_int32_t));
|
||||||
int __sm_get_schema_sig __P((sm_t *, u_int32_t *));
|
int __sm_get_schema_sig __P((sm_t *, u_int32_t *));
|
||||||
void __register_builtin_funcs __P((DBSQL *));
|
void __register_builtin_funcs __P((DBSQL *));
|
||||||
int get_keyword_code __P((const char *, int));
|
int __get_keyword_code __P((const char *, int));
|
||||||
int __run_sql_parser __P((parser_t *, const char *, char **));
|
int __run_sql_parser __P((parser_t *, const char *, char **));
|
||||||
int __api_step __P((dbsql_stmt_t *, int *, const char ***, const char ***));
|
int __api_step __P((dbsql_stmt_t *, int *, const char ***, const char ***));
|
||||||
int __vdbe_exec __P((vdbe_t *));
|
int __vdbe_exec __P((vdbe_t *));
|
||||||
|
|
|
@ -202,7 +202,7 @@ struct __dbsql_db {
|
||||||
* Similarly, the DBSQL_COOKIE flag is set when the OP_VerifyCookie opcode
|
* Similarly, the DBSQL_COOKIE flag is set when the OP_VerifyCookie opcode
|
||||||
* is emitted, and prevents duplicate OP_VerifyCookies from taking up space
|
* is emitted, and prevents duplicate OP_VerifyCookies from taking up space
|
||||||
* and slowing down execution. TODO: do we need this?
|
* and slowing down execution. TODO: do we need this?
|
||||||
*
|
*
|
||||||
* The DBSQL_SCHEMA_LOADED flag is set after the database schema has been
|
* The DBSQL_SCHEMA_LOADED flag is set after the database schema has been
|
||||||
* read into internal hash tables.
|
* read into internal hash tables.
|
||||||
*
|
*
|
||||||
|
@ -447,7 +447,7 @@ struct foreign_key {
|
||||||
* key is set to NULL. CASCADE means that a DELETE or UPDATE of the
|
* key is set to NULL. CASCADE means that a DELETE or UPDATE of the
|
||||||
* referenced table row is propagated into the row that holds the
|
* referenced table row is propagated into the row that holds the
|
||||||
* foreign key.
|
* foreign key.
|
||||||
*
|
*
|
||||||
* The following symbolic values are used to record which type
|
* The following symbolic values are used to record which type
|
||||||
* of action to take.
|
* of action to take.
|
||||||
*/
|
*/
|
||||||
|
@ -479,7 +479,7 @@ struct foreign_key {
|
||||||
* In the table_t structure describing Ex1, nCol==3 because there are
|
* In the table_t structure describing Ex1, nCol==3 because there are
|
||||||
* three columns in the table. In the index_t structure describing
|
* three columns in the table. In the index_t structure describing
|
||||||
* Ex2, nColumn==2 since 2 of the 3 columns of Ex1 are indexed.
|
* Ex2, nColumn==2 since 2 of the 3 columns of Ex1 are indexed.
|
||||||
* The value of aiColumn is {2, 0}. aiColumn[0]==2 because the
|
* The value of aiColumn is {2, 0}. aiColumn[0]==2 because the
|
||||||
* first column to be indexed (c3) has an index of 2 in Ex1.aCol[].
|
* first column to be indexed (c3) has an index of 2 in Ex1.aCol[].
|
||||||
* The second column to be indexed (c1) has an index of 0 in
|
* The second column to be indexed (c1) has an index of 0 in
|
||||||
* Ex1.aCol[], hence Ex2.aiColumn[1]==0.
|
* Ex1.aCol[], hence Ex2.aiColumn[1]==0.
|
||||||
|
@ -587,7 +587,7 @@ struct expr {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These macros can be used to test, set, or clear bits in the
|
* These macros can be used to test, set, or clear bits in the
|
||||||
* expr_t.flags field.
|
* expr_t.flags field.
|
||||||
*/
|
*/
|
||||||
#define ExprHasProperty(E,P) (((E)->flags&(P))==(P))
|
#define ExprHasProperty(E,P) (((E)->flags&(P))==(P))
|
||||||
|
@ -862,10 +862,10 @@ struct auth_context {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Each trigger present in the database schema is stored as an instance of
|
* Each trigger present in the database schema is stored as an instance of
|
||||||
* struct trigger.
|
* struct trigger.
|
||||||
*
|
*
|
||||||
* Pointers to instances of struct trigger are stored in two ways.
|
* Pointers to instances of struct trigger are stored in two ways.
|
||||||
* 1. In the "trigHash" hash table (part of the DBSQL* that represents the
|
* 1. In the "trigHash" hash table (part of the DBSQL* that represents the
|
||||||
* database). This allows trigger_t structures to be retrieved by name.
|
* database). This allows trigger_t structures to be retrieved by name.
|
||||||
* 2. All triggers associated with a single table form a linked list, using the
|
* 2. All triggers associated with a single table form a linked list, using the
|
||||||
* pNext member of struct trigger. A pointer to the first element of the
|
* pNext member of struct trigger. A pointer to the first element of the
|
||||||
|
@ -897,15 +897,15 @@ struct trigger {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* An instance of struct trigger_step_t is used to store a single SQL statement
|
* An instance of struct trigger_step_t is used to store a single SQL statement
|
||||||
* that is a part of a trigger-program.
|
* that is a part of a trigger-program.
|
||||||
*
|
*
|
||||||
* Instances of struct trigger_step_t are stored in a singly linked list
|
* Instances of struct trigger_step_t are stored in a singly linked list
|
||||||
* (linked using the "pNext" member) referenced by the "step_list" member of
|
* (linked using the "pNext" member) referenced by the "step_list" member of
|
||||||
* the associated struct trigger instance. The first element of the linked
|
* the associated struct trigger instance. The first element of the linked
|
||||||
* list is the first step of the trigger-program.
|
* list is the first step of the trigger-program.
|
||||||
*
|
*
|
||||||
* The "op" member indicates whether this is a "DELETE", "INSERT", "UPDATE" or
|
* The "op" member indicates whether this is a "DELETE", "INSERT", "UPDATE" or
|
||||||
* "SELECT" statement. The meanings of the other members is determined by the
|
* "SELECT" statement. The meanings of the other members is determined by the
|
||||||
* value of "op" as follows:
|
* value of "op" as follows:
|
||||||
*
|
*
|
||||||
* (op == TK_INSERT)
|
* (op == TK_INSERT)
|
||||||
|
@ -915,7 +915,7 @@ struct trigger {
|
||||||
* target -> A token holding the name of the table to insert into.
|
* target -> A token holding the name of the table to insert into.
|
||||||
* pExprList -> If this is an INSERT INTO ... VALUES ... statement, then
|
* pExprList -> If this is an INSERT INTO ... VALUES ... statement, then
|
||||||
* this stores values to be inserted. Otherwise NULL.
|
* this stores values to be inserted. Otherwise NULL.
|
||||||
* pIdList -> If this is an INSERT INTO ... (<column-names>) VALUES ...
|
* pIdList -> If this is an INSERT INTO ... (<column-names>) VALUES ...
|
||||||
* statement, then this stores the column-names to be
|
* statement, then this stores the column-names to be
|
||||||
* inserted into.
|
* inserted into.
|
||||||
*
|
*
|
||||||
|
@ -923,7 +923,7 @@ struct trigger {
|
||||||
* target -> A token holding the name of the table to delete from.
|
* target -> A token holding the name of the table to delete from.
|
||||||
* pWhere -> The WHERE clause of the DELETE statement if one is specified.
|
* pWhere -> The WHERE clause of the DELETE statement if one is specified.
|
||||||
* Otherwise NULL.
|
* Otherwise NULL.
|
||||||
*
|
*
|
||||||
* (op == TK_UPDATE)
|
* (op == TK_UPDATE)
|
||||||
* target -> A token holding the name of the table to update rows of.
|
* target -> A token holding the name of the table to update rows of.
|
||||||
* pWhere -> The WHERE clause of the UPDATE statement if one is specified.
|
* pWhere -> The WHERE clause of the UPDATE statement if one is specified.
|
||||||
|
@ -931,18 +931,18 @@ struct trigger {
|
||||||
* pExprList -> A list of the columns to update and the expressions to update
|
* pExprList -> A list of the columns to update and the expressions to update
|
||||||
* them to. See __update() documentation of "pChanges"
|
* them to. See __update() documentation of "pChanges"
|
||||||
* argument.
|
* argument.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct trigger_step {
|
struct trigger_step {
|
||||||
int op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT,
|
int op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT,
|
||||||
TK_SELECT */
|
TK_SELECT */
|
||||||
int orconf; /* OE_Rollback etc. */
|
int orconf; /* OE_Rollback etc. */
|
||||||
trigger_t *pTrig; /* The trigger that this step is a part of */
|
trigger_t *pTrig; /* The trigger that this step is a part of */
|
||||||
select_t *pSelect; /* Valid for SELECT and sometimes
|
select_t *pSelect; /* Valid for SELECT and sometimes
|
||||||
INSERT steps (when pExprList == 0) */
|
INSERT steps (when pExprList == 0) */
|
||||||
token_t target; /* Valid for DELETE, UPDATE, INSERT steps */
|
token_t target; /* Valid for DELETE, UPDATE, INSERT steps */
|
||||||
expr_t *pWhere; /* Valid for DELETE, UPDATE steps */
|
expr_t *pWhere; /* Valid for DELETE, UPDATE steps */
|
||||||
expr_list_t *pExprList; /* Valid for UPDATE statements and sometimes
|
expr_list_t *pExprList; /* Valid for UPDATE statements and sometimes
|
||||||
INSERT steps (when pSelect == 0) */
|
INSERT steps (when pSelect == 0) */
|
||||||
id_list_t *pIdList; /* Valid for INSERT statements only */
|
id_list_t *pIdList; /* Valid for INSERT statements only */
|
||||||
trigger_step_t * pNext; /* Next in the link-list */
|
trigger_step_t * pNext; /* Next in the link-list */
|
||||||
|
@ -954,15 +954,15 @@ struct trigger_step {
|
||||||
* being coded, its associated trigger_stack_t instance is pointed to by the
|
* being coded, its associated trigger_stack_t instance is pointed to by the
|
||||||
* "pTriggerStack" member of the Parse structure.
|
* "pTriggerStack" member of the Parse structure.
|
||||||
*
|
*
|
||||||
* The pTab member points to the table that triggers are being coded on. The
|
* The pTab member points to the table that triggers are being coded on. The
|
||||||
* newIdx member contains the index of the vdbe cursor that points at the temp
|
* newIdx member contains the index of the vdbe cursor that points at the temp
|
||||||
* table that stores the new.* references. If new.* references are not valid
|
* table that stores the new.* references. If new.* references are not valid
|
||||||
* for the trigger being coded (for example an ON DELETE trigger), then newIdx
|
* for the trigger being coded (for example an ON DELETE trigger), then newIdx
|
||||||
* is set to -1. The oldIdx member is analogous to newIdx, for old.*
|
* is set to -1. The oldIdx member is analogous to newIdx, for old.*
|
||||||
* references.
|
* references.
|
||||||
*
|
*
|
||||||
* The ON CONFLICT policy to be used for the trigger program steps is stored
|
* The ON CONFLICT policy to be used for the trigger program steps is stored
|
||||||
* as the orconf member. If this is OE_Default, then the ON CONFLICT clause
|
* as the orconf member. If this is OE_Default, then the ON CONFLICT clause
|
||||||
* specified for individual triggers steps is used.
|
* specified for individual triggers steps is used.
|
||||||
*
|
*
|
||||||
* struct trigger_stack_t has a "pNext" member, to allow linked lists to be
|
* struct trigger_stack_t has a "pNext" member, to allow linked lists to be
|
||||||
|
@ -972,7 +972,7 @@ struct trigger_step {
|
||||||
* restored to the pTriggerStack member of the Parse stucture and coding of
|
* restored to the pTriggerStack member of the Parse stucture and coding of
|
||||||
* the parent trigger continues.
|
* the parent trigger continues.
|
||||||
*
|
*
|
||||||
* Before a nested trigger is coded, the linked list pointed to by the
|
* Before a nested trigger is coded, the linked list pointed to by the
|
||||||
* pTriggerStack is scanned to ensure that the trigger is not about to be coded
|
* pTriggerStack is scanned to ensure that the trigger is not about to be coded
|
||||||
* recursively. If this condition is detected, the nested trigger is not coded.
|
* recursively. If this condition is detected, the nested trigger is not coded.
|
||||||
*/
|
*/
|
||||||
|
@ -990,7 +990,7 @@ struct trigger_stack {
|
||||||
/*
|
/*
|
||||||
* The following structure contains information used by the __ref_normalizeXXX
|
* The following structure contains information used by the __ref_normalizeXXX
|
||||||
* routines as they walk the parse tree to make database references
|
* routines as they walk the parse tree to make database references
|
||||||
* explicit.
|
* explicit.
|
||||||
*/
|
*/
|
||||||
typedef struct ref_normalizer_ctx ref_normalizer_ctx_t;
|
typedef struct ref_normalizer_ctx ref_normalizer_ctx_t;
|
||||||
struct ref_normalizer_ctx {
|
struct ref_normalizer_ctx {
|
||||||
|
|
|
@ -37,10 +37,16 @@ extern "C" {
|
||||||
#define DBSQL_ASSERT(e)
|
#define DBSQL_ASSERT(e)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Purposly ignore return value.
|
||||||
|
*/
|
||||||
|
#define IGNORE_RESULT(x) \
|
||||||
|
(void)!(x)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "Shut that bloody compiler up!"
|
* "Shut that bloody compiler up!"
|
||||||
*
|
*
|
||||||
* Unused, or not-used-yet variable. We need to write and then read the
|
* Unused, or not-usedyet variable. We need to write and then read the
|
||||||
* variable, some compilers are too bloody clever by half.
|
* variable, some compilers are too bloody clever by half.
|
||||||
*/
|
*/
|
||||||
#define COMPQUIET(n, v) \
|
#define COMPQUIET(n, v) \
|
||||||
|
|
|
@ -45,7 +45,7 @@ struct keyword {
|
||||||
u_int8_t token_type; /* token_t value for this keyword */
|
u_int8_t token_type; /* token_t value for this keyword */
|
||||||
u_int8_t len; /* Length of this keyword */
|
u_int8_t len; /* Length of this keyword */
|
||||||
u_int8_t inext; /* Index in sql_tokens_table[] of next with
|
u_int8_t inext; /* Index in sql_tokens_table[] of next with
|
||||||
same hash */
|
same hash */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -164,10 +164,10 @@ static u_int8_t ai_table[KEY_HASH_SIZE];
|
||||||
/*
|
/*
|
||||||
* __get_keyword_code --
|
* __get_keyword_code --
|
||||||
* This function looks up an identifier to determine if it is a
|
* This function looks up an identifier to determine if it is a
|
||||||
* keyword. If it is a keyword, the token code of that keyword is
|
* keyword. If it is a keyword, the token code of that keyword is
|
||||||
* returned. If the input is not a keyword, TK_ID is returned.
|
* returned. If the input is not a keyword, TK_ID is returned.
|
||||||
*
|
*
|
||||||
* PUBLIC: int get_keyword_code __P((const char *, int));
|
* PUBLIC: int __get_keyword_code __P((const char *, int));
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
__get_keyword_code(z, n)
|
__get_keyword_code(z, n)
|
||||||
|
@ -234,7 +234,7 @@ static const char id_char_p[] = {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* __get_token --
|
* __get_token --
|
||||||
* Return the length of the token that begins at z[0].
|
* Return the length of the token that begins at z[0].
|
||||||
* Store the token type in *token_type before returning.
|
* Store the token type in *token_type before returning.
|
||||||
*
|
*
|
||||||
* STATIC: static int __get_token __P((const unsigned char *, int *));
|
* STATIC: static int __get_token __P((const unsigned char *, int *));
|
||||||
|
@ -459,7 +459,7 @@ __get_token(z, token_type)
|
||||||
* PUBLIC: int __run_sql_parser __P((parser_t *, const char *, char **));
|
* PUBLIC: int __run_sql_parser __P((parser_t *, const char *, char **));
|
||||||
*/
|
*/
|
||||||
/*TODO: REMOVE THIS If an error occurs
|
/*TODO: REMOVE THIS If an error occurs
|
||||||
* and pzErrMsg!=NULL then an error message might be written into
|
* and pzErrMsg!=NULL then an error message might be written into
|
||||||
* memory obtained from malloc() and *pzErrMsg made to point to that
|
* memory obtained from malloc() and *pzErrMsg made to point to that
|
||||||
* error message. Or maybe not.
|
* error message. Or maybe not.
|
||||||
*/
|
*/
|
||||||
|
@ -598,7 +598,7 @@ __run_sql_parser(parser, sql, err_msgs)
|
||||||
* returns 1 if it ends in the START state and 0 if it ends
|
* returns 1 if it ends in the START state and 0 if it ends
|
||||||
* in any other state.
|
* in any other state.
|
||||||
*
|
*
|
||||||
* (1) EXPLAIN The keyword EXPLAIN has been seen at the beginning of
|
* (1) EXPLAIN The keyword EXPLAIN has been seen at the beginning of
|
||||||
* a statement.
|
* a statement.
|
||||||
*
|
*
|
||||||
* (2) CREATE The keyword CREATE has been seen at the beginning of a
|
* (2) CREATE The keyword CREATE has been seen at the beginning of a
|
||||||
|
@ -649,7 +649,7 @@ dbsql_complete_stmt(sql)
|
||||||
* returns the next state.
|
* returns the next state.
|
||||||
*/
|
*/
|
||||||
static const u_int8_t trans[7][8] = {
|
static const u_int8_t trans[7][8] = {
|
||||||
/* Token: */
|
/* Token: */
|
||||||
/* State: ** EXPLAIN CREATE TEMP TRIGGER END SEMI WS OTHER */
|
/* State: ** EXPLAIN CREATE TEMP TRIGGER END SEMI WS OTHER */
|
||||||
/* 0 START: */ { 1, 2, 3, 3, 3, 0, 0, 3, },
|
/* 0 START: */ { 1, 2, 3, 3, 3, 0, 0, 3, },
|
||||||
/* 1 EXPLAIN: */ { 3, 2, 3, 3, 3, 0, 1, 3, },
|
/* 1 EXPLAIN: */ { 3, 2, 3, 3, 3, 0, 1, 3, },
|
||||||
|
|
Loading…
Reference in a new issue