Skip to content

Conversation

@ibarakaiev
Copy link

Fixes a bug where WHERE clauses with integer literals larger than 2,147,483,647 (int32 max) would fail with an error like:

** (ArgumentError) errors were found at the given arguments:
  * 1st argument: not a textual representation of a float

Root cause:

  • libpg_query/PgQuery uses int32 for integer constants in the AST
  • Integers exceeding int32 max are stored as Float nodes with string values (e.g., {:fval, "2793017076"}) - this is documented behavior
  • The parser called String.to_float/1 on these strings, but Elixir's String.to_float/1 requires a decimal point and fails on "2793017076"

Solution:

  • Use Integer.parse/1 to detect pure integer strings in fval values
  • Parse them as int8 (bigint) instead of numeric
  • This matches PostgreSQL's type inference for integer literals and ensures correct type matching with bigint columns (no implicit cast exists from numeric to int8)

Affected queries (now working):

  • WHERE id = 2793017076
  • WHERE id IN (2147483648, 3500000000)
  • WHERE id > 2147483647

References:

Copy link
Contributor

@icehaunter icehaunter left a comment

Choose a reason for hiding this comment

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

Thanks a lot for your contribution! I think this can be slightly simplified

Comment on lines +1237 to +1243
case Integer.parse(value) do
{int_value, ""} when is_pg_int8(int_value) ->
{:ok, %Const{type: :int8, value: int_value, location: loc}}

_ ->
{:ok, %Const{type: :numeric, value: String.to_float(value), location: loc}}
end
Copy link
Contributor

Choose a reason for hiding this comment

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

There's no reason to make this case, because there exists a Float.parse/1 function which parses strings without a decimal point just fine

Copy link
Author

@ibarakaiev ibarakaiev Dec 10, 2025

Choose a reason for hiding this comment

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

@icehaunter Happy to make this change, quick question:

If we have an integer like 2^53 = 9007199254740993 which gets parsed by libpg_query as a float string and Float.parse("9007199254740993") returns {9007199254740992.0, ""}, wouldn't that be an issue since we just lost precision due to it being outside of Elixir's float range (2^53)? The use case is if someone uses BIGINT with some random IDs up to 10^18.

@codecov
Copy link

codecov bot commented Dec 10, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 75.32%. Comparing base (ebdc25d) to head (21b47f9).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3575      +/-   ##
==========================================
- Coverage   75.40%   75.32%   -0.08%     
==========================================
  Files          51       51              
  Lines        2744     2744              
  Branches      408      405       -3     
==========================================
- Hits         2069     2067       -2     
- Misses        673      675       +2     
  Partials        2        2              
Flag Coverage Δ
electric-telemetry 22.71% <ø> (ø)
elixir 57.74% <ø> (ø)
elixir-client 74.47% <ø> (ø)
packages/experimental 87.73% <ø> (ø)
packages/react-hooks 86.48% <ø> (ø)
packages/typescript-client 92.99% <ø> (-0.17%) ⬇️
packages/y-electric 55.12% <ø> (ø)
typescript 87.40% <ø> (-0.13%) ⬇️
unit-tests 75.32% <ø> (-0.08%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

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

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@icehaunter
Copy link
Contributor

You should also run mix format it seems

@netlify
Copy link

netlify bot commented Dec 10, 2025

Deploy Preview for electric-next ready!

Name Link
🔨 Latest commit ff6d63a
🔍 Latest deploy log https://app.netlify.com/projects/electric-next/deploys/6939d1d7b39eb30008239c88
😎 Deploy Preview https://deploy-preview-3575--electric-next.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@ibarakaiev ibarakaiev force-pushed the fix/bigint-where-clause-parsing branch from 47c1ee9 to 90c6ac5 Compare December 10, 2025 19:59
ibarakaiev and others added 2 commits December 10, 2025 12:02
Fixes a bug where WHERE clauses with integer literals larger than
2,147,483,647 (int32 max) would fail with an error like:

    ** (ArgumentError) errors were found at the given arguments:
      * 1st argument: not a textual representation of a float

Root cause:
- libpg_query/PgQuery uses int32 for integer constants in the AST
- Integers exceeding int32 max are stored as Float nodes with string values
  (e.g., {:fval, "2793017076"}) - this is documented behavior
- The parser called String.to_float/1 on these strings, but Elixir's
  String.to_float/1 requires a decimal point and fails on "2793017076"

Solution:
- Use Integer.parse/1 to detect pure integer strings in fval values
- Parse them as int8 (bigint) instead of numeric
- This matches PostgreSQL's type inference for integer literals and
  ensures correct type matching with bigint columns (no implicit cast
  exists from numeric to int8)

Affected queries (now working):
- WHERE id = 2793017076
- WHERE id IN (2147483648, 3500000000)
- WHERE id > 2147483647

References:
- libpg_query wiki: https://github.com/pganalyze/libpg_query/wiki/Differences-between-JSON-output-formats
  ("This leads to problems with overly long integers or floats")

Co-Authored-By: Claude <[email protected]>
@ibarakaiev ibarakaiev force-pushed the fix/bigint-where-clause-parsing branch from 90c6ac5 to ff6d63a Compare December 10, 2025 20:02
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