Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass FuncCtx to Insn::Function to keep track of arg count #323

Closed
wants to merge 1 commit into from

Conversation

jussisaurio
Copy link
Collaborator

#321 recently fixed an error with register allocation order concerning binary expressions in translate_condition_expr. I noticed we had the same bug in translate_expr as well, and this led into noticing that our implementation of Insn::Function diverges from SQLite in that it doesn't provide a context object that keeps track of how many arguments the function call has.

Not having the arg count available at runtime means that e.g.:

do_execsql_test length-date-binary-expr {
  select length(date('now')) = 10;
} {1}

Returned 0 instead of 1, because at runtime another register was already allocated, and date() was implemented like this:

                    Func::Scalar(ScalarFunc::Date) => {
                        let result = exec_date(&state.registers[*start_reg..]); // all registers starting from start_reg
                        state.registers[*dest] = result;
                        state.pc += 1;
                    }

SQlite bytecode engine docs for Function say:

Invoke a user function (P4 is a pointer to an sqlite3_context object that contains a pointer to the function to be run) with arguments taken from register P2 and successors. The number of arguments is in the sqlite3_context object that P4 points to.

Accordingly, this PR implements a FuncCtx struct that contains a Func and arg_count (usize).

@jussisaurio jussisaurio force-pushed the func-context branch 2 times, most recently from 2408f8c to 1c9a4d9 Compare September 14, 2024 09:37
@@ -1114,7 +1125,6 @@ pub fn translate_expr(
crate::bail_parse_error!("nullif function with no arguments");
};

let func_reg = program.alloc_register();
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this was a bug in nullif()

impl Func {
pub fn to_string(&self) -> String {
match self {
Func::Agg(agg_func) => agg_func.to_string().to_string(),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

double to_string?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah AggFunc has a separate non-trait method to_string() that returns a &str, should change that at some point 😂

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah okay

penberg pushed a commit that referenced this pull request Sep 22, 2024
…m Jussi Saurio

#321 recently fixed an error with
register allocation order concerning binary expressions in
`translate_condition_expr`. I noticed we had the same bug in
`translate_expr` as well, and this led into noticing that our
implementation of `Insn::Function` diverges from SQLite in that it
doesn't provide a context object that keeps track of how many arguments
the function call has.
Not having the arg count available at runtime means that e.g.:
```
do_execsql_test length-date-binary-expr {
  select length(date('now')) = 10;
} {1}
```
Returned 0 instead of 1, because at runtime another register was already
allocated, and `date()` was implemented like this:
```
                    Func::Scalar(ScalarFunc::Date) => {
                        let result = exec_date(&state.registers[*start_reg..]); // all registers starting from start_reg
                        state.registers[*dest] = result;
                        state.pc += 1;
                    }
```
SQlite bytecode engine docs for Function say:
> Invoke a user function (P4 is a pointer to an sqlite3_context object
that contains a pointer to the function to be run) with arguments taken
from register P2 and successors. The number of arguments is in the
sqlite3_context object that P4 points to.
Accordingly, this PR implements a `FuncCtx` struct that contains a
`Func` and `arg_count` (usize).

Reviewed-by: Pere Diaz Bou <pere-altea@hotmail.com>

Closes #323
@penberg penberg deleted the func-context branch January 5, 2025 18:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants