Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@ArNine
Copy link
Contributor

@ArNine ArNine commented Dec 27, 2025

this pr fix: #20306

@hannes
Copy link
Member

hannes commented Dec 29, 2025

Postgres also returns false for this, needs careful consideration.

@ArNine
Copy link
Contributor Author

ArNine commented Dec 29, 2025

@hannes I got it! Postgres returns '' when executing select concat(null), but duckdb(main) returns null when executing select concat(null). Can I modify it to also return ''?

@hannes
Copy link
Member

hannes commented Dec 29, 2025

Yes, that makes sense

@ArNine
Copy link
Contributor Author

ArNine commented Dec 29, 2025

Yes, that makes sense

I noticed that select concat(null) return single '' in v1.4, but now it returns null in the main branch. This change seems to originate from this pr https://github.com/duckdb/duckdb/pull/19565/files. Is this normal? Should this sql return null or single ''?

@lnkuiper
Copy link
Collaborator

lnkuiper commented Dec 29, 2025

PostgreSQL:

postgres=# SELECT concat(NULL::VARCHAR) IS NULL r;
 r 
---
 f
(1 row)

postgres=# SELECT concat(NULL::VARCHAR, NULL::VARCHAR) IS NULL r;
 r 
---
 f
(1 row)

postgres=# SELECT NULL::VARCHAR || NULL::VARCHAR IS NULL r;
 r 
---
 t
(1 row)

postgres=# SELECT array_cat(NULL::INT[]) IS NULL r;
ERROR:  function array_cat(integer[]) does not exist
LINE 1: SELECT array_cat(NULL::INT[]) IS NULL r;
               ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
postgres=# SELECT array_cat(NULL::INT[], NULL::INT[]) IS NULL r;
 r 
---
 t
(1 row)

postgres=# SELECT NULL::INT[] || NULL::INT[] IS NULL r;
 r 
---
 t
(1 row)

DuckDB v1.4.3:

D SELECT concat(NULL::VARCHAR) IS NULL r;
┌─────────┐
│    r    │
│ boolean │
├─────────┤
│ false   │
└─────────┘
D SELECT concat(NULL::VARCHAR, NULL::VARCHAR) IS NULL r;
┌─────────┐
│    r    │
│ boolean │
├─────────┤
│ false   │
└─────────┘
D SELECT NULL::VARCHAR || NULL::VARCHAR IS NULL r;
┌─────────┐
│    r    │
│ boolean │
├─────────┤
│ true    │
└─────────┘
D SELECT array_cat(NULL::INT[]) IS NULL r;
┌─────────┐
│    r    │
│ boolean │
├─────────┤
│ false   │
└─────────┘
D SELECT array_cat(NULL::INT[], NULL::INT[]) IS NULL r;
┌─────────┐
│    r    │
│ boolean │
├─────────┤
│ false   │
└─────────┘
D SELECT NULL::INT[] || NULL::INT[] IS NULL r;
┌─────────┐
│    r    │
│ boolean │
├─────────┤
│ true    │
└─────────┘

DuckDB main:

memory D SELECT concat(NULL::VARCHAR) IS NULL r;
┌─────────┐
│    r    │
│ boolean │
├─────────┤
│ false   │
└─────────┘
memory D SELECT concat(NULL::VARCHAR, NULL::VARCHAR) IS NULL r;
┌─────────┐
│    r    │
│ boolean │
├─────────┤
│ false   │
└─────────┘
memory D SELECT NULL::VARCHAR || NULL::VARCHAR IS NULL r;
┌─────────┐
│    r    │
│ boolean │
├─────────┤
│ true    │
└─────────┘
memory D SELECT array_cat(NULL::INT[]) IS NULL r;
┌─────────┐
│    r    │
│ boolean │
├─────────┤
│ false   │
└─────────┘
memory D SELECT array_cat(NULL::INT[], NULL::INT[]) IS NULL r;
┌─────────┐
│    r    │
│ boolean │
├─────────┤
│ false   │
└─────────┘
memory D SELECT NULL::INT[] || NULL::INT[] IS NULL r;
┌─────────┐
│    r    │
│ boolean │
├─────────┤
│ true    │
└─────────┘

EDIT: in PostgreSQL the concat function is NULL-tolerant, whereas the concatenation operator (||) is not. Any operator acting on a NULL value in PostgreSQL will return NULL, while functions aren't guaranteed to. I'm not sure if I understand this PR, as it seems like we already have the correct behaviour.

@lnkuiper lnkuiper self-requested a review December 30, 2025 12:31
@ArNine ArNine marked this pull request as draft January 5, 2026 16:11
@ArNine
Copy link
Contributor Author

ArNine commented Jan 5, 2026

PostgreSQL:

postgres=# SELECT concat(NULL::VARCHAR) IS NULL r;
 r 
---
 f
(1 row)

postgres=# SELECT concat(NULL::VARCHAR, NULL::VARCHAR) IS NULL r;
 r 
---
 f
(1 row)

postgres=# SELECT NULL::VARCHAR || NULL::VARCHAR IS NULL r;
 r 
---
 t
(1 row)

postgres=# SELECT array_cat(NULL::INT[]) IS NULL r;
ERROR:  function array_cat(integer[]) does not exist
LINE 1: SELECT array_cat(NULL::INT[]) IS NULL r;
               ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
postgres=# SELECT array_cat(NULL::INT[], NULL::INT[]) IS NULL r;
 r 
---
 t
(1 row)

postgres=# SELECT NULL::INT[] || NULL::INT[] IS NULL r;
 r 
---
 t
(1 row)

DuckDB v1.4.3:

D SELECT concat(NULL::VARCHAR) IS NULL r;
┌─────────┐
│    r    │
│ boolean │
├─────────┤
│ false   │
└─────────┘
D SELECT concat(NULL::VARCHAR, NULL::VARCHAR) IS NULL r;
┌─────────┐
│    r    │
│ boolean │
├─────────┤
│ false   │
└─────────┘
D SELECT NULL::VARCHAR || NULL::VARCHAR IS NULL r;
┌─────────┐
│    r    │
│ boolean │
├─────────┤
│ true    │
└─────────┘
D SELECT array_cat(NULL::INT[]) IS NULL r;
┌─────────┐
│    r    │
│ boolean │
├─────────┤
│ false   │
└─────────┘
D SELECT array_cat(NULL::INT[], NULL::INT[]) IS NULL r;
┌─────────┐
│    r    │
│ boolean │
├─────────┤
│ false   │
└─────────┘
D SELECT NULL::INT[] || NULL::INT[] IS NULL r;
┌─────────┐
│    r    │
│ boolean │
├─────────┤
│ true    │
└─────────┘

DuckDB main:

memory D SELECT concat(NULL::VARCHAR) IS NULL r;
┌─────────┐
│    r    │
│ boolean │
├─────────┤
│ false   │
└─────────┘
memory D SELECT concat(NULL::VARCHAR, NULL::VARCHAR) IS NULL r;
┌─────────┐
│    r    │
│ boolean │
├─────────┤
│ false   │
└─────────┘
memory D SELECT NULL::VARCHAR || NULL::VARCHAR IS NULL r;
┌─────────┐
│    r    │
│ boolean │
├─────────┤
│ true    │
└─────────┘
memory D SELECT array_cat(NULL::INT[]) IS NULL r;
┌─────────┐
│    r    │
│ boolean │
├─────────┤
│ false   │
└─────────┘
memory D SELECT array_cat(NULL::INT[], NULL::INT[]) IS NULL r;
┌─────────┐
│    r    │
│ boolean │
├─────────┤
│ false   │
└─────────┘
memory D SELECT NULL::INT[] || NULL::INT[] IS NULL r;
┌─────────┐
│    r    │
│ boolean │
├─────────┤
│ true    │
└─────────┘

EDIT: in PostgreSQL the concat function is NULL-tolerant, whereas the concatenation operator (||) is not. Any operator acting on a NULL value in PostgreSQL will return NULL, while functions aren't guaranteed to. I'm not sure if I understand this PR, as it seems like we already have the correct behaviour.

the title of this PR is no longer appropriate. the results of executing SELECT concat(NULL::VARCHAR) are different in main and V1.4; In V1.4 and PostgreSQL, it returns ''; in main, it returns NULL.
The original problem was that select concat(null) returned NULL in the main, but select concat(null) is null returned false. Although I don't know why this happens(select concat(null) is null return false in main), PostgreSQL and v1.4 both return '' when select concat(null) is executed. Therefore, I tried to directly fix it so that select concat(null) returns ''.

@ArNine ArNine marked this pull request as ready for review January 5, 2026 16:26
@ArNine ArNine marked this pull request as draft January 5, 2026 16:28
@ArNine ArNine marked this pull request as ready for review January 5, 2026 16:30
Copy link
Collaborator

@lnkuiper lnkuiper left a comment

Choose a reason for hiding this comment

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

Thanks for the changes!

@lnkuiper lnkuiper merged commit 60a92c8 into duckdb:main Jan 6, 2026
58 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Potential Unexpected Results of CONCAT(NULL)

4 participants