Hello, I've been running into an issue when trying to set up a filter by field to filter items on a table, using vision client tags for the influencing values for said filter.
For some reason these vision tags are interacting weirdly with my SQL query I have linked to my table that is being filtered.
SQL query on table.
SELECT itemName,partNum,zoneFrom,zoneTo,TimeOfMove FROM itemmoverec
WHERE
partNum = {[client]filterTagsForItemMoveRecord/filterByTag.value}
AND
{[client]filterTagsForItemMoveRecord/filterOnOffTag} = true
OR
{[client]filterTagsForItemMoveRecord/filterOnOffTag} = false
Whenever the table produces an error, it shows the filterOnOfTag.value as either 1 or 0 dependent on the current state of the tag itself, to combat this I removed the .value from the query and it still produced the same error message. It makes sense that this would throw an error, but I am wondering why the change is occurring at all.
Error Message.
Exception: Error running query:
SQLQuery(query=SELECT itemName,partNum,zoneFrom,zoneTo,TimeOfMove FROM itemmoverec
WHERE
partNum = hello
AND
0 = 1
OR
0 = 0
, database=RFIDINV)@0ms
On: itemMovementRecordScreen.Root Container.Power Table.data
caused by GatewayException: Unknown column 'hello' in 'where clause'
caused by SQLSyntaxErrorException: Unknown column 'hello' in 'where clause'
Thanks,
Dalton
Vision SQL queries use an (insecure, non-ideal) substitution method - tag values are dropped in as literal strings before the query is passed on to the rest of the system. So if your client tag's value is hello
, your query is literally something like:
SELECT itemName,partNum,zoneFrom,zoneTo,TimeOfMove FROM itemmoverec
WHERE
partNum = hello
AND
0 = 1
OR
0 = 0
And as the error message is telling you, that's not valid SQL syntax. You're trying to compare a column partNum
against a literal string, but what you're actually doing is comparing partNum
against "an arbitrary SQL keyword hello
".
TL;DR: Wrap your filter input in single quotes.
SELECT itemName,partNum,zoneFrom,zoneTo,TimeOfMove FROM itemmoverec
WHERE
partNum = '{[client]filterTagsForItemMoveRecord/filterByTag.value}'
AND
{[client]filterTagsForItemMoveRecord/filterOnOffTag} = true
OR
{[client]filterTagsForItemMoveRecord/filterOnOffTag} = false
To expand on this: The preferred migration path is named queries, which close the security hole (SQL injection, in particular from insecure clients) opened for straight DB queries in Vision. That's why you have to opt in to "legacy database access" in the project permissions.
2 Likes
Would a way to close this security loophole be to pass the filter parameters into a named query and link the table to said named query?
How to run Script faster - Ignition - Inductive Automation Forum
See here for a named query with filtering capabilities. Not the most ergonomic thing in the world, but it works well.
1 Like
Thanks @PGriffith for the help I appreciate it, I will look into setting up a named query to handle the filter as well.
What I've done in the past for an optional filter construct like this is a statement in the where clause that assumes that null is the "no filter applied" state and only if the filter parameter is not null does it actually run the LIKE
or whatever other clause.
E.G. in named queries, where :param
is the syntax for parameter substitution (and you don't want to wrap in single quotes):
SELECT itemName,partNum,zoneFrom,zoneTo,TimeOfMove FROM itemmoverec
WHERE
:partNum IS NULL OR partNum = :partNum
EDIT: Exactly as in @dkhayes117's link above 
1 Like
Thanks, I did not think of that. That should make things simpler and more efficient.
I appreciate the help.