diff --git a/README.md b/README.md index fde60fa..0412a6a 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ pairing with smart people at Hashrocket. For a steady stream of TILs, [sign up for my newsletter](https://crafty-builder-6996.ck.page/e169c61186). -_1578 TILs and counting..._ +_1579 TILs and counting..._ See some of the other learning resources I work on: - [Ruby Operator Lookup](https://www.visualmode.dev/ruby-operators) @@ -905,6 +905,7 @@ See some of the other learning resources I work on: - [Two Ways To Compute Factorial](postgres/two-ways-to-compute-factorial.md) - [Two Ways To Escape A Quote In A String](postgres/two-ways-to-escape-a-quote-in-a-string.md) - [Types By Category](postgres/types-by-category.md) +- [Unable To Infer Data Type In Production](postgres/unable-to-infer-data-type-in-production.md) - [Union All Rows Including Duplicates](postgres/union-all-rows-including-duplicates.md) - [Use A psqlrc File For Common Settings](postgres/use-a-psqlrc-file-for-common-settings.md) - [Use A Trigger To Mirror Inserts To Another Table](postgres/use-a-trigger-to-mirror-inserts-to-another-table.md) diff --git a/postgres/unable-to-infer-data-type-in-production.md b/postgres/unable-to-infer-data-type-in-production.md new file mode 100644 index 0000000..646df9b --- /dev/null +++ b/postgres/unable-to-infer-data-type-in-production.md @@ -0,0 +1,45 @@ +# Unable To Infer Data Type In Production + +Inspired by [You Probably Don't Need Query +Builders](https://mattrighetti.com/2025/01/20/you-dont-need-sql-builders), I +wrote a query in one of my applications that has filter clauses that get +short-circuited if the filter value hasn't been included. + +That query looked something like this: + +```ruby +@tags = + Tag.where("? is null or normalized_value ilike ?", normalized_query, "%#{normalized_query}%") + .order(:normalized_value) + .limit(10) +``` + +The `normalized_value ilike ?` filtering won't be applied if the +`normalized_query` value isn't present (`nil`). This helps me avoid writing +messy ternaries or if-else conditional query building madness. + +Unfortunately, when I shipped this query to production, the page started +failing and Postgres was reporting this error in the logs. + +``` +Caused by: PG::IndeterminateDatatype (ERROR: could not determine data type of parameter $1) +``` + +The query is prepared as a parameterized statement and Postgres appears to be +unable to determine the datatype of the first parameter (`$1`) — +`normalized_query`. + +I was unable to reproduce the issue in development. It was only occuring in +production. Until I can come up with a root cause analysis, I have the +following fix that does a casting to `text`. This helps out with the type +inference and makes the issue go away. + +```ruby +@tags = + Tag.where("cast(? as text) is null or normalized_value ilike ?", normalized_query, "%#{normalized_query}%") + .order(:normalized_value) + .limit(10) +``` + +Interestingly, this person using `pgtyped` [ran into the exact same issue with +the same type of query](https://github.com/adelsz/pgtyped/issues/354).