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

add ON CONFLICT DO NOTHING for insert #6

Merged
merged 1 commit into from
Nov 28, 2023

Conversation

JasonYangShadow
Copy link
Member

@JasonYangShadow JasonYangShadow commented Nov 24, 2023

in this PR, I added a new method named CreateIgnore, which will add ON CONFLICT DO NOTHING to INSERT query (https://www.postgresql.org/docs/current/sql-insert.html), it'll help avoid returning the duplicated key violation error thus application does not need to do this check at each place where Create method is called.

@WestleyK
Copy link

Can @mstg also review this?

@mstg
Copy link
Contributor

mstg commented Nov 24, 2023

I'm not fully against merging this, just not sure if introducing further operations is the best way to go. What if we used something like

type PikaOption byte

const OnConflictDoNothing PikaOption = 1 << 2

func test(a string, options ...PikaOption) {
	var opt PikaOption
	for _, v := range options {
		opt |= v
	}
	if opt&OnConflictDoNothing != 0 {
		fmt.Println("do nothing on conflict")
	} else {
		fmt.Println("fail on conflict")
	}
}

That way we could continue using Create without breaking any current usage (due to the spread operator) and we could potentially introduce other options.

@JasonYangShadow @WestleyK What do you think? We could just merge this too and get back to it later. This library is due for some changes that is going to simplify its use but that is going to be long term and gradual. I'm OK with both approaches at the moment

@WestleyK
Copy link

@mstg I like that approach better. I think we can include that in this PR if its okay with @JasonYangShadow.

@JasonYangShadow JasonYangShadow force-pushed the insert_ignore branch 2 times, most recently from c09f067 to bddf2a0 Compare November 27, 2023 03:41
Copy link

@WestleyK WestleyK left a comment

Choose a reason for hiding this comment

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

Couple small comments, otherwise looks good.

pika_psql.go Outdated
@@ -67,6 +67,10 @@ type basePsql[T any] struct {
psql *PostgreSQL
}

type PikaOption byte

const InsertOnConflictionDoNothing PikaOption = (iota + 1) << 2

Choose a reason for hiding this comment

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

So if this is intended to be a bitbask type option(s), I think this byte shift will collide, we can use this instead for unique bitmask values:

1 << iota

Copy link
Member Author

Choose a reason for hiding this comment

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

yeah, this one looks better. thanks!

pika_psql.go Outdated
@@ -67,6 +67,10 @@ type basePsql[T any] struct {
psql *PostgreSQL
}

type PikaOption byte

Choose a reason for hiding this comment

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

Would it make sense to call this PikaCreateOption? This is specifically create options, this is a very generic name.

Copy link
Member Author

Choose a reason for hiding this comment

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

though I feel like this originally is designed for any pika option. but PikaCreateOption looks more clear in this case

pika_psql.go Outdated
b.ignoreOrderBy = origIgnoreOrderBy

// Execute query
err := b.psql.Queryable().Get(x, q, args...)
if err != nil {
// ignore no rows in resultset error when ignoreConflict is set to true, this is a normal case
if errors.Is(err, sql.ErrNoRows) && insertOnConflict(options...) {

Choose a reason for hiding this comment

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

Just a suggestion, maybe you could do something like this:

if errors.Is(err, sql.ErrNoRows) && getOptions(opts...)&InsertOnConflictionDoNothing > 0 {

...

func getOptions(opts ...PikaOption) PikaOption {
	o := 0
	if opts == nil {
		return o
	}
	for _, opt := range opts {
		o = o | opt
	}

	return o
}

You dont need to change this, just thinking, this could make it easier when (if) theres lots of options, since we dont need a dedicated function to return each option.

Copy link

@WestleyK WestleyK left a comment

Choose a reason for hiding this comment

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

This looks good to me, can @mstg take another look?

@mstg
Copy link
Contributor

mstg commented Nov 27, 2023

@JasonYangShadow Could you rename PikaCreateOption to CreateOption? The linter caught that one

@JasonYangShadow
Copy link
Member Author

@JasonYangShadow Could you rename PikaCreateOption to CreateOption? The linter caught that one

Thanks! done rename.

@mstg
Copy link
Contributor

mstg commented Nov 28, 2023

Awesome, thank you!

@mstg mstg merged commit 131e7ce into ctrliq:main Nov 28, 2023
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants