Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(core): Validate values which are intentionally 0 #12382

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

dana-gill
Copy link
Contributor

@dana-gill dana-gill commented Dec 27, 2024

Summary

Allow for resource mapper nodes to handle intentional 0 values.

This was especially problematic in the Postgres Insert Node when a user
wants to insert 0 as a value in a table in both Fixed and Expression
mode.

In validateValueAgainstSchema, when a resolvedValue is 0, the value
is considered invalid since in Javascript, 0 is considered a falsey
value which makes !0 is equal to true.

When we are in Expression Mode and value a 0, we hit
validateFieldType with an unparsed number. This means, the value
passed in is a string (ie: '0'). This causes validateFieldType to
be consider the value as invalid because it check the type of the value
before properly parsing the value.

Workflow for testing:

{
  "nodes": [
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "7e8e5d58-8178-4dd8-acfd-6a438dbcb982",
              "name": "num",
              "value": 0,
              "type": "number"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        600,
        240
      ],
      "id": "d8ffe610-f0f1-4e7f-8aa9-dd8b6cb50c70",
      "name": "Edit Fields"
    },
    {
      "parameters": {
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public"
        },
        "table": {
          "__rl": true,
          "value": "dummy_table",
          "mode": "list",
          "cachedResultName": "dummy_table"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "retail_price_per_unit": "={{ parseFloat($json.num) }}"
          },
          "matchingColumns": [
            "id"
          ],
          "schema": [
            {
              "id": "id",
              "displayName": "id",
              "required": false,
              "defaultMatch": true,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "retail_price_per_unit",
              "displayName": "retail_price_per_unit",
              "required": true,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            }
          ],
          "ignoreTypeMismatchErrors": false,
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        820,
        240
      ],
      "id": "9e8a2ef1-1d6b-4d62-9610-2f7faaeeaa22",
      "name": "Insert 0 with Insert w/ json (Bug)",
      "credentials": {
        "postgres": {
          "id": "UeO14x83grJWzgYI",
          "name": "dgl neon"
        }
      }
    },
    {
      "parameters": {
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public"
        },
        "table": {
          "__rl": true,
          "value": "dummy_table",
          "mode": "list",
          "cachedResultName": "dummy_table"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "retail_price_per_unit": 0
          },
          "matchingColumns": [
            "id"
          ],
          "schema": [
            {
              "id": "id",
              "displayName": "id",
              "required": false,
              "defaultMatch": true,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "retail_price_per_unit",
              "displayName": "retail_price_per_unit",
              "required": true,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            }
          ],
          "ignoreTypeMismatchErrors": false,
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        820,
        440
      ],
      "id": "968b73c1-d174-47d2-8cd2-d7a181011699",
      "name": "Insert 0 with Insert (Bug)",
      "credentials": {
        "postgres": {
          "id": "UeO14x83grJWzgYI",
          "name": "dgl neon"
        }
      }
    }
  ],
  "connections": {
    "Edit Fields": {
      "main": [
        [
          {
            "node": "Insert 0 with Insert w/ json (Bug)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Insert 0 with Insert w/ json (Bug)": {
      "main": [
        []
      ]
    }
  },
  "pinData": {}
}

Related Linear tickets, Github issues, and Community forum posts

Partially resolves https://linear.app/n8n/issue/NODE-2085/community-issue-postgres-node-validation-fails-with-0

Partially resolves #11939

Review / Merge checklist

  • PR title and summary are descriptive. (conventions)
  • Docs updated or follow-up ticket created.
  • Tests included.
  • PR Labeled with release/backport (if the PR is an urgent fix that needs to be backported)

This was especially problematic in the Postgres Insert Node when a user
wants to insert `0` as a value in a table in Fixed mode.

In `validateValueAgainstSchema`, when a resolvedValue is `0`, the value
is considered invalid since in Javascript, `0` is considered a falsey
value which makes `!0` is equal to `true`.
@dana-gill dana-gill force-pushed the node-2085-pg-validation-0 branch from 3fb5268 to ad473cc Compare December 27, 2024 10:13
@n8n-assistant n8n-assistant bot added core Enhancement outside /nodes-base and /editor-ui n8n team Authored by the n8n team labels Dec 27, 2024
Copy link

codecov bot commented Dec 27, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

📢 Thoughts on this report? Let us know!

@dana-gill dana-gill marked this pull request as ready for review December 27, 2024 11:21
Copy link
Member

@netroy netroy left a comment

Choose a reason for hiding this comment

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

besides a minor comment, LGTM

@@ -44,7 +44,7 @@ const validateResourceMapperValue = (
!skipRequiredCheck &&
schemaEntry?.required === true &&
schemaEntry.type !== 'boolean' &&
!resolvedValue
resolvedValue === undefined
Copy link
Member

Choose a reason for hiding this comment

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

I don't actually know what the correct behavior here should be, but changing this means that now we will treat nulls and empty string also differently than before. Perhaps that is okay, perhaps it's now. Maybe we need to expand the check here to block both undefined and null.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core Enhancement outside /nodes-base and /editor-ui n8n team Authored by the n8n team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Postgres node validation fails with 0
2 participants