博客 Engineering

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

英文文章. 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.

简短回答

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.

常见问题解答

Where can I read more?

See the pull request and the original issue.

目标

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

运行闭环

把生产信号转化为已审查的修复。

开始免费试用,了解 Prilog 如何把真实事故映射到代码级 Pull Request。