Blogs Engineering

When % Isn't a Format Verb: Fixing LIKE Patterns in StackQL Views

Engelstalig artikel. StackQL inlined view queries with fmt.Sprintf, so % in LIKE patterns broke the SQL. The merged fix uses explicit placeholder tokens instead.

Gostackql/stackqlSQLstring formattingquery rewriting

User SQL passed through fmt.Sprintf, where every % means something.

Kort antwoord

StackQL builds the final SQL for views and subqueries by substituting the inner query into a template with fmt.Sprintf. A LIKE '%TLS12%' pattern in a query on a view therefore contained characters that Go read as format verbs, and the result failed with sql packet preparation error: near "(": syntax error. The fix replaces the printf-based substitution with explicit placeholder tokens and a literal-safe expander. It was merged as PR #723 and closed issue #472.

The problem

Issue #472, opened in October 2024, showed a query on the azure.network.vw_application_gateways view with ssl_policy NOT LIKE '%TLS12%' failing, while the equivalent query on the base resource worked.

The fix

Templates now carry named tokens instead of %s:

IndirectQueryPlaceholder   = "__iql__placeholder_indirect_query__"
ControlOnClausePlaceholder = "__iql__placeholder_control_on_clause__"
-       query = fmt.Sprintf(ca.GetQuery(), childQueryStrings...)
+       query = textutil.ExpandPlaceholders(query, textutil.IndirectQueryPlaceholder, childQueryStrings)

ExpandPlaceholders replaces tokens left to right and never interprets the replacement text. Unit tests include a template with NOT LIKE '%TLS12%', and a Robot Framework scenario was updated.

By the numbers

  • Repository: stackql/stackql, 1,074 stars (Nov 3, 2026), Go, MIT
  • Files changed: 8
  • Lines: +164 / -30
  • Commits: 1
  • Opened: Aug 21, 2026. Merged: Aug 22, 2026. Time to merge: 16 hours
  • Review: approved and merged by a maintainer

How the review went

The maintainer approved and merged it alongside PR #722, with "thanks again".

Takeaways

  • Never use user text as a format string. Any % in a SQL literal is fair game for Sprintf once it lands in the template.
  • Use tokens that can't collide. A long, distinctive placeholder reduces accidental collisions with ordinary SQL text.

Veelgestelde vragen

Where can I read more?

See the pull request and the original issue.

Het doel

Templating and user input should never share a syntax. Separating them makes the rewriter safe for whatever SQL people write.

Voer de loop uit

Zet productiesignalen om in gereviewde fixes.

Start een gratis proefperiode en zie hoe Prilog echte incidenten koppelt aan pull requests op codeniveau.