Skip to content

support standalone optimizer hints#4367

Open
replu wants to merge 1 commit intosqlc-dev:mainfrom
replu:support-standalone-optimizer-hint
Open

support standalone optimizer hints#4367
replu wants to merge 1 commit intosqlc-dev:mainfrom
replu:support-standalone-optimizer-hint

Conversation

@replu
Copy link
Copy Markdown

@replu replu commented Apr 7, 2026

Context

When a MySQL query contains an optimizer hint (/*+ ... */) placed on its own line, sqlc strips it from the generated SQL constant. This is because StripComments in internal/source/code.go treats any line starting with /* and ending with */ as a block comment and removes it.

The inline form is unaffected — SELECT /*+ MAX_EXECUTION_TIME(1000) */ id FROM t1 works correctly since the line does not start with /*.

Fixes #4353

Fix Proposal

Add a /*+ prefix check in StripComments before stripping a block comment line. Lines starting with /*+ are optimizer hints and must be preserved as part of the SQL string.

The /*+ syntax is a cross-database convention (MySQL, PostgreSQL with pg_hint_plan), so placing this check in the shared StripComments function is appropriate rather than adding engine-specific handling.

I also considered the following alternatives:

  • Add OptimizerHint bool to CommentSyntax: Follows the project pattern of passing engine-specific behavior as parameters, but optimizer hints are not truly engine-specific so a per-engine flag felt like over-engineering.

  • Add a keepPatterns parameter to StripComments: More general, but requires changing the function signature and all call sites.

Happy to switch to the CommentSyntax approach if the project prefers keeping engine-specific knowledge out of StripComments.

Verification

query

-- name: GetAuthor :one
SELECT
/*+ MAX_EXECUTION_TIME(1000) */
*
FROM authors
WHERE id = ? LIMIT 1;

Before :

const getAuthor = `-- name: GetAuthor :one
SELECT
id, name, bio FROM authors
WHERE id = ? LIMIT 1
`

// + MAX_EXECUTION_TIME(1000)
func (q *Queries) GetAuthor(ctx context.Context, id int64) (Author, error) {
	row := q.db.QueryRowContext(ctx, getAuthor, id)
	var i Author
	err := row.Scan(&i.ID, &i.Name, &i.Bio)
	return i, err
}

— the hint is lost.

After :

const getAuthor = `-- name: GetAuthor :one
SELECT
/*+ MAX_EXECUTION_TIME(1000) */
id, name, bio FROM authors
WHERE id = ? LIMIT 1
`

func (q *Queries) GetAuthor(ctx context.Context, id int64) (Author, error) {
	row := q.db.QueryRowContext(ctx, getAuthor, id)
	var i Author
	err := row.Scan(&i.ID, &i.Name, &i.Bio)
	return i, err
}

Note: the inline form (SELECT /*+ ... */ id FROM t1) was already working and is unaffected by this change.

@dosubot dosubot bot added the size:XS This PR changes 0-9 lines, ignoring generated files. label Apr 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XS This PR changes 0-9 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: Support Optimizer Hints in generated queries

1 participant