Add the sqlite3_overload_function() API - part of the virtual table
interface. (CVS 3426) FossilOrigin-Name: aa7728f9f5b80dbb1b3db124f84b9166bf72bdd3
This commit is contained in:
+2
-15
@@ -16,7 +16,7 @@
|
||||
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
|
||||
** All other code has file scope.
|
||||
**
|
||||
** $Id: func.c,v 1.133 2006/08/19 11:34:01 drh Exp $
|
||||
** $Id: func.c,v 1.134 2006/09/16 21:45:14 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@@ -548,19 +548,6 @@ static void versionFunc(
|
||||
sqlite3_result_text(context, sqlite3_version, -1, SQLITE_STATIC);
|
||||
}
|
||||
|
||||
/*
|
||||
** The MATCH() function is unimplemented. If anybody tries to use it,
|
||||
** return an error.
|
||||
*/
|
||||
static void matchStub(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
static const char zErr[] = "MATCH is not implemented";
|
||||
sqlite3_result_error(context, zErr, sizeof(zErr)-1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** EXPERIMENTAL - This is not an official function. The interface may
|
||||
@@ -1043,7 +1030,6 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
|
||||
{ "last_insert_rowid", 0, 1, SQLITE_UTF8, 0, last_insert_rowid },
|
||||
{ "changes", 0, 1, SQLITE_UTF8, 0, changes },
|
||||
{ "total_changes", 0, 1, SQLITE_UTF8, 0, total_changes },
|
||||
{ "match", 2, 0, SQLITE_UTF8, 0, matchStub },
|
||||
#ifdef SQLITE_SOUNDEX
|
||||
{ "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc},
|
||||
#endif
|
||||
@@ -1116,6 +1102,7 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
|
||||
}
|
||||
}
|
||||
sqlite3RegisterDateTimeFunctions(db);
|
||||
sqlite3_overload_function(db, "MATCH", 2);
|
||||
#ifdef SQLITE_SSE
|
||||
(void)sqlite3SseFunctions(db);
|
||||
#endif
|
||||
|
||||
+28
-2
@@ -14,7 +14,7 @@
|
||||
** other files are for internal use by SQLite and should not be
|
||||
** accessed by users of the library.
|
||||
**
|
||||
** $Id: main.c,v 1.357 2006/09/15 07:28:50 drh Exp $
|
||||
** $Id: main.c,v 1.358 2006/09/16 21:45:14 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@@ -541,6 +541,32 @@ int sqlite3_create_function16(
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Declare that a function has been overloaded by a virtual table.
|
||||
**
|
||||
** If the function already exists as a regular global function, then
|
||||
** this routine is a no-op. If the function does not exist, then create
|
||||
** a new one that always throws a run-time error.
|
||||
**
|
||||
** When virtual tables intend to provide an overloaded function, they
|
||||
** should call this routine to make sure the global function exists.
|
||||
** A global function must exist in order for name resolution to work
|
||||
** properly.
|
||||
*/
|
||||
int sqlite3_overload_function(
|
||||
sqlite3 *db,
|
||||
const char *zName,
|
||||
int nArg
|
||||
){
|
||||
int nName = strlen(zName);
|
||||
if( sqlite3FindFunction(db, zName, nName, nArg, SQLITE_UTF8, 0)==0 ){
|
||||
sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8,
|
||||
0, sqlite3InvalidFunction, 0, 0);
|
||||
}
|
||||
return sqlite3ApiExit(db, SQLITE_OK);
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_TRACE
|
||||
/*
|
||||
** Register a trace function. The pArg from the previously registered trace
|
||||
@@ -908,8 +934,8 @@ static int openDatabase(
|
||||
** is accessed.
|
||||
*/
|
||||
if( !sqlite3MallocFailed() ){
|
||||
sqlite3RegisterBuiltinFunctions(db);
|
||||
sqlite3Error(db, SQLITE_OK, 0);
|
||||
sqlite3RegisterBuiltinFunctions(db);
|
||||
}
|
||||
db->magic = SQLITE_MAGIC_OPEN;
|
||||
|
||||
|
||||
+19
-1
@@ -12,7 +12,7 @@
|
||||
** This header file defines the interface that the SQLite library
|
||||
** presents to client programs.
|
||||
**
|
||||
** @(#) $Id: sqlite.h.in,v 1.193 2006/09/15 07:28:50 drh Exp $
|
||||
** @(#) $Id: sqlite.h.in,v 1.194 2006/09/16 21:45:14 drh Exp $
|
||||
*/
|
||||
#ifndef _SQLITE3_H_
|
||||
#define _SQLITE3_H_
|
||||
@@ -1782,6 +1782,24 @@ struct sqlite3_vtab_cursor {
|
||||
*/
|
||||
int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable);
|
||||
|
||||
/*
|
||||
** Virtual tables can provide alternative implementations of functions
|
||||
** using the xFindFunction method. But global versions of those functions
|
||||
** must exist in order to be overloaded.
|
||||
**
|
||||
** This API makes sure a global version of a function with a particular
|
||||
** name and number of parameters exists. If no such function exists
|
||||
** before this API is called, a new function is created. The implementation
|
||||
** of the new function always causes an exception to be thrown. So
|
||||
** the new function is not good for anything by itself. Its only
|
||||
** purpose is to be a place-holder function that can be overloaded
|
||||
** by virtual tables.
|
||||
**
|
||||
** This API should be considered part of the virtual table interface,
|
||||
** which is experimental and subject to change.
|
||||
*/
|
||||
int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
|
||||
|
||||
/*
|
||||
** The interface to the virtual-table mechanism defined above (back up
|
||||
** to a comment remarkably similar to this one) is currently considered
|
||||
|
||||
+2
-1
@@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.527 2006/09/15 07:28:50 drh Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.528 2006/09/16 21:45:14 drh Exp $
|
||||
*/
|
||||
#ifndef _SQLITEINT_H_
|
||||
#define _SQLITEINT_H_
|
||||
@@ -1874,6 +1874,7 @@ int sqlite3VtabCallConnect(Parse*, Table*);
|
||||
int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
|
||||
int sqlite3VtabBegin(sqlite3 *, sqlite3_vtab *);
|
||||
FuncDef *sqlite3VtabOverloadFunction(FuncDef*, int nArg, Expr*);
|
||||
void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**);
|
||||
|
||||
#ifdef SQLITE_SSE
|
||||
#include "sseInt.h"
|
||||
|
||||
@@ -267,6 +267,27 @@ void *sqlite3_user_data(sqlite3_context *p){
|
||||
return p->pFunc->pUserData;
|
||||
}
|
||||
|
||||
/*
|
||||
** The following is the implementation of an SQL function that always
|
||||
** fails with an error message stating that the function is used in the
|
||||
** wrong context. The sqlite3_overload_function() API might construct
|
||||
** SQL function that use this routine so that the functions will exist
|
||||
** for name resolution but are actually overloaded by the xFindFunction
|
||||
** method of virtual tables.
|
||||
*/
|
||||
void sqlite3InvalidFunction(
|
||||
sqlite3_context *context, /* The function calling context */
|
||||
int argc, /* Number of arguments to the function */
|
||||
sqlite3_value **argv /* Value of each argument */
|
||||
){
|
||||
const char *zName = context->pFunc->zName;
|
||||
char *zErr;
|
||||
zErr = sqlite3MPrintf(
|
||||
"unable to use function %s in the requested context", zName);
|
||||
sqlite3_result_error(context, zErr, -1);
|
||||
sqliteFree(zErr);
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate or return the aggregate context for a user function. A new
|
||||
** context is allocated on the first call. Subsequent calls return the
|
||||
|
||||
Reference in New Issue
Block a user