On Wed, Oct 16, 2013 at 1:28 PM, Richard Hipp <d...@sqlite.org> wrote:

> Please see http://www.sqlite.org/src/artifact/2ece66438?ln=13-75


Thanks. Being familiar with vtables, I had imagined as much, even though
stopped short of doing it in practice.

This takes care of hiding the DML statements from auth/trace hooks, by
inserting/deleting behind the scene in native code.
But it does not hide from SQL the DDL for creating the vtable or dropping
it OTOH. Those will be seen by hooks still.

I realize I'm pushing my luck here Dr Hipp, but thinking about this more,
what I think SQLite is missing is some kind of unprotected
sqlite3_table_value, a subtype of sqlite3_value, with APIs to define the
columns, and fill in the values of a "table value".

Once you have such a beast, you can bind such "table value" for the << in
%1 >> case I was describing above, since there's already
sqlite3_bind_value().

But you can also now create "table functions", i.e. custom SQLite functions
that do not return scalars but anonymous temporary "tables", returning
these sqlite3_table_values via sqlite3_result_value().

vtables can already do pretty much the same thing, except that
* vtables cannot be used "inline" to a given statement (i.e. created on the
fly), and
* vtables cannot be used in an anonymous manner (the vtable must have a
name)
* vtables cannot dynamically process "document cells" that belong to other
tables (real or virtual) in a statement. (you can explicit insert stuff
into them like FTS does, but it's more a custom index than a custom table).

You can easily create a virtual table that parses a comma separated list,
and return one row per string between commans, but you must name the
vtable, and pass it the comma separated list explicitly, "hardcoding" its
rows. But if you make it a table function, you can select from that
function, passing arbitrary strings to parse, each time returning a new
unnamed result-table (i.e. a table), and you're not limited to literals,
you can also "join" to another table to process specific strings (in a
given column) of that other table and have an implicit union-all of those
anonymous per-string-value result-sets.

In pseudo-code, this would look something like this:

sqlite> select * from parse_csv('a, b, a');
a
b
a
sqlite> create table s (name text, csv text);
sqlite> insert into s values ('dec', '1, 2, 3'), ('hex', '1, A'), ('alpha',
'a, B, TT');
sqlite> select s.name, p* from s, parse_csv(s.csv) p;
dec|1
dec|2
dec|3
hex|1
hex|A
alpha|a
alpha|B
alpha|TT
sqlite> select s.name, count(parse_csv(s.csv)) from s;
dec|3
hex|2
alpha|3

With such table functions, you can imagine all sorts of interesting
scenarios, like getting info out of XML or JSON documents stored in table
cells (UnQL anyone?), or getting a list of doubles as rows from a blob cell
value (since SQLite lacks array support, any user-defined-type is basically
a blob or a string that aggregate denormalized info).

OK, it's probably fever-induced wandering. I'll stop there ;) --DD

Oracle XMLTable http://stackoverflow.com/questions/12690868

http://www.oracle-base.com/articles/misc/pipelined-table-functions.php

PS: BTW, this taught me the << in table >> alternative to << in (list) >> I
was not aware of. Thanks for that.
sqlite> create table t (name text, type text);
sqlite> insert into t values ('foo', 'en'), ('bar', 'en');
sqlite> insert into t values ('toto', 'fr'), ('titi', 'fr');
sqlite> insert into t values ('furtch', 'gr');
sqlite> create table type_sel (type text);
sqlite> insert into type_sel values ('gr'), ('fr');
sqlite> select * from t where type in type_sel;
toto|fr
titi|fr
furtch|gr
sqlite> delete from type_sel;
sqlite> insert into type_sel values ('en');
sqlite> select * from t where type in type_sel;
foo|en
bar|en
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to