SQLite User Forum

Partially override functions
Login

Partially override functions

(1) By anonymous on 2022-07-08 07:13:00 [link] [source]

Can a function be partially overridden? For example, I may want to override the -> and ->> functions so that if the left operand is text then it calls the default implementation but if it is blob then instead it will be treated as SQLite record format (possibly more than one concatenated together) and will extract the data.

(2) By Gunter Hick (gunter_hick) on 2022-07-08 09:02:30 in reply to 1 [source]

I don't think SQLite supports overloading operators; functions may be overloaded, but generally differentiate by number of parameters and preferred text encoding only. Of course you could still overload the json_extract() function and check the parameter types yourself, but may end up getting called with a BLOB converted to TEXT instead of the original BLOB.

(3) By curmudgeon on 2022-07-08 09:12:31 in reply to 2 [link] [source]

Are you sure Gunter? I'm thinking zFunctionName = "->" and then using sqlite3_value_type to determine if value is a blob.

int sqlite3_create_function(
  sqlite3 *db,
  const char *zFunctionName,
  int nArg,
  int eTextRep,
  void *pApp,
  void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
  void (*xStep)(sqlite3_context*,int,sqlite3_value**),
  void (*xFinal)(sqlite3_context*)

(4) By Gunter Hick (gunter_hick) on 2022-07-08 10:34:30 in reply to 3 [link] [source]

The docs say nothing about overriding operators, although at least some operators are implemented as functions.

The create_function docs state that SQLite picks the function it calls by "closest match" of the number of parameters and the text encoding. They also state that if the text encoding of the argument does not match that expected by the function, the argument will be translated.

Of course the OP is free to try this for himself and report the results.

(5) By Richard Hipp (drh) on 2022-07-08 10:42:07 in reply to 1 [link] [source]

New function implementations can be added with a different number of parameters or with a different text encoding (UTF8 vs UTF16). But SQLite does not distinguish between argument datatype because that is not known until run-time. So, no, you cannot create a new variant of the -> operator that is only invoked when the left argument is a BLOB.

The only thing you can do in this case is to completely overload -> and then do different computations at run-time depending on the datatype of the left operand.

Some operators can be overloaded because they are implemented as functions:

  • ->
  • ->>
  • LIKE
  • GLOB
  • REGEXP
  • MATCH

Other built-in operators like + and / cannot be overloaded, however.

(6) By anonymous on 2022-07-08 17:31:25 in reply to 5 [link] [source]

It is not my intention to override operators such as + and /, although -> and ->> are functions, so they can be overridden.

Some way to call the existing function implementation from an overridden one without having to duplicate the code for JSON dealing (or other functions) would be helpful, I think. This might need something to keep track that the function has not been destroyed if you access.

For example:

static int misc1(sqlite3_context*cxt,int argc,sqlite3_value**argv) {
  sqlite3_call_function(sqlite3_user_data(cxt),cxt,argc,argv);
}

static void register_functions(sqlite3*db) {
  sqlite3_function*f=sqlite3_get_function(db,"->",2,SQLITE_UTF8);
  sqlite3_create_function_v2(db,"->",2,SQLITE_UTF8|SQLITE_DETERMINISTIC,f,misc1,0,0,destroy_function);
}

However, implementing something like the above code may have some problems such as additional function properties which are not exposed, and probably others, too. So, I do not know that it will be suitable.

Exposing C API functions to deal with JSON and record formats might also be possible, although I am unsure how to do it. (But, it might be helpful in programs that use JSON stuff both within SQL codes and in C codes, without needing two copies of the JSON functions or preparing SQL statements to handle all JSON stuff (which might not work if the JSON data is too big; in one program, I dealt with this by splitting the data using a very simplified JSON parser (which only checks for nested {} and [], and checking if it is a string literal or not (including possibility of escaped quotation marks), in order to split records in a JSON array) before being passed to SQL).)

The only way that I can think to do with the existing implementation is either to duplicate the built-in implementations of whatever functions are needed, or to need a separate database connection which is used to call the built-in functions (and keeping prepared statements that call them, dealing with errors, etc), but that doesn't seem to me to be a very good way to do it, I think. Still, it is something that I may consider if necessary.