Skip to content

fix: bug fixes — full join operators, HASH formula, filter float values, chat delete loader#14

Merged
wicky-zipstack merged 6 commits into
mainfrom
bug-fixes
Apr 2, 2026
Merged

fix: bug fixes — full join operators, HASH formula, filter float values, chat delete loader#14
wicky-zipstack merged 6 commits into
mainfrom
bug-fixes

Conversation

@Deepak-Gnanasekar

@Deepak-Gnanasekar Deepak-Gnanasekar commented Mar 31, 2026

Copy link
Copy Markdown
Contributor

What

  • Remove unsupported conditional operators (!=, <, >, <=, >=) and BETWEEN from Full Join conditions
  • Remove BETWEEN operator from all join types
  • Fix HASH synthesis formula to support multiple columns
  • Add HASH to the formula list and help text (was missing from both backend and frontend)
  • Allow float/decimal values in filter value fields for Number type columns
  • Add loading spinner when deleting chats in chat history

Why

  • PostgreSQL does not support non-equality operators in FULL OUTER JOIN ON clauses — using them causes SQL generation errors at runtime
  • BETWEEN is not a valid join condition operator for any join type
  • HASH formula was completely broken — it only accepted exactly 2 inputs and incorrectly passed a second argument to ibis .hash() which takes zero arguments,
    causing a TypeError
  • HASH was not listed in the formula dropdown or help text, so users couldn't discover or use it
  • Filter value fields for Number columns only allowed digits (regex /\D/g), blocking valid float inputs like 3.14 or -5.5 needed for decimal comparisons
  • Chat deletion had no visual feedback — the card silently disappeared after the API call, with no indication that deletion was in progress

How

Full Join operators (filter.jsx, configure-joins.jsx):

  • Extended the existing Cross Join operator restriction to also apply to Full Joins using ["Cross", "Full"].includes(joinType)
  • Added BETWEEN to the filtered-out operators list alongside NULL/NOTNULL for all join types
  • Disabled "Add another filter" button when joinType === "Full"
  • On join type switch to Full, auto-trims criteria to first condition and resets operator to EQ
  • Passed joinType prop from configure-joins.jsx to the Filter component

HASH formula (text.py, constants.py, formula-editor.jsx):

  • Changed input validation from == 2 to >= 1 to accept variable number of columns
  • Concatenates all inputs as strings before hashing — same pattern as the existing CONCATENATE function
  • Calls .hash() with no arguments, matching ibis API signature (Value.hash(self) -> IntegerValue)
  • Corrected data_types output from 'string' to 'numeric' to match the actual int64 return type
  • Added HASH entry to backend FORMULA_DICT and frontend FUNCTION_SIGNATURES

Float filter values (filter.jsx):

  • Updated regex from /\D/g to /[^\d.-]/g for regular value and BETWEEN fields
  • Updated IN/NOTIN regex from /[^\d,]/g to /[^\d,.-]/g
  • Validation is gated on dataType === "number" which reads from the LHS column's data_type — String and other types are unaffected

Chat delete loader (PastConversationActions.jsx):

  • Added isDeleting state, shows <Spin size="small" /> during the delete API call
  • Follows the identical isSaving / <Spin> pattern already used for edit operations in the same component

Can this PR break any existing features. If yes, please list possible items. If no, please explain why. (PS: Admins do not merge the PR without this section filled)

  • NO

Database Migrations

Env Config

Relevant Docs

  • ibis Value.hash() API: takes no arguments, returns IntegerValue (int64)
  • ibis translates .hash() to database-native functions: PostgreSQL → HASHTEXTEXTENDED(), Snowflake → HASH(), BigQuery → FARM_FINGERPRINT(), DuckDB →
    HASH()

Related Issues or PRs

Dependencies Versions

  • No changes

Notes on Testing

  • Full Join: Create a Full Join → verify only == operator available, no BETWEEN, no "Add another filter"
  • Inner/Left/Right Joins: Verify all operators except BETWEEN/NULL/NOTNULL are still available
  • HASH single column: =HASH(col1) → produces integer hash values
  • HASH multiple columns: =HASH(col1, col2, col3) → works across all supported databases
  • HASH help text: Open formula editor → HASH appears in formula list with parameter hints
  • Filter float values: Select Number column → enter 3.14, -5.5 → accepted
  • Filter string columns: Verify no regression — any characters still accepted
  • Chat delete: Click delete → confirm → spinner shows → chat removed on success

Screenshots

  • N/A

Checklist

I have read and understood the Contribution Guidelines.

@Deepak-Gnanasekar Deepak-Gnanasekar self-assigned this Mar 31, 2026
@Deepak-Gnanasekar Deepak-Gnanasekar added the bug Something isn't working label Mar 31, 2026
@greptile-apps

greptile-apps Bot commented Mar 31, 2026

Copy link
Copy Markdown

Greptile Summary

This PR delivers six targeted bug fixes across the full-stack: restricting Full/Cross join conditions to equality-only operators, removing BETWEEN from all join operator lists, fixing the HASH formula to accept variable inputs and call the correct zero-argument ibis .hash() API, exposing HASH in both the backend formula dictionary and the frontend formula editor, allowing float/decimal values in Number-type filter fields, and adding a loading spinner for chat deletion.

Key changes and observations:

  • HASH formula (text.py): Correctly rewritten — the old implementation required exactly 2 inputs and incorrectly passed a second argument to .hash(), causing a TypeError. The new implementation casts all inputs to string, concatenates them (mirroring the CONCATENATE pattern), and calls .hash() with no arguments. data_types output is now 'numeric' which is consistent with every other numeric-output formula in math.py.
  • function_type: "Text" for HASH (constants.py): HASH is registered under function_type: "Text" even though it produces an int64 hash value. All other numeric-output formulas in the codebase use "Math". This is a minor categorisation mismatch worth reviewing.
  • Full Join operators (filter.jsx, configure-joins.jsx): The joinType prop was never previously passed from configure-joins.jsx to Filter, meaning the existing Cross-join restriction was silently broken. This PR fixes both Cross and Full joins in one pass.
  • Float filter values (filter.jsx): The updated regex plus the new sanitizeNumericSegment helper correctly handles floats, negatives, and prevents malformed values like 3.1.4 or --3 from reaching SQL generation.
  • Chat delete spinner (PastConversationActions.jsx): Follows the existing isSaving/Spin pattern faithfully.

Confidence Score: 5/5

  • Safe to merge — all changes are well-scoped bug fixes with no regressions expected.
  • The single open comment is a P2 categorisation mismatch (HASH as "Text" vs "Math") that does not affect runtime behaviour or SQL generation. All other changes are correct, well-tested by the author's notes, and consistent with existing codebase patterns. Prior P1 concerns from earlier rounds are addressed.
  • backend/backend/application/config_parser/constants.py — minor function_type category mismatch for HASH.

Important Files Changed

Filename Overview
backend/backend/application/config_parser/constants.py Adds HASH to FORMULA_DICT; categorised as "Text" but the function returns a numeric (int64) type, inconsistent with all other numeric-output formulas in the codebase which use "Math".
backend/formulasql/functions/text.py HASH rewritten to accept ≥1 inputs, concatenate via ibis string addition, call .hash() with no arguments, and output 'numeric' — correctly matches the ibis API and is consistent with how CONCATENATE is implemented.
frontend/src/ide/chat-ai/PastConversationActions.jsx Adds isDeleting state and Spin feedback during deletion, following the existing isSaving/Spin pattern. No new issues introduced beyond the previously-flagged try/finally without catch.
frontend/src/ide/editor/no-code-configuration/configure-joins.jsx Passes joinType prop to Filter and auto-trims criteria to first condition with operator reset to EQ when switching to Full join type. Logic is sound.
frontend/src/ide/editor/no-code-toolbar/formula-editor.jsx Adds HASH to FUNCTION_SIGNATURES with min:1, max:Infinity — correctly surfaces the function in the formula editor UI.
frontend/src/ide/editor/no-code-ui/filter/filter.jsx Three independent fixes: float-friendly regex with sanitizeNumericSegment post-processing; Full join operator restriction + Add-filter button disabled for Full; BETWEEN removed from all join operator lists. All changes are correct.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[User selects Join Type] --> B{Join Type?}
    B -->|Full| C[Trim criteria to first condition\nReset operator to EQ\nDisable Add another filter]
    B -->|Cross| D[Filter operators to EQ only]
    B -->|Inner / Left / Right| E[All operators except\nNULL, NOTNULL, BETWEEN]

    subgraph HASH_Formula["HASH Formula — text.py"]
        H1[Receive n inputs] --> H2{n >= 1?}
        H2 -->|No| H3[raise ValueError]
        H2 -->|Yes| H4[Cast each input to string]
        H4 --> H5[Concatenate all strings]
        H5 --> H6[Call .hash with no args]
        H6 --> H7[Output type: numeric int64]
    end

    subgraph Float_Sanitise["Float Filter Sanitisation — filter.jsx"]
        F1[User types numeric value] --> F2[Strip non-digit / dot / minus chars]
        F2 --> F3[sanitizeNumericSegment\npreserve leading minus\ncollapse extra dots]
        F3 --> F4[Store clean value]
    end
Loading
Prompt To Fix All With AI
This is a comment left during a code review.
Path: backend/backend/application/config_parser/constants.py
Line: 325-328

Comment:
**`function_type` mismatch — HASH is categorised as "Text" but returns a numeric value**

The HASH entry uses `"function_type": "Text"`, but `text.py` explicitly sets `data_types[node['outputs'][0]] = 'numeric'` and ibis `.hash()` returns `IntegerValue` (int64). Every other formula that produces a numeric output (all of `math.py`) uses `"function_type": "Math"`.

If the frontend uses `function_type` to group or filter formulas in the picker, users scanning the **Text** category will encounter a function that yields an integer, which is unexpected. Consider changing this to `"Math"` to match the output semantics and be consistent with the rest of the codebase.

```suggestion
    "HASH": {
        "key": "HASH",
        "value": "HASH",
        "description": (
            "Returns a hash of the concatenated values. Accepts one or more columns."
            " \n Example: HASH(col1) or HASH(col1, col2, col3)"
        ),
        "function_type": "Math",
    },
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (3): Last reviewed commit: "lint fixes" | Re-trigger Greptile

Comment thread frontend/src/ide/chat-ai/PastConversationActions.jsx
Comment thread frontend/src/ide/editor/no-code-ui/filter/filter.jsx
Comment thread frontend/src/ide/editor/no-code-configuration/configure-joins.jsx
Comment thread backend/formulasql/functions/text.py Outdated
Comment thread backend/formulasql/functions/text.py Outdated

@tahierhussain tahierhussain left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@abhizipstack abhizipstack left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@wicky-zipstack wicky-zipstack merged commit 15710be into main Apr 2, 2026
2 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants