How to annotate unique constraint with WHERE clause in JPA - postgresql

I need to use these unique constraints in PostgreSQL
CREATE UNIQUE INDEX favorites_3col_uni_idx
ON favorites (user_id, menu_id, recipe_id)
WHERE menu_id IS NOT NULL;
CREATE UNIQUE INDEX favorites_2col_uni_idx
ON favorites (user_id, recipe_id)
WHERE menu_id IS NULL;
The first one I annotate in JPA:
#Table(uniqueConstraints= {
#UniqueConstraint(name="favorites_3col_uni_idx", columnNames = {"user_id", "menu_id", "recipe_id"})
})
But, ¿it is possible to annotate in JPA the second unique index?
Thx.

You appear to want to create partial indexes (CREATE INDEX ... ON ... WHERE) using JPA constraint definitions.
These are fairly PostgreSQL specific, and aren't specified by JPA. You will need to use native syntax to create them. I don't believe JPA offers any features for index definition.
You cannot use a unique constraint for this purpose because unique partial indexes are not unique constraints. Partial unique indexes cannot be created with CONSTRAINT constraint_name UNIQUE(columns) in PostgreSQL. It's only an implementation detail that PostgreSQL creates a unique index for a unique constraint at all.
See:
Specifying an Index (Non-Unique Key) Using JPA
JPA: defining an index column
Some JPA providers offer extension annotations specific to that JPA provider that add features for running native DDL scripts, defining indexes with annoations, etc. Since you haven't mentioned which JPA provider you are using I can't tell you more. Here's the documentation for EclipseLink index DDL; this will not work if you are using Hibernate, OpenJPA, or something other than EclipseLink.
A JPA standard workaround is to check for the presence of those indexes during startup by querying pg_catalog.pg_index. If you don't find them, use an EntityManager native query to send the appropriate native SQL CREATE UNIQUE INDEX commands. A #Startup #Singleton bean is useful for this sort of task if you're using EJB3.1. See the PostgreSQL documentation for the structure of pg_catalog.pg_index. To just check if an index of a given name exists, run:
SELECT EXISTS(
SELECT 1
FROM pg_index
WHERE indexrelid = 'public.indexname'::regclass
);
Note that the above query does nothing to verify it's the index you expect, but you can do that with some additional checks. Just examine the contents of pg_index after creating the index so you know what to test for. I don't recommend trying to check for any particular value of indpred; just make sure it isn't null.

Related

Postgres Gin index definition in Spring JPA

I have created a Postgres Gin index in a Spring Boot JPA application to allow fast text based search queries on a Text type column. Is it possible to define it using any native command that would execute on application deployment so I don't have to remember adding it to the table manually every time I deploy the microservice?
Using #Index in the #Table for the entity creates btree indexes.
This problem is also for a Hash type index I need. Btree is fine but Hash will be a bit faster for my queries so I'd like to automate those Gin & hash creation.

jOOQ code generator does not generate corresponding Index if a UNIQUE index has the function defined on the field

I have a unique index as below to achieve case-insensitive unique constraint on the project name
CREATE UNIQUE INDEX IF NOT EXISTS unique_project_name__idx ON project (UPPER(name));
It seems that jOOQ code generator does not generate the corresponding constant in Indexes.java for such UNIQUE index.
However, it works for the index without UPPER() function
CREATE UNIQUE INDEX IF NOT EXISTS unique_project_name__idx ON project (name);
// corresponding generation in Indexes.java
public static Index UNIQUE_PROJECT_NAME__IDX = Internal.createIndex("unique_project_name__idx", Project.PROJECT, new OrderField[] { Project.PROJECT.NAME }, true);
I use jOOQ 3.13.2 and PostgreSQL 11.2.
Any idea?
Is citext a better way for case-insensitive unique constraint?
This is a missing feature in jOOQ 3.13: https://github.com/jOOQ/jOOQ/issues/6310

Is there any benefit using index or foreignKey in slick table schema?

Should i use indexes and foreignKey in slick schema table? Is there any benefits like performance or query planner?
We are using Flyway DB migration tool so we wont use this schema with schema.create
Foreign keys in slick schema table would help you in two cases
first is from slick doc
...foreign key can be used to navigate to the referenced data with a join. For this purpose, it behaves the same as a manually defined utility method for finding the joined data ...
And if you generate DB schema using slick (for example, in tests)
Setting up indexes help you to fasten your searching(data retrieval), but slows down insertion. So you need to decide according to your requirement what you want. If there is more searching and data in DB is huge you should go for indexing.
Foreign keys, on the other hand, are used to maintain the relationship between different tables which are used for join in relational DB. Adding foreign keys will not have any impact on performance.
You can get more insight on indexing here -> Indexing,
And for foreign key here -> Foreign Key

Conditional onDuplicateKeyUpdate in Jooq

I tried to use the jooq dsl for an insert/update query.
We have a unique (MemberId, GroupId) combination in our table, and a group membership Enum.
On sending a subscription request with (MemberId, GroupId, RoleEnum)
The query should insert a new entry to the db, but if the MemberId, GroupId combination already exists - then only update the entry if the new RoleEnum is larger than the existing one.
I failed to do this using one query with the jooq Dsl, so instead I had to use two queries (get, then insert or update accordingly) but then I lose the atomicity of the operation...
Is there a way to do this with one query with the jooqDsl?
jOOQ emulates PostgreSQL 9.5's support for the ON CONFLICT clause via:
insertInto(...).values(...).onDuplicateKeyUpdate()... of the MySQL syntax. This is possible only if your table is generated with explicit primary key information on it. (https://github.com/jOOQ/jOOQ/issues/5093, since jOOQ 3.8)
mergeInto(...).key(...).values(...) of the H2 syntax. With this syntax, you can providean explicit key column list specification, so the code generator is not needed to provide constraint meta information. (https://github.com/jOOQ/jOOQ/issues/4464, since jOOQ 3.7).
Unfortunately, there is not yet any native ON CONFLICT support in jOOQ.

Entity Framework Many-to-Many Clustered vs. Nonclustered Index

I designed an entity data model with two entities between which there exists a many to many relationship. When I auto-generate SQL code to generate the database for this model, it has generated a table (two columns) to keep track of this many-to-many association. However, this table has a PRIMARY KEY NONCLUSTERED on both columns.
Since I want this to work on SQL Azure which doesn't like tables with only nonclustered indices, I was wondering whether there is a good way of telling the code generation to generate clustered indices? Thanks!
I have another file called Model.indexes.sql that contains scripts to create additional indexes beyond the basic ones EF generates, such as those for performance optimizations.
Although this is not ideal, I added into this an index drop and create for each EF association to convert the Non-Clustered indexes into indexed ones:
ALTER TABLE [dbo].[MyAssociation]
DROP CONSTRAINT [PK_MyAssociation]
GO
ALTER TABLE [dbo].[MyAssociation]
ADD CONSTRAINT [PK_MyAssociation]
PRIMARY KEY CLUSTERED ([Table1_Id], [Table2_Id] ASC);
GO
This is executed after every "Generate Database from Model...". I would love a more elegant solution.