sqlite updates -- throw error name, modernize to FUNCTION: and put ffi in libsqlite.factor, remove indirect structs
parent
56aa601146
commit
ea73010a04
|
@ -0,0 +1,111 @@
|
||||||
|
! Copyright (C) 2005 Chris Double, Doug Coleman.
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
!
|
||||||
|
! An interface to the sqlite database. Tested against sqlite v3.0.8.
|
||||||
|
! Remeber to pass the following to factor:
|
||||||
|
! -libraries:sqlite=libsqlite3.so
|
||||||
|
!
|
||||||
|
! Not all functions have been wrapped yet. Only those directly involving
|
||||||
|
! executing SQL calls and obtaining results.
|
||||||
|
!
|
||||||
|
IN: libsqlite
|
||||||
|
USING: alien compiler errors kernel math namespaces sequences strings ;
|
||||||
|
|
||||||
|
! Return values from sqlite functions
|
||||||
|
: SQLITE_OK 0 ; ! Successful result
|
||||||
|
: SQLITE_ERROR 1 ; ! SQL error or missing database
|
||||||
|
: SQLITE_INTERNAL 2 ; ! An internal logic error in SQLite
|
||||||
|
: SQLITE_PERM 3 ; ! Access permission denied
|
||||||
|
: SQLITE_ABORT 4 ; ! Callback routine requested an abort
|
||||||
|
: SQLITE_BUSY 5 ; ! The database file is locked
|
||||||
|
: SQLITE_LOCKED 6 ; ! A table in the database is locked
|
||||||
|
: SQLITE_NOMEM 7 ; ! A malloc() failed
|
||||||
|
: SQLITE_READONLY 8 ; ! Attempt to write a readonly database
|
||||||
|
: SQLITE_INTERRUPT 9 ; ! Operation terminated by sqlite_interrupt()
|
||||||
|
: SQLITE_IOERR 10 ; ! Some kind of disk I/O error occurred
|
||||||
|
: SQLITE_CORRUPT 11 ; ! The database disk image is malformed
|
||||||
|
: SQLITE_NOTFOUND 12 ; ! (Internal Only) Table or record not found
|
||||||
|
: SQLITE_FULL 13 ; ! Insertion failed because database is full
|
||||||
|
: SQLITE_CANTOPEN 14 ; ! Unable to open the database file
|
||||||
|
: SQLITE_PROTOCOL 15 ; ! Database lock protocol error
|
||||||
|
: SQLITE_EMPTY 16 ; ! (Internal Only) Database table is empty
|
||||||
|
: SQLITE_SCHEMA 17 ; ! The database schema changed
|
||||||
|
: SQLITE_TOOBIG 18 ; ! Too much data for one row of a table
|
||||||
|
: SQLITE_CONSTRAINT 19 ; ! Abort due to contraint violation
|
||||||
|
: SQLITE_MISMATCH 20 ; ! Data type mismatch
|
||||||
|
: SQLITE_MISUSE 21 ; ! Library used incorrectly
|
||||||
|
: SQLITE_NOLFS 22 ; ! Uses OS features not supported on host
|
||||||
|
: SQLITE_AUTH 23 ; ! Authorization denied
|
||||||
|
: SQLITE_FORMAT 24 ; ! Auxiliary database format error
|
||||||
|
: SQLITE_RANGE 25 ; ! 2nd parameter to sqlite3_bind out of range
|
||||||
|
: SQLITE_NOTADB 26 ; ! File opened that is not a database file
|
||||||
|
|
||||||
|
: sqlite-error-messages ( -- seq ) {
|
||||||
|
"Successful result"
|
||||||
|
"SQL error or missing database"
|
||||||
|
"An internal logic error in SQLite"
|
||||||
|
"Access permission denied"
|
||||||
|
"Callback routine requested an abort"
|
||||||
|
"The database file is locked"
|
||||||
|
"A table in the database is locked"
|
||||||
|
"A malloc() failed"
|
||||||
|
"Attempt to write a readonly database"
|
||||||
|
"Operation terminated by sqlite_interrupt()"
|
||||||
|
"Some kind of disk I/O error occurred"
|
||||||
|
"The database disk image is malformed"
|
||||||
|
"(Internal Only) Table or record not found"
|
||||||
|
"Insertion failed because database is full"
|
||||||
|
"Unable to open the database file"
|
||||||
|
"Database lock protocol error"
|
||||||
|
"(Internal Only) Database table is empty"
|
||||||
|
"The database schema changed"
|
||||||
|
"Too much data for one row of a table"
|
||||||
|
"Abort due to contraint violation"
|
||||||
|
"Data type mismatch"
|
||||||
|
"Library used incorrectly"
|
||||||
|
"Uses OS features not supported on host"
|
||||||
|
"Authorization denied"
|
||||||
|
"Auxiliary database format error"
|
||||||
|
"2nd parameter to sqlite3_bind out of range"
|
||||||
|
"File opened that is not a database file"
|
||||||
|
} ;
|
||||||
|
|
||||||
|
: SQLITE_ROW 100 ; ! sqlite_step() has another row ready
|
||||||
|
: SQLITE_DONE 101 ; ! sqlite_step() has finished executing
|
||||||
|
|
||||||
|
! Return values from the sqlite3_column_type function
|
||||||
|
: SQLITE_INTEGER 1 ;
|
||||||
|
: SQLITE_FLOAT 2 ;
|
||||||
|
: SQLITE_TEXT 3 ;
|
||||||
|
: SQLITE_BLOB 4 ;
|
||||||
|
: SQLITE_NULL 5 ;
|
||||||
|
|
||||||
|
! Values for the 'destructor' parameter of the 'bind' routines.
|
||||||
|
: SQLITE_STATIC 0 ;
|
||||||
|
: SQLITE_TRANSIENT -1 ;
|
||||||
|
|
||||||
|
TYPEDEF: void sqlite3
|
||||||
|
TYPEDEF: void sqlite3_stmt
|
||||||
|
|
||||||
|
LIBRARY: sqlite
|
||||||
|
FUNCTION: int sqlite3_open ( char* filename, void* ppDb ) ;
|
||||||
|
FUNCTION: int sqlite3_close ( sqlite3* pDb ) ;
|
||||||
|
FUNCTION: int sqlite3_prepare ( sqlite3* pDb, char* zSql, int nBytes, void* ppStmt, void* pzTail ) ;
|
||||||
|
FUNCTION: int sqlite3_finalize ( sqlite3_stmt* pStmt ) ;
|
||||||
|
FUNCTION: int sqlite3_reset ( sqlite3_stmt* pStmt ) ;
|
||||||
|
FUNCTION: int sqlite3_step ( sqlite3_stmt* pStmt ) ;
|
||||||
|
FUNCTION: int sqlite3_last_insert_rowid ( sqlite3* pStmt ) ;
|
||||||
|
FUNCTION: int sqlite3_bind_blob ( sqlite3_stmt* pStmt, int index, void* ptr, int len, int destructor ) ;
|
||||||
|
FUNCTION: int sqlite3_bind_int ( sqlite3_stmt* pStmt, int index, int n ) ;
|
||||||
|
FUNCTION: int sqlite3_bind_null ( sqlite3_stmt* pStmt, int n ) ;
|
||||||
|
FUNCTION: int sqlite3_bind_text ( sqlite3_stmt* pStmt, int index, char* text, int len, int destructor ) ;
|
||||||
|
FUNCTION: int sqlite3_bind_parameter_index ( sqlite3_stmt* pStmt, char* name ) ;
|
||||||
|
FUNCTION: int sqlite3_column_count ( sqlite3_stmt* pStmt ) ;
|
||||||
|
FUNCTION: void* sqlite3_column_blob ( sqlite3_stmt* pStmt, int col ) ;
|
||||||
|
FUNCTION: int sqlite3_column_bytes ( sqlite3_stmt* pStmt, int col ) ;
|
||||||
|
FUNCTION: char* sqlite3_column_decltype ( sqlite3_stmt* pStmt, int col ) ;
|
||||||
|
FUNCTION: int sqlite3_column_int ( sqlite3_stmt* pStmt, int col ) ;
|
||||||
|
FUNCTION: int sqlite3_column_name ( sqlite3_stmt* pStmt, int col ) ;
|
||||||
|
FUNCTION: char* sqlite3_column_text ( sqlite3_stmt* pStmt, int col ) ;
|
||||||
|
FUNCTION: int sqlite3_column_type ( sqlite3_stmt* pStmt, int col ) ;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
PROVIDE: contrib/sqlite {
|
PROVIDE: contrib/sqlite {
|
||||||
|
"libsqlite.factor"
|
||||||
"sqlite.factor"
|
"sqlite.factor"
|
||||||
"sqlite.facts"
|
"sqlite.facts"
|
||||||
"tuple-db.factor"
|
"tuple-db.factor"
|
||||||
|
|
|
@ -9,148 +9,25 @@
|
||||||
! executing SQL calls and obtaining results.
|
! executing SQL calls and obtaining results.
|
||||||
!
|
!
|
||||||
IN: sqlite
|
IN: sqlite
|
||||||
USE: kernel
|
USING: alien compiler errors libsqlite kernel namespaces sequences strings ;
|
||||||
USE: alien
|
|
||||||
USE: errors
|
|
||||||
USE: strings
|
|
||||||
USE: namespaces
|
|
||||||
USE: sequences
|
|
||||||
USE: compiler
|
|
||||||
|
|
||||||
"sqlite" windows? [ "sqlite3.dll" ] [ "libsqlite3.so" ] if "cdecl" add-library
|
TUPLE: sqlite-error n message ;
|
||||||
BEGIN-STRUCT: sqlite3
|
|
||||||
END-STRUCT
|
|
||||||
|
|
||||||
BEGIN-STRUCT: sqlite3-indirect
|
|
||||||
FIELD: sqlite3* pointer
|
|
||||||
END-STRUCT
|
|
||||||
|
|
||||||
BEGIN-STRUCT: sqlite3-stmt
|
|
||||||
END-STRUCT
|
|
||||||
|
|
||||||
BEGIN-STRUCT: sqlite3-stmt-indirect
|
|
||||||
FIELD: sqlite3-stmt* pointer
|
|
||||||
END-STRUCT
|
|
||||||
|
|
||||||
BEGIN-STRUCT: char*-indirect
|
|
||||||
FIELD: char* pointer
|
|
||||||
END-STRUCT
|
|
||||||
|
|
||||||
! Return values from sqlite functions
|
|
||||||
: SQLITE_OK 0 ; ! Successful result
|
|
||||||
: SQLITE_ERROR 1 ; ! SQL error or missing database
|
|
||||||
: SQLITE_INTERNAL 2 ; ! An internal logic error in SQLite
|
|
||||||
: SQLITE_PERM 3 ; ! Access permission denied
|
|
||||||
: SQLITE_ABORT 4 ; ! Callback routine requested an abort
|
|
||||||
: SQLITE_BUSY 5 ; ! The database file is locked
|
|
||||||
: SQLITE_LOCKED 6 ; ! A table in the database is locked
|
|
||||||
: SQLITE_NOMEM 7 ; ! A malloc() failed
|
|
||||||
: SQLITE_READONLY 8 ; ! Attempt to write a readonly database
|
|
||||||
: SQLITE_INTERRUPT 9 ; ! Operation terminated by sqlite_interrupt()
|
|
||||||
: SQLITE_IOERR 10 ; ! Some kind of disk I/O error occurred
|
|
||||||
: SQLITE_CORRUPT 11 ; ! The database disk image is malformed
|
|
||||||
: SQLITE_NOTFOUND 12 ; ! (Internal Only) Table or record not found
|
|
||||||
: SQLITE_FULL 13 ; ! Insertion failed because database is full
|
|
||||||
: SQLITE_CANTOPEN 14 ; ! Unable to open the database file
|
|
||||||
: SQLITE_PROTOCOL 15 ; ! Database lock protocol error
|
|
||||||
: SQLITE_EMPTY 16 ; ! (Internal Only) Database table is empty
|
|
||||||
: SQLITE_SCHEMA 17 ; ! The database schema changed
|
|
||||||
: SQLITE_TOOBIG 18 ; ! Too much data for one row of a table
|
|
||||||
: SQLITE_CONSTRAINT 19 ; ! Abort due to contraint violation
|
|
||||||
: SQLITE_MISMATCH 20 ; ! Data type mismatch
|
|
||||||
: SQLITE_MISUSE 21 ; ! Library used incorrectly
|
|
||||||
: SQLITE_NOLFS 22 ; ! Uses OS features not supported on host
|
|
||||||
: SQLITE_AUTH 23 ; ! Authorization denied
|
|
||||||
: SQLITE_ROW 100 ; ! sqlite_step() has another row ready
|
|
||||||
: SQLITE_DONE 101 ; ! sqlite_step() has finished executing
|
|
||||||
|
|
||||||
! Return values from the sqlite3_column_type function
|
|
||||||
: SQLITE_INTEGER 1 ;
|
|
||||||
: SQLITE_FLOAT 2 ;
|
|
||||||
: SQLITE_TEXT 3 ;
|
|
||||||
: SQLITE_BLOB 4 ;
|
|
||||||
: SQLITE_NULL 5 ;
|
|
||||||
|
|
||||||
! Values for the 'destructor' parameter of the 'bind' routines.
|
|
||||||
: SQLITE_STATIC 0 ;
|
|
||||||
: SQLITE_TRANSIENT -1 ;
|
|
||||||
|
|
||||||
: sqlite3_open ( filename sqlite3-indirect -- result )
|
|
||||||
"int" "sqlite" "sqlite3_open" [ "char*" "sqlite3-indirect*" ] alien-invoke ;
|
|
||||||
|
|
||||||
: sqlite3_close ( db -- result )
|
|
||||||
"int" "sqlite" "sqlite3_close" [ "sqlite3*" ] alien-invoke ;
|
|
||||||
|
|
||||||
: sqlite3_prepare ( db sql sql-len sqlite3-stmt-indirect tail -- result )
|
|
||||||
"int" "sqlite" "sqlite3_prepare" [ "sqlite3*" "char*" "int" "sqlite3-stmt-indirect*" "char*-indirect*" ] alien-invoke ;
|
|
||||||
|
|
||||||
: sqlite3_finalize ( stmt -- result )
|
|
||||||
"int" "sqlite" "sqlite3_finalize" [ "sqlite3-stmt*" ] alien-invoke ;
|
|
||||||
|
|
||||||
: sqlite3_reset ( stmt -- result )
|
|
||||||
"int" "sqlite" "sqlite3_reset" [ "sqlite3-stmt*" ] alien-invoke ;
|
|
||||||
|
|
||||||
: sqlite3_step ( stmt -- result )
|
|
||||||
"int" "sqlite" "sqlite3_step" [ "sqlite3-stmt*" ] alien-invoke ;
|
|
||||||
|
|
||||||
: sqlite3_last_insert_rowid ( stmt -- result )
|
|
||||||
"int" "sqlite" "sqlite3_last_insert_rowid" [ "sqlite3*" ] alien-invoke ;
|
|
||||||
|
|
||||||
: sqlite3_bind_blob ( stmt index pointer len destructor -- result )
|
|
||||||
"int" "sqlite" "sqlite3_bind_blob" [ "sqlite3-stmt*" "int" "void*" "int" "int" ] alien-invoke ;
|
|
||||||
|
|
||||||
: sqlite3_bind_int ( stmt index int -- result )
|
|
||||||
"int" "sqlite" "sqlite3_bind_int" [ "sqlite3-stmt*" "int" "int" ] alien-invoke ;
|
|
||||||
|
|
||||||
: sqlite3_bind_null ( stmt index -- result )
|
|
||||||
"int" "sqlite" "sqlite3_bind_null" [ "sqlite3-stmt*" "int" ] alien-invoke ;
|
|
||||||
|
|
||||||
: sqlite3_bind_text ( stmt index text len destructor -- result )
|
|
||||||
"int" "sqlite" "sqlite3_bind_text" [ "sqlite3-stmt*" "int" "char*" "int" "int" ] alien-invoke ;
|
|
||||||
|
|
||||||
: sqlite3_bind_parameter_index ( stmt name -- result )
|
|
||||||
"int" "sqlite" "sqlite3_bind_parameter_index" [ "sqlite3-stmt*" "char*" ] alien-invoke ;
|
|
||||||
|
|
||||||
: sqlite3_column_count ( stmt -- count )
|
|
||||||
"int" "sqlite" "sqlite3_column_count" [ "sqlite3-stmt*" ] alien-invoke ;
|
|
||||||
|
|
||||||
: sqlite3_column_blob ( stmt col -- void* )
|
|
||||||
"void*" "sqlite" "sqlite3_column_blob" [ "sqlite3-stmt*" "int" ] alien-invoke ;
|
|
||||||
|
|
||||||
: sqlite3_column_bytes ( stmt col -- int )
|
|
||||||
"int" "sqlite" "sqlite3_column_bytes" [ "sqlite3-stmt*" "int" ] alien-invoke ;
|
|
||||||
|
|
||||||
: sqlite3_column_decltype ( stmt col -- string )
|
|
||||||
"char*" "sqlite" "sqlite3_column_decltype" [ "sqlite3-stmt*" "int" ] alien-invoke ;
|
|
||||||
|
|
||||||
: sqlite3_column_int ( stmt col -- int )
|
|
||||||
"int" "sqlite" "sqlite3_column_int" [ "sqlite3-stmt*" "int" ] alien-invoke ;
|
|
||||||
|
|
||||||
: sqlite3_column_name ( stmt col -- string )
|
|
||||||
"char*" "sqlite" "sqlite3_column_name" [ "sqlite3-stmt*" "int" ] alien-invoke ;
|
|
||||||
|
|
||||||
: sqlite3_column_text ( stmt col -- string )
|
|
||||||
"char*" "sqlite" "sqlite3_column_text" [ "sqlite3-stmt*" "int" ] alien-invoke ;
|
|
||||||
|
|
||||||
: sqlite3_column_type ( stmt col -- int )
|
|
||||||
"int" "sqlite" "sqlite3_column_type" [ "sqlite3-stmt*" "int" ] alien-invoke ;
|
|
||||||
|
|
||||||
! High level sqlite routines
|
! High level sqlite routines
|
||||||
: sqlite-check-result ( result -- )
|
: sqlite-check-result ( result -- )
|
||||||
#! Check the result from a sqlite call is ok. If it is
|
#! Check the result from a sqlite call is ok. If it is
|
||||||
#! return, otherwise throw an error. TODO: Throw the actual
|
#! return, otherwise throw an error.
|
||||||
#! error text message.
|
|
||||||
dup SQLITE_OK = [
|
dup SQLITE_OK = [
|
||||||
drop
|
drop
|
||||||
] [
|
] [
|
||||||
"sqlite returned an error. See datastack for the error value." throw
|
dup sqlite-error-messages nth <sqlite-error> throw
|
||||||
] if ;
|
] if ;
|
||||||
|
|
||||||
: sqlite-open ( filename -- db )
|
: sqlite-open ( filename -- db )
|
||||||
#! Open the database referenced by the filename and return
|
#! Open the database referenced by the filename and return
|
||||||
#! a handle to that database. An error is thrown if the database
|
#! a handle to that database. An error is thrown if the database
|
||||||
#! failed to open.
|
#! failed to open.
|
||||||
"sqlite3-indirect" <c-object> tuck sqlite3_open sqlite-check-result sqlite3-indirect-pointer ;
|
"void*" <c-object> [ sqlite3_open sqlite-check-result ] keep *void* ;
|
||||||
|
|
||||||
: sqlite-close ( db -- )
|
: sqlite-close ( db -- )
|
||||||
#! Close the given database
|
#! Close the given database
|
||||||
|
@ -164,9 +41,9 @@ END-STRUCT
|
||||||
#! Prepare a SQL statement. Returns the statement which
|
#! Prepare a SQL statement. Returns the statement which
|
||||||
#! can have values bound to parameters or simply executed.
|
#! can have values bound to parameters or simply executed.
|
||||||
#! TODO: Support multiple statements in the SQL string.
|
#! TODO: Support multiple statements in the SQL string.
|
||||||
dup length "sqlite3-stmt-indirect" <c-object> dup >r
|
dup length "void*" <c-object> "void*" <c-object>
|
||||||
"char*-indirect" <c-object> sqlite3_prepare sqlite-check-result
|
[ sqlite3_prepare sqlite-check-result ] 2keep
|
||||||
r> sqlite3-stmt-indirect-pointer ;
|
drop *void* ;
|
||||||
|
|
||||||
: sqlite-bind-text ( statement index text -- )
|
: sqlite-bind-text ( statement index text -- )
|
||||||
#! Bind the text to the parameterized value in the statement.
|
#! Bind the text to the parameterized value in the statement.
|
||||||
|
|
|
@ -1,25 +1,4 @@
|
||||||
! Copyright (C) 2005 Chris Double.
|
! Copyright (C) 2005 Chris Double.
|
||||||
!
|
|
||||||
! Redistribution and use in source and binary forms, with or without
|
|
||||||
! modification, are permitted provided that the following conditions are met:
|
|
||||||
!
|
|
||||||
! 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
! this list of conditions and the following disclaimer.
|
|
||||||
!
|
|
||||||
! 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
! this list of conditions and the following disclaimer in the documentation
|
|
||||||
! and/or other materials provided with the distribution.
|
|
||||||
!
|
|
||||||
! THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
||||||
! INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
||||||
! FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
! DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
! SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
! PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
||||||
! OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
||||||
! WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
||||||
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
!
|
!
|
||||||
! A tuple that is persistent has its delegate set as 'persistent'.
|
! A tuple that is persistent has its delegate set as 'persistent'.
|
||||||
! 'persistent' holds the numeric rowid for that tuple in its table.
|
! 'persistent' holds the numeric rowid for that tuple in its table.
|
||||||
|
|
Loading…
Reference in New Issue