Add the sqlite3_overload_function() API - part of the virtual table

interface. (CVS 3426)

FossilOrigin-Name: aa7728f9f5b80dbb1b3db124f84b9166bf72bdd3
This commit is contained in:
drh
2006-09-16 21:45:14 +00:00
parent 572d11dc8f
commit b7481e70c5
11 changed files with 192 additions and 53 deletions
+2 -15
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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"
+21
View File
@@ -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