| From: | Mario González Troncoso <gonzalemario(at)gmail(dot)com> |
|---|---|
| To: | Suraj Kharage <suraj(dot)kharage(at)enterprisedb(dot)com> |
| Cc: | PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org> |
| Subject: | Re: [PATCH] Add support for INSERT ... SET syntax |
| Date: | 2026-07-12 18:48:00 |
| Message-ID: | CAFsReFUAPGb5EbfZS4dGyzCqcbAMU8GZgnodUO_jm7yfxJdksg@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
On Wed, 1 Jul 2026 at 15:27, Suraj Kharage <suraj(dot)kharage(at)enterprisedb(dot)com>
wrote:
> Hi,
>
> I would like to propose adding support for an alternative INSERT syntax
> that uses named column assignments via a SET clause. This provides a more
> convenient and readable way to write inserts, particularly when only
> specific columns need values.
>
> Currently, PostgreSQL requires INSERT statements to separate the column
> list from the values:
>
> INSERT INTO users (name, email, status) VALUES ('Alice', '
> alice(at)example(dot)com', 'active');
>
> For inserts with many columns or where only a subset of columns are
> specified, the proposed SET syntax offers better readability by keeping
> column names adjacent to their values:
>
> INSERT INTO users SET name='Alice', email='alice(at)example(dot)com',
> status='active';
>
> Proposed Syntax:
>
> INSERT INTO table_name
> SET (column1=value1, column2=value2, ...), (, ...)
> [ ON CONFLICT ... ]
> [ RETURNING ... ];
>
>
This is some feedback for -v3. I had some problems resending the other
conversations in the thread from the archives[1], that's why I'm replying
to this, sorry.
I like the idea. In spite it's not (yet) part of the SQL standard, it
wouldn't be odd if we see that happening in the near future.
diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c
index 2a2e00b372e..11cb4fcd2da 100644
--- a/src/backend/nodes/nodeFuncs.c
+++ b/src/backend/nodes/nodeFuncs.c
@@ -4370,6 +4370,8 @@ raw_expression_tree_walker_impl(Node *node,
return true;
if (WALK(stmt->selectStmt))
return true;
+ if (WALK(stmt->setClauseList))
+ return true;
if (WALK(stmt->onConflictClause))
you used `stmt->setClauseList` however, I read the entire
`raw_expression_tree_walker_impl`
function and it seems we don't mix "clause" with "List" in the variable
names. Reading the whole file, I just found "targetList" and "valuesList".
If you get my point, maybe you could use "setClause" only? I know that
sounds like something that exists in setter/getters stuff. Like we're
setting a clause up but would it be worth looking for a new variable name?
I personally think so. Actually, after reading
`src/include/nodes/parsenodes.h`,
I think we should go for a change.
----
Also, in src/backend/parser/analyze.c we can change a lot of those foreach
by foreach_node, however, I need to ask, did you have a reason to not use
foreach_node() when you first wrote the code? Maybe I'm missing something.
Because this patch is on a commitfest already, I didn't want to send a
patch we might need to squash if I'm right afterwards. That's why I'd like
to show you what I did:
https://github.com/postgres/postgres/commit/7be0538f2a5d916f2fb4a39764985b358cf6d379
If you like I could send a v4- with the squashed version.
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 70c75d0bb20..d2f5b0edcc8 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -679,31 +679,23 @@ transformInsertSetClause(ParseState *pstate, List
*setClauseList,
{
List *all_cols = NIL; /* List of all unique
column names */
List *valuesLists = NIL;
- ListCell *outer_lc;
- ListCell *lc;
/*
* First pass: collect all unique column names from all rows.
* We need to scan all rows first to determine the complete set of
columns.
* Also check for duplicate columns within each row.
*/
- foreach(outer_lc, setClauseList)
+ foreach_node(List, set_clause, setClauseList)
{
- List *set_clause = (List *) lfirst(outer_lc);
List *row_cols = NIL; /* Columns seen in
this row */
- ListCell *set_lc;
[...]
(more of that in the link to the diff in GH)
That's all for now.
Thanks!
> Below INSERT features are supported:
> - DEFAULT keyword: SET col=DEFAULT
> - Expressions and functions: SET col=expr, col2=function(...)
> - Subqueries: SET col=(SELECT ...)
> - RETURNING clause
> - ON CONFLICT DO UPDATE/NOTHING
> - OVERRIDING SYSTEM VALUE
> - Multi-row syntax: SET (col1=val1, col2=val2), (col1=val3, col2=val4)
>
> Columns not mentioned receive their default values or NULL, consistent
> with standard INSERT behavior.
>
> I've attached the patch. Looking forward to your feedback.
> --
>
> Thanks & Regards,
> Suraj kharage,
>
--
Mario Gonzalez
EDB: https://www.enterprisedb.com
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Pavel Stehule | 2026-07-12 18:48:28 | toast table corrupted by vacuum - missing chunk number 0 for toast value |
| Previous Message | Srinath Reddy Sadipiralla | 2026-07-12 18:18:44 | Re: Clarify or fix SIGINT handling in data checksums launcher |