I hope your work makes into the SQLite source code. It will be useful.

Gerry Snyder

On Tue, Jan 29, 2019 at 12:16 AM Andy Goth <andrew.m.g...@gmail.com> wrote:

> I wish to define custom aggregate functions in Tcl, but this capability is
> currently not exposed through the Tcl interface. Thus I am thinking about
> how best to add it. Here's a first crack at a design proposal:
>
> Extend the [db function] command to accept an -aggregate switch that makes
> the new function be an aggregate function. Otherwise, the function defaults
> to being a scalar function.
>
> When an aggregate Tcl function is called from SQL, it is invoked in two
> phases: step and final. The step phase receives the input data, and the
> final phase produces the result.
>
> During step, the function is invoked once for each row (in the group). For
> the first row (in the group), the first argument to the function will be
> empty string, and subsequent arguments are the SQL values from the row
> being processed. For each additional row (in the group), the first argument
> is the Tcl value returned by the prior invocation, and subsequent arguments
> are as above.
>
> During final, the function is invoked one last time (at the end of each
> group). Its sole argument is the return value of the last step invocation,
> or empty string if there were no rows. The return value of the Tcl function
> is used as the return value of the SQL function.
>
> If there were no rows and GROUP BY was used, the function is not invoked at
> all, because there were no groups.
>
> The Tcl function can tell whether it is in the step or final phase by how
> many arguments it receives. If it receives multiple, it is in step. If it
> receives only one, it is in final.
>
> Depending on how it is written, the Tcl function may be able to tell if
> it's being called for the first time (within the group) by checking if its
> first argument is empty string. If non-empty, it definitely has been called
> before (within the group). If empty, it is most likely on the first row
> and, if in step, may need to initialize.
>
> However, if the aggregate function wishes to disregard some of its input
> data, it may choose to return empty string to discard any state data
> arising from the current and prior rows (in the group). This will result in
> empty string being the first argument to the next invocation. This mode of
> operation is ill-advised but not illegal, though maybe some valid use cases
> may exist, provided that ORDER BY is being used.
>
> It is an error to pass an aggregate Tcl function zero arguments.
>
> Here's an example that will return the entire Fossil global_config table as
> a key/value dict:
>
> db function list -deterministic -aggregate {
>     apply {{state args} {
>         concat $state $args
>     }
> }
>
> db onecolumn {
>     SELECT list(name, value)
>       FROM global_config
>      ORDER BY name
> }
>
> As for implementation, I think the existing code can be leveraged to a
> great extent. Adapt the existing tclSqlFunc() to be the backend to new
> tclSqlFuncScalar(), tclSqlFuncStep(), and tclSqlFuncFinal() functions, and
> adjust the DB_FUNCTION code to recognize -aggregate and pass different
> function pointers accordingly. Use sqlite3_aggregate_context() to hold the
> Tcl_Obj * resulting from each invocation, then let it be the first argument
> to the next invocation.
>
> I would be happy to implement this myself, since this is functionality I
> will be needing soon. Once I'm satisfied with it and have test suite
> updates, what's the recommended method for sharing my patch?
>
> Question: does xFinal() get called if an error occurs during (or between)
> calling xStep()? Are errors even possible? I'm curious if there's any way
> to leak the Tcl_Obj pointed to by the aggregate context.
> _______________________________________________
> sqlite-users mailing list
> sqlite-users@mailinglists.sqlite.org
> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>
_______________________________________________
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to