These are contributed by Daniele Sciascia. I only modified them a
little to support DML queries and to improve error reporting. Paolo --- orig/configure.ac +++ mod/configure.ac @@ -279,6 +279,12 @@ AC_MSG_RESULT($enable_mysql_tests) GST_PACKAGE_ENABLE([DBD-PostgreSQL], [dbd-postgresql], [GST_HAVE_LIB(pq, PQconnectdb)], [ac_cv_lib_pq_PQconnectdb]) + +GST_PACKAGE_ENABLE([DBD-SQLite], [dbd-sqlite], + [AC_CHECK_HEADER([sqlite3.h])], + [ac_cv_header_sqlite3_h], + [Makefile], [dbd-sqlite3.la]) + GST_PACKAGE_ENABLE([DBI], [dbi]) GST_PACKAGE_ENABLE([GDBM], [gdbm], --- orig/tests/testsuite.at +++ mod/tests/testsuite.at @@ -148,4 +148,5 @@ AT_OPTIONAL_PACKAGE_TEST([GDBM]) AT_OPTIONAL_PACKAGE_TEST([Iconv]) AT_PACKAGE_TEST([MySQL], [], [$mysqlvars], [test "$enable_mysql_tests" != no]) AT_PACKAGE_TEST([Sport]) +AT_OPTIONAL_PACKAGE_TEST([DBD-SQLite]) AT_OPTIONAL_PACKAGE_TEST([ZLib]) --- /dev/null +++ mod/packages/dbd-sqlite/ColumnInfo.st @@ -0,0 +1,95 @@ +"====================================================================== +| +| SQLite bindings, ColumnInfo class +| +| + ======================================================================" + + +"====================================================================== +| +| Copyright 2007 Free Software Foundation, Inc. +| Written by Daniele Sciascia +| +| This 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 2, or (at your option) any later version. +| +| This code 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. +| +| You should have received a copy of the GNU General Public License along with +| Mumble; see the file COPYING. If not, write to the Free Software +| Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +| + ====================================================================== +" + + +ColumnInfo subclass: SQLiteColumnInfo [ + | resultSet index | + + TypeNames := nil. + + SQLiteColumnInfo class >> in: aResultSet at: anIndex [ + ^(self new) + index: anIndex; + resultSet: aResultSet; + yourself + ] + + SQLiteColumnInfo class >> initTypes [ + TypeNames := LookupTable new. + TypeNames at: 1 put: 'Integer'. + TypeNames at: 2 put: 'Float'. + TypeNames at: 3 put: 'Text'. + TypeNames at: 4 put: 'Blob'. + TypeNames at: 5 put: 'Null'. + ] + + resultSet: aResultSet [ + <category: 'private'> + resultSet := aResultSet + ] + + name [ + <category: 'accessing'> + ^resultSet columnAt: self index + ] + + index [ + <category: 'accessing'> + ^index + ] + + index: anIndex [ + <category: 'private'> + index := anIndex + ] + + type [ + <category: 'accessing'> + ^TypeNames at: (resultSet columnTypeAt: self index) + ] + + size [ + "Return the size of the column (abstract)." + <category: 'accessing'> + self notYetImplemented + ] + + printOn: aStream [ + <category: 'printing'> + aStream + nextPutAll: self name; + nextPut: $(; + nextPutAll: self type; + nextPut: $) + ] +] + +Eval [ + SQLiteColumnInfo initTypes +] --- /dev/null +++ mod/packages/dbd-sqlite/Connection.st @@ -0,0 +1,96 @@ +"====================================================================== +| +| SQLite bindings, Connection class +| +| + ======================================================================" + + +"====================================================================== +| +| Copyright 2007 Free Software Foundation, Inc. +| Written by Daniele Sciascia +| +| This 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 2, or (at your option) any later version. +| +| This code 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. +| +| You should have received a copy of the GNU General Public License along with +| Mumble; see the file COPYING. If not, write to the Free Software +| Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +| + ====================================================================== +" + + +Connection subclass: SQLiteConnection [ + | stmtHandles handle | + + <category: 'DBI-Drivers'> + <comment: 'I represent a connection to a SQLite database'> + + + SQLiteConnection class >> paramConnect: params user: aUserName password: aPassword [ + <category: 'connecting'> + | dbName aSqlite3Handle | + + dbName := params at: 'dbname' + ifAbsent: [self error: 'Missing parameter: dbname']. + aSqlite3Handle := SQLite3DBHandle open: dbName. + ^(self new) + initializeWithHandle: aSqlite3Handle; + yourself + ] + + initializeWithHandle: aSqlite3Handle [ + handle := aSqlite3Handle. + stmtHandles := WeakIdentitySet new. + ] + + close [ + <category: 'connecting'> + stmtHandles do: [ :each | each removeToBeFinalized; finalize ]. + ^handle close + ] + + SQLiteConnection class >> driverName [ + <category: 'initialization'> + ^'SQLite' + ] + + handle [ + <category: 'private'> + ^handle + ] + + finalize [ + <category: 'private'> + self close + ] + + do: aSQLQuery [ + <category: 'querying'> + ^(self prepare: aSQLQuery) execute + ] + + select: aSQLQuery [ + <category: 'querying'> + ^(self prepare: aSQLQuery) execute + ] + + prepare: aSQLQuery [ + <category: 'querying'> + | stmtHandle | + stmtHandle := self handle prepare: aSQLQuery. + stmtHandle addToBeFinalized. + stmtHandles add: stmtHandle. + ^(SQLiteStatement on: self) + handle: stmtHandle; + queryString: aSQLQuery. + ] +] --- /dev/null +++ mod/packages/dbd-sqlite/Makefile.am @@ -0,0 +1,11 @@ +pkglib_LTLIBRARIES = dbd-sqlite3.la + +AM_CPPFLAGS = -I$(top_srcdir)/libgst -I$(top_srcdir)/lib-src + +gst_module_ldflags = -rpath $(pkglibdir) -release $(VERSION) -module \ + -no-undefined -export-symbols-regex gst_initModule + +dbd_sqlite3_la_SOURCES = sqlite3.c +dbd_sqlite3_la_LIBADD = -lsqlite3 +dbd_sqlite3_la_LDFLAGS = $(gst_module_ldflags) + --- /dev/null +++ mod/packages/dbd-sqlite/Makefile.frag @@ -0,0 +1,5 @@ +DBD-SQLite_FILES = \ +packages/dbd-sqlite/SQLite.st packages/dbd-sqlite/Connection.st packages/dbd-sqlite/ResultSet.st packages/dbd-sqlite/Statement.st packages/dbd-sqlite/Row.st packages/dbd-sqlite/ColumnInfo.st packages/dbd-sqlite/SQLiteTests.st +$(DBD-SQLite_FILES): +$(srcdir)/packages/dbd-sqlite/stamp-classes: $(DBD-SQLite_FILES) + touch $(srcdir)/packages/dbd-sqlite/stamp-classes --- /dev/null +++ mod/packages/dbd-sqlite/ResultSet.st @@ -0,0 +1,157 @@ +"====================================================================== +| +| SQLite bindings, ResultSet class +| +| + ======================================================================" + + +"====================================================================== +| +| Copyright 2007 Free Software Foundation, Inc. +| Written by Daniele Sciascia +| +| This 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 2, or (at your option) any later version. +| +| This code 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. +| +| You should have received a copy of the GNU General Public License along with +| Mumble; see the file COPYING. If not, write to the Free Software +| Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +| + ====================================================================== +" + + +ResultSet subclass: SQLiteResultSet [ + | handle rows columns index | + + SQLiteResultSet class >> on: aStatement [ + <category: 'instance creation'> + ^self new initializeWithStatement: aStatement + ] + + initializeWithStatement: aStatement [ + <category: 'initialization'> + index := 0. + self statement: aStatement. + self handle: (aStatement handle). + self isSelect + ifTrue: [self populate] + ifFalse: [self exec] + ] + + exec [ + <category: 'initialization'> + | resCode | + resCode := self handle exec. + self handle checkError: resCode = 101. + rows := handle changes + ] + + populate [ + <category: 'initialization'> + | resCode | + + rows := OrderedCollection new. + [ resCode := self handle exec. + resCode = 100 + ] whileTrue: [rows addLast: + (SQLiteRow forValues: (self handle returnedRow) in: self)]. + + self handle checkError: resCode = 101. + ] + + handle [ + <category: 'private'> + ^handle + ] + + handle: aSQLite3StmtHandle [ + <category: 'private'> + handle := aSQLite3StmtHandle + ] + + next [ + <category: 'cursor access'> + self atEnd ifTrue: [self error: 'No more rows']. + index := index + 1. + ^self rows at: index + ] + + atEnd [ + <category: 'cursor access'> + ^index >= self rowCount + ] + + position [ + <category: 'stream protocol'> + ^index + ] + + position: anInteger [ + <category: 'stream protocol'> + (anInteger between: 0 and: self size) + ifTrue: [ index := anInteger ] + ifFalse: [ SystemExceptions.IndexOutOfRange signalOn: self withIndex: anInteger ]. + ^index + ] + + columns [ + <category: 'accessing'> + columns isNil + ifTrue: [| n | + n := self handle colCount. + columns := LookupTable new: n. + 1 to: n do: [:i | columns at: (self columnNames at: i) + put: (SQLiteColumnInfo in: self at: i)]]. + ^columns + ] + + columnNames [ + <category: 'accessing'> + ^self handle colNames + ] + + columnTypes [ + ^self handle colTypes + ] + + columnTypeAt: index [ + ^self columnTypes at: index + ] + + isSelect [ + <category: 'accessing'> + ^self statement isSelect + ] + + isDML [ + <category: 'accessing'> + ^self statement isSelect not + ] + + rows [ + <category: 'accessing'> + ^rows + ] + + rowCount [ + <category: 'accessing'> + self isSelect + ifTrue: [^self rows size] + ifFalse: [^self error: 'Not a SELECT statement.'] + ] + + rowsAffected [ + <category: 'accessing'> + self isDML + ifTrue: [^self rows] + ifFalse: [^self error: 'Not a DML statement.'] + ] +] --- /dev/null +++ mod/packages/dbd-sqlite/Row.st @@ -0,0 +1,56 @@ +"====================================================================== +| +| SQLite bindings, Row class +| +| + ======================================================================" + + +"====================================================================== +| +| Copyright 2007 Free Software Foundation, Inc. +| Written by Daniele Sciascia +| +| This 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 2, or (at your option) any later version. +| +| This code 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. +| +| You should have received a copy of the GNU General Public License along with +| Mumble; see the file COPYING. If not, write to the Free Software +| Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +| + ====================================================================== +" + + +Row subclass: SQLiteRow [ + | values | + + SQLiteRow class >> forValues: anArray in: aResultSet [ + ^super new + values: anArray; + resultSet: aResultSet; + yourself + ] + + values: anArray [ + <category: 'private'> + values := anArray + ] + + at: aColumnName [ + <category: 'accessing'> + ^self atIndex: (resultSet columns at: aColumnName) index + ] + + atIndex: aColumnIndex [ + <category: 'accessing'> + ^values at: aColumnIndex + ] +] + --- /dev/null +++ mod/packages/dbd-sqlite/SQLite.st @@ -0,0 +1,125 @@ +"====================================================================== +| +| SQLite bindings, bridge to the C library +| +| + ======================================================================" + + +"====================================================================== +| +| Copyright 2007 Free Software Foundation, Inc. +| Written by Daniele Sciascia +| +| This 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 2, or (at your option) any later version. +| +| This code 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. +| +| You should have received a copy of the GNU General Public License along with +| Mumble; see the file COPYING. If not, write to the Free Software +| Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +| + ====================================================================== +" + + +Object subclass: SQLite3Handle [ + | db | + + errorMessage [ + <cCall: 'gst_sqlite3_error_message' returing: #string args: #(#self)> + ] + + checkError: aBoolean [ + aBoolean ifFalse: [ self error: self errorMessage ] + ] + + changes [ + <category: 'sqlite3 wrapper'> + <cCall: 'gst_sqlite3_changes' returning: #int args: #(#self)> + ] +] + +SQLite3Handle subclass: SQLite3DBHandle [ + SQLite3DBHandle class >> open: dbname [ + | result rc | + result := self new. + rc := result open: dbname. + rc = 0 ifFalse: [ self error: 'error: ', rc printString ]. + ^result + ] + + open: dbname [ + <cCall: 'gst_sqlite3_open' returning: #int args: #(#self #string)> + ] + + close [ + <cCall: 'gst_sqlite3_close' returning: #int args: #(#self)> + ] + + prepare: aSQLQuery [ + ^SQLite3StmtHandle forQuery: aSQLQuery onHandle: db + ] +] + +SQLite3Handle subclass: SQLite3StmtHandle [ + | stmt colCount colTypes colNames returnedRow | + + SQLite3StmtHandle class >> forQuery: aSQLQuery onHandle: aDbHandle [ + | result rc | + result := self new db: aDbHandle. + rc := result prepare: aSQLQuery. + rc = 0 ifFalse: [ self error: 'error: ', rc printString ]. + ^result + ] + + db [ + <category: 'private'> + ^db + ] + + db: aDbHandle [ + <category: 'private'> + db := aDbHandle + ] + + finalize [ + <category: 'private'> + <cCall: 'gst_sqlite3_finalize' returning: #int args: #(#self)> + ] + + prepare: aSQLQuery [ + <category: 'sqlite3 wrapper'> + <cCall: 'gst_sqlite3_prepare' returning: #int args: #(#self #string)> + ] + + exec [ + <category: 'sqlite3 wrapper'> + <cCall: 'gst_sqlite3_exec' returning: #int args: #(#self)> + ] + + colCount [ + <category: 'accessing'> + ^colCount + ] + + colTypes [ + <category: 'accessing'> + ^colTypes + ] + + colNames [ + <category: 'accessing'> + ^colNames + ] + + returnedRow [ + <category: 'accessing'> + ^returnedRow + ] +] --- /dev/null +++ mod/packages/dbd-sqlite/SQLiteTests.st @@ -0,0 +1,159 @@ +"====================================================================== +| +| SQLite bindings test suite +| +| + ======================================================================" + + +"====================================================================== +| +| Copyright 2007 Free Software Foundation, Inc. +| Written by Daniele Sciascia +| +| This 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 2, or (at your option) any later version. +| +| This code 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. +| +| You should have received a copy of the GNU General Public License along with +| Mumble; see the file COPYING. If not, write to the Free Software +| Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +| + ====================================================================== +" + + + +TestCase subclass: SQLiteBaseTest [ + | connection | + + setUp [ + | f | + f := File name: 'testdb'. + f exists ifTrue: [ f remove ]. + connection := DBI.Connection + connect: 'dbi:SQLite:dbname=testdb' + user: nil + password: nil. + connection do: ' + BEGIN TRANSACTION'. + connection do: ' + CREATE TABLE test(int_field integer, string_field text, + double_field double)'. + connection do: ' + INSERT INTO "test" VALUES(1, "one", 1.0)'. + connection do: ' + INSERT INTO "test" VALUES(2, "two", 2.0)'. + connection do: ' + INSERT INTO "test" VALUES(3, "three", 3.0)'. + connection do: ' + COMMIT'. + ] + + tearDown [ + connection close + ] + + connection [ + ^connection + ] +] + +SQLiteBaseTest subclass: SQLiteDMLResultSetTestCase [ + | rs | + + setUp [ + super setUp. + rs := self connection + do: 'delete from test where string_field like "t%"' + ] + + testRowsAffected [ + self assert: rs rowsAffected = 2 + ] +] + + +SQLiteBaseTest subclass: SQLiteResultSetTestCase [ + | rs | + + setUp [ + super setUp. + rs := self connection + select: 'select * from test' + ] + + testNext [ + self should: [rs position = 0]. + rs next. + self should: [rs position = 1]. + rs next. + self should: [rs position = 2]. + rs next. + self should: [rs atEnd] + ] + + testAtEnd [ + self shouldnt: [rs atEnd]. + rs next. + self shouldnt: [rs atEnd]. + rs next. + self shouldnt: [rs atEnd]. + rs next. + self should: [rs atEnd] + ] + + testColumnNames [ + self should: [rs columnNames = #('int_field' 'string_field' 'double_field')] + ] + + testRowCount [ + self should: [rs rowCount = 3] + ] +] + +SQLiteBaseTest subclass: SQLiteRowTestCase [ + | rs row | + + setUp [ + super setUp. + rs := self connection select: 'select * from test where int_field = 1'. + row := rs rows at: 1. + ] + + testAt [ + self should: [(row at: 'int_field') = 1]. + self should: [(row at: 'string_field') = 'one']. + self should: [(row at: 'double_field') = 1.0] + ] + + testAtIndex [ + self should: [(row atIndex: 1) = 1]. + self should: [(row atIndex: 2) = 'one']. + self should: [(row atIndex: 3) = 1.0] + ] +] + +TestSuite subclass: SQLiteTestSuite [ + SQLiteTestSuite class >> suite [ + ^super new initialize + ] + + initialize [ + self name: 'SQLite-Test'. + self addTest: (SQLiteResultSetTestCase selector: #testNext). + self addTest: (SQLiteResultSetTestCase selector: #testAtEnd). + self addTest: (SQLiteResultSetTestCase selector: #testColumnNames). + self addTest: (SQLiteResultSetTestCase selector: #testRowCount). + + self addTest: (SQLiteRowTestCase selector: #testAt). + self addTest: (SQLiteRowTestCase selector: #testAtIndex). + + self addTest: (SQLiteDMLResultSetTestCase selector: #testRowsAffected). + ] +] --- /dev/null +++ mod/packages/dbd-sqlite/Statement.st @@ -0,0 +1,89 @@ +"====================================================================== +| +| SQLite bindings, Statement class +| +| + ======================================================================" + + +"====================================================================== +| +| Copyright 2007 Free Software Foundation, Inc. +| Written by Daniele Sciascia +| +| This 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 2, or (at your option) any later version. +| +| This code 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. +| +| You should have received a copy of the GNU General Public License along with +| Mumble; see the file COPYING. If not, write to the Free Software +| Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +| + ====================================================================== +" + + + +Statement subclass: SQLiteStatement [ + | handle queryString isSelect | + + <category: 'DBI-Drivers'> + <comment: 'I represent a SQLite prepared statement'> + + SelectQueries := #('EXPLAIN' 'SELECT') asSet. + + handle [ + <category: 'private'> + ^handle + ] + + handle: aSqlite3StmtHandle [ + <category: 'private'> + handle := aSqlite3StmtHandle + ] + + queryString [ + <category: 'accessing'> + ^queryString + ] + + queryString: aSQLQuery [ + <category: 'accessing'> + queryString := aSQLQuery. + + ] + + isSelect [ + <category: 'accessing'> + isSelect isNil + ifTrue: [isSelect := SelectQueries includes: self getCommand]. + ^isSelect + ] + + execute [ + <category: 'querying'> + ^SQLiteResultSet on: self + ] + + executeWithAll: aParams [ + <category: 'querying'> + self notYetImplemented + ] + + getCommand [ + <category: 'private'> + | readStream writeStream aCharacter | + writeStream := WriteStream on: String new. + readStream := ReadStream on: queryString. + readStream skipSeparators. + [readStream atEnd + or: [aCharacter := readStream next. aCharacter isSeparator]] + whileFalse: [writeStream nextPut: aCharacter asUppercase]. + ^writeStream contents + ] +] --- /dev/null +++ mod/packages/dbd-sqlite/package.xml @@ -0,0 +1,27 @@ +<package> + <name>DBD-SQLite</name> + <prereq>DBI</prereq> + <namespace>DBI.SQLite</namespace> + <module>dbd-sqlite3</module> + + <filein>SQLite.st</filein> + <filein>Connection.st</filein> + <filein>ResultSet.st</filein> + <filein>Statement.st</filein> + <filein>Row.st</filein> + <filein>ColumnInfo.st</filein> + + <file>SQLite.st</file> + <file>Connection.st</file> + <file>ResultSet.st</file> + <file>Statement.st</file> + <file>Row.st</file> + <file>ColumnInfo.st</file> + + <test> + <sunit>DBI.SQLite.SQLiteTestSuite</sunit> + <filein>SQLiteTests.st</filein> + </test> + + <file>SQLiteTests.st</file> +</package> --- /dev/null +++ mod/packages/dbd-sqlite/sqlite3.c @@ -0,0 +1,248 @@ +/******************************* -*- C -*- **************************** + * + * SQLite bindings + * + * + ***********************************************************************/ + +/*********************************************************************** + * + * Copyright 2007 Free Software Foundation, Inc. + * Written by Daniele Sciascia. + * + * This file is part of GNU Smalltalk. + * + * GNU Smalltalk 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 2, or (at your option) any later + * version. + * + * Linking GNU Smalltalk statically or dynamically with other modules is + * making a combined work based on GNU Smalltalk. Thus, the terms and + * conditions of the GNU General Public License cover the whole + * combination. + * + * In addition, as a special exception, the Free Software Foundation + * give you permission to combine GNU Smalltalk with free software + * programs or libraries that are released under the GNU LGPL and with + * independent programs running under the GNU Smalltalk virtual machine. + * + * You may copy and distribute such a system following the terms of the + * GNU GPL for GNU Smalltalk and the licenses of the other code + * concerned, provided that you include the source code of that other + * code when and as the GNU GPL requires distribution of source code. + * + * Note that people who make modified versions of GNU Smalltalk are not + * obligated to grant this special exception for their modified + * versions; it is their choice whether to do so. The GNU General + * Public License gives permission to release a modified version without + * this exception; this exception also makes it possible to release a + * modified version which carries forward this exception. + * + * GNU Smalltalk 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. + * + * You should have received a copy of the GNU General Public License along with + * GNU Smalltalk; see the file COPYING. If not, write to the Free Software + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + ***********************************************************************/ + + +#include <stdio.h> +#include "gstpub.h" +#include "sqlite3.h" + +typedef struct st_Sqlite3Handle +{ + OBJ_HEADER; + OOP db; +} *SQLite3Handle; + +typedef struct st_SQLite3StmtHandle +{ + OBJ_HEADER; + OOP db; + OOP stmt; + OOP colCount; + OOP colTypes; + OOP colNames; + OOP returnedRow; +} *SQLite3StmtHandle; + + +static VMProxy *vmProxy; + + +int +gst_sqlite3_open (OOP self, const char *db_name) +{ + int rc; + sqlite3 *db; + OOP dbHandle; + SQLite3Handle h; + + rc = sqlite3_open (db_name, &db); + dbHandle = vmProxy->cObjectToOOP (db); + h = (SQLite3Handle) OOP_TO_OBJ (self); + h->db = dbHandle; + + return rc; +} + +int +gst_sqlite3_close (OOP self) +{ + sqlite3 *db; + SQLite3Handle h; + + h = (SQLite3Handle) OOP_TO_OBJ (self); + db = (sqlite3 *) vmProxy->OOPToCObject (h->db); + return sqlite3_close (db); +} + +int +gst_sqlite3_prepare (OOP self, const char *sql) +{ + int rc, i, cols; + sqlite3 *db; + sqlite3_stmt *stmt; + OOP tmpOOP; + SQLite3StmtHandle h; + + h = (SQLite3StmtHandle) OOP_TO_OBJ (self); + db = (sqlite3 *) vmProxy->OOPToCObject (h->db); + + rc = sqlite3_prepare (db, sql, -1, &stmt, 0); + tmpOOP = vmProxy->cObjectToOOP (stmt); + h->stmt = tmpOOP; + + if (rc != SQLITE_OK) + return rc; + + cols = sqlite3_column_count (stmt); + + tmpOOP = vmProxy->intToOOP (cols); + h->colCount = tmpOOP; + + tmpOOP = vmProxy->objectAlloc (vmProxy->arrayClass, cols); + h->colTypes = tmpOOP; + + tmpOOP = vmProxy->objectAlloc (vmProxy->arrayClass, cols); + h->colNames = tmpOOP; + + tmpOOP = vmProxy->objectAlloc (vmProxy->arrayClass, cols); + h->returnedRow = tmpOOP; + + for (i = 0; i < cols; i++) + { + tmpOOP = vmProxy->stringToOOP (sqlite3_column_name (stmt, i)); + vmProxy->OOPAtPut (h->colNames, i, tmpOOP); + } + + return rc; +} + +int +gst_sqlite3_exec (OOP self) +{ + int rc; + sqlite3_stmt *stmt; + SQLite3StmtHandle h; + + h = (SQLite3StmtHandle) OOP_TO_OBJ (self); + stmt = (sqlite3_stmt *) vmProxy->OOPToCObject (h->stmt); + + rc = sqlite3_step (stmt); + + if (rc == SQLITE_ROW) + { + int i, cols, type; + OOP tmpOOP; + + cols = sqlite3_column_count (stmt); + for (i = 0; i < cols; i++) + { + type = sqlite3_column_type (stmt, i); + tmpOOP = vmProxy->intToOOP (type); + vmProxy->OOPAtPut (h->colTypes, i, tmpOOP); + + switch (type) + { + case SQLITE_INTEGER: + tmpOOP = vmProxy->intToOOP (sqlite3_column_int (stmt, i)); + break; + case SQLITE_FLOAT: + tmpOOP = vmProxy->floatToOOP (sqlite3_column_double (stmt, i)); + break; + case SQLITE_TEXT: + tmpOOP = vmProxy->stringToOOP (sqlite3_column_text (stmt, i)); + break; + case SQLITE_BLOB: + tmpOOP = vmProxy->stringToOOP (sqlite3_column_text (stmt, i)); + break; + case SQLITE_NULL: + tmpOOP = vmProxy->nilOOP; + break; + default: + fprintf (stderr, "sqlite3 error: %s\n", + "returned type not recognized"); + } + + vmProxy->OOPAtPut (h->returnedRow, i, tmpOOP); + } + } + + return rc; +} + +const char * +gst_sqlite3_error_message (OOP self) +{ + sqlite3 *db; + SQLite3Handle h; + + h = (SQLite3Handle) OOP_TO_OBJ (self); + db = (sqlite3 *) vmProxy->OOPToCObject (h->db); + + return sqlite3_errmsg (db); +} + +int +gst_sqlite3_finalize (OOP self) +{ + sqlite3_stmt *stmt; + SQLite3StmtHandle h; + + h = (SQLite3StmtHandle) OOP_TO_OBJ (self); + stmt = (sqlite3_stmt *) vmProxy->OOPToCObject (h->stmt); + + return sqlite3_finalize (stmt); +} + +int +gst_sqlite3_changes (OOP self) +{ + sqlite3 *db; + SQLite3StmtHandle h; + + h = (SQLite3StmtHandle) OOP_TO_OBJ (self); + db = (sqlite3 *) vmProxy->OOPToCObject (h->db); + + return sqlite3_changes (db); +} + +void +gst_initModule (VMProxy * proxy) +{ + vmProxy = proxy; + vmProxy->defineCFunc ("gst_sqlite3_open", gst_sqlite3_open); + vmProxy->defineCFunc ("gst_sqlite3_close", gst_sqlite3_close); + vmProxy->defineCFunc ("gst_sqlite3_prepare", gst_sqlite3_prepare); + vmProxy->defineCFunc ("gst_sqlite3_exec", gst_sqlite3_exec); + vmProxy->defineCFunc ("gst_sqlite3_changes", gst_sqlite3_changes); + vmProxy->defineCFunc ("gst_sqlite3_error_message", gst_sqlite3_error_message); + vmProxy->defineCFunc ("gst_sqlite3_finalize", gst_sqlite3_finalize); +} _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
Free forum by Nabble | Edit this page |