On Fri, Mar 7, 2014 at 7:37 PM, Max Vlasov <max.vla...@gmail.com> wrote: > On Fri, Mar 7, 2014 at 6:39 PM, Clemens Ladisch <clem...@ladisch.de> wrote: >> Max Vlasov wrote: >>> >>> Nice suggestion. This probably falls into case when a small new part >>> needed on sqlite side >> >> Actually, no change to SQLite itself would be needed. It's possible >> to create an extension that provides a function that allows to register >> another function that executes a custom SQL expression: >> >> SELECT register_simple_function('rpad', 2, 'SELECT printf(''%-*s'', ?, ?)'); >> >> > > Brilliant :) this is a solution not requiring adding anything to > sqlite. I'd only prefer not using full-features sql queries, but > rather expression that is automatically wrapped in SELECT without > FROM, otherwise they would create dimensions (columns, rows) when our > function strictly expected one result. And also support for numbered > parameters. So my example whould be implemented as > > SELECT register_function('complexcase', 2, 'Case when ?1 < 10 then ?2 > else ?2 + 10 end'); > > It's interesting that such approach makes this super-function > Pragma-like. It changes some internal state (reveals a new function) > and also optionally returns some result, for example 1 for success.
OK, reading Max's answer, I realize I misunderstood your original post Clemens. Sorry about that. But doesn't the above assume you can bind values inside the select clause? I thought one couldn't... The new CTE might work-around that, if that's really the case, since hopefully it should be possible to use bind variables in the first statement below, while somehow I thought one couldn't in the second statement. sqlite> with args(x, y) as (VALUES('foo', 16)) select printf('%-*s', y, x) from args; foo sqlite> select printf('%-*s', y, x) from (select 'foo' as x, 16 as y); foo sqlite> basically register_function('rpad', 'x', 'y', 'printf(''%-*s'', y, x)') would register a 2-arg function (register_function's argc-2) named $argv[0], which executes the following statement with args($argv[1], $argv[2], ... $argv[argc-2]) as (VALUES(?, ?)) select $argv[argc-1) from args; with $argv[i] textually replaced. On executing the registered rpad function, one would forward the args to the inner statement prepared above via sqlite3_bind_value, and execute it. Of course, during inner query preparation, one can verify the expression returns a single scalar value, and at execution time, that it returns a single row (it can't I think, but I'm not experienced in SQL injection techniques, so I'd assert it myself ;) I think I might try to code such a super-function inside our app. I agree with Max. Brilliant! --DD _______________________________________________ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users