diff --git a/HACKING b/HACKING index cae3366..a5e59c7 100644 --- a/HACKING +++ b/HACKING @@ -196,6 +196,31 @@ column to require more than one byte (if the sum of the lengths of columns is greater than 255). I have no idea how this is represented in the data as I have not looked at tables large enough for this to occur yet. +Indices +------- + +Indices are not completely understood but here is what we know. + +On the page pointed to by the table definition a series of records start at +byte offset 0xf8. + +The record generally begins with 0x7f or 0x80. 0x80 is the one's complement of 0x7f and all text data in the index would then need to be negated. The reason +for this negation is unknown, although I suspect it has to do with descending +order. + +Access stored an 'alphabetic sort order' version of the text key columns in the index. Basically this means that upper and lower case characters A-Z are merged and start at 0x60. Digits are 0x56 through 0x5f. Once converted into this +(non-ascii) character set, the text value is able to be sorted in 'alphabetic' +order. A text column will end with a NULL (0x00 or 0xff if negated). + +Beyond the key columns is stored a 3 byte page number and 1 byte row number. + +So to search the index, you need to convert your value into the alphabetic +character set, compare against each index entry, and on successful comparison +follow the page and row number to the data. Because text data is managled +during this conversion there is no 'covered querys' possible (a query that can +be satisfied by reading the index, without descending to the leaf page to read +the data). + KKD Records ----------- diff --git a/config.cache b/config.cache index 9ebf24a..30c75cc 100644 --- a/config.cache +++ b/config.cache @@ -19,6 +19,7 @@ ac_cv_header_fcntl_h=${ac_cv_header_fcntl_h=yes} ac_cv_header_limits_h=${ac_cv_header_limits_h=yes} ac_cv_header_stdc=${ac_cv_header_stdc=no} ac_cv_header_unistd_h=${ac_cv_header_unistd_h=yes} +ac_cv_header_wordexp_h=${ac_cv_header_wordexp_h=yes} ac_cv_lib_fl_yywrap=${ac_cv_lib_fl_yywrap=yes} ac_cv_lib_ibs_main=${ac_cv_lib_ibs_main=no} ac_cv_lib_mdb_mdb_free_handle=${ac_cv_lib_mdb_mdb_free_handle=yes} diff --git a/configure b/configure index 5395a8e..feea0f4 100755 --- a/configure +++ b/configure @@ -2011,14 +2011,54 @@ else fi done +for ac_hdr in wordexp.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2019: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2029: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + echo $ac_n "checking for working const""... $ac_c" 1>&6 -echo "configure:2017: checking for working const" >&5 +echo "configure:2057: checking for working const" >&5 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2111: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else @@ -2088,12 +2128,12 @@ EOF fi echo $ac_n "checking for size_t""... $ac_c" 1>&6 -echo "configure:2092: checking for size_t" >&5 +echo "configure:2132: checking for size_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -2122,14 +2162,14 @@ fi echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6 -echo "configure:2126: checking whether byte ordering is bigendian" >&5 +echo "configure:2166: checking whether byte ordering is bigendian" >&5 if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_cv_c_bigendian=unknown # See if sys/param.h defines the BYTE_ORDER macro. cat > conftest.$ac_ext < #include @@ -2140,11 +2180,11 @@ int main() { #endif ; return 0; } EOF -if { (eval echo configure:2144: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2184: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* # It does; now see whether it defined to BIG_ENDIAN or not. cat > conftest.$ac_ext < #include @@ -2155,7 +2195,7 @@ int main() { #endif ; return 0; } EOF -if { (eval echo configure:2159: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2199: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_bigendian=yes else @@ -2175,7 +2215,7 @@ if test "$cross_compiling" = yes; then { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2232: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_c_bigendian=no else @@ -2216,7 +2256,7 @@ fi OLDLDFLAGS=$LDFLAGS echo $ac_n "checking for initscr in -lncurses""... $ac_c" 1>&6 -echo "configure:2220: checking for initscr in -lncurses" >&5 +echo "configure:2260: checking for initscr in -lncurses" >&5 ac_lib_var=`echo ncurses'_'initscr | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2224,7 +2264,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lncurses $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2279: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -2260,7 +2300,7 @@ fi echo $ac_n "checking for add_history in -lreadline""... $ac_c" 1>&6 -echo "configure:2264: checking for add_history in -lreadline" >&5 +echo "configure:2304: checking for add_history in -lreadline" >&5 ac_lib_var=`echo readline'_'add_history | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2268,7 +2308,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lreadline $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2323: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else diff --git a/configure.in b/configure.in index 0d280e1..635a80e 100644 --- a/configure.in +++ b/configure.in @@ -19,6 +19,7 @@ AC_CHECK_LIB(mdb, mdb_free_handle) dnl Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS(fcntl.h limits.h unistd.h) +AC_CHECK_HEADERS(wordexp.h) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST diff --git a/include/mdbtools.h b/include/mdbtools.h index 913ee3b..ee8b96c 100644 --- a/include/mdbtools.h +++ b/include/mdbtools.h @@ -76,6 +76,7 @@ enum { MDB_LT, MDB_GTEQ, MDB_LTEQ, + MDB_LIKE, MDB_ISNULL, MDB_NOTNULL }; diff --git a/src/extras/Makefile b/src/extras/Makefile index 06daeb3..39e250d 100644 --- a/src/extras/Makefile +++ b/src/extras/Makefile @@ -85,7 +85,7 @@ CONFIG_CLEAN_FILES = PROGRAMS = $(bin_PROGRAMS) -DEFS = -DPACKAGE=\"mdbtools\" -DVERSION=\"0.3\" -DYYTEXT_POINTER=1 -DHAVE_LIBMDB=1 -DHAVE_FCNTL_H=1 -DHAVE_LIMITS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_READLINE=1 -I. -I$(srcdir) +DEFS = -DPACKAGE=\"mdbtools\" -DVERSION=\"0.3\" -DYYTEXT_POINTER=1 -DHAVE_LIBMDB=1 -DHAVE_FCNTL_H=1 -DHAVE_LIMITS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_WORDEXP_H=1 -DHAVE_READLINE=1 -I. -I$(srcdir) CPPFLAGS = LDFLAGS = mdb_dump_OBJECTS = mdb-dump.o mdbsupport.o diff --git a/src/libmdb/Makefile b/src/libmdb/Makefile index 445ce66..c7e00c9 100644 --- a/src/libmdb/Makefile +++ b/src/libmdb/Makefile @@ -76,7 +76,7 @@ VERSION = 0.3 YACC = bison -y lib_LTLIBRARIES = libmdb.la -libmdb_la_SOURCES = catalog.c mem.c file.c kkd.c table.c data.c dump.c backend.c money.c sargs.c index.c +libmdb_la_SOURCES = catalog.c mem.c file.c kkd.c table.c data.c dump.c backend.c money.c sargs.c index.c like.c INCLUDES = -I$(top_srcdir)/include `glib-config --cflags` LIBS = `glib-config --libs` mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs @@ -84,13 +84,13 @@ CONFIG_CLEAN_FILES = LTLIBRARIES = $(lib_LTLIBRARIES) -DEFS = -DPACKAGE=\"mdbtools\" -DVERSION=\"0.3\" -DYYTEXT_POINTER=1 -DHAVE_LIBMDB=1 -DHAVE_FCNTL_H=1 -DHAVE_LIMITS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_READLINE=1 -I. -I$(srcdir) +DEFS = -DPACKAGE=\"mdbtools\" -DVERSION=\"0.3\" -DYYTEXT_POINTER=1 -DHAVE_LIBMDB=1 -DHAVE_FCNTL_H=1 -DHAVE_LIMITS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_WORDEXP_H=1 -DHAVE_READLINE=1 -I. -I$(srcdir) CPPFLAGS = LDFLAGS = libmdb_la_LDFLAGS = libmdb_la_LIBADD = libmdb_la_OBJECTS = catalog.lo mem.lo file.lo kkd.lo table.lo data.lo \ -dump.lo backend.lo money.lo sargs.lo index.lo +dump.lo backend.lo money.lo sargs.lo index.lo like.lo CFLAGS = -g -O2 COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @@ -104,8 +104,8 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) TAR = gtar GZIP_ENV = --best DEP_FILES = .deps/backend.P .deps/catalog.P .deps/data.P .deps/dump.P \ -.deps/file.P .deps/index.P .deps/kkd.P .deps/mem.P .deps/money.P \ -.deps/sargs.P .deps/table.P +.deps/file.P .deps/index.P .deps/kkd.P .deps/like.P .deps/mem.P \ +.deps/money.P .deps/sargs.P .deps/table.P SOURCES = $(libmdb_la_SOURCES) OBJECTS = $(libmdb_la_OBJECTS) diff --git a/src/libmdb/Makefile.am b/src/libmdb/Makefile.am index a93ca1e..9cacf9f 100644 --- a/src/libmdb/Makefile.am +++ b/src/libmdb/Makefile.am @@ -1,4 +1,4 @@ lib_LTLIBRARIES = libmdb.la -libmdb_la_SOURCES= catalog.c mem.c file.c kkd.c table.c data.c dump.c backend.c money.c sargs.c index.c +libmdb_la_SOURCES= catalog.c mem.c file.c kkd.c table.c data.c dump.c backend.c money.c sargs.c index.c like.c INCLUDES = -I$(top_srcdir)/include `glib-config --cflags` LIBS = `glib-config --libs` diff --git a/src/libmdb/Makefile.in b/src/libmdb/Makefile.in index 19e8690..d6968d5 100644 --- a/src/libmdb/Makefile.in +++ b/src/libmdb/Makefile.in @@ -76,7 +76,7 @@ VERSION = @VERSION@ YACC = @YACC@ lib_LTLIBRARIES = libmdb.la -libmdb_la_SOURCES = catalog.c mem.c file.c kkd.c table.c data.c dump.c backend.c money.c sargs.c index.c +libmdb_la_SOURCES = catalog.c mem.c file.c kkd.c table.c data.c dump.c backend.c money.c sargs.c index.c like.c INCLUDES = -I$(top_srcdir)/include `glib-config --cflags` LIBS = `glib-config --libs` mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs @@ -90,7 +90,7 @@ LDFLAGS = @LDFLAGS@ libmdb_la_LDFLAGS = libmdb_la_LIBADD = libmdb_la_OBJECTS = catalog.lo mem.lo file.lo kkd.lo table.lo data.lo \ -dump.lo backend.lo money.lo sargs.lo index.lo +dump.lo backend.lo money.lo sargs.lo index.lo like.lo CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @@ -104,8 +104,8 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) TAR = gtar GZIP_ENV = --best DEP_FILES = .deps/backend.P .deps/catalog.P .deps/data.P .deps/dump.P \ -.deps/file.P .deps/index.P .deps/kkd.P .deps/mem.P .deps/money.P \ -.deps/sargs.P .deps/table.P +.deps/file.P .deps/index.P .deps/kkd.P .deps/like.P .deps/mem.P \ +.deps/money.P .deps/sargs.P .deps/table.P SOURCES = $(libmdb_la_SOURCES) OBJECTS = $(libmdb_la_OBJECTS) diff --git a/src/libmdb/file.c b/src/libmdb/file.c index fbaead6..8bb787f 100644 --- a/src/libmdb/file.c +++ b/src/libmdb/file.c @@ -65,6 +65,17 @@ int j,pos; return mdb; } +void mdb_close(MdbHandle *mdb) +{ + if (mdb->fd > 0) { + close(mdb->fd); + if (mdb->filename) { + free(mdb->filename); + mdb->filename = NULL; + } + } +} + /* ** mdb_read a wrapper for read that bails if anything is wrong */ diff --git a/src/libmdb/like.c b/src/libmdb/like.c new file mode 100644 index 0000000..1fbd90e --- /dev/null +++ b/src/libmdb/like.c @@ -0,0 +1,38 @@ +#include + +int likecmp(char *s, char *r) +{ +int i, ret; + + switch (r[0]) { + case '\0': + if (s[0]=='\0') { + return 1; + } else { + return 0; + } + case '_': + /* skip one character */ + return likecmp(&s[1],&r[1]); + case '%': + /* skip any number of characters */ + /* the strlen(s)+1 is important so the next call can */ + /* if there are trailing characters */ + for(i=0;iop == MDB_LIKE) { + return likecmp(s,sarg->value.s); + } + rc = strncmp(sarg->value.s, s, 255); + switch (sarg->op) { + case MDB_EQUAL: + if (rc==0) return 1; + break; + case MDB_GT: + if (rc<0) return 1; + break; + case MDB_LT: + if (rc>0) return 1; + break; + case MDB_GTEQ: + if (rc<=0) return 1; + break; + case MDB_LTEQ: + if (rc>=0) return 1; + break; + default: + fprintf(stderr, "Calling mdb_test_sarg on unknown operator. Add code to mdb_test_string() for operator %d\n",sarg->op); + break; + } + return 0; +} int mdb_test_int(MdbSarg *sarg, gint32 i) { switch (sarg->op) { @@ -45,6 +75,9 @@ int mdb_test_int(MdbSarg *sarg, gint32 i) } int mdb_test_sarg(MdbHandle *mdb, MdbColumn *col, MdbSarg *sarg, int offset, int len) { +char tmpbuf[256]; +int lastchar; + switch (col->col_type) { case MDB_BYTE: return mdb_test_int(sarg, mdb_get_byte(mdb, offset)); @@ -55,6 +88,11 @@ int mdb_test_sarg(MdbHandle *mdb, MdbColumn *col, MdbSarg *sarg, int offset, int case MDB_LONGINT: return mdb_test_int(sarg, mdb_get_int32(mdb, offset)); break; + case MDB_TEXT: + strncpy(tmpbuf, &mdb->pg_buf[offset],255); + lastchar = len > 255 ? 255 : len; + tmpbuf[lastchar]='\0'; + return mdb_test_string(sarg, tmpbuf); default: fprintf(stderr, "Calling mdb_test_sarg on unknown type. Add code to mdb_test_sarg() for type %d\n",col->col_type); break; @@ -95,7 +133,7 @@ int i; for (i=0;inum_cols;i++) { col = g_ptr_array_index (table->columns, i); - if (!strcmp(col->name,colname)) { + if (!strcasecmp(col->name,colname)) { return mdb_add_sarg(col, in_sarg); } } diff --git a/src/sql/Makefile b/src/sql/Makefile index d3194a9..6550207 100644 --- a/src/sql/Makefile +++ b/src/sql/Makefile @@ -85,7 +85,7 @@ CONFIG_CLEAN_FILES = PROGRAMS = $(bin_PROGRAMS) -DEFS = -DPACKAGE=\"mdbtools\" -DVERSION=\"0.3\" -DYYTEXT_POINTER=1 -DHAVE_LIBMDB=1 -DHAVE_FCNTL_H=1 -DHAVE_LIMITS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_READLINE=1 -I. -I$(srcdir) +DEFS = -DPACKAGE=\"mdbtools\" -DVERSION=\"0.3\" -DYYTEXT_POINTER=1 -DHAVE_LIBMDB=1 -DHAVE_FCNTL_H=1 -DHAVE_LIMITS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_WORDEXP_H=1 -DHAVE_READLINE=1 -I. -I$(srcdir) CPPFLAGS = LDFLAGS = mdb_sql_OBJECTS = mdbsql.o main.o parser.o lexer.o diff --git a/src/sql/lexer.c b/src/sql/lexer.c index 4e7c77c..8d6cef5 100644 --- a/src/sql/lexer.c +++ b/src/sql/lexer.c @@ -1,7 +1,7 @@ /* A lexical scanner generated by flex */ /* Scanner skeleton version: - * $Header: /Users/brian/cvs/mdbtools/mdbtools/src/sql/Attic/lexer.c,v 1.1 2001/04/11 23:33:19 brianb Exp $ + * $Header: /Users/brian/cvs/mdbtools/mdbtools/src/sql/Attic/lexer.c,v 1.2 2001/04/20 21:06:46 brianb Exp $ */ #define FLEX_SCANNER @@ -282,16 +282,19 @@ static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); *yy_cp = '\0'; \ yy_c_buf_p = yy_cp; -#define YY_NUM_RULES 15 -#define YY_END_OF_BUFFER 16 -static yyconst short int yy_accept[61] = +#define YY_NUM_RULES 21 +#define YY_END_OF_BUFFER 22 +static yyconst short int yy_accept[85] = { 0, - 12, 12, 16, 14, 9, 15, 14, 13, 14, 12, - 10, 10, 10, 10, 10, 10, 10, 10, 0, 11, - 0, 13, 0, 13, 13, 12, 10, 10, 10, 10, - 10, 10, 10, 4, 10, 0, 12, 12, 7, 10, - 10, 10, 10, 10, 10, 10, 2, 5, 10, 10, - 10, 10, 10, 10, 6, 10, 1, 8, 3, 0 + 18, 18, 22, 20, 15, 21, 20, 19, 20, 18, + 20, 20, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 20, 0, 17, 0, 19, 0, 19, 19, 18, + 12, 13, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 5, 16, 0, 18, 18, 8, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, + 14, 6, 16, 16, 16, 16, 16, 16, 16, 10, + 7, 16, 16, 16, 1, 9, 3, 16, 16, 11, + 16, 16, 4, 0 } ; static yyconst int yy_ec[256] = @@ -301,15 +304,15 @@ static yyconst int yy_ec[256] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 4, 5, 5, 1, 6, 1, 7, 8, 9, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 1, 1, 1, - 1, 1, 1, 1, 11, 11, 11, 11, 12, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 12, 11, 11, 11, 11, 11, 13, 14, 15, 16, + 10, 10, 10, 10, 10, 10, 10, 1, 1, 11, + 12, 13, 1, 1, 14, 14, 14, 14, 15, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 15, 14, 14, 14, 14, 14, 16, 17, 18, 19, - 17, 18, 11, 19, 20, 11, 11, 21, 22, 23, - 24, 11, 11, 25, 26, 27, 11, 11, 28, 11, - 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, + 20, 21, 14, 22, 23, 14, 24, 25, 26, 27, + 28, 14, 14, 29, 30, 31, 14, 14, 32, 14, + 14, 14, 1, 1, 1, 33, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -326,91 +329,116 @@ static yyconst int yy_ec[256] = 1, 1, 1, 1, 1 } ; -static yyconst int yy_meta[29] = +static yyconst int yy_meta[34] = { 0, 1, 1, 2, 1, 3, 3, 1, 4, 4, 4, + 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4 + 4, 4, 1 } ; -static yyconst short int yy_base[64] = +static yyconst short int yy_base[88] = { 0, - 0, 0, 111, 199, 199, 199, 96, 24, 26, 37, - 29, 31, 40, 42, 48, 44, 50, 57, 87, 79, - 63, 52, 69, 74, 80, 0, 63, 85, 87, 90, - 94, 96, 98, 100, 107, 65, 45, 79, 110, 113, - 117, 119, 121, 123, 125, 132, 134, 139, 143, 145, - 147, 151, 159, 161, 163, 165, 167, 169, 171, 199, - 192, 194, 40 + 0, 0, 119, 279, 279, 279, 111, 29, 31, 45, + 83, 75, 33, 37, 39, 48, 50, 52, 54, 57, + 61, 68, 78, 73, 74, 78, 81, 86, 92, 0, + 279, 279, 95, 97, 100, 102, 105, 109, 112, 114, + 116, 120, 132, 62, 42, 91, 122, 135, 137, 139, + 141, 145, 150, 152, 155, 160, 162, 165, 167, 169, + 175, 177, 179, 182, 184, 190, 192, 197, 201, 203, + 205, 208, 210, 213, 217, 220, 222, 226, 228, 233, + 235, 241, 243, 279, 272, 274, 39 } ; -static yyconst short int yy_def[64] = +static yyconst short int yy_def[88] = { 0, - 60, 1, 60, 60, 60, 60, 61, 62, 62, 62, - 63, 63, 63, 63, 63, 63, 63, 63, 61, 61, - 60, 10, 10, 10, 10, 10, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 60, 60, 10, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, 63, 0, - 60, 60, 60 + 84, 1, 84, 84, 84, 84, 85, 86, 86, 86, + 84, 84, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 10, 85, 85, 84, 10, 10, 10, 10, 10, + 84, 84, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 84, 84, 10, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 0, 84, 84, 84 } ; -static yyconst short int yy_nxt[228] = +static yyconst short int yy_nxt[313] = { 0, 4, 5, 6, 7, 4, 4, 4, 8, 9, 10, - 11, 11, 12, 11, 13, 11, 11, 14, 11, 11, - 15, 11, 11, 11, 11, 16, 17, 18, 21, 21, - 60, 60, 23, 24, 60, 24, 22, 23, 22, 23, - 24, 60, 60, 27, 25, 23, 26, 22, 23, 22, - 23, 22, 23, 28, 37, 22, 23, 22, 23, 22, - 32, 22, 33, 29, 22, 23, 30, 31, 36, 36, - 22, 23, 37, 34, 37, 35, 22, 60, 22, 36, - 36, 22, 20, 38, 21, 21, 22, 22, 38, 24, - 20, 24, 22, 23, 22, 23, 24, 22, 23, 20, + 11, 4, 12, 13, 13, 14, 13, 15, 16, 13, + 17, 13, 13, 13, 18, 13, 13, 13, 13, 19, + 20, 21, 22, 25, 25, 84, 84, 27, 28, 84, + 26, 27, 33, 28, 26, 27, 26, 27, 28, 84, + 84, 45, 29, 27, 30, 26, 27, 26, 27, 26, + 27, 26, 27, 34, 26, 27, 35, 36, 26, 27, + 37, 45, 41, 40, 39, 26, 24, 26, 38, 44, + 44, 24, 43, 45, 42, 26, 32, 26, 26, 84, + 26, 44, 44, 26, 31, 46, 25, 25, 26, 26, - 39, 22, 23, 22, 23, 22, 23, 22, 23, 40, - 60, 44, 60, 41, 22, 23, 43, 22, 23, 42, - 22, 23, 60, 45, 22, 23, 22, 23, 22, 23, - 22, 23, 22, 23, 60, 46, 60, 49, 47, 22, - 23, 22, 23, 50, 60, 48, 22, 23, 52, 51, - 22, 23, 22, 23, 22, 23, 60, 53, 22, 23, - 60, 54, 60, 55, 60, 56, 22, 23, 22, 23, - 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, - 60, 60, 60, 60, 60, 57, 58, 60, 60, 60, - 60, 59, 19, 60, 19, 19, 22, 22, 3, 60, + 46, 28, 26, 27, 26, 27, 28, 26, 27, 26, + 27, 28, 26, 27, 24, 47, 26, 27, 84, 26, + 27, 26, 27, 26, 27, 84, 48, 26, 27, 26, + 27, 49, 55, 84, 50, 52, 51, 84, 54, 26, + 27, 53, 26, 27, 26, 27, 26, 27, 26, 27, + 84, 56, 26, 27, 58, 84, 59, 26, 27, 26, + 27, 57, 26, 27, 61, 84, 60, 26, 27, 26, + 27, 63, 26, 27, 26, 27, 26, 27, 84, 64, + 62, 66, 26, 27, 26, 27, 26, 27, 65, 26, + 27, 26, 27, 67, 68, 84, 69, 26, 27, 26, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 60, 60 + 27, 70, 84, 71, 26, 27, 84, 72, 26, 27, + 26, 27, 26, 27, 73, 26, 27, 26, 27, 84, + 26, 27, 84, 74, 26, 27, 78, 26, 27, 26, + 27, 75, 76, 26, 27, 26, 27, 84, 77, 79, + 26, 27, 26, 27, 84, 80, 84, 81, 26, 27, + 26, 27, 82, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 83, 23, 84, 23, 23, 26, 26, 3, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84 } ; -static yyconst short int yy_chk[228] = +static yyconst short int yy_chk[313] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 8, 8, - 9, 9, 8, 8, 9, 8, 11, 11, 12, 12, - 8, 10, 10, 63, 10, 10, 10, 13, 13, 14, - 14, 16, 16, 12, 37, 15, 15, 17, 17, 22, - 16, 22, 17, 13, 18, 18, 14, 15, 21, 21, - 27, 27, 21, 17, 36, 18, 23, 23, 23, 24, - 24, 24, 20, 24, 25, 25, 38, 25, 38, 25, - 19, 25, 28, 28, 29, 29, 25, 30, 30, 7, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 8, 8, 9, 9, 8, 8, 9, + 13, 13, 87, 8, 14, 14, 15, 15, 8, 10, + 10, 45, 10, 10, 10, 16, 16, 17, 17, 18, + 18, 19, 19, 14, 20, 20, 15, 16, 21, 21, + 16, 44, 20, 19, 18, 22, 24, 22, 17, 25, + 25, 23, 21, 25, 20, 26, 12, 26, 27, 27, + 27, 28, 28, 28, 11, 28, 29, 29, 46, 29, - 28, 31, 31, 32, 32, 33, 33, 34, 34, 29, - 3, 33, 0, 30, 35, 35, 32, 39, 39, 31, - 40, 40, 0, 35, 41, 41, 42, 42, 43, 43, - 44, 44, 45, 45, 0, 40, 0, 43, 41, 46, - 46, 47, 47, 44, 0, 42, 48, 48, 46, 45, - 49, 49, 50, 50, 51, 51, 0, 49, 52, 52, - 0, 50, 0, 51, 0, 52, 53, 53, 54, 54, - 55, 55, 56, 56, 57, 57, 58, 58, 59, 59, - 0, 0, 0, 0, 0, 53, 54, 0, 0, 0, - 0, 56, 61, 0, 61, 61, 62, 62, 60, 60, + 46, 29, 33, 33, 34, 34, 29, 35, 35, 36, + 36, 29, 37, 37, 7, 34, 38, 38, 3, 39, + 39, 40, 40, 41, 41, 0, 35, 42, 42, 47, + 47, 36, 41, 0, 37, 39, 38, 0, 40, 43, + 43, 39, 48, 48, 49, 49, 50, 50, 51, 51, + 0, 43, 52, 52, 49, 0, 50, 53, 53, 54, + 54, 48, 55, 55, 52, 0, 51, 56, 56, 57, + 57, 54, 58, 58, 59, 59, 60, 60, 0, 55, + 53, 57, 61, 61, 62, 62, 63, 63, 56, 64, + 64, 65, 65, 58, 59, 0, 63, 66, 66, 67, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 60, 60, 60, 60 + 67, 64, 0, 65, 68, 68, 0, 66, 69, 69, + 70, 70, 71, 71, 67, 72, 72, 73, 73, 0, + 74, 74, 0, 68, 75, 75, 73, 76, 76, 77, + 77, 69, 70, 78, 78, 79, 79, 0, 72, 74, + 80, 80, 81, 81, 0, 78, 0, 79, 82, 82, + 83, 83, 81, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 85, 0, 85, 85, 86, 86, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84 } ; static yy_state_type yy_last_accepting_state; @@ -432,7 +460,7 @@ char *yytext; #include "parser.h" extern MdbSQL *g_sql; -#line 436 "lex.yy.c" +#line 464 "lex.yy.c" /* Macros after this point can all be overridden by user definitions in * section 1. @@ -585,7 +613,7 @@ YY_DECL #line 9 "lexer.l" -#line 589 "lex.yy.c" +#line 617 "lex.yy.c" if ( yy_init ) { @@ -636,13 +664,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 61 ) + if ( yy_current_state >= 85 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_base[yy_current_state] != 199 ); + while ( yy_base[yy_current_state] != 279 ); yy_find_action: yy_act = yy_accept[yy_current_state]; @@ -686,66 +714,96 @@ YY_RULE_SETUP case 4: YY_RULE_SETUP #line 13 "lexer.l" -{ return TO; } +{ return DISCONNECT; } YY_BREAK case 5: YY_RULE_SETUP #line 14 "lexer.l" -{ return LIST; } +{ return TO; } YY_BREAK case 6: YY_RULE_SETUP #line 15 "lexer.l" -{ return WHERE; } +{ return LIST; } YY_BREAK case 7: YY_RULE_SETUP #line 16 "lexer.l" -{ return AND; } +{ return WHERE; } YY_BREAK case 8: YY_RULE_SETUP #line 17 "lexer.l" -{ return TABLES; } +{ return AND; } YY_BREAK case 9: YY_RULE_SETUP #line 18 "lexer.l" -; +{ return TABLES; } YY_BREAK case 10: YY_RULE_SETUP #line 19 "lexer.l" -{ yylval.name = strdup(yytext); return NAME; } +{ return TABLE; } YY_BREAK case 11: YY_RULE_SETUP #line 20 "lexer.l" -{ yylval.name = strdup(yytext); return STRING; } +{ return DESCRIBE; } YY_BREAK case 12: YY_RULE_SETUP #line 21 "lexer.l" +{ return LTEQ; } + YY_BREAK +case 13: +YY_RULE_SETUP +#line 22 "lexer.l" +{ return GTEQ; } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 23 "lexer.l" +{ return LIKE; } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 24 "lexer.l" +; + YY_BREAK +case 16: +YY_RULE_SETUP +#line 25 "lexer.l" +{ yylval.name = strdup(yytext); return NAME; } + YY_BREAK +case 17: +YY_RULE_SETUP +#line 26 "lexer.l" +{ yylval.name = strdup(yytext); return STRING; } + YY_BREAK +case 18: +YY_RULE_SETUP +#line 27 "lexer.l" { yylval.name = strdup(yytext); return NUMBER; } YY_BREAK -case 13: +case 19: YY_RULE_SETUP -#line 24 "lexer.l" +#line 30 "lexer.l" { yylval.name = strdup(yytext); return PATH; } YY_BREAK -case 14: +case 20: YY_RULE_SETUP -#line 25 "lexer.l" +#line 31 "lexer.l" { return yytext[0]; } YY_BREAK -case 15: +case 21: YY_RULE_SETUP -#line 26 "lexer.l" +#line 32 "lexer.l" ECHO; YY_BREAK -#line 749 "lex.yy.c" +#line 807 "lex.yy.c" case YY_STATE_EOF(INITIAL): yyterminate(); @@ -1037,7 +1095,7 @@ static yy_state_type yy_get_previous_state() while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 61 ) + if ( yy_current_state >= 85 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -1072,11 +1130,11 @@ yy_state_type yy_current_state; while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 61 ) + if ( yy_current_state >= 85 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 60); + yy_is_jam = (yy_current_state == 84); return yy_is_jam ? 0 : yy_current_state; } @@ -1631,7 +1689,7 @@ int main() return 0; } #endif -#line 26 "lexer.l" +#line 32 "lexer.l" void yyerror(char *s) diff --git a/src/sql/lexer.l b/src/sql/lexer.l index 0298347..0399cfc 100644 --- a/src/sql/lexer.l +++ b/src/sql/lexer.l @@ -10,18 +10,24 @@ extern MdbSQL *g_sql; select { return SELECT; } from { return FROM; } connect { return CONNECT; } +disconnect { return DISCONNECT; } to { return TO; } list { return LIST; } where { return WHERE; } and { return AND; } tables { return TABLES; } +table { return TABLE; } +describe { return DESCRIBE; } +(<=) { return LTEQ; } +(>=) { return GTEQ; } +like { return LIKE; } [ \t\r] ; [A-z][A-z0-9]* { yylval.name = strdup(yytext); return NAME; } '.*' { yylval.name = strdup(yytext); return STRING; } ([0-9]+|([0-9]*\.[0-9+)([eE][-+]?[0-9]+)?) { yylval.name = strdup(yytext); return NUMBER; } -(\/?[A-z0-9\.]+)+ { yylval.name = strdup(yytext); return PATH; } +~?(\/?[A-z0-9\.]+)+ { yylval.name = strdup(yytext); return PATH; } . { return yytext[0]; } %% diff --git a/src/sql/main.c b/src/sql/main.c index 623b234..6a08692 100644 --- a/src/sql/main.c +++ b/src/sql/main.c @@ -52,13 +52,14 @@ int parse(char *buf) g_input_ptr = buf; if (yyparse()) { fprintf(stderr, "Couldn't parse SQL\n"); + mdb_sql_reset(g_sql); return 1; } else { return 0; } } -main() +main(int argc, char **argv) { char *s; char prompt[20]; @@ -69,6 +70,9 @@ int done = 0; /* initialize the SQL engine */ g_sql = mdb_sql_init(); + if (argc>1) { + mdb_sql_open(g_sql, argv[1]); + } /* give the buffer an initial size */ bufsz = 4096; @@ -86,6 +90,10 @@ int done = 0; line = 0; mybuf[0]='\0'; } else { + while (strlen(mybuf) + strlen(s) > bufsz) { + bufsz *= 2; + mybuf = (char *) realloc(mybuf, bufsz); + } add_history(s); strcat(mybuf,s); /* preserve line numbering for the parser */ diff --git a/src/sql/mdbsql.c b/src/sql/mdbsql.c index ab59c98..e764182 100644 --- a/src/sql/mdbsql.c +++ b/src/sql/mdbsql.c @@ -1,6 +1,11 @@ #include "mdbsql.h" #include +#ifdef HAVE_WORDEXP_H +#define HAVE_WORDEXP +#include +#endif + mdb_sql_error(char *fmt, ...) { va_list ap; @@ -49,13 +54,36 @@ MdbSQLTable *t; return t; } +MdbHandle *mdb_sql_close(MdbSQL *sql) +{ + if (sql->mdb) { + mdb_close(sql->mdb); + mdb_free_handle(sql->mdb); + sql->mdb = NULL; + } else { + mdb_sql_error("Not connected."); + } +} + MdbHandle *mdb_sql_open(MdbSQL *sql, char *db_name) { int fail = 0; - if (!(sql->mdb = mdb_open(db_name))) { - if (!strstr(db_name, ".mdb")) { - char *tmpstr = (char *) malloc(strlen(db_name)+5); - strcpy(tmpstr,db_name); +char *db_namep = db_name; + +#ifdef HAVE_WORDEXP +wordexp_t words; + + if (wordexp(db_name, &words, 0)==0) { + if (words.we_wordc>0) + db_namep = words.we_wordv[0]; + } + +#endif + + if (!(sql->mdb = mdb_open(db_namep))) { + if (!strstr(db_namep, ".mdb")) { + char *tmpstr = (char *) malloc(strlen(db_namep)+5); + strcpy(tmpstr,db_namep); strcat(tmpstr,".mdb"); if (!(sql->mdb = mdb_open(tmpstr))) { fail++; @@ -68,17 +96,31 @@ int fail = 0; if (fail) { mdb_sql_error("Unable to locate database %s", db_name); } + +#ifdef HAVE_WORDEXP + wordfree(&words); +#endif + return sql->mdb; - } int mdb_sql_add_sarg(MdbSQL *sql, char *col_name, int op, char *constant) { MdbSQLSarg *sql_sarg; +int lastchar; sql_sarg = mdb_sql_alloc_sarg(); sql_sarg->col_name = g_strdup(col_name); sql_sarg->sarg->op = op; - sql_sarg->sarg->value.i = atoi(constant); + /* FIX ME -- we should probably just be storing the ascii value until the + ** column definition can be checked for validity + */ + if (constant[0]=='\'') { + lastchar = strlen(constant) > 256 ? 256 : strlen(constant); + strncpy(sql_sarg->sarg->value.s, &constant[1], lastchar - 2); + sql_sarg->sarg->value.s[lastchar - 1]='\0'; + } else { + sql_sarg->sarg->value.i = atoi(constant); + } g_ptr_array_add(sql->sargs, sql_sarg); sql->num_sargs++; } @@ -236,6 +278,73 @@ MdbHandle *mdb = sql->mdb; print_break (30,1); fprintf(stdout,"\n"); } +void mdb_sql_describe_table(MdbSQL *sql) +{ +MdbTableDef *table = NULL; +MdbSQLTable *sql_tab; +MdbCatalogEntry entry; +MdbHandle *mdb = sql->mdb; +MdbColumn *col; +int i; +char colsize[11]; + + if (!mdb) { + mdb_sql_error("You must connect to a database first"); + return; + } + + sql_tab = g_ptr_array_index(sql->tables,0); + + mdb_read_catalog(mdb, MDB_TABLE); + + for (i=0;inum_catalog;i++) { + entry = g_array_index(mdb->catalog,MdbCatalogEntry,i); + if (entry.object_type == MDB_TABLE && + !strcasecmp(entry.object_name,sql_tab->name)) { + table = mdb_read_table(&entry); + break; + } + } + if (!table) { + mdb_sql_error("%s is not a table in this database", sql_tab->name); + /* the column and table names are no good now */ + mdb_sql_reset(sql); + return; + } + + mdb_read_columns(table); + + print_break (30,1); + print_break (20,0); + print_break (10,0); + fprintf(stdout,"\n"); + print_value ("Column Name",30,1); + print_value ("Type",20,0); + print_value ("Size",10,0); + fprintf(stdout,"\n"); + print_break (30,1); + print_break (20,0); + print_break (10,0); + fprintf(stdout,"\n"); + + for (i=0;inum_cols;i++) { + col = g_ptr_array_index(table->columns,i); + + print_value (col->name,30,1); + print_value (mdb_get_coltype_string(mdb->default_backend, col->col_type),20,0); + sprintf(colsize,"%d",col->col_size); + print_value (colsize,10,0); + fprintf(stdout,"\n"); + } + print_break (30,1); + print_break (20,0); + print_break (10,0); + fprintf(stdout,"\n"); + + /* the column and table names are no good now */ + mdb_sql_reset(sql); + +} void mdb_sql_select(MdbSQL *sql) { int i,j; @@ -261,7 +370,7 @@ int found = 0; for (i=0;inum_catalog;i++) { entry = g_array_index(mdb->catalog,MdbCatalogEntry,i); if (entry.object_type == MDB_TABLE && - !strcmp(entry.object_name,sql_tab->name)) { + !strcasecmp(entry.object_name,sql_tab->name)) { table = mdb_read_table(&entry); break; } @@ -289,7 +398,7 @@ int found = 0; found=0; for (j=0;jnum_cols;j++) { col=g_ptr_array_index(table->columns,j); - if (!strcmp(sqlcol->name, col->name)) { + if (!strcasecmp(sqlcol->name, col->name)) { bound_values[i] = (char *) malloc(MDB_BIND_SIZE); bound_values[i][0] = '\0'; /* bind the column to its listed (SQL) position */ @@ -309,7 +418,6 @@ int found = 0; /* now add back the sargs */ for (i=0;inum_sargs;i++) { sql_sarg=g_ptr_array_index(sql->sargs,i); - fprintf(stdout,"Sarg for %s\n",sql_sarg->col_name); mdb_add_sarg_by_name(table,sql_sarg->col_name, sql_sarg->sarg); } diff --git a/src/sql/parser.c b/src/sql/parser.c new file mode 100644 index 0000000..b31d781 --- /dev/null +++ b/src/sql/parser.c @@ -0,0 +1,482 @@ +#ifndef lint +static char yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93"; +#endif +#define YYBYACC 1 +#define YYMAJOR 1 +#define YYMINOR 9 +#define yyclearin (yychar=(-1)) +#define yyerrok (yyerrflag=0) +#define YYRECOVERING (yyerrflag!=0) +#define YYPREFIX "yy" +#line 2 "parser.y" +#include "mdbsql.h" + +MdbSQL *g_sql; +#line 7 "parser.y" +typedef union { + char *name; + double dval; + int ival; +} YYSTYPE; +#line 22 "y.tab.c" +#define NAME 257 +#define PATH 258 +#define NUMBER 259 +#define STRING 260 +#define SELECT 261 +#define FROM 262 +#define WHERE 263 +#define CONNECT 264 +#define DISCONNECT 265 +#define TO 266 +#define LIST 267 +#define TABLES 268 +#define AND 269 +#define DESCRIBE 270 +#define TABLE 271 +#define LTEQ 272 +#define GTEQ 273 +#define LIKE 274 +#define YYERRCODE 256 +short yylhs[] = { -1, + 0, 0, 0, 0, 0, 3, 3, 5, 5, 6, + 6, 7, 7, 7, 7, 7, 7, 8, 8, 4, + 4, 2, 1, 1, 1, 9, +}; +short yylen[] = { 2, + 5, 3, 1, 3, 2, 0, 2, 1, 3, 3, + 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 1, +}; +short yydefred[] = { 0, + 0, 0, 3, 0, 0, 0, 26, 23, 0, 0, + 0, 5, 0, 0, 0, 21, 20, 2, 22, 4, + 0, 25, 0, 1, 0, 18, 19, 7, 0, 0, + 15, 16, 17, 12, 13, 14, 0, 0, 0, 10, + 9, 11, +}; +short yydgoto[] = { 6, + 9, 20, 24, 18, 28, 29, 37, 30, 10, +}; +short yysindex[] = { -254, + -42, -263, 0, -250, -252, 0, 0, 0, -242, -27, + -256, 0, -236, -236, -42, 0, 0, 0, 0, 0, + -241, 0, -245, 0, -56, 0, 0, 0, -246, -56, + 0, 0, 0, 0, 0, 0, -251, -245, -233, 0, + 0, 0, +}; +short yyrindex[] = { 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, -237, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 26, 0, 0, 0, 0, 0, 0, 0, 27, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, +}; +short yygindex[] = { 0, + 13, 15, 0, 0, -8, 0, 1, -5, 0, +}; +#define YYTABLESIZE 218 +short yytable[] = { 8, + 16, 17, 11, 36, 34, 35, 1, 26, 27, 2, + 3, 25, 4, 26, 27, 5, 15, 12, 13, 14, + 19, 23, 38, 42, 24, 6, 8, 22, 21, 41, + 39, 40, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 31, 32, 33, +}; +short yycheck[] = { 42, + 257, 258, 266, 60, 61, 62, 261, 259, 260, 264, + 265, 257, 267, 259, 260, 270, 44, 268, 271, 262, + 257, 263, 269, 257, 262, 0, 0, 15, 14, 38, + 30, 37, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 257, 272, 273, 274, +}; +#define YYFINAL 6 +#ifndef YYDEBUG +#define YYDEBUG 0 +#endif +#define YYMAXTOKEN 274 +#if YYDEBUG +char *yyname[] = { +"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,"'*'",0,"','",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'<'","'='","'>'",0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"NAME","PATH", +"NUMBER","STRING","SELECT","FROM","WHERE","CONNECT","DISCONNECT","TO","LIST", +"TABLES","AND","DESCRIBE","TABLE","LTEQ","GTEQ","LIKE", +}; +char *yyrule[] = { +"$accept : query", +"query : SELECT column_list FROM table where_clause", +"query : CONNECT TO database", +"query : DISCONNECT", +"query : DESCRIBE TABLE table", +"query : LIST TABLES", +"where_clause :", +"where_clause : WHERE sarg_list", +"sarg_list : sarg", +"sarg_list : sarg AND sarg_list", +"sarg : NAME operator constant", +"sarg : constant operator NAME", +"operator : '='", +"operator : '>'", +"operator : '<'", +"operator : LTEQ", +"operator : GTEQ", +"operator : LIKE", +"constant : NUMBER", +"constant : STRING", +"database : PATH", +"database : NAME", +"table : NAME", +"column_list : '*'", +"column_list : column", +"column_list : column ',' column_list", +"column : NAME", +}; +#endif +#ifdef YYSTACKSIZE +#undef YYMAXDEPTH +#define YYMAXDEPTH YYSTACKSIZE +#else +#ifdef YYMAXDEPTH +#define YYSTACKSIZE YYMAXDEPTH +#else +#define YYSTACKSIZE 500 +#define YYMAXDEPTH 500 +#endif +#endif +int yydebug; +int yynerrs; +int yyerrflag; +int yychar; +short *yyssp; +YYSTYPE *yyvsp; +YYSTYPE yyval; +YYSTYPE yylval; +short yyss[YYSTACKSIZE]; +YYSTYPE yyvs[YYSTACKSIZE]; +#define yystacksize YYSTACKSIZE +#define YYABORT goto yyabort +#define YYREJECT goto yyabort +#define YYACCEPT goto yyaccept +#define YYERROR goto yyerrlab +int +yyparse() +{ + register int yym, yyn, yystate; +#if YYDEBUG + register char *yys; + extern char *getenv(); + + if (yys = getenv("YYDEBUG")) + { + yyn = *yys; + if (yyn >= '0' && yyn <= '9') + yydebug = yyn - '0'; + } +#endif + + yynerrs = 0; + yyerrflag = 0; + yychar = (-1); + + yyssp = yyss; + yyvsp = yyvs; + *yyssp = yystate = 0; + +yyloop: + if (yyn = yydefred[yystate]) goto yyreduce; + if (yychar < 0) + { + if ((yychar = yylex()) < 0) yychar = 0; +#if YYDEBUG + if (yydebug) + { + yys = 0; + if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; + if (!yys) yys = "illegal-symbol"; + printf("%sdebug: state %d, reading %d (%s)\n", + YYPREFIX, yystate, yychar, yys); + } +#endif + } + if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yychar) + { +#if YYDEBUG + if (yydebug) + printf("%sdebug: state %d, shifting to state %d\n", + YYPREFIX, yystate, yytable[yyn]); +#endif + if (yyssp >= yyss + yystacksize - 1) + { + goto yyoverflow; + } + *++yyssp = yystate = yytable[yyn]; + *++yyvsp = yylval; + yychar = (-1); + if (yyerrflag > 0) --yyerrflag; + goto yyloop; + } + if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yychar) + { + yyn = yytable[yyn]; + goto yyreduce; + } + if (yyerrflag) goto yyinrecovery; +#ifdef lint + goto yynewerror; +#endif +yynewerror: + yyerror("syntax error"); +#ifdef lint + goto yyerrlab; +#endif +yyerrlab: + ++yynerrs; +yyinrecovery: + if (yyerrflag < 3) + { + yyerrflag = 3; + for (;;) + { + if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) + { +#if YYDEBUG + if (yydebug) + printf("%sdebug: state %d, error recovery shifting\ + to state %d\n", YYPREFIX, *yyssp, yytable[yyn]); +#endif + if (yyssp >= yyss + yystacksize - 1) + { + goto yyoverflow; + } + *++yyssp = yystate = yytable[yyn]; + *++yyvsp = yylval; + goto yyloop; + } + else + { +#if YYDEBUG + if (yydebug) + printf("%sdebug: error recovery discarding state %d\n", + YYPREFIX, *yyssp); +#endif + if (yyssp <= yyss) goto yyabort; + --yyssp; + --yyvsp; + } + } + } + else + { + if (yychar == 0) goto yyabort; +#if YYDEBUG + if (yydebug) + { + yys = 0; + if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; + if (!yys) yys = "illegal-symbol"; + printf("%sdebug: state %d, error recovery discards token %d (%s)\n", + YYPREFIX, yystate, yychar, yys); + } +#endif + yychar = (-1); + goto yyloop; + } +yyreduce: +#if YYDEBUG + if (yydebug) + printf("%sdebug: state %d, reducing by rule %d (%s)\n", + YYPREFIX, yystate, yyn, yyrule[yyn]); +#endif + yym = yylen[yyn]; + yyval = yyvsp[1-yym]; + switch (yyn) + { +case 1: +#line 21 "parser.y" +{ + mdb_sql_select(g_sql); + } +break; +case 2: +#line 24 "parser.y" +{ + mdb_sql_open(g_sql, yyvsp[0].name); free(yyvsp[0].name); + } +break; +case 3: +#line 27 "parser.y" +{ + mdb_sql_close(g_sql); + } +break; +case 4: +#line 30 "parser.y" +{ + mdb_sql_describe_table(g_sql); + } +break; +case 5: +#line 33 "parser.y" +{ + mdb_sql_listtables(g_sql); + } +break; +case 10: +#line 49 "parser.y" +{ + mdb_sql_add_sarg(g_sql, yyvsp[-2].name, yyvsp[-1].ival, yyvsp[0].name); + free(yyvsp[-2].name); + free(yyvsp[0].name); + } +break; +case 11: +#line 54 "parser.y" +{ + mdb_sql_add_sarg(g_sql, yyvsp[0].name, yyvsp[-1].ival, yyvsp[-2].name); + free(yyvsp[-2].name); + free(yyvsp[0].name); + } +break; +case 12: +#line 62 "parser.y" +{ yyval.ival = MDB_EQUAL; } +break; +case 13: +#line 63 "parser.y" +{ yyval.ival = MDB_GT; } +break; +case 14: +#line 64 "parser.y" +{ yyval.ival = MDB_LT; } +break; +case 15: +#line 65 "parser.y" +{ yyval.ival = MDB_LTEQ; } +break; +case 16: +#line 66 "parser.y" +{ yyval.ival = MDB_GTEQ; } +break; +case 17: +#line 67 "parser.y" +{ yyval.ival = MDB_LIKE; } +break; +case 18: +#line 70 "parser.y" +{ yyval.name = yyvsp[0].name; } +break; +case 19: +#line 71 "parser.y" +{ yyval.name = yyvsp[0].name; } +break; +case 22: +#line 79 "parser.y" +{ mdb_sql_add_table(g_sql, yyvsp[0].name); free(yyvsp[0].name); } +break; +case 23: +#line 83 "parser.y" +{ mdb_sql_all_columns(g_sql); } +break; +case 26: +#line 89 "parser.y" +{ mdb_sql_add_column(g_sql, yyvsp[0].name); free(yyvsp[0].name); } +break; +#line 427 "y.tab.c" + } + yyssp -= yym; + yystate = *yyssp; + yyvsp -= yym; + yym = yylhs[yyn]; + if (yystate == 0 && yym == 0) + { +#if YYDEBUG + if (yydebug) + printf("%sdebug: after reduction, shifting from state 0 to\ + state %d\n", YYPREFIX, YYFINAL); +#endif + yystate = YYFINAL; + *++yyssp = YYFINAL; + *++yyvsp = yyval; + if (yychar < 0) + { + if ((yychar = yylex()) < 0) yychar = 0; +#if YYDEBUG + if (yydebug) + { + yys = 0; + if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; + if (!yys) yys = "illegal-symbol"; + printf("%sdebug: state %d, reading %d (%s)\n", + YYPREFIX, YYFINAL, yychar, yys); + } +#endif + } + if (yychar == 0) goto yyaccept; + goto yyloop; + } + if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yystate) + yystate = yytable[yyn]; + else + yystate = yydgoto[yym]; +#if YYDEBUG + if (yydebug) + printf("%sdebug: after reduction, shifting from state %d \ +to state %d\n", YYPREFIX, *yyssp, yystate); +#endif + if (yyssp >= yyss + yystacksize - 1) + { + goto yyoverflow; + } + *++yyssp = yystate; + *++yyvsp = yyval; + goto yyloop; +yyoverflow: + yyerror("yacc stack overflow"); +yyabort: + return (1); +yyaccept: + return (0); +} diff --git a/src/sql/parser.h b/src/sql/parser.h new file mode 100644 index 0000000..a7403c1 --- /dev/null +++ b/src/sql/parser.h @@ -0,0 +1,24 @@ +#define NAME 257 +#define PATH 258 +#define NUMBER 259 +#define STRING 260 +#define SELECT 261 +#define FROM 262 +#define WHERE 263 +#define CONNECT 264 +#define DISCONNECT 265 +#define TO 266 +#define LIST 267 +#define TABLES 268 +#define AND 269 +#define DESCRIBE 270 +#define TABLE 271 +#define LTEQ 272 +#define GTEQ 273 +#define LIKE 274 +typedef union { + char *name; + double dval; + int ival; +} YYSTYPE; +extern YYSTYPE yylval; diff --git a/src/sql/parser.y b/src/sql/parser.y index 7bb4112..25f20a7 100644 --- a/src/sql/parser.y +++ b/src/sql/parser.y @@ -11,7 +11,9 @@ MdbSQL *g_sql; } %token NAME PATH NUMBER STRING -%token SELECT FROM WHERE CONNECT TO LIST TABLES WHERE AND +%token SELECT FROM WHERE CONNECT DISCONNECT TO LIST TABLES WHERE AND +%token DESCRIBE TABLE +%token LTEQ GTEQ LIKE %% @@ -22,6 +24,12 @@ query: | CONNECT TO database { mdb_sql_open(g_sql, $3.name); free($3.name); } + | DISCONNECT { + mdb_sql_close(g_sql); + } + | DESCRIBE TABLE table { + mdb_sql_describe_table(g_sql); + } | LIST TABLES { mdb_sql_listtables(g_sql); } @@ -54,6 +62,9 @@ operator: '=' { $$.ival = MDB_EQUAL; } | '>' { $$.ival = MDB_GT; } | '<' { $$.ival = MDB_LT; } + | LTEQ { $$.ival = MDB_LTEQ; } + | GTEQ { $$.ival = MDB_GTEQ; } + | LIKE { $$.ival = MDB_LIKE; } ; constant: NUMBER { $$.name = $1.name; } diff --git a/src/util/Makefile b/src/util/Makefile index f20918d..f619514 100644 --- a/src/util/Makefile +++ b/src/util/Makefile @@ -84,7 +84,7 @@ CONFIG_CLEAN_FILES = PROGRAMS = $(bin_PROGRAMS) -DEFS = -DPACKAGE=\"mdbtools\" -DVERSION=\"0.3\" -DYYTEXT_POINTER=1 -DHAVE_LIBMDB=1 -DHAVE_FCNTL_H=1 -DHAVE_LIMITS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_READLINE=1 -I. -I$(srcdir) +DEFS = -DPACKAGE=\"mdbtools\" -DVERSION=\"0.3\" -DYYTEXT_POINTER=1 -DHAVE_LIBMDB=1 -DHAVE_FCNTL_H=1 -DHAVE_LIMITS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_WORDEXP_H=1 -DHAVE_READLINE=1 -I. -I$(srcdir) CPPFLAGS = LDFLAGS = mdb_export_SOURCES = mdb-export.c diff --git a/src/util/sargtest.c b/src/util/sargtest.c index 85c3504..b9b71a0 100644 --- a/src/util/sargtest.c +++ b/src/util/sargtest.c @@ -66,9 +66,10 @@ MdbSarg sarg; mdb_read_columns(table); - sarg.op = MDB_GTEQ; - sarg.value.i = 11070; - mdb_add_sarg_by_name(table, "OrderID", &sarg); + sarg.op = MDB_EQUAL; + // sarg.value.i = 11070; + strcpy(sarg.value.s, "Reggiani Caseifici"); + mdb_add_sarg_by_name(table, "ShipName", &sarg); mdb_rewind_table(table);