3

in node, i'm creating the following query:

let sql_query = "\
   SELECT \
      ... \
   WHERE \
      FACILITY_ID = $1 \
      AND (EVENT_START_TIME_UNIX_MS < $2) \
      AND (EVENT_END_TIME_UNIX_MS > $3) \
      AND (LOWER(DESCRIPTION_TEXT) ~* '\yden\y')"

that fourth line is doing a word boundary regex for the term "den" but i need it to be parameterized like the preceding lines. i tried the below but it doesn't work.

      AND (LOWER(DESCRIPTION_TEXT) ~* '\y$4\y')

i also tried this:

      AND (LOWER(DESCRIPTION_TEXT) ~* $4)

where $4 is set to '\yden\y'. but that didn't work either.

thanks for any tips.

2
  • 1
    Use ~* $4 instead and pass the full pattern as the parameter value. Parameterized queries don't use string interpolation. The parameter values never become part of the query text. The database compiles the query into a parameterized execution plan that's executed using the parameter values. That's why SQL injection and formatting errors are avoided. The parameter values remain strongly typed, outside the query itself, even when the execution plan gets executed. Unless of course you use the parameter values to construct and execute dynamic SQL inside the query text Commented Sep 5 at 12:11
  • 1
    PS: ~* is case-insensitive, there's no reason to use LOWER(...). This could prevent the database from using trigram indexes to accelerate the regex search Commented Sep 5 at 12:18

1 Answer 1

5

You're not properly using postgresql concatenation syntax. In postgresql, || is used to concatenate strings. Try:

AND (DESCRIPTION_TEXT) ~* ('\y' || $4 || '\y'))

Also, if you use ~* you don't need to use lower(), since ~* performs a case-insensitive matching.

As a bonus, if $4 is null, the sequence of || nullifies the whole string. With concat(), it'd end up as a '\y\y' pattern leading to false positives since that matches even a single [:word:] class character.

Sign up to request clarification or add additional context in comments.

3 Comments

The issue is with your regex pattern syntax for PostgreSQL parameterized queries. You need to use word boundaries correctly with the parameter. Try this approach: ```sql AND (LOWER(DESCRIPTION_TEXT) ~ ('\\y' || $4 || '\\y'))
The key points: Use \\y for word boundaries in PostgreSQL (not \b) Concatenate the parameter with the word boundary markers The parameter $4 should contain just the word (e.g., 'den'), not the full pattern If you want to test and debug your regex patterns before using them in PostgreSQL, I find orbit2x.com/regex-tester helpful for validating the pattern logic. You can test patterns like \yden\y to see exactly what they match. Alternative approach using SIMILAR TO:
Both OP and the author of this answer use the right word boundary constraint escape syntax. '\y' is correct. '\\y' is just a y preceded by a literal backslash: dbfiddle.uk/TUD0Ti7U Nobody's suggesting '\b' which I think would be just a backspace.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.