Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion parser/boundargs.py
Original file line number Diff line number Diff line change
Expand Up @@ -1086,7 +1086,9 @@ def _notnull_default(body: str, var: str, nargs: int) -> tuple[int, str] | None:
re.finditer(r"(?<![\w.>])" + v + r"\s*=(?!=)|&\s*" + v + r"\b", b)]
if len(writes) < 2 or writes[0][1]:
return None
init = re.match(r"\s*([^;]+?)\s*;", b[b.index("=", writes[0][0]) + 1:])
# an initialiser ends at the comma of a declaration of several locals, `int nrows = 0,
# ncols = 0;`, as at its semicolon, as #_guarded_default reads it
init = re.match(r"\s*([^;,]+?)\s*[;,]", b[b.index("=", writes[0][0]) + 1:])
lit = _literal(init.group(1)) if init else None
if lit is None:
return None
Expand Down
40 changes: 39 additions & 1 deletion tests/test_boundargs.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
import unittest
from pathlib import Path

from parser.boundargs import (_sql_arg_params, attach_call_literals, attach_null_default_binds,
from parser.boundargs import (_notnull_default, _sql_arg_params, attach_call_literals,
attach_null_default_binds,
attach_type_derived_args,
extract_call_literals,
extract_wrappers, merge_boundargs, merge_sql_arg_params,
Expand Down Expand Up @@ -1845,5 +1846,42 @@ def test_every_signature_stating_every_argument_binds_nothing(self):
self.assertNotIn("boundArgs", idl["functions"][0]["sqlSignatures"][0])



SET_VALUES_WRAPPER = r"""
Datum
Raster_set_values(PG_FUNCTION_ARGS)
{
Raster *rast = (Raster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
bool *noset = NULL;
int nrows = 0, ncols = 0;
if (! PG_ARGISNULL(5))
{
int ncount;
bool *nnulls;
Datum *nelems = raster_block_extract(PG_GETARG_ARRAYTYPE_P(5), &nrows,
&ncols, &nnulls, &ncount);
}
Raster *result = raster_set_values(rast, noset, ncols, nrows);
PG_RETURN_POINTER(result);
}
"""


class DeclarationListTests(unittest.TestCase):
"""#_notnull_default over the locals of one declaration, as #_guarded_default reads
them: `int nrows = 0, ncols = 0;` starts both from 0, each written only where
argument 5 is not NULL, as Raster_set_values reads the size of its flags."""

def test_each_local_of_the_declaration_starts_from_its_literal(self):
self.assertEqual(_notnull_default(SET_VALUES_WRAPPER, "ncols", 7), (5, "0"))
self.assertEqual(_notnull_default(SET_VALUES_WRAPPER, "nrows", 7), (5, "0"))

def test_a_local_starting_from_a_call_states_no_literal(self):
body = SET_VALUES_WRAPPER.replace("int nrows = 0, ncols = 0;",
"int nrows = f(a, b), ncols = 0;")
self.assertIsNone(_notnull_default(body, "nrows", 7))
self.assertEqual(_notnull_default(body, "ncols", 7), (5, "0"))


if __name__ == "__main__":
unittest.main()
Loading