Page 1 of 1
SQLite create function
Posted: Tue Feb 03, 2009 10:45 am
by Polly
Hi, I'm trying to create a user-defined function in SQLite, something like this:
Code: Select all
ProcedureCDLL test(ctx, nArg, ppArg)
Debug PeekS(ppArg)
pArg=PeekL(ppArg)
Debug pArg
Debug PeekS(pArg)
EndProcedure
Debug sqlite3_create_function(handleDatabase, "test", 1, 1, 0, @test(), 0, 0)
sql$="select test(field) from table"
The creation returns ok, the callback procedure gets invoked properly, but I'm not able to read the argument (the table field), that what is in C: **argv. The Debugs only report nonsense or an empty string.
Does anybody have a working example?
Posted: Tue Feb 03, 2009 11:43 am
by srod
The callback function parameters (pointed to by the ppArg array) are in fact 'protected SQLite3 objects' and so you need to use SQLite3 functions to get at 'em!
The following works for me on a little database I cooked up :
Code: Select all
ImportC "sqlite3.lib"
sqlite3_create_function(hDB, zFunctionName.s, nArg, eTextRep, pApp, xFunc, xStep, xFinal)
sqlite3_value_text(sqlite3_value)
EndImport
ProcedureC test(ctx, nArg, ppArg)
pArg=PeekI(ppArg)
Debug PeekS(sqlite3_value_text(pArg))
EndProcedure
UseSQLiteDatabase()
; Open database
Nr=OpenDatabase(#PB_Any, "addresses.db", "", "", #PB_Database_SQLite)
If Nr
hDB = PeekI(PeekI(Nr+SizeOf(INTEGER)))
sqlite3_create_function(hDB, "test", 1, 1, 0, @test(), 0, 0)
cmd$="select test(Surname) from customers"
If DatabaseQuery(Nr, cmd$)
While NextDatabaseRow(Nr)
Wend
FinishDatabaseQuery(Nr)
EndIf
CloseDatabase(nr)
EndIf
You may need to import the sqlite3_value_type() function as well.
I hope it helps?
Posted: Tue Feb 03, 2009 1:13 pm
by Polly
Yepp, thanks, helpful as always. One has to use the value* function for the arguments and the result* functions for the return value, that's all:
Code: Select all
ProcedureC test(ctx, nArg, ppArg)
pArg=PeekL(ppArg)
Global strg$=PeekS(sqlite3_value_text(pArg))
strg$=UCase(strg$)
sqlite3_result_text(ctx, @strg$, Len(strg$), 0)
ProcedureReturn 0
EndProcedure
Posted: Tue Feb 03, 2009 3:02 pm
by srod
Indeed.
btw, you can use
to get the SQLite DB handle as opposed to all the Peeking I did in the above code!
Re:
Posted: Fri Jan 25, 2019 6:30 pm
by Oliver13
Sorry for bringing up this topic - but I do not see the forest for the trees..
Obviously, also this funtcion must be imported:
sqlite3_result_text(ctx, @strg$, Len(strg$), 0)
I tried as following, but does not work.
ImportC "sqlite3.lib"
sqlite3_result_text(*sqlite3_context, *returnvalue, nBytes, nParam)
EndImport
So can anybody help ?
TX
Re: SQLite create function
Posted: Fri Jan 25, 2019 8:28 pm
by infratec
Hi,
a small example:
Code: Select all
ImportC "sqlite3.lib"
sqlite3_create_function.l(DatabaseID, zFunctionName.p-utf8, nArg.l, eTextRep.l, *pApp, *xFunc, *xStep, *xFinal)
sqlite3_aggregate_context(*sqlite3_context, nBytes.l)
sqlite3_result_double(*sqlite3_context, dbl.d)
sqlite3_result_text(*sqlite3_context, *returnvalue, nBytes.l, *nParam)
sqlite3_value_numeric_type.l(*sqlite3_value)
sqlite3_value_double.d(*sqlite3_value)
sqlite3_value_int.i(*sqlite3_value)
sqlite3_value_type.i(*argv)
;Neue Funktionen
sqlite3_backup_init(pDest, zDestName.p-ascii, pSource, zSourceName.p-ascii)
sqlite3_backup_step(sqlite3_backup, nPage)
sqlite3_backup_finish(sqlite3_backup)
sqlite3_errcode(db)
EndImport
#SQLITE_UTF8 = 1 ; IMP: R-37514-35566
#SQLITE_UTF16LE = 2 ; IMP: R-03371-37637
#SQLITE_UTF16BE = 3 ; IMP: R-51971-34154
#SQLITE_UTF16 = 4 ; Use native byte order
#SQLITE_ANY = 5 ; Deprecated
#SQLITE_UTF16_ALIGNED = 8 ; sqlite3_create_collation only
#SQLITE_INTEGER = 1
#SQLITE_FLOAT = 2
#SQLITE_TEXT = 3
#SQLITE_BLOB = 4
#SQLITE_NULL = 5
#SQLITE_STATIC = 0
#SQLITE_TRANSIENT = -1
ProcedureC TypeOfFunc(*context, argc.l, *argv)
Protected *Buffer
Select sqlite3_value_type(PeekL(*argv))
Case #SQLITE_NULL
*Buffer = UTF8("null")
Case #SQLITE_INTEGER
*Buffer = UTF8("integer")
Case #SQLITE_TEXT
*Buffer = UTF8("text")
Case #SQLITE_FLOAT
*Buffer = UTF8("real")
Case #SQLITE_BLOB
*Buffer = UTF8("blob")
EndSelect
sqlite3_result_text(*context, *Buffer, -1, #SQLITE_TRANSIENT)
If *Buffer
FreeMemory(*Buffer)
EndIf
EndProcedure
Procedure RegisterSQLiteFunctions(dataBase.i)
Protected dataBaseID.i
dataBaseID = DatabaseID(dataBase)
sqlite3_create_function(dataBaseID, "typeofcol", 1, #SQLITE_UTF8, #Null, @TypeofFunc(), #Null, #Null)
EndProcedure
UseSQLiteDatabase()
DB = OpenDatabase(#PB_Any, ":memory:", "", "", #PB_Database_SQLite)
If DB
RegisterSQLiteFunctions(DB)
DatabaseUpdate(DB, "CREATE TABLE myTable (id INTEGER, data DOUBLE, description text)")
DatabaseUpdate(DB, "INSERT INTO myTable VALUES ( 1, 18.5, 'bla')")
If DatabaseQuery(DB, "SELECT typeofcol(id), typeofcol(data), typeofcol(description) FROM myTable")
If NextDatabaseRow(DB)
Debug GetDatabaseString(DB, 0)
Debug GetDatabaseString(DB, 1)
Debug GetDatabaseString(DB, 2)
EndIf
FinishDatabaseQuery(DB)
Else
Debug DatabaseError()
EndIf
CloseDatabase(DB)
EndIf
Bernd
Re: SQLite create function
Posted: Fri Jan 25, 2019 11:32 pm
by mk-soft
Cool
But so work with Window, Linux, MacOS and x86,x64
Code: Select all
ImportC ""
sqlite3_create_function.i(DatabaseID, zFunctionName.p-utf8, nArg.i, eTextRep.i, *pApp, *xFunc, *xStep, *xFinal)
sqlite3_aggregate_context(*sqlite3_context, nBytes.i)
sqlite3_result_double(*sqlite3_context, dbl.d)
sqlite3_result_text(*sqlite3_context, *returnvalue, nBytes.i, *nParam)
sqlite3_value_numeric_type.i(*sqlite3_value)
sqlite3_value_double.d(*sqlite3_value)
sqlite3_value_int.i(*sqlite3_value)
sqlite3_value_type.i(*argv)
;Neue Funktionen
sqlite3_backup_init(pDest, zDestName.p-ascii, pSource, zSourceName.p-ascii)
sqlite3_backup_step(sqlite3_backup, nPage)
sqlite3_backup_finish(sqlite3_backup)
sqlite3_errcode(db)
EndImport
#SQLITE_UTF8 = 1 ; IMP: R-37514-35566
#SQLITE_UTF16LE = 2 ; IMP: R-03371-37637
#SQLITE_UTF16BE = 3 ; IMP: R-51971-34154
#SQLITE_UTF16 = 4 ; Use native byte order
#SQLITE_ANY = 5 ; Deprecated
#SQLITE_UTF16_ALIGNED = 8 ; sqlite3_create_collation only
#SQLITE_INTEGER = 1
#SQLITE_FLOAT = 2
#SQLITE_TEXT = 3
#SQLITE_BLOB = 4
#SQLITE_NULL = 5
#SQLITE_STATIC = 0
#SQLITE_TRANSIENT = -1
ProcedureC TypeOfFunc(*context, argc.i, *argv.integer)
Protected *Buffer
Select sqlite3_value_type(*argv\i)
Case #SQLITE_NULL
*Buffer = UTF8("null")
Case #SQLITE_INTEGER
*Buffer = UTF8("integer")
Case #SQLITE_TEXT
*Buffer = UTF8("text")
Case #SQLITE_FLOAT
*Buffer = UTF8("real")
Case #SQLITE_BLOB
*Buffer = UTF8("blob")
EndSelect
sqlite3_result_text(*context, *Buffer, -1, #SQLITE_TRANSIENT)
If *Buffer
FreeMemory(*Buffer)
EndIf
EndProcedure
Procedure RegisterSQLiteFunctions(dataBase.i)
Protected dataBaseID.i
dataBaseID = DatabaseID(dataBase)
sqlite3_create_function(dataBaseID, "typeofcol", 1, #SQLITE_UTF8, #Null, @TypeofFunc(), #Null, #Null)
EndProcedure
UseSQLiteDatabase()
DB = OpenDatabase(#PB_Any, ":memory:", "", "", #PB_Database_SQLite)
If DB
RegisterSQLiteFunctions(DB)
DatabaseUpdate(DB, "CREATE TABLE myTable (id INTEGER, data DOUBLE, description text)")
DatabaseUpdate(DB, "INSERT INTO myTable VALUES ( 1, 18.5, 'bla')")
If DatabaseQuery(DB, "SELECT typeofcol(id), typeofcol(data), typeofcol(description) FROM myTable")
If NextDatabaseRow(DB)
Debug GetDatabaseString(DB, 0)
Debug GetDatabaseString(DB, 1)
Debug GetDatabaseString(DB, 2)
EndIf
FinishDatabaseQuery(DB)
Else
Debug DatabaseError()
EndIf
CloseDatabase(DB)
EndIf