在 Delphi Rio (10.3.3) 中,当宏为 NULL 时,fdQuery 无法正确转换条件函数 'iif'
In Delphi Rio (10.3.3) fdQuery does not correctly translate conditional function 'iif' when a macro is NULL
我有以下 SQL 命令来 运行 使用 PostgreSQL 作为数据库的 TFDQuery
查询:
fdqr.SQL.Text: =
'select * from (values (current_date-1), (current_date), (current_date + 1)) as t (datetest) ' +
'{iif (! Datevalue, where datetest =! Datevalue)}';
当我使用Clear
方法清除宏值时,我希望脚本被解释以便过滤器被消除,但事实并非如此。
fdqr.MacroByName('datevalue').Clear;
fdqr.Open;
生成的数据库日志:
select * from (values(current_date-1), (current_date), (current_date+1)) as t(datetest)
where datetest = NULL
但是,如果您通过 AsRaw
包含赋值,它会按预期工作,即使先前的值为 ''
(空字符串)并且 IsNull
为 True
.
fdqr.MacroByName('datevalue').Clear;
{ at this point IsNull = True and AsRaw is '' }
fdqr.MacroByName('datevalue').AsRaw := '';
fdqr.Open;
生成的数据库日志:
select * from (values(current_date-1), (current_date), (current_date+1)) as t(datetest)
这是 FireDAC 错误还是 feature 我没有理解正确?
为了根据宏变量应用 {IIF(…)}
或 {IF}…{FI}
的替换,变量值不能为空。 Conditional Substitution 的文档就是这么说的。它的字面意思是,如果宏变量扩展为 non-empty 字符串,则应用替换。这个事实可以通过检查 FireDAC 源代码来验证,特别是单元 FireDAC.Phys.Meta
中的方法 TFDPhysConnectionMetadata.TranslateEscapeSequence
。如果 eskIF
你可以找到:
s := Trim(ASeq.FArgs[0]);
…
else if s <> '' then
Result := 'True';
让我们看看当您 Clear
宏变量时会发生什么。其 Value
设置为 Null
,其 DataType
设置为 mdUnknown
。在这种情况下,预处理器将变量扩展为 NULL
文字,这不是空字符串。 AsRaw
的值无关紧要,因为预处理器使用 SQL
属性 进行替换。
除了设置AsRaw := ''
,似乎没有其他方法可以将宏变量扩展为空字符串。在这种情况下,它的 DataType
设置为 mdRaw
并且值 SQL
属性 等于 AsRaw
.
我不确定此行为是错误还是功能,但更改它可能会破坏现有代码库,因此我不希望此问题得到修复。我宁愿说它最终成为一个功能。
除上述之外,您还可以通过使用简单的参数来避免宏:
select * from (values(current_date-1), (current_date), (current_date+1)) as t(datetest)
where :Datevalue is null or datetest = :Datevalue
通过这种方式,您可以按照预期清除或设置 Datevalue
参数的值:
{ to bind null value }
fdqr.ParamByName('Datevalue').Clear;
{ to bind some value }
fdqr.ParamByName('Datevalue').AsDate := Today;
我有以下 SQL 命令来 运行 使用 PostgreSQL 作为数据库的 TFDQuery
查询:
fdqr.SQL.Text: =
'select * from (values (current_date-1), (current_date), (current_date + 1)) as t (datetest) ' +
'{iif (! Datevalue, where datetest =! Datevalue)}';
当我使用Clear
方法清除宏值时,我希望脚本被解释以便过滤器被消除,但事实并非如此。
fdqr.MacroByName('datevalue').Clear;
fdqr.Open;
生成的数据库日志:
select * from (values(current_date-1), (current_date), (current_date+1)) as t(datetest)
where datetest = NULL
但是,如果您通过 AsRaw
包含赋值,它会按预期工作,即使先前的值为 ''
(空字符串)并且 IsNull
为 True
.
fdqr.MacroByName('datevalue').Clear;
{ at this point IsNull = True and AsRaw is '' }
fdqr.MacroByName('datevalue').AsRaw := '';
fdqr.Open;
生成的数据库日志:
select * from (values(current_date-1), (current_date), (current_date+1)) as t(datetest)
这是 FireDAC 错误还是 feature 我没有理解正确?
为了根据宏变量应用 {IIF(…)}
或 {IF}…{FI}
的替换,变量值不能为空。 Conditional Substitution 的文档就是这么说的。它的字面意思是,如果宏变量扩展为 non-empty 字符串,则应用替换。这个事实可以通过检查 FireDAC 源代码来验证,特别是单元 FireDAC.Phys.Meta
中的方法 TFDPhysConnectionMetadata.TranslateEscapeSequence
。如果 eskIF
你可以找到:
s := Trim(ASeq.FArgs[0]);
…
else if s <> '' then
Result := 'True';
让我们看看当您 Clear
宏变量时会发生什么。其 Value
设置为 Null
,其 DataType
设置为 mdUnknown
。在这种情况下,预处理器将变量扩展为 NULL
文字,这不是空字符串。 AsRaw
的值无关紧要,因为预处理器使用 SQL
属性 进行替换。
除了设置AsRaw := ''
,似乎没有其他方法可以将宏变量扩展为空字符串。在这种情况下,它的 DataType
设置为 mdRaw
并且值 SQL
属性 等于 AsRaw
.
我不确定此行为是错误还是功能,但更改它可能会破坏现有代码库,因此我不希望此问题得到修复。我宁愿说它最终成为一个功能。
除上述之外,您还可以通过使用简单的参数来避免宏:
select * from (values(current_date-1), (current_date), (current_date+1)) as t(datetest)
where :Datevalue is null or datetest = :Datevalue
通过这种方式,您可以按照预期清除或设置 Datevalue
参数的值:
{ to bind null value }
fdqr.ParamByName('Datevalue').Clear;
{ to bind some value }
fdqr.ParamByName('Datevalue').AsDate := Today;