To learn more about how to use Additional Scope with queries in Retool.
2) Issue:
I have questions about how to use Additional Scope with Retool, and would appreciate any advice.
Can I provide additionalScope when using the GUI to test a query, or do I have to use the console?
What are the semantics and limitations of using additionalScope this way? For example, unless I'm doing something wrong, I don't believe I can do this (but would like to): {{ categorizedOnly ? 'category_id IS NOT NULL' : ' ' }}.
I've been doing a bit of trial and error to discover capabilities but wonder if there is documentation that goes into greater detail.
3) Steps I've taken to troubleshoot:
I searched the forums, but had a difficult time finding anything on it.
I see that somebody marked this solved, but I'd like to leave it open. @WidleStudioLLP's answer was much appreciated, but I was looking for something more concrete and complete with regards to how {{ }} substitutions work in queries.
Further, I'm not sure how to apply @WidleStudioLLP's suggestion. I've tried a few things that I thought might work and they don't. The SQL Statement popup show me the correct working query, but what gets executed is different because the error message includes a NULL symbol that the SQL Statement popup doesn't show. I wish I could see the final executed query to help me reverse engineer what happens to my parameters.
I've tried a few combinations but none have worked so far. My working query is:
SELECT t.id, tc.category_id
FROM track t
LEFT JOIN track_category tc ON t.id = tc.track_id
WHERE ...
WHERE 1=1 {{ condition }}
With condition='AND category_id IS NOT NULL', I get a syntax error near ''AND category_id IS NOT NULL''
With condition='' I get a syntax error near ''''
With condition omitted I get a syntax error near NULL
WHERE {{ condition }}
Successful query but 0 results in all three cases
I'm wondering if {{ ... }} can only be used the way ? is in traditional parameterized query APIs, such that it can only be used in place of a literal value or list of values, but can't include extra query language like "IS NOT NULL" .
I agree the popup isn't always as helpful as it should be I recommend keeping SQL syntax, such as AND, IS NOT NULL, etc hardcoded in the query, rather than passing it in as additionalScope. You'll often run into prepared statements issues when wrapping sql syntax in double curly brackets.
To your earlier question, I am not sure if I'm following correctly, but we don't have a way to define additionalScope values for testing. You will need to define the additionalScope values in the console or in a JS query/script.
One quirk of GUI mode is that the values will always show as red/undefined, but as long as you define them properly in your Javascript additionalScope, it will work.
On the prepared statement behavior -- that is what I suspected, and appreciate you confirming. It does mean that I can't do what I'd like to (for the same reason I couldn't with traditional prepared statements alone), because the semantics change:
If I want all: WHERE 1=1 AND true
If I want only categorized: WHERE 1=1 AND category_id IS NOT NULL
I can't express what I'm trying to do as a single value flip, unfortunately. It seems that whatever you get it is converted into a literal value, so if my {{ }} resolves to a string, it gets wrapped in "the string". I'm guessing my query ends up looking like this:
SELECT ... FROM ... WHERE 1=1 AND "category_id IS NOT NULL"
I looked for docs on additionalScope and curly braces, but didn't find anything covering how it works / expected behavior. If you're taking suggestions -- I would have benefitted from a page or section on "Curly brace substitution in SQL queries" that covers this, or even better would be a tooltip near the editor.
Regarding setting additionalScope in the GUI, got it. I'll keep using query.trigger(). It means dispatching an erroneous query each time I save (because it auto-runs on save), but I can just ignore the errors.
One way I've found to execute more complex statements is to make them the output of a JS Query (but not a Transformer) and setup my SQL to do an EXEC with the result.
It's basically an end run around the prepared statement settings so be sure you aren't letting anyone inject things into your components.
Just following up to say that I tested this and it did the trick. It's not how I ever thought I'd implement something but it's good enough for a POC. I have to escape my own values and I'm doing that in a very lazy way. If the stakeholders like it, I'll probably replace it with an actual backend.
I'm using MySQL, so here was the analogous query for posterity:
SET @GETSTATEMENT = {{ queryName.value }};
PREPARE stmt FROM @GETSTATEMENT;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;