JOOQ doesn't return auto generated value for normal column - sql

I have table user_profile, with 3 fields:
id: UUID, primary key, not null, auto generated
created: TIMESTAMP, not null, auto generated
name: VARCHAR
Below is my code to insert a new row to the table.
// dsl is DslContext, which is a bean, injected by Spring Boot
dsl.newRecord(Tables.USER_PROFILE).apply {
name = "My Name"
insert()
// UserProfile is an immutable pojo class, generated by jooq.
}.into(UserProfile::class.java)
In the code above, "id" field (primary key) is updated to the pojo,
while "created" field (normal field) is "null".
What is the "best way" to include the returning value for "created" field?

There are 2 flags governing this behaviour:
Settings.returnIdentityOnUpdatableRecord, default true
Settings.returnAllOnUpdatableRecord, default false
You want to set the second flag to true as well.

Related

Order of columns in the table created does not have 'id' first, despite id being the first field in the SQLModel

I am creating a table using the following code:
from sqlmodel import Field, SQLModel, JSON, Column, Time
class MyTable(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str
type: str
slug: str = Field(index=True, unique=True)
resource_data: dict | None = Field(default=None, sa_column=Column(JSON)) # type: ignore
# ... create engine
SQLModel.metadata.create_all(engine)
The CREATE table script generated for the model above ends up putting the resource_data column above everything else, instead of preserving the natural order of 'id' first
CREATE TABLE mytable (
resource_data JSON, <----- why is this the FIRST column created?
id SERIAL NOT NULL,
name VARCHAR NOT NULL,
type VARCHAR NOT NULL,
slug VARCHAR NOT NULL,
PRIMARY KEY (id)
)
This feels unusual when I inspect my postgresql tables in a db tool like pgAdmin.
How do I ensure the table is created with the 'natural' order of the declarative model, that is 'id' first?

Why is Sequelize upsert not working with composite unique key?

I use this table in a PostgreSQL database:
create table if not exists "Service" (
_id uuid not null primary key,
service text not null,
"count" integer not null,
"date" timestamp with time zone,
team uuid,
organisation uuid,
"createdAt" timestamp with time zone not null,
"updatedAt" timestamp with time zone not null,
unique (service, "date", organisation),
foreign key ("team") references "Team"("_id"),
foreign key ("organisation") references "Organisation"("_id")
);
When I try an upsert with Sequelize with the following code, it throws an error:
Service.upsert({ team, date, service, organisation, count }, { returning: true })
Error is:
error: duplicate key value violates unique constraint "Service_service_date_organisation_key"
Key (service, date, organisation)= (xxx, 2022-12-30 01:00:00+01, 12345678-5f63-1bc6-3924-517713f97cc3) already exists.
But according to Sequelize documentation it should work: https://sequelize.org/docs/v6/other-topics/upgrade/#modelupsert
Note for Postgres users: If upsert payload contains PK field, then PK will be used as the conflict target. Otherwise first unique constraint will be selected as the conflict key.
How can I find this duplicate key error and get it work with the composite unique key: unique (service, "date", organisation)?
It looks like your problem is related to issue #13240.
If you're on Sequelize 6.12 or above, you should be able to use an explicit list of conflictFields:
Service.upsert(
{ team, date, service, organisation, count },
{ conflictFields: ["service", "date", "organisation"] },
{ returning: true }
)
References
Similar questions were asked on GitHub, see:
https://github.com/sequelize/sequelize/issues/13240
https://github.com/sequelize/sequelize/issues/13412
and they were not solved so far, so, as the time of this writing, this issue seems to be unresolved, so you will need to work-around it. Below I will provide a few ideas to solve this, but since I have never worked with Sequelize, it is possible that I have some syntax error or some misunderstanding. If so, please point it out and I'll fix it.
Approach 1: Querying by your unique key and inserting/updating by it
Post.findAll({
where: {
service: yourservice,
date: yourdate,
organization: yourorganization
}
});
And then insert if the result is empty, update otherwise.
Approach 2: Modifying your schema
Since your composite unique key is a candidate key, an option would be to remove your _id field and make your (service, "date", organization) unique.
Approach 3: Implement an insert trigger on your table
You could simply call insert from Sequelize and let a PostgreSQL trigger handle the upserting, see: How to write an upsert trigger in PostgreSQL?
Example trigger:
CREATE OR REPLACE FUNCTION on_before_insert_versions() RETURNS trigger
LANGUAGE plpgsql AS
$$BEGIN
IF pg_trigger_depth() = 1 THEN
INSERT INTO versions (key, version) VALUES (NEW.key, NEW.version)
ON CONFLICT (key)
DO UPDATE SET version = NEW.version;
RETURN NULL;
ELSE
RETURN NEW;
END IF;
END;$$;
You of course will need to change table and field names accordingly to your schema and command.

Postgres GENERATED AS IDENTITY column nullability

I want to create a table, which contains a nullable column having GENERATED BY DEFAULT AS IDENTITY option, therefore I run the following query:
CREATE TABLE my_table (
generated INTEGER NULL GENERATED BY DEFAULT AS IDENTITY,
data TEXT NOT NULL
);
But once I try to insert a row in the table, which generated field is null like this:
INSERT INTO my_table(generated, data) VALUES(NULL, "some data");
I get a null-constraint violation error.
However if I change the order of my_table.generated column properties:
CREATE TABLE my_table (
generated INTEGER GENERATED BY DEFAULT AS IDENTITY NULL,
data TEXT NOT NULL
);
It inserts rows, which generated field is NULL, without any issues.
Is this the expected behavior for the case?
Postgres developers told me this is a bug since identity columns weren't supposed to be nullable (see the patch file under the response).

How to update the nested tables in sql using gorm?

Here the code is written in Go. I am using two tables where one table has a foreign key that refers to the other table's primary key. Let's say I have a database as following struct defined:
type User struct{
ID uint `gorm:"primary_key;column:id"`
Name string `gorm:"column:name"`
Place place
PlaceID
}
type Place struct{
ID uint `gorm:"primary_key;column:id"`
Name string `gorm:"column:name"`
Pincode uint `gorm:"column:pincode"`
}
And the sql schema is:
create table place(
id int(20) NOT NULL AUTO_INCREMENT,
name varchar(100) NOT NULL,
pincode uint(20) NOT NULL,
PRIMARY KEY (id),
)
create table user(
id int(20) NOT NULL AUTO_INCREMENT,
name varchar(100) NOT NULL,
place_id uint(20) NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (place_id) REFERENCES place(id)
)
Now while inserting in user by gorm as:
place := Place{Name:"new delhi",Pincode:1234}
user := User{Name: "sam", Age: 15, Place: place}
err = db.Debug().Create(&user).Error
//It inserts to both user and place table in mysql
//now while updating to name in user table as Samuel and place as
//following
place := Place{Name:"mumbai",Pincode:1234}
err = db.Debug().Model(&User{}).Where("id =?",
1,).Update(&user{Name:"Samuel",Place:place}).Error
It updates the row in user table but creates a new row in place table.But it should update the matching row in place table and not create a new one
Is there any way to do it? Here I am not using auto migrate function to create db tables.
The answer to your question should be sought in a relations or Association Mode.
The example below shows how to add new associations for many to many, has many, replace current associations for has one, belongs to
db.Model(&user).Association("Place").Append(Place{Name:"mumbai",Pincode:1234})
Or you can replace current associations with new ones:
db.Model(&user).Association("Place").Replace(Place{Name:"mumbai",Pincode:1234},Place{Name:"new delhi",Pincode:1234})
Probably It's creating a new row because you didn't set the ID on Place{Name:"mumbai",Pincode:1234}.

OpenJPA: Assign a sequence generated value to ID if null

I am using jpa for persisting my database along with java pojos
#Entity
#Table(schema = "CENTRALSERVICES", name = "APPLICATION")
public class Application {
#Id
#Column(name = "id", nullable = false, length = 128)
private long id;
}
My database is like this:
CREATE TABLE CENTRALSERVICES.APPLICATION(
id bigint(8) NOT NULL, PRIMARY KEY(id));
The problem is that each application object that I persist was having an Id till now, but the requirement changed and now its not guaranteed if Id will be there. I saw something with sequence but I want to assign a sequence generated value only when the Id is null.
How to solve this. Please help
I changed my database schema and now my primary key is autogenerated whereas id for my application object I have created another field which can be null.