numerous fixes

This commit is contained in:
Gregory Burd 2023-10-21 13:06:35 -04:00
parent 8f5855b6b6
commit bdd732cef7
23 changed files with 305 additions and 158 deletions

2
.gitignore vendored
View file

@ -8,4 +8,4 @@ dist/config.hin
dist/configure
src/py/setup.py
test/scr050/Makefile
result-bin

2
README
View file

@ -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.

17
dist/Makefile.in vendored
View file

@ -125,8 +125,8 @@ C_FILES=\
$(srcdir)/os/os_jtime.c $(srcdir)/clib/memcmp.c \
$(srcdir)/clib/strcasecmp.c $(srcdir)/os/dbsql_alloc.c \
$(srcdir)/common/str.c $(srcdir)/common/dbsql_atoi.c \
$(srcdir)/common/dbsql_atof.c $(srcdir)/safety.c \
$(srcdir)/clib/strdup.c
$(srcdir)/common/dbsql_atof.c $(srcdir)/common/dbsql_fop.c \
$(srcdir)/safety.c $(srcdir)/clib/strdup.c
##################################################
# 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@ \
sql_fns@o@ random@o@ cg_update@o@ cg_delete@o@ hash@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@ \
os_jtime@o@ memcmp@o@ dbsql_atof@o@ safety@o@ dbsql_atoi@o@ \
strcasecmp@o@ strdup@o@ dbsql_alloc@o@ str@o@
vdbe@o@ vdbe_method@o@ sm@o@ snprintf@o@ dbsql_err@o@ \
dbsql_fop@o@ cg_select@o@ os_jtime@o@ memcmp@o@ \
dbsql_atof@o@ safety@o@ dbsql_atoi@o@ strcasecmp@o@ \
strdup@o@ dbsql_alloc@o@ str@o@
LEMON_OBJS=\
lemon@o@
@ -187,12 +188,12 @@ $(libdbsql): $(DEF_LIB)
$(ln) -s $(libdbsql_version) $@)
# 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)
test ! -f $(ranlib) || $(ranlib) $@
# 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)
##################################################
@ -396,6 +397,8 @@ dbsql_atoi@o@: $(srcdir)/common/dbsql_atoi.c
$(CC) $(CFLAGS) $?
dbsql_err@o@: $(srcdir)/common/dbsql_err.c
$(CC) $(CFLAGS) $?
dbsql_fop@o@: $(srcdir)/common/dbsql_fop.c
$(CC) $(CFLAGS) $?
str@o@: $(srcdir)/common/str.c
$(CC) $(CFLAGS) $?
hash@o@: $(srcdir)/common/hash.c

20
dist/sqlconf vendored
View file

@ -28,10 +28,19 @@ args="--enable-test $args"
args="--enable-tcl $args"
#args="--enable-sqlite-compat $args"
args="--enable-soundex-sqlfn $args"
args="--with-tcl=/nix/store/aqlscqccxp85w5zxrcmim7qf1i88xyli-tcl-8.5.19/lib $args"
args="--with-berkeleydb=/nix/store/mlhib3c2ra8bj36vhxmwqhyxph8a8sgf-db-4.8.30 $args"
#args="--with-tcl=/usr/lib/tcl-8.5.19/lib $args"
#args="--with-berkeleydb=/usr/local/db-4.8.30 $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"
env $cppflags $ldflags $libs sh ../dist/configure -C $args
@ -57,3 +66,8 @@ rm -f tags
ln -s ../dist/tags tags
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

View file

@ -49,6 +49,12 @@
configureFlags = [
"--host ${system}"
];
buildInputs = [
(enableDebuging db4)
glibc.out
glibc.static
tcl-8_5
];
nativeBuildInputs = [ autoreconfHook ];
meta = {
changelog = "https://git.burd.me/greg/dbsql/raw/branch/main/ChangeLog";

View file

@ -1,25 +1,26 @@
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
# nativeBuildInputs is usually what you want -- tools you need to run
nativeBuildInputs = with pkgs.buildPackages; [
act
autoconf
db4
ed
gcc
gdb
gettext
libtool
m4
pkg-config
perl
ripgrep
tcl-8_5
];
buildInputs = with pkgs; [
# (enableDebuging db4)
db4
glibc.out
glibc.static
tcl-8_5
];
DOCKER_BUILDKIT = 1;

View file

@ -1360,20 +1360,21 @@ dbsql_create_env(dbpp, dir, crypt, mode, flags)
return DBSQL_CANTOPEN;
}
} else {
if (__os_exists(dbenv, dir, &dir_p) == 0) {
if (__dbsql_exists(NULL, dir, &dir_p) == 0) {
if (dir_p) {
char buf[1024];
snprintf(buf, 1024, "%s%s%s", 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;
} else {
__dbsql_err(NULL,
"Environment must be a directory.");
return DBSQL_INVALID_NAME;
}
} else { /* TODO __db_omode("rwxrwxrwx"):mode) != 0) */
if (mkdir(dir, mode == 0 ? 0777 : mode) != 0)
} else {
mode = mode == 0 ? __dbsql_omode(NULL, "rwxrwxrwx") : mode;
if (__dbsql_mkdir(NULL, dir, mode) != 0)
return errno;
}
}

View file

@ -100,7 +100,7 @@ __null_callback(not_used, n, a, b)
/*
* __parse_exec --
* 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
* constructed VDBE code to do the work of the SQL statement.
* This routine just has to execute the VDBE code.
@ -163,7 +163,7 @@ __parse_exec(parser)
/*
* __find_table --
* Locate the in-memory structure that describes
* Locate the in-memory structure that describes
* a particular database table given the name
* of that table and (optionally) the name of the database
* containing the table. Return NULL if not found.
@ -199,7 +199,7 @@ __find_table(dbp, name, database)
/*
* __locate_table --
* Locate the in-memory structure that describes
* Locate the in-memory structure that describes
* a particular database table given the name
* of that table and (optionally) the name of the database
* containing the table. Return NULL if not found.
@ -236,7 +236,7 @@ __locate_table(parser, name, database)
/*
* __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
* and the name of the database that contains the index.
* Return NULL if not found.
@ -433,7 +433,7 @@ __commit_internal_changes(dbp)
* This routine just deletes the data structure. It does not unlink
* the table data structure from the hash table. Nor does it remove
* 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.
* Indices associated with the table are unlinked from the "db"
* 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
* 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) {
next_fkey = fkey->pNextFrom;
@ -548,7 +548,7 @@ __table_name_from_token(name)
/*
* __open_master_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
* on cursor 0.
*
@ -636,9 +636,9 @@ void __start_table(parser, start, name, temp, view)
}
}
#endif
/*
/*
* Before trying to create a temporary table, make sure the DB for
* 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 &&
(idx->iDb == 0 || !parser->initFlag)) {
__str_append(&parser->zErrMsg,
"there is already an index named ",
"there is already an index named ",
n, (char*)0);
__dbsql_free(dbp, n);
parser->nErr++;
@ -813,7 +813,7 @@ __add_not_null(parser, on_error)
* in 'type'.
*
* PUBLIC: void __add_column_type __P((parser_t *, token_t *, token_t *));
*/
*/
void
__add_column_type(parser, first, last)
parser_t *parser;
@ -884,7 +884,7 @@ __add_default_value(parser, val, minus)
/*
* __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
* 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
@ -1045,7 +1045,8 @@ __add_collate_type(parser, type)
*
* PUBLIC: void __change_schema_signature __P((DBSQL *, vdbe_t *));
*/
void __change_schema_signature(dbp, v)
void
__change_schema_signature(dbp, v)
DBSQL *dbp;
vdbe_t *v;
{
@ -1184,7 +1185,7 @@ __gen_create_table_stmt(table)
* recently changed, so the entry for this table already exists in
* the master table. We do not want to create it again.
* 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
* 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) {
int n;
vdbe_t *v;
v = __parser_get_vdbe(parser);
if (v == 0)
return;
@ -1305,8 +1306,8 @@ __ending_create_table_paren(parser, end, select)
if (parser->explain == 0 && parser->nErr == 0) {
table_t *old;
foreign_key_t *fkey;
old = __hash_insert(&dbp->aDb[table->iDb].tblHash,
table->zName, strlen(table->zName) + 1, table);
old = __hash_insert(&dbp->aDb[table->iDb].tblHash,
table->zName, strlen(table->zName) + 1, table);
if (old) {
/* Malloc must have failed inside __hash_insert() */
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 nCol == 0, then 'table' must be a VIEW */
/* If nCol == 0, then 'table' must be a VIEW */
DBSQL_ASSERT(table->pSelect);
sel = table->pSelect;
@ -1483,7 +1484,7 @@ __view_get_column_names(parser, table)
__select_unbind(sel);
__expr_list_delete(sel->pEList);
sel->pEList = elist;
return nerr;
return nerr;
}
/*
@ -1627,7 +1628,7 @@ __drop_table(parser, name, view)
}
#endif
if (table->readOnly) {
__str_append(&parser->zErrMsg, "table ", table->zName,
__str_append(&parser->zErrMsg, "table ", table->zName,
" may not be dropped", (char*)0);
parser->nErr++;
return;
@ -1819,7 +1820,7 @@ void __create_foreign_key(parser, from_col, to, to_col, flags)
if (to_col && to_col->nId!=1 ){
__str_nappend(&parser->zErrMsg,
"foreign key on ", -1,
table->aCol[col].zName, -1,
table->aCol[col].zName, -1,
" should reference only one column "
"of table ", -1, to->z, to->n, NULL);
parser->nErr++;
@ -1827,7 +1828,7 @@ void __create_foreign_key(parser, from_col, to, to_col, flags)
}
ncol = 1;
} 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 "
"match the number of columns in the referenced "
"table", (char*)0);
@ -1870,7 +1871,7 @@ void __create_foreign_key(parser, from_col, to, to_col, flags)
}
if (j >= table->nCol) {
__str_append(&parser->zErrMsg,
"unknown column \"",
"unknown column \"",
from_col->a[i].zName,
"\" in foreign key definition",
(char*)0);
@ -1929,8 +1930,8 @@ __defer_foreign_key(parser, deferred)
}
/*
* __creat_index --
* Create a new index for an SQL table. 'index' is the name of the
* __create_index --
* 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.
* 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,
@ -1954,7 +1955,8 @@ __defer_foreign_key(parser, deferred)
* 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;
token_t *token;
src_list_t *sltable;
@ -1969,7 +1971,7 @@ void __create_index(parser, token, sltable, list, on_error, start, end)
int i, j;
token_t null_id; /* Fake token for an empty ID list */
ref_normalizer_ctx_t normctx; /* For assigning database
names to sltable */
names to sltable */
int temp; /* True for a temporary index */
DBSQL *dbp = parser->db;
@ -2002,7 +2004,7 @@ void __create_index(parser, token, sltable, list, on_error, start, end)
goto exit_create_index;
}
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);
parser->nErr++;
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
* 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
* 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)
goto exit_create_index;
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);
parser->nErr++;
goto exit_create_index;
@ -2098,8 +2100,8 @@ void __create_index(parser, token, sltable, list, on_error, start, end)
goto exit_create_index;
}
/*
* Allocate the index structure.
/*
* Allocate the index structure.
*/
if (__dbsql_calloc(dbp, 1, sizeof(index_t) + (strlen(name) + 1) +
(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;
}
/*
/*
* Link the new index_t structure to its table and to the other
* in-memory database structures.
* in-memory database structures.
*/
if (!parser->explain) {
index_t *rindex;
rindex = __hash_insert(&dbp->aDb[index->iDb].idxHash,
index->zName, strlen(index->zName) + 1, index);
rindex = __hash_insert(&dbp->aDb[index->iDb].idxHash,
index->zName, strlen(index->zName) + 1, index);
if (rindex) {
/* Malloc must have failed */
/* Malloc must have failed */
DBSQL_ASSERT(rindex == index);
__dbsql_free(dbp, 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
* filling in the index with the current table contents.
*
* The initFlag is 0 when the user first enters a CREATE INDEX
* command. The initFlag is 1 when a database is opened and
* The initFlag is 0 when the user first enters a CREATE INDEX
* command. The initFlag is 1 when a database is opened and
* CREATE INDEX statements are read out of the master table.
* In the latter case the index already exists on disk, which
* 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
* 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
__drop_index(parser, name)
@ -2335,7 +2337,7 @@ __drop_index(parser, name)
v = __parser_get_vdbe(parser);
if( v ){
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_MemStore, 1, 1, 0},
{ OP_MemLoad, 1, 0, 0}, /* 3 */
@ -2494,7 +2496,7 @@ __src_list_append(list, table, database)
* __src_list_assign_cursors --
* 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
__src_list_assign_cursors(parser, list)
@ -2685,7 +2687,7 @@ __dbsql_txn_abort(parser)
if ((dbp->flags & DBSQL_InTrans) == 0) {
__error_msg(parser,
"cannot rollback - no transaction is active");
return;
return;
}
v = __parser_get_vdbe(parser);
if (v) {
@ -2771,7 +2773,7 @@ __vdbe_prepare_write(parser, checkpoint, idb)
* the database. If a statement transaction was started, then emit
* an OP_Commit that will cause the changes to be committed to disk.
* 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
* call to __vdbe_conclude_write() at the conclusion of the statement.
*
@ -2789,7 +2791,7 @@ __vdbe_conclude_write(parser)
if (v == 0)
return;
if (dbp->flags & DBSQL_InTrans) {
/*
/*
* A BEGIN has executed. Do not commit until we see an
* explicit COMMIT statement.
*/

View file

@ -869,7 +869,7 @@ __code_trigger_program(parser, steplist, orconfin)
* pointing at a row containing values to be substituted for old.*
* expressions in the trigger program(s).
*
* PUBlIC: int __code_row_trigger __P(());
* PUBLIC: int __code_row_trigger __P(());
*
* parser Parser context
* op One of TK_UPDATE, TK_INSERT, TK_DELETE

View file

@ -18,8 +18,12 @@
* General Public License for more details.
*/
#include "dbsql.h"
#include "dbsql_config.h"
#include "dbsql_int.h"
#include "db_int.h"
#include <string.h>
/*
* __dbsql_umalloc --

View file

@ -21,6 +21,8 @@
#include "dbsql_config.h"
#include "dbsql_int.h"
#include <ctype.h>
/*
* __dbsql_atof --
* The string z[] is an ascii representation of a real number.

View file

@ -21,6 +21,8 @@
#include "dbsql_config.h"
#include "dbsql_int.h"
#include <ctype.h>
/*
* __dbsql_atoi --
* Return TRUE if 'str' is a 32-bit signed integer and write

View file

@ -280,8 +280,8 @@ __dbsql_errcall(dbp, error, error_set, fmt, ap)
* are pretty rare anymore.
*/
if ((size_t)(p - errbuf) > sizeof(errbuf)) {
write(
STDERR_FILENO, OVERFLOW_ERROR, sizeof(OVERFLOW_ERROR) - 1);
IGNORE_RESULT(write(
STDERR_FILENO, OVERFLOW_ERROR, sizeof(OVERFLOW_ERROR) - 1));
abort();
/* NOTREACHED */
}

101
src/common/dbsql_fop.c Normal file
View 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;
}

View file

@ -95,6 +95,9 @@
#include "dbsql_config.h"
#include "dbsql_int.h"
#include <ctype.h>
unsigned char __str_upper_to_lower[] = {
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,
@ -164,9 +167,9 @@ __str_append(result, fmt, va_alist)
/*
* __str_nappend --
* Works like __str_append, but each string is now followed by
* a length integer which specifies how much of the source string
* to copy (in bytes). -1 means use the whole string. The 1st
* argument must either be NULL or point to memory obtained from
* a length integer which specifies how much of the source string
* to copy (in bytes). -1 means use the whole string. The 1st
* argument must either be NULL or point to memory obtained from
* __dbsql_calloc().
*
* PUBLIC: void __str_nappend __P((char **, ...));
@ -273,8 +276,8 @@ __str_urealloc(pz)
char *new;
if (pz == 0 || *pz == NULL)
return;
return rc;
if (__dbsql_umalloc(NULL, strlen(*pz) + 1, &new) == ENOMEM) {
rc = ENOMEM;
__dbsql_free(NULL, *pz);
@ -394,7 +397,7 @@ static int __utf8_to_int(const unsigned char *z) {
* '?' Matches exactly one character.
*
* [...] Matches one character from the enclosed list of
* characters.
* characters.
*
* [^...] 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:
*
* abc[*]xyz Matches "abc*xyz" only
* abc[*]xyz Matches "abc*xyz" only
*
* PUBLIC: int __str_glob_cmp __P((const unsigned char *,
* PUBLIC: const unsigned char *));
*/
int
int
__str_glob_cmp(pattern, string)
const unsigned char *pattern;
const unsigned char *string;
@ -526,7 +529,7 @@ __str_glob_cmp(pattern, string)
* PUBLIC: int __str_like_cmp __P((const unsigned char *,
* PUBLIC: const unsigned char *));
*/
int
int
__str_like_cmp(pattern, string)
const unsigned char *pattern;
const unsigned char *string;
@ -588,10 +591,10 @@ __str_like_cmp(pattern, string)
* do not necessarily contain numbers. They could contain text.
*
* 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
* 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()).
*
* PUBLIC: int __str_numeric_cmp __P((const char *, const char *));
@ -631,7 +634,7 @@ __str_numeric_cmp(left, right)
} else {
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.
* This means we can not use the traditional base-64 digit set.
*/
static const char digit[] =
static const char digit[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"

View file

@ -30,6 +30,7 @@
#include <ctype.h>
#include "dbsql_config.h"
#include "dbsql_int.h"
#include "dbsql.h"
#if !defined(_WIN32) && !defined(WIN32)
@ -51,29 +52,29 @@
#endif
struct globals {
/* The Berkeley DBSQL database manager. */
/* The Berkeley DBSQL database manager. */
DBSQL *dbp;
/* The Berkeley DB database environment. */
/* The Berkeley DB database environment. */
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;
/*
* This is the name of our program. It is set in main(), used
* in a number of other places, mostly for error messages.
*/
/*
* This is the name of our program. It is set in main(), used
* in a number of other places, mostly for error messages.
*/
char *progname;
/* An output stream for error messages, normally stdout. */
FILE *errfp;
/*
* Prompt strings. Initialized in main. Settable using the
* '.prompt [main] [continuation]' command.
*/
char prompt[20]; /* First line prompt. default: "SQL> "*/
/*
* Prompt strings. Initialized in main. Settable using the
* '.prompt [main] [continuation]' command.
*/
char prompt[20]; /* First line prompt. default: "SQL> "*/
char prompt2[20]; /* Continuation prompt. default: "...> " */
};
@ -222,11 +223,6 @@ char *modeDescr[MODE_NUM_OF] = {
"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.
*/
@ -326,7 +322,7 @@ callback(arg, num_args, args, cols)
if (p->cnt++ > 0)
fprintf(p->out, "\n");
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));
}
break;
@ -368,7 +364,7 @@ callback(arg, num_args, args, cols)
w = 10;
}
fprintf(p->out, "%-*.*s%s", w, w,
"----------------------------------------------------------"
"----------------------------------------------------------"
"-----------------------------------",
(i == num_args - 1) ?
"\n" : " ");
@ -696,7 +692,7 @@ do_meta_command(line, p)
p->db->exec_printf(p->db,
"SELECT name, type, sql FROM " MASTER_NAME " "
"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,
&err_msgs, args[i]);
}
@ -1490,26 +1486,26 @@ main(argc, argv)
int
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. */
(void)dbsql_version(&v_major, &v_minor, &v_patch);
if (v_major != DBSQL_VERSION_MAJOR || v_minor != DBSQL_VERSION_MINOR) {
fprintf(stderr,
/* Make sure we're loaded with the right version of the DB library. */
(void)dbsql_version(&v_major, &v_minor, &v_patch);
if (v_major != DBSQL_VERSION_MAJOR || v_minor != DBSQL_VERSION_MINOR) {
fprintf(stderr,
"%s: version %d.%d doesn't match library version %d.%d\n",
g.progname, DBSQL_VERSION_MAJOR, DBSQL_VERSION_MINOR,
v_major, v_minor);
return (EXIT_FAILURE);
}
return (EXIT_FAILURE);
}
/* Make sure we're loaded with the right version of the DB library. */
(void)db_version(&v_major, &v_minor, &v_patch);
if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) {
fprintf(stderr,
/* Make sure we're loaded with the right version of the DB library. */
(void)db_version(&v_major, &v_minor, &v_patch);
if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) {
fprintf(stderr,
"%s: version %d.%d doesn't match library version %d.%d\n",
g.progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
v_major, v_minor);
return (EXIT_FAILURE);
}
return (0);
return (EXIT_FAILURE);
}
return (0);
}

View file

@ -23,7 +23,6 @@
*/
#include "dbsql_config.h"
#include "dbsql_int.h"
#include "tcl.h"
@ -42,9 +41,9 @@ static char main_loop[] =
"append line [gets stdin]\n"
"if {[info complete $line]} {\n"
"if {[catch {uplevel #0 $line} result]} {\n"
"puts stderr \"Error: $result\"\n"
"puts stderr \"Error: $result\"\n"
"} elseif {$result!=\"\"} {\n"
"puts $result\n"
"puts $result\n"
"}\n"
"set line {}\n"
"} else {\n"

View file

@ -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_errfile __P((const DBSQL *, int, int, const char *, va_list));
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_clear __P((hash_t *));
void *__hash_find __P((const hash_t *, const void *, int));

View file

@ -32,21 +32,22 @@
extern "C" {
#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_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_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 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)
}

View file

@ -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 __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 __drop_index __P((parser_t *, src_list_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 *));
void __src_list_assign_cursors __P((parser_t *, src_list_t *));
void __src_list_add_alias __P((src_list_t *, token_t *));
void __id_list_delete __P((id_list_t *));
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_ptr __P((parser_t *, trigger_t *, int));
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 __vacuum __P((parser_t *, token_t *));
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_get_schema_sig __P((sm_t *, u_int32_t *));
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 __api_step __P((dbsql_stmt_t *, int *, const char ***, const char ***));
int __vdbe_exec __P((vdbe_t *));

View file

@ -202,7 +202,7 @@ struct __dbsql_db {
* Similarly, the DBSQL_COOKIE flag is set when the OP_VerifyCookie opcode
* is emitted, and prevents duplicate OP_VerifyCookies from taking up space
* and slowing down execution. TODO: do we need this?
*
*
* The DBSQL_SCHEMA_LOADED flag is set after the database schema has been
* 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
* referenced table row is propagated into the row that holds the
* foreign key.
*
*
* The following symbolic values are used to record which type
* of action to take.
*/
@ -479,7 +479,7 @@ struct foreign_key {
* In the table_t structure describing Ex1, nCol==3 because there are
* three columns in the table. In the index_t structure describing
* 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[].
* The second column to be indexed (c1) has an index of 0 in
* 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.
*/
#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
* struct trigger.
* struct trigger.
*
* 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.
* 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
@ -897,15 +897,15 @@ struct trigger {
/*
* 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
* (linked using the "pNext" member) referenced by the "step_list" member of
* the associated struct trigger instance. The first element of the linked
* list is the first step of the trigger-program.
*
*
* 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:
*
* (op == TK_INSERT)
@ -915,7 +915,7 @@ struct trigger {
* target -> A token holding the name of the table to insert into.
* pExprList -> If this is an INSERT INTO ... VALUES ... statement, then
* 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
* inserted into.
*
@ -923,7 +923,7 @@ struct trigger {
* target -> A token holding the name of the table to delete from.
* pWhere -> The WHERE clause of the DELETE statement if one is specified.
* Otherwise NULL.
*
*
* (op == TK_UPDATE)
* 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.
@ -931,18 +931,18 @@ struct trigger {
* pExprList -> A list of the columns to update and the expressions to update
* them to. See __update() documentation of "pChanges"
* argument.
*
*
*/
struct trigger_step {
int op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT,
TK_SELECT */
int orconf; /* OE_Rollback etc. */
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) */
token_t target; /* Valid for DELETE, UPDATE, INSERT 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) */
id_list_t *pIdList; /* Valid for INSERT statements only */
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
* "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
* 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
* is set to -1. The oldIdx member is analogous to newIdx, for old.*
* references.
*
* 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
* 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
* specified for individual triggers steps is used.
*
* 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
* 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
* 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
* routines as they walk the parse tree to make database references
* explicit.
* explicit.
*/
typedef struct ref_normalizer_ctx ref_normalizer_ctx_t;
struct ref_normalizer_ctx {

View file

@ -37,10 +37,16 @@ extern "C" {
#define DBSQL_ASSERT(e)
#endif
/*
* Purposly ignore return value.
*/
#define IGNORE_RESULT(x) \
(void)!(x)
/*
* "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.
*/
#define COMPQUIET(n, v) \

View file

@ -45,7 +45,7 @@ struct keyword {
u_int8_t token_type; /* token_t value for this keyword */
u_int8_t len; /* Length of this keyword */
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 --
* 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.
*
* PUBLIC: int get_keyword_code __P((const char *, int));
* PUBLIC: int __get_keyword_code __P((const char *, int));
*/
int
__get_keyword_code(z, n)
@ -234,7 +234,7 @@ static const char id_char_p[] = {
/*
* __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.
*
* 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 **));
*/
/*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
* 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
* 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.
*
* (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.
*/
static const u_int8_t trans[7][8] = {
/* Token: */
/* Token: */
/* State: ** EXPLAIN CREATE TEMP TRIGGER END SEMI WS OTHER */
/* 0 START: */ { 1, 2, 3, 3, 3, 0, 0, 3, },
/* 1 EXPLAIN: */ { 3, 2, 3, 3, 3, 0, 1, 3, },