Skip to content

feat: Use true division for the / operator in Polars SQL - #27391

Merged
nameexhaustion merged 14 commits into
pola-rs:mainfrom
Kevin-Patyk:refactor/use_true_division_sql
May 18, 2026
Merged

feat: Use true division for the / operator in Polars SQL#27391
nameexhaustion merged 14 commits into
pola-rs:mainfrom
Kevin-Patyk:refactor/use_true_division_sql

Conversation

@Kevin-Patyk

Copy link
Copy Markdown
Contributor

Resolves #25396.

I saw you self-assigned @alexander-beedie, but figured I would give it a stab since it's been awhile. I hope that's okay 😃!

🤖 Claude Sonnet 4.6 for navigating and explaining existing code.

@Kevin-Patyk Kevin-Patyk changed the title feat: Use true division for / operator in SQL feat: Use true division for the / operator in SQL Apr 23, 2026
@Kevin-Patyk Kevin-Patyk changed the title feat: Use true division for the / operator in SQL feat: Use true division for the / operator in Polars SQL Apr 23, 2026
@github-actions github-actions Bot added A-sql Area: Polars SQL functionality enhancement New feature or an improvement of an existing feature python Related to Python Polars rust Related to Rust Polars labels Apr 23, 2026
@codecov

codecov Bot commented Apr 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.46%. Comparing base (1e3a7b4) to head (51a2aea).
⚠️ Report is 5 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #27391      +/-   ##
==========================================
+ Coverage   79.88%   81.46%   +1.58%     
==========================================
  Files        1840     1840              
  Lines      256051   256054       +3     
  Branches     3180     3180              
==========================================
+ Hits       204546   208595    +4049     
+ Misses      50680    46634    -4046     
  Partials      825      825              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Kevin-Patyk

Copy link
Copy Markdown
Contributor Author

As a random thought, @alexander-beedie do you think maybe we should add a warning that this behaviour changed for the end user?

@alexander-beedie

alexander-beedie commented May 14, 2026

Copy link
Copy Markdown
Collaborator

As a random thought, @alexander-beedie do you think maybe we should add a warning that this behaviour changed for the end user?

SQL support is still marked as being technically "unstable" so it's not required to do so, but is probably good to note it with a .. versionchanged:: in the associated SQL operator docs. I'll try to take a look at this at the weekend and get it merged if everything looks good 👍

@Kevin-Patyk

Copy link
Copy Markdown
Contributor Author

@alexander-beedie Okay so I updated the documentation is py-polars/docs/source/reference/sql/operators/index.rst. I put the version as 1.41.0 for the change. Thanks! 😄

@nameexhaustion
nameexhaustion merged commit 18e3422 into pola-rs:main May 18, 2026
33 checks passed
ritchie46 added a commit that referenced this pull request Jul 22, 2026
Reclassify 873 baseline entries from sqlite/select{1,2,3}.slt that fail
only due to integer division divergence. Polars SQL deliberately uses
true (float) division for `/` (PR #27391), while SQLite truncates int/int
toward zero. These records are now marked with `skipif polars` instead of
being tracked in the expected_failures baseline.

Conversions:
- select1.slt: 168 converted (98 baseline → 95 after renumbering)
- select2.slt: 151 converted (84 baseline → 83 after renumbering)
- select3.slt: 554 converted (416 baseline → 416 after renumbering)

Baseline: 1610 entries → 733 entries
Total test records: 10091 (unchanged)
Pass rate: 92.0%

All conversions verified with cargo run -p polars-sqllogictest (exit 0,
zero unexpected FAILs/PASSes). Updated UPSTREAM documentation with new
skipif cluster counts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ritchie46 added a commit that referenced this pull request Jul 22, 2026
Vendors a curated subset of the public-domain SQLite sqllogictest corpus
(gregrahn/sqllogictest mirror, pinned commit c67f97bf3ca7e590d12e073408bcacaf2ff0f3a0,
fetched 2026-07-21) into crates/polars-sqllogictest/slt/sqlite/: select1-4.test,
evidence/{slt_lang_aggfunc,slt_lang_createview,slt_lang_dropview,in1,in2}.test, and
4 truncated random/{select,aggregates}/slt_good_{0,50}.test files (150 records each
after setup). select5.test is dropped: every one of its 732 records is a 4-to-64-way
implicit join stress test ("join-N-M"), and without join reordering polars-sql
attempts a literal N-way cross product that is combinatorially intractable past
~N=20 - bisection confirmed the harness process gets OOM-killed inside a
`join-24-4` record. A hang has no representation in the expected_failures.txt
ratchet, so the file can't be used as conformance signal; see UPSTREAM for the
full drop list (triggers, REPLACE/UPDATE, index existence-tracking cases) and
the other vendoring-time transformations (inline-comment stripping so the
sqllogictest-rs 0.29.1 parser accepts onlyif/skipif lines, hash-threshold
backfill, and reflowing one-value-per-line result blocks to one-row-per-line to
match this crate's default validator).

Shim extensions (crates/polars-sqllogictest/src/{setup,engine}.rs), minimal,
harness-only:
- untyped CREATE TABLE columns (sqlparser DataType::Unspecified) default to Int64
- CREATE INDEX / DROP INDEX are unconditional no-ops
- CREATE VIEW registers the view's SELECT as a LazyFrame via SQLContext, with
  existence tracking so duplicate-create and drop-of-nonexistent-view error
  correctly; DROP VIEW unregisters it
- a single "statement ok" record containing multiple setup statements (occurs
  once in the corpus) now runs each statement in sequence instead of bailing

160 records get `skipif polars` (intentional divergences, each noted in
UPSTREAM): 135 for Polars' true (float) division for `/` vs SQLite/C-style
truncating int division (pre-existing decision, #27391), 17 for Postgres-aligned
native booleans vs SQLite's integer-as-boolean convention, 8 for rejecting empty
`IN ()` lists (SQL92/Postgres reject them; SQLite permits them as an extension).

Verification: `cargo run -p polars-sqllogictest --release` exits 0 with
4829 passed / 5200 expected-fail / 10029 total (48.2% pass rate); slt/polars/
alone is 96/96 (100%); slt/sqlite/ alone is 4733/9933 (47.6%). Removing one
baseline entry was spot-checked to turn the run red. cargo fmt --check clean.

Ranked triage (failure records -> Phase 3 mapping):
 1484  scalar/EXISTS subquery used as a comparison operand    -> 3a subqueries
 1309  self-join / multi-table FROM: duplicate column names   -> new (context.rs
       across joined tables collide in projections/with_columns    join handling,
                                                                     adjacent to 3a)
  878  3+ chained/mixed UNION/EXCEPT/INTERSECT in one query   -> 3e set-ops
                                                                    (process_except_intersect)
  709  EXISTS subquery outside simple WHERE position          -> 3a subqueries
  655  subquery comparison operators (>, <, = ...) rejected    -> 3a subqueries
                                                                    (sql_expr.rs:567-577)
  135  integer division semantics                             -> skipif (intentional)
   74  SubPlan not allowed outside equality context            -> 3a subqueries
   25  DISTINCT inside SUM/MIN/MAX/AVG                         -> 3c function library
   17  boolean vs 0/1 representation                           -> skipif (intentional)
   11  TOTAL() aggregate function missing                      -> 3c function library
    8  empty IN() list                                         -> skipif (intentional)
    8  IN-list element is an arbitrary expression, not literal -> 3e small semantics
    8  unary negation of COUNT() wraps via unsigned overflow   -> new (correctness bug,
                                                                    not dialect-specific)
    7  shim: INSERT ... SELECT not supported (VALUES only)     -> harness limitation
    7  IN/NOT IN with NULL: should return NULL, not false/true -> 3e small semantics
    6  SQLite "NOT INDEXED" query hint (proprietary syntax)     -> no fix planned
    6  SQLite dynamic type-affinity edge cases (aggfunc.slt)    -> not fixable (static
                                                                    typing, like Postgres)
    3  SUM(<literal>) doesn't multiply by row count             -> new (correctness bug)
    3  SUM/MIN over all-NULL or empty group returns 0, not NULL -> 3c / new
    2  hex string literal (x'...')                              -> 3c function library
    2  query expected to fail but our engine succeeds           -> baseline (low value)
    2  shim: bit-shift literal in INSERT VALUES unsupported      -> harness limitation
    1  misc one-off join constraint error                       -> baseline

Two items above ("self-join duplicate column names", "COUNT negation
wraparound") are not on the pre-existing Phase 3 list and are flagged here as
new, high-value findings - the duplicate-column one alone accounts for more
baseline records than any single subquery cluster.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ritchie46 added a commit that referenced this pull request Jul 22, 2026
Reclassify 873 baseline entries from sqlite/select{1,2,3}.slt that fail
only due to integer division divergence. Polars SQL deliberately uses
true (float) division for `/` (PR #27391), while SQLite truncates int/int
toward zero. These records are now marked with `skipif polars` instead of
being tracked in the expected_failures baseline.

Conversions:
- select1.slt: 168 converted (98 baseline → 95 after renumbering)
- select2.slt: 151 converted (84 baseline → 83 after renumbering)
- select3.slt: 554 converted (416 baseline → 416 after renumbering)

Baseline: 1610 entries → 733 entries
Total test records: 10091 (unchanged)
Pass rate: 92.0%

All conversions verified with cargo run -p polars-sqllogictest (exit 0,
zero unexpected FAILs/PASSes). Updated UPSTREAM documentation with new
skipif cluster counts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-sql Area: Polars SQL functionality enhancement New feature or an improvement of an existing feature python Related to Python Polars rust Related to Rust Polars

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ensure SQL division returns a float when required

3 participants