Commit Graph

10 Commits

Author SHA1 Message Date
Mihir Kandoi
0922d85bf0 docs: catalog second-order GROUP BY traps (wrap-is-the-bug classes)
A full audit of the loose-GROUP-BY fixes found four recurring mistakes in the fixes themselves: incoherent Max/Min pairs over coupled columns, NULL-skipping Max on discriminators, Sum(x)*Max(y) fabricated arithmetic, and wrong-bound picks. Add them to the compatibility catalog (new 3.1) and to the Greptile review instructions so future PRs get flagged.
2026-07-05 19:00:47 +05:30
Mihir Kandoi
b6382dce52 ci(postgres): add the return-contract note to the over-rollback bullet
Mirror the config.json guidance in POSTGRES_COMPATIBILITY.md: when scoping a rollback, keep the function's
success/None return contract -- don't return the doc that was just rolled back. (greptile #56688)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 13:21:18 +05:30
Mihir Kandoi
c976b86714 ci(postgres): teach the parity guide the over-broad-rollback trap
Recovering a poisoned Postgres txn with a full frappe.db.rollback() discards rows the handler already
created before the failure -- which MariaDB keeps (no statement-abort) -- so it's a silent MariaDB
regression. 'Owns the txn' does not make a full rollback safe in a loop handler. Document the safe cases
(re-raise / single op / atomic batch) and the per-iteration/per-record savepoint alternative.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 13:05:56 +05:30
Mihir Kandoi
f560767eb0 ci(postgres): include §6 in the How-to-review closing summary
The closing paragraph named only the §2/§3 semantic divergences as static-checker-invisible;
§6 (refactor/conversion row-set changes) is equally invisible and belongs there too. (greptile nit.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 20:58:52 +05:30
Mihir Kandoi
a26329b2a0 ci(postgres): teach the parity guide the DISTINCT row-count trap + refactor faithfulness
Two review lessons from the post-merge net-diff/whole-repo re-audit of the SQL-dialect classes:

- Section 3 (row-count trap) now covers SELECT DISTINCT too: adding the ORDER BY column to the
  select to satisfy Postgres grows the DISTINCT key and changes the MariaDB row count when the
  column is not single-valued per distinct row -- sort in Python instead.
- New section 6: a 'refactor' / raw-SQL->qb conversion is not automatically 1:1. Diff the
  WHERE/predicate and the resulting row set, not just the SELECT shape -- a conversion that widens
  a filter (e.g. posting_datetime > X gaining an OR (== X AND creation > ...) branch under a
  sql->qb refactor) changes the rows touched on both engines and hides under a refactor label.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 20:41:34 +05:30
Mihir Kandoi
f751f80158 ci(postgres): flag division by a possibly-zero divisor in the compat guard (#56363)
Adds the division-by-zero divergence class to the PG-compat review tooling:
on a divisor that the data can drive to 0 (e.g. Sum(a)/Sum(b)), MariaDB
returns NULL for division by zero while PostgreSQL raises `division by zero`
and aborts the query. The portable fix is to wrap the divisor in
NullIf(divisor, 0), which yields NULL on both engines (matching MariaDB).

- .greptile/config.json: add it to the "would ERROR on PostgreSQL" list.
- .github/POSTGRES_COMPATIBILITY.md: document it under §1 (hard breaks).
- .github/helper/postgres_compat.py: note it in the docstring as a
  deliberately-not-statically-checked semantic divergence (data-dependent,
  like integer-division intent), so it stays a reviewer/Greptile concern.

Tooling-only; no source query changes. The instance fix shipped in #56361.
2026-06-23 12:00:50 +00:00
Mihir Kandoi
2f4e78f09e ci(postgres): flag COALESCE/IfNull of a typed column with a mismatched-type literal (#56358)
ci(postgres): teach the guard about COALESCE(date, int) type mismatch

New class found by the whole-repo audit (the Asset Depreciations report fix in this PR): IfNull/Coalesce of a typed column with a different-typed literal -- e.g. IfNull(date_col, 0) -> COALESCE(date, integer), which PostgreSQL rejects (DatatypeMismatch). Added to the Greptile config and POSTGRES_COMPATIBILITY.md (not statically checkable without column types).
2026-06-23 16:52:48 +05:30
Mihir Kandoi
fc9544435e ci(postgres): teach the PG-compat tooling the audit 6-9 divergence classes
The whole-repo MariaDB<->PostgreSQL audits surfaced classes the checker and
review guide did not yet cover. Add them:

Static checker (.github/helper/postgres_compat.py) - new mechanical breaks:
- .rlike() / raw RLIKE: frappe rewrites REGEXP->~* on Postgres but NOT RLIKE.
- Cast(x, "char") / raw CAST AS CHAR: bare CHAR is character(1) on Postgres
  and truncates multi-digit values; use "varchar".
(Both flag zero production code; the only repo hit is in patches/, which the
hook already excludes.)

Greptile config + POSTGRES_COMPATIBILITY.md - new semantic/hard classes:
- aggregate (Sum/Count) selected next to bare columns with no GROUP BY at all.
- .like()/LIKE on a non-text column (bigint ILIKE) -> Cast_ to varchar.
- get_all(fields=["CapitalCase"]) identifier-case (extends the get_value case).
- bool into a Check column via qb.update().set() (extends set_value/db_set).
- int/int division: float a literal (col/1440 -> col/1440.0).
- Concat over a nullable column leaking a bare prefix on Postgres.
- clarify REGEXP/.regexp() is translated but RLIKE/.rlike() is not.
2026-06-23 12:22:22 +05:30
Mihir Kandoi
3e2d61262a ci(greptile): widen guide scope to SQL-bearing non-Python files; fix HAVING-alias wording
Address Greptile review:
- customContext.files scope was **/*.py only, so Query Report SQL in .js/.sql/report .json
  files didn't get the guide attached as context (the global instructions still applied).
  Widen to .py/.js/.sql/report **/*.json.
- The guide's HAVING-alias rule said "with no GROUP BY"; PostgreSQL rejects a SELECT-alias in
  HAVING regardless of GROUP BY. Reworded to match (repeat the expression, or move a
  non-aggregate predicate to WHERE).
2026-06-22 09:34:23 +05:30
Mihir Kandoi
4a690c86d2 ci(greptile): teach the review bot to enforce MariaDB↔PostgreSQL parity
The PostgreSQL server-test job is label-gated, so until it is required the Greptile
PR-review bot is the always-on guard against cross-engine breaks. Extend
.greptile/config.json with `instructions` (and a `customContext` reference to a new
guide) so every review flags new/changed queries that would error on PostgreSQL or
silently diverge from MariaDB, under the prime rule that MariaDB output must not change.

- .github/POSTGRES_COMPATIBILITY.md — the catalogue the bot (and contributors) follow:
  hard breaks (loose GROUP BY, MySQL-only funcs, UPDATE..JOIN, HAVING-on-alias,
  DISTINCT+ORDER BY, single-quoted alias, varchar bitwise OR, capital identifiers,
  set_value(Check,bool)), silent divergences (text case-sensitivity, name-lookup case,
  empty-string↔NULL, NULL ordering, ORDER BY..LIMIT 1 tiebreakers, integer division,
  distinct-drops-ORDER-BY-on-PG + casefold sorting, function-rewrite parity, UnixTimestamp
  TZ), the GROUP BY row-count trap (Max()-wrap vs add-to-GROUP-BY; FD-by-source-table),
  the InFailedSqlTransaction/savepoint rule, and the false positives NOT to flag
  (.like→ILIKE, ifnull/backtick/LOCATE/REGEXP auto-translation, MariaDB-changing tiebreakers).
- Existing disabledLabels and frappe/frappe context are preserved.
2026-06-22 09:29:19 +05:30