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

Unable to construct on conflict with multiple columns dynamically #671

Closed
nnmrts opened this issue Sep 5, 2023 · 5 comments
Closed

Unable to construct on conflict with multiple columns dynamically #671

nnmrts opened this issue Sep 5, 2023 · 5 comments

Comments

@nnmrts
Copy link

nnmrts commented Sep 5, 2023

Whatever I'm trying, I'm unable to make an insert query with an on conflict clause depending on two or more columns...

What I want to do:

insert into table
	(a, b, c)
	values (1, 2, 3)
on conflict (a, b)
do update set
	(
		a = excluded.a
		b = excluded.b
		c = excluded.c
	)

To do this, after some general issues, I followed the comment #217 (comment) and this is what I came up with:

/**
 * Upsert data into a table.
 *
 * @param {Function} db - Postgres instance.
 * @param {string} table - Table name.
 * @param {object} data - Data to upsert. Looks like this: {a: 1, b: 2, c: 3}.
 * @param {Array} conflict - Conflict columns. Looks like this: ["a", "b"].
 *
 * @return {Promise} - Promise.
 */
const upsert = async (
	db,
	table,
	data,
	conflict
) => {
	const conflictString = conflict.map((x, i) => db`${i ? db`,` : db``}${db(x)}`);
	const updateSetClause = Object.keys(data[0]).map((x, i) => db`${i ? db`,` : db``}${db(x)} = excluded.${db(x)}`);

	return db`
	  insert into ${db(table)} ${db(data)}
	  on conflict (${conflictString})
	  do update set ${updateSetClause}
	`;
};

But the result looks like this and obviously fails:

insert into "table" ("a","b","c")values($1,$2,$3)
on conflict ( "a, b")
do update set  "a" = excluded."a" ,"b" = excluded."b" ,"c" = excluded."c"

Is it possible to fix this without using unsafe?

@porsager
Copy link
Owner

porsager commented Sep 5, 2023

Not bad, but why are you saying it obviously fails? Looks correct to me based on the sample input.

@nnmrts
Copy link
Author

nnmrts commented Sep 5, 2023

@porsager Ah sorry, didn't make it clear: on conflict ( "a, b") is invalid, I think it should either be on conflict ( "a", "b") or on conflict ( a, b)

@porsager
Copy link
Owner

porsager commented Sep 5, 2023

It works when I test it. I think your conflict array might look like this: ['a, b'] instead of this ['a', 'b'].

@nnmrts
Copy link
Author

nnmrts commented Sep 5, 2023

Don't ask me why but yeah, that was the issue. I'm sorry........

@nnmrts nnmrts closed this as completed Sep 5, 2023
@porsager
Copy link
Owner

porsager commented Sep 5, 2023

Cool :) It didn't catch my eye in your sample either, so understandable :D

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

No branches or pull requests

2 participants