Skip to content

fix(search): order cross-chain results by block time and escape LIKE wildcards - #35

Open
Ayush7614 wants to merge 2 commits into
Gitlawb:mainfrom
Ayush7614:fix/search-correctness
Open

fix(search): order cross-chain results by block time and escape LIKE wildcards#35
Ayush7614 wants to merge 2 commits into
Gitlawb:mainfrom
Ayush7614:fix/search-correctness

Conversation

@Ayush7614

Copy link
Copy Markdown
Contributor

searchLaunches ordered cross-chain results by raw block number (pre-limit) and tie-broke in JS the same way, so exact matches on low-height chains never reached the ranker; findLaunchChain had the same flaw for the legacy /t/ redirect. Both now use block time (chain id, block number tiebreaks), matching the newestFirst invariant the list sorts already follow. LIKE metacharacters (%_) are escaped with ESCAPE backslash so they match literally. New pure compareSearchHit + escapeLike are unit-tested (search.test.ts: 9 pass). Verified: full app suite 337/337, lint, typecheck, build.

…wildcards

- searchLaunches pre-limit and JS tiebreak used raw block numbers across
  chains, hiding exact matches on low-height chains; both now use block
  time (chain id, block number tiebreaks), matching the newestFirst invariant
- findLaunchChain picks the newest row by block time, not height
- escape %/_ in ILIKE patterns (ESCAPE '\') so they match literally
- compareSearchHit + escapeLike are pure and unit-tested
@coderabbitai

coderabbitai Bot commented Sep 12, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 59 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

This review ran on the open-source allowance, not this organization's plan, because the pull request author doesn't have an assigned seat. Waiting won't change this — ask an organization admin to assign them a seat, or add seats in Billing if every seat is already assigned, then retry.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 0071c2ba-a3ae-415a-a0fc-880574b2b4ce

📥 Commits

Reviewing files that changed from the base of the PR and between 400143b and e043cf5.

📒 Files selected for processing (3)
  • app/src/lib/launchpad/queries.ts
  • app/src/lib/launchpad/search.test.ts
  • app/src/lib/launchpad/search.ts

Comment @coderabbitai help to get the list of available commands.

@Vasanthdev2004 Vasanthdev2004 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ordering cross-chain results by block time is a good fix. The wildcard change needs one correction before this can land: JavaScript consumes the backslash in the tagged template, so the SQL receives an empty ESCAPE string and does not treat the helper's backslashes as escapes.

I confirmed this from the exact-head TypeScript template's cooked text and the postgres driver's use of cooked template strings. This is a query-construction reproduction, not a live-database test. The helper tests do not exercise that boundary.

Requesting changes for the escaping issue below; the rest of the search ordering change can stay in this PR.

Comment thread app/src/lib/launchpad/queries.ts Outdated
// "_" matches those literal characters, not every row. Pre-limit orders by
// block time — never raw block numbers across chains (Base heights dwarf
// Robinhood's, so the old ORDER BY hid exact matches on the low chain).
: await db<Raw[]>`${db.unsafe(SELECT)} WHERE (l.name ILIKE ${"%" + escapeLike(n) + "%"} ESCAPE '\' OR l.symbol ILIKE ${"%" + escapeLike(n) + "%"} ESCAPE '\') ${chainCond} ORDER BY l.block_time DESC, l.chain_id DESC, l.block_number DESC LIMIT 200`;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The single backslash in this JavaScript template is consumed before the SQL reaches postgres: both fragments cook to ESCAPE ''. That disables SQL escaping, while escapeLike(n) still inserts backslashes, so literal % and _ searches no longer match as intended. Please double the backslash at the JavaScript layer, or use an unambiguous fixed escape character with a matching helper. Add a regression that inspects the generated SQL or executes literal %, _ and backslash searches, rather than only testing escapeLike.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Vasanthdev2004 Thanks — doubled to ESCAPE '\\\\' in source so cooked SQL is now ESCAPE '\\' and escapeLike's backslashes are honored. Verified the cooked SQL no longer collapses to ESCAPE ''.

… '\'

JS template cooked text consumes a single backslash, so ESCAPE '\' in source was cooking to ESCAPE '' (empty escape) and the helper's backslashes were ignored. Using ESCAPE '\\' in source cooks to ESCAPE '\' in SQL, matching escapeLike('\%','\_','\\').

Verified: search.test.ts 9/9; query-construction check shows ESCAPE '\' in cooked SQL.
@Ayush7614

Copy link
Copy Markdown
Contributor Author

@Vasanthdev2004 Thanks for catching this! Fixed the ESCAPE handling:

  • Doubled the backslash at the JS layer: ESCAPE '\\\\' in source (was ESCAPE '\\') so the cooked SQL now correctly receives ESCAPE '\\' instead of ESCAPE ''. Verified via query-construction check that the helper's \, %, _ are now actually treated as escapes, and literal %/_ searches match correctly.
  • Rest of the cross-chain ordering change (block_time ordering + compareSearchHit) left as-is.

Pushed to fix/search-correctness (e043cf5). Let me know if you'd like a SQL-level regression added as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants