From e371033ddf2eab3c77e746fe95b13329ca8f57e8 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 29 Sep 2000 13:30:53 +0000 Subject: [PATCH] :-) (CVS 147) FossilOrigin-Name: e11f7527f9187e8902db84069baad0d3b7e17ad0 --- Makefile.in | 6 +- VERSION | 2 +- manifest | 29 ++++---- manifest.uuid | 2 +- src/shell.c | 60 ++++++++++++---- src/sqlite.h.in | 31 ++++++++- src/table.c | 163 ++++++++++++++++++++++++++++++++++++++++++++ www/arch.fig | 2 +- www/arch.png | Bin 1747 -> 1857 bytes www/arch.tcl | 8 ++- www/c_interface.tcl | 68 +++++++++++++++++- www/changes.tcl | 10 +++ 12 files changed, 342 insertions(+), 39 deletions(-) create mode 100644 src/table.c diff --git a/Makefile.in b/Makefile.in index 4e45100e54..6d28a33662 100644 --- a/Makefile.in +++ b/Makefile.in @@ -48,7 +48,7 @@ LIBREADLINE = @TARGET_READLINE_LIBS@ # Object files for the SQLite library. # LIBOBJ = build.o dbbe.o delete.o expr.o insert.o \ - main.o parse.o select.o tokenize.o update.o \ + main.o parse.o select.o table.o tokenize.o update.o \ util.o vdbe.o where.o tclsqlite.o # All of the source code files. @@ -66,6 +66,7 @@ SRC = \ $(TOP)/src/shell.c \ $(TOP)/src/sqlite.h.in \ $(TOP)/src/sqliteInt.h \ + $(TOP)/src/table.c \ $(TOP)/src/tclsqlite.c \ $(TOP)/src/tokenize.c \ $(TOP)/src/update.c \ @@ -154,6 +155,9 @@ insert.o: $(TOP)/src/insert.c $(HDR) select.o: $(TOP)/src/select.c $(HDR) $(TCC) $(GDBM_FLAGS) -c $(TOP)/src/select.c +table.o: $(TOP)/src/table.c $(HDR) + $(TCC) $(GDBM_FLAGS) -c $(TOP)/src/table.c + update.o: $(TOP)/src/update.c $(HDR) $(TCC) $(GDBM_FLAGS) -c $(TOP)/src/update.c diff --git a/VERSION b/VERSION index 90a27f9cea..238d6e882a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.5 +1.0.7 diff --git a/manifest b/manifest index a0b6a253a0..8d883b76cb 100644 --- a/manifest +++ b/manifest @@ -1,9 +1,9 @@ -C Obj-ify\stclsqlite\s(CVS\s146) -D 2000-09-21T13:01:36 +C :-)\s(CVS\s147) +D 2000-09-29T13:30:54 F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4 -F Makefile.in e699d55492bcfe06ab93e2d3f86da4705d45692c +F Makefile.in 39f684ee06a661157793f01cce98d43026fc2c06 F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958 -F VERSION 4edef6ec60a55c61b01fc0abebbf5a2f67c4f0e7 +F VERSION c4ef5804e5824ee814fdd368026a5d21314bdbed F configure bc917320fcc6d8a1a5154737304763acb5f7f68c x F configure.in ae915ce37ff010e8aac34b90b9136d4a32659bdb F doc/lemon.html e233a3e97a779c7a87e1bc4528c664a58e49dd47 @@ -16,10 +16,11 @@ F src/insert.c f146f149ad2422a1dc3bfa7a1651a25940f98958 F src/main.c 9a89579b40e498920f86e89878f52185457b9c2c F src/parse.y 5d199034de5d29ebedb42c1c51f34db4df40cbe5 F src/select.c d382e96c2221d08367cc87976f2b574537c9de97 -F src/shell.c f1ef4268c679e4a9faedc7b0bbf8045d062d1f9c +F src/shell.c 3d25f6709c2794cd910733a48a14f105eed6d7f3 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e -F src/sqlite.h.in d341439fc1432c7d7014bcff5f7b6e914571232c +F src/sqlite.h.in 1e0e4495172f752935ad534871ff726ae509d2f0 F src/sqliteInt.h b65fdecac7281aafb4c9ff3e79ea1b5546478385 +F src/table.c 12f0165b47178b54a675d25ed373ee7e798d6ff0 F src/tclsqlite.c a08428125ba2429b71764d5365653771ded4a2b8 F src/tokenize.c 097bec5843d4a0fb4509e036fee93bac080c5e73 F src/update.c 51b9ef7434b15e31096155da920302e9db0d27fc @@ -58,11 +59,11 @@ F tool/memleak.awk a0a11dd84bf4582acc81c3c61271021ae49b3f15 F tool/opNames.awk 2bd9071a138e4e2be13dc98fe066398a61219e1e F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c F tool/renumberOps.awk 6d067177ad5f8d711b79577b462da9b3634bd0a9 -F www/arch.fig 4e26e9dca3c49724fc8f554c695ddea9f2413156 -F www/arch.png c4d908b79065a72e7dcf19317f36d1324c550e87 -F www/arch.tcl 4f6a9afecc099a27bba17b4f8cc9561abc15dc40 -F www/c_interface.tcl 1b79e404a0dd46f44cd453a44b01df568c9586d1 -F www/changes.tcl 5f047e9e0154cf1b800e626e635c4334420ddb9b +F www/arch.fig 4f246003b7da23bd63b8b0af0618afb4ee3055c8 +F www/arch.png 8dae0766d42ed3de9ed013c1341a5792bcf633e6 +F www/arch.tcl a40380c1fe0080c43e6cc5c20ed70731511b06be +F www/c_interface.tcl 73b5c1354e250a12ceaaccc376611351c867146a +F www/changes.tcl e4fb0a308d62309dba40527ad3fddba825745e4c F www/crosscompile.tcl 19734ce7f18b16ff2ed8479412abf8aca56e1dcc F www/fileformat.tcl cfb7fba80b7275555281ba2f256c00734bcdd1c9 F www/index.tcl 2f5cc070b8fa8c3fc2f71bba4e6b7877d528fbde @@ -71,7 +72,7 @@ F www/mingw.tcl fc5f4ba9d336b6e8c97347cc6496d6162461ef60 F www/opcode.tcl cb3a1abf8b7b9be9f3a228d097d6bf8b742c2b6f F www/sqlite.tcl cb0d23d8f061a80543928755ec7775da6e4f362f F www/vdbe.tcl bcbfc33bcdd0ebad95eab31286adb9e1bc289520 -P 84839d8764ecdfac4d8c56618d9c107c8bbf65ab -R c08eefda2a9f502c4bc4de062c9d0908 +P 85a4254ef0998fac06ddc285decd79345968fee1 +R fad0a2ae1fae99e59e2510dbd713bcbd U drh -Z 23e467b7f382bfed639e5b43f4e92064 +Z 97f25b6b3274d7f182f155f5491676b3 diff --git a/manifest.uuid b/manifest.uuid index 9687829177..b3ac248e90 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -85a4254ef0998fac06ddc285decd79345968fee1 \ No newline at end of file +e11f7527f9187e8902db84069baad0d3b7e17ad0 \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index 0d5198aa36..9ef5896337 100644 --- a/src/shell.c +++ b/src/shell.c @@ -24,7 +24,7 @@ ** This file contains code to implement the "sqlite" command line ** utility for accessing SQLite databases. ** -** $Id: shell.c,v 1.24 2000/08/28 16:21:59 drh Exp $ +** $Id: shell.c,v 1.25 2000/09/29 13:30:55 drh Exp $ */ #include #include @@ -140,8 +140,9 @@ struct callback_data { #define MODE_Line 0 /* One column per line. Blank line between records */ #define MODE_Column 1 /* One record per line in neat columns */ #define MODE_List 2 /* One record per line with a separator */ -#define MODE_Html 3 /* Generate an XHTML table */ -#define MODE_Insert 4 /* Generate SQL "insert" statements */ +#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */ +#define MODE_Html 4 /* Generate an XHTML table */ +#define MODE_Insert 5 /* Generate SQL "insert" statements */ /* ** Number of elements in an array @@ -237,9 +238,14 @@ static int callback(void *pArg, int nArg, char **azArg, char **azCol){ struct callback_data *p = (struct callback_data*)pArg; switch( p->mode ){ case MODE_Line: { + int w = 5; + for(i=0; iw ) w = len; + } if( p->cnt++>0 ) fprintf(p->out,"\n"); for(i=0; iout,"%s = %s\n", azCol[i], azArg[i] ? azArg[i] : 0); + fprintf(p->out,"%*s = %s\n", w, azCol[i], azArg[i] ? azArg[i] : 0); } break; } @@ -291,6 +297,7 @@ static int callback(void *pArg, int nArg, char **azArg, char **azCol){ } break; } + case MODE_Semi: case MODE_List: { if( p->cnt++==0 && p->showHeader ){ for(i=0; iout, "%s", i==nArg-1 ? "\n" : p->separator); + if( iout, "%s", p->separator); + }else if( p->mode==MODE_Semi ){ + fprintf(p->out, ";\n"); + }else{ + fprintf(p->out, "\n"); + } } break; } @@ -388,8 +401,8 @@ static char zHelp[] = ".header ON|OFF Turn display of headers on or off\n" ".help Show this message\n" ".indices TABLE Show names of all indices on TABLE\n" - ".mode MODE Set mode to one of \"line\", \"column\", " - "\"list\", or \"html\"\n" + ".mode MODE Set mode to one of \"line\", \"column\", \n" + " \"insert\", \"list\", or \"html\"\n" ".mode insert TABLE Generate SQL insert statements for TABLE\n" ".output FILENAME Send output to FILENAME\n" ".output stdout Send output to the screen\n" @@ -549,7 +562,7 @@ static void do_meta_command(char *zLine, sqlite *db, struct callback_data *p){ char zSql[1000]; memcpy(&data, p, sizeof(data)); data.showHeader = 0; - data.mode = MODE_List; + data.mode = MODE_Semi; if( nArg>1 ){ sprintf(zSql, "SELECT sql FROM sqlite_master " "WHERE tbl_name LIKE '%.800s' AND type!='meta'" @@ -572,12 +585,10 @@ static void do_meta_command(char *zLine, sqlite *db, struct callback_data *p){ }else if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){ - struct callback_data data; - char *zErrMsg = 0; + char **azResult; + int nRow, rc; + char *zErrMsg; char zSql[1000]; - memcpy(&data, p, sizeof(data)); - data.showHeader = 0; - data.mode = MODE_List; if( nArg==1 ){ sprintf(zSql, "SELECT name FROM sqlite_master " @@ -589,11 +600,32 @@ static void do_meta_command(char *zLine, sqlite *db, struct callback_data *p){ "WHERE type='table' AND name LIKE '%%%.100s%%' " "ORDER BY name", azArg[1]); } - sqlite_exec(db, zSql, callback, &data, &zErrMsg); + rc = sqlite_get_table(db, zSql, &azResult, &nRow, 0, &zErrMsg); if( zErrMsg ){ fprintf(stderr,"Error: %s\n", zErrMsg); free(zErrMsg); } + if( rc==SQLITE_OK ){ + int len, maxlen = 0; + int i, j; + int nPrintCol, nPrintRow; + for(i=1; i<=nRow; i++){ + if( azResult[i]==0 ) continue; + len = strlen(azResult[i]); + if( len>maxlen ) maxlen = len; + } + nPrintCol = 80/(maxlen+2); + if( nPrintCol<1 ) nPrintCol = 1; + nPrintRow = (nRow + nPrintCol - 1)/nPrintCol; + for(i=0; i1 && strncmp(azArg[0], "timeout", n)==0 && nArg>=2 ){ diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 1c43c2f3a9..9b06b21525 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -24,7 +24,7 @@ ** This header file defines the interface that the sqlite library ** presents to client programs. ** -** @(#) $Id: sqlite.h.in,v 1.2 2000/08/22 13:40:20 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.3 2000/09/29 13:30:55 drh Exp $ */ #ifndef _SQLITE_H_ #define _SQLITE_H_ @@ -182,4 +182,33 @@ void sqlite_busy_handler(sqlite*, int(*)(void*,const char*,int), void*); */ void sqlite_busy_timeout(sqlite*, int ms); +/* +** This next routine is really just a wrapper around sqlite_exec(). +** Instead of invoking a user-supplied callback for each row of the +** result, this routine remembers each row of the result in memory +** obtained from malloc(), then returns all of the result after the +** query has finished. After the calling function has finished using +** the result, it should pass the result data pointer to +** sqlite_free_table() in order to release the memory that was malloc-ed. +** Because of the way the malloc() happens, the calling function must +** not try to call malloc() directly. Only sqlite_free_table() is able +** to release the memory properly and safely. +** +** The return value of this routine is the same as from sqlite_exec(). +*/ +int sqlite_get_table( + sqlite*, /* An open database */ + char *sql, /* SQL to be executed */ + char ***resultp, /* Result written to a char *[] that this points to */ + int *nrow, /* Number of result rows written here */ + int *ncolumn, /* Number of result columns written here */ + char **errmsg /* Error msg written here */ +); + +/* +** Call this routine to free the memory that sqlite_get_table() allocated. +*/ +void sqlite_free_table(char **result); + + #endif /* _SQLITE_H_ */ diff --git a/src/table.c b/src/table.c new file mode 100644 index 0000000000..9a46a13d80 --- /dev/null +++ b/src/table.c @@ -0,0 +1,163 @@ +/* +** This file contains the sqlite_get_table() and sqlite_free_table() +** interface routines. These are just wrappers around the main +** interface routine of sqlite_exec(). +** +** This routines are in a separate files to that they will not be linked +** if they are not used. +*/ +#include +#include "sqlite.h" + +/* +** This structure is used to pass data from sqlite_get_table() through +** to the callback function is uses to build the result. +*/ +typedef struct TabResult { + char **azResult; + int nResult; + int nAlloc; + int nRow; + int nColumn; + int nData; + int rc; +} TabResult; + +/* +** This routine is called once for each row in the result table. Its job +** is to fill in the TabResult structure appropriately, allocating new +** memory as necessary. +*/ +static int sqlite_get_table_cb(void *pArg, int nCol, char **argv, char **colv){ + TabResult *p = (TabResult*)pArg; + int need; + int i, len; + char *z, *zVal; + + /* Make sure there is enough space in p->azResult to hold everything + ** we need to remember from this invocation of the callback. + */ + if( p->nRow==0 ){ + p->nColumn = nCol; + need = nCol*2; + }else{ + need = nCol; + } + if( p->nData + need >= p->nAlloc ){ + p->nAlloc = p->nAlloc*2 + need + 1; + p->azResult = realloc( p->azResult, sizeof(char*)*p->nAlloc ); + if( p->azResult==0 ){ + p->rc = SQLITE_NOMEM; + return 1; + } + } + + /* If this is the first row, then generate an extra row containing + ** the names of all columns. + */ + if( p->nRow==0 ){ + for(i=0; irc = SQLITE_NOMEM; + return 1; + } + strcpy(z, colv[i]); + } + p->azResult[p->nData++] = z; + } + } + + /* Copy over the row data + */ + for(i=0; irc = SQLITE_NOMEM; + return 1; + } + strcpy(z, argv[i]); + } + p->azResult[p->nData++] = z; + } + p->nRow++; + return 0; +} + +/* +** Query the database. But instead of invoking a callback for each row, +** malloc() for space to hold the result and return the entire results +** at the conclusion of the call. +** +** The result that is written to ***pazResult is held in memory obtained +** from malloc(). But the caller cannot free this memory directly. +** Instead, the entire table should be passed to sqlite_free_table() when +** the calling procedure is finished using it. +*/ +int sqlite_get_table( + sqlite *db, /* The database on which the SQL executes */ + char *zSql, /* The SQL to be executed */ + char ***pazResult, /* Write the result table here */ + int *pnRow, /* Write the number of rows in the result here */ + int *pnColumn, /* Write the number of columns of result here */ + char **pzErrMsg /* Write error messages here */ +){ + int rc; + TabResult res; + if( pazResult==0 ){ return SQLITE_ERROR; } + *pazResult = 0; + if( pnColumn ) *pnColumn = 0; + if( pnRow ) *pnRow = 0; + res.nResult = 0; + res.nRow = 0; + res.nColumn = 0; + res.nData = 1; + res.nAlloc = 200; + res.rc = SQLITE_OK; + res.azResult = malloc( sizeof(char*)*res.nAlloc ); + if( res.azResult==0 ){ + return SQLITE_NOMEM; + } + res.azResult[0] = 0; + rc = sqlite_exec(db, zSql, sqlite_get_table_cb, &res, pzErrMsg); + if( res.azResult ){ + res.azResult[0] = (char*)res.nData; + } + if( rc==SQLITE_ABORT ){ + sqlite_free_table(&res.azResult[1]); + return res.rc; + } + if( rc!=SQLITE_OK ){ + sqlite_free_table(&res.azResult[1]); + return rc; + } + if( res.nAlloc>res.nData ){ + res.azResult = realloc( res.azResult, sizeof(char*)*(res.nData+1) ); + if( res.azResult==0 ) return SQLITE_NOMEM; + } + *pazResult = &res.azResult[1]; + if( pnColumn ) *pnColumn = res.nColumn; + if( pnRow ) *pnRow = res.nRow; + return rc; +} + +/* +** This routine frees the space the sqlite_get_table() malloced. +*/ +void sqlite_free_table( + char **azResult /* Result returned from from sqlite_get_table() */ +){ + if( azResult ){ + int i, n; + azResult--; + n = (int)azResult[0]; + for(i=1; iWB4Z#i}iBL{Q4GJ0x0000DNk~Le0001{0008F0RR9104L@N&5Gy2XKo}JFrR1Hb~cCR>pLDv#QzDG--~lgTC45Uast4SG(lRn#A6! z6;rQ+VPr_%5JrPh2ZQy^*vcHH!`7r^=qxc|d$BFV7_II?sm&j+G&yp)XLreIl6#)A zIPHw>9T?@q!_VLSp5yXOq7?vfe=rpr*Hi_3SS!+qwOgXBitmyTuf@188leP8Lv=Bh z02HJehf?$GLOfoq4YJNJ)ib1lDAE=m{ukx-`-@fMv+Sc%ez#b0np*Pv0j%Cq^+h}7 z7WKgHnNrp-kQPzDWw1k%N-F8*E6e|+C%A_ZFj%M=;3By1VGtw=Dy(T(f6$eqeFLd; zt(V&vUHz=(cLjGR<&=K1X_`7eGhm`8$e&(_sO36S**Ty<(CJr9)44j~l%e{7mREi8X7l5VZ0sy3{0lrrm4Rq4v2b>q_^Pzu(gpg_w! zPtI5I*)bwg(#Rq-+5s@Q0yi(D${Rd(veH&pq}@iXea~cTW3gJP=EHp?*`*Tc!5xl> zuM!if9CJj539;58^*K%tiL~3;V0Vyeb&)cdtmR1cYn44kJ(R-^e@QB-qz^|K0Fsa< z*#{|HVd0{$@l-V-7p<)g1zrhGm_^#I+wZ)j7uRjSo_124F7pt3U zp^mje6^qYT}phTv>p}f zis5E(A|}?Pb?%%V)-z!(_yAHJo*3WZvLJX4;L$w04Xlwsfv}R`L!b>e_3#?X(p?=3fQVrz%w5Q z7_0Q#>SVH-W2%42KbNC7DiDg4qjZs5ld36)mrE0Pgo6?X(!CHXX z8Lmv-n$lSv;Z<+UD~(bH=X;pcc_V6l)l)t}f!s510dZE*+M`lmRAObcLk~&);Ig0F zIjmS?z!?K9e{jV_nndVrd$ZgVU%cv3c@n*~{kEJgg~rT-WXNfX4Msx)2b*&m4UNTI z(HmDxa@YLgI6)L@*cs(YCy|<8yF5Mi=FpOF^!u|zk@p6=v^iZ^s(jj$_)vlG_QZR? z)!Gne>_W}~t*ZYpNnt3$UzcEc<=@FlgG~0f#nvhye{@>c_O)JhQQN=Es+-oeaP#DK zdC+u|37-zOpQb04?W5d0dA%E$pUVK<{+*dLdp9`2%`>aBF;0il-C6zF1adlO=5$6- z=c)#c?=QzbzH{hoVD1gO+H`h^S9fo`|0Pw;UYqP)?0MbWqq{xgGtMCAfY#JTu2c%C z>C(0LfAe#{^)HAu6lngaV+PXT6?0WstarzqF#^(CT9hWcMt?ZugS1U?v8U31tj z`Y(C1;1 z-|C&m+2nAQnp2?%hB=V<1wX)a$kjcH&l)`CvqO?f`j}}QQk^Ahs_*3lgNZd0_|ZhW ze;^GyPo$v=?6}ihs)EiYw8ap$4U#$^UQ0-%`?Zn0E zuroRqQoEgTAhi$H7NvL6fQx##VD%{$KdKwt<+nqUO1hOg5J71$S+cUve1b@LOrWvk zgvY75RAmNH36Fij^0*|t^2(F>V>AAj7ODRL{8ehKBAFO>HY(ut|#0RU{is{0# zTt#V6O0%sG+mSSZ`QXdgh6Us3X4FGtFy1{3rX}i`btDXpNq1nA<#PYs#iUK||10z6 zx+e1u8rly(e)rGs!riy+zX?Idf4!zc znYFKM-P`3RtqVE6JJ`2RaM2-EH4%733WUI`cp$LCEfF~r#*({02nb-|$@!GcowKM{ za-uW3s>>Bnue*LOn$9}wyv)pNVyKC0Q4UGe+cHoFxwL6 z2Jw}&bvC~QtfZdiy#x$DqUURT^WW-RZ!9(c8{7h)QX8+-#NH(wRS0HY6Qf#gj2xS9 zRw8Rb%>`N+6voBza=^uUhZbQb?nt?Yk}(z2Z0fDfui__FOy1ynEk6XKYQBEaZV`q! zH8Wh=k`7@UgZY}wEXH))e`dFg#8qryM%OTFhLYapzB)SVtaDwm6_s!-<0E0(mfMT8ptrpFNkI z#JI$pg9dO`}eNlLOJA*y1@qg1EUWy#JnRp!|;b8{@BT%NRY$V((+ z%yIA79H#~>Ar5WZ6hGo%<0C9_?${M#j+tEEXceu)>yzI2f3(+7e-~{DSwO!F^3#t~ zaS>&T2t~3*HJ2d%)7H)8#IA>1qdD<|=T9dqTrl_hQ-yGUVlq_>_g%kHZ4&OE%oe{t zwDEX0-}R8^7jQUJl-rkJ&e!m^{xQ3Y_~!n&-F36?E?eQetLchEe0z_PafofNjwYcu zpM__#2uJ_fe_$&Us_gdRYB?g`z7e97QxBS8UYf<46c1;LJkI%1kV|(T+-D~u7~kHrHhCU9rN)^w z9P2r@fmzS70Eb}aH8HAXJ;y?PDXC0aM5bx^;VR7Ww4iVv`Q)dzZ=Qu&<#&Iv%r*b} zpP5y*e>{lD>s`Qwbl|f+B#F+PVUlry&Q&?Po=#hSL}xnu@oT+nQdA{zWCO0WC4f$M z(4ngXBV2_=E>K8YjcCF?6JiGf7pr_gW-@@z+G7fH)xfH-+~jc#V3Qi6@6Qt#Z`eMblYlf1OnvgE^ytrOm5JXn(BpkpBX(Kh~MK zwF~I|Z6+Z-Ip6K3f5G?1BK`%^tnZI~x*Ur%RWD_eXM*({3vdW#UK68Q)^qG)tn6g4 z${!(WAq&3pA4xDJ*J`88J4aY`b@VE=r8$6cx}7pu zQgKe%s1BGn1I(@@I_ZFVCHG9kaM$it4(qaC9i4S @@ -30,8 +30,10 @@ follows will provide a quick overview of each of these components.

Interface

-

The public interface to the SQLite library is implemented by -four functions found in the main.c source file. Additional +

Most of the public interface to the SQLite library is implemented by +four functions found in the main.c source file. The +sqlite_get_table() routine is implemented in table.c. +The Tcl interface is implemented by tclsqlite.c. More information on the C interface to SQLite is available separately.

diff --git a/www/c_interface.tcl b/www/c_interface.tcl index 15a73a0f6c..108214cdc4 100644 --- a/www/c_interface.tcl +++ b/www/c_interface.tcl @@ -1,7 +1,7 @@ # # Run this Tcl script to generate the sqlite.html file. # -set rcsid {$Id: c_interface.tcl,v 1.7 2000/08/22 13:40:20 drh Exp $} +set rcsid {$Id: c_interface.tcl,v 1.8 2000/09/29 13:30:55 drh Exp $} puts { @@ -22,8 +22,8 @@ programming interface.

The API

-

The interface to the SQLite library consists of six functions -(only three of which are required), +

The interface to the SQLite library consists of eight functions +(only the first three of which are required), one opaque data structure, and some constants used as return values from sqlite_exec():

@@ -42,6 +42,17 @@ int sqlite_exec( char **errmsg ); +int sqlite_get_table( + sqlite*, + char *sql, + char ***result, + int *nrow, + int *ncolumn, + char **errmsg +); + +void sqlite_free_table(char**); + int sqlite_complete(const char *sql); void sqlite_busy_handler(sqlite*, int (*)(void*,const char*,int), void*); @@ -210,6 +221,57 @@ being queried. +

Querying without using a callback function

+ +

The sqlite_get_table() function is a wrapper around +sqlite_exec() that collects all the information from successive +callbacks and write it into memory obtained from malloc(). This +is a convenience function that allows the application to get the +entire result of a database query with a single function call.

+ +

The main result from sqlite_get_table() is an array of pointers +to strings. There is one element in this array for each column of +each row in the result. NULL results are represented by a NULL +pointer. In addition to the regular data, there is an added row at the +beginning of the array that contains the names of each column of the +result.

+ +

As an example, consider the following query:

+ +
+SELECT employee_name, login, host FROM users WHERE logic LIKE 'd%'; +
+ +

This query will return the name, login and host computer name +for every employee whose login begins with the letter "d". If this +query is submitted to sqlite_get_table() the result might +look like this:

+ +
+nrow = 2
+ncolumn = 3
+result[0] = "employee_name"
+result[1] = "login"
+result[2] = "host"
+result[3] = "dummy"
+result[4] = "No such user"
+result[5] = 0
+result[6] = "D. Richard Hipp"
+result[7] = "drh"
+result[8] = "zadok" +
+ +

Notice that the "host" value for the "dummy" record is NULL so +the result[] array contains a NULL pointer at that slot.

+ +

Memory to hold the information returned by sqlite_get_table() +is obtained from malloc(). But the calling function should not try +to free this information directly. Instead, pass the complete table +to sqlite_free_table() when the table is no longer needed.

+ +

The sqlite_get_table() routine returns the same integer +result code as sqlite_exec().

+

Testing for a complete SQL statement

The last interface routine to SQLite is a convenience function used diff --git a/www/changes.tcl b/www/changes.tcl index 9ff6bc6e77..5b6e9090bd 100644 --- a/www/changes.tcl +++ b/www/changes.tcl @@ -17,6 +17,16 @@ proc chng {date desc} { puts "

    $desc

" } +chng {2000 Sep 29 (Not Released)} { +
  • Added the sqlite_get_table() API
  • +
  • Updated the documtation for due to the above change.
  • +
  • Modified the sqlite shell to make use of the new + sqlite_get_table() API in order to print a list of tables + in multiple columns, similar to the way "ls" prints filenames.
  • +
  • Modified the sqlite shell to print a semicolon at the + end of each CREATE statement in the output of the ".schema" command.
  • +} + chng {2000 Sep 21 (Not Released)} {
  • Change the tclsqlite "eval" method to return a list of results if no callback script is specified.