How to COUNT(*) in Slick 2.0? - scala

According to the Slick 2.0 documentation,
to get the count of rows in a table:
val q1 = coffees.length
// compiles to SQL (simplified):
// select count(1) from "COFFEES"
However, it turns out that coffees.length is of type Column[Int].
How does one execute the query and get the value?

I just had this same problem upgrading to slick 2.0. I forget where the exact method lives, but the generic .run seems to work for me, i.e.
coffees.length.run

StaticQuery.queryNA[Int]("select count(*) from \"" + TableName + "\"").first
Quotes are needed if your table name is not upper case.

Try coffees.length.first should execute and return Int
Sorry, indeed, in the slick 1.0 there was first method to do this, in Slick 2.0 they get rid of it in favor of more generic run.
The function to execute query is
coffees.length.run

Related

PostgreSQL, allow to filter by not existing fields

I'm using a PostgreSQL with a Go driver. Sometimes I need to query not existing fields, just to check - maybe something exists in a DB. Before querying I can't tell whether that field exists. Example:
where size=10 or length=10
By default I get an error column "length" does not exist, however, the size column could exist and I could get some results.
Is it possible to handle such cases to return what is possible?
EDIT:
Yes, I could get all the existing columns first. But the initial queries can be rather complex and not created by me directly, I can only modify them.
That means the query can be simple like the previous example and can be much more complex like this:
WHERE size=10 OR (length=10 AND n='example') OR (c BETWEEN 1 and 5 AND p='Mars')
If missing columns are length and c - does that mean I have to parse the SQL, split it by OR (or other operators), check every part of the query, then remove any part with missing columns - and in the end to generate a new SQL query?
Any easier way?
I would try to check within information schema first
"select column_name from INFORMATION_SCHEMA.COLUMNS where table_name ='table_name';"
And then based on result do query
Why don't you get a list of columns that are in the table first? Like this
select column_name
from information_schema.columns
where table_name = 'table_name' and (column_name = 'size' or column_name = 'length');
The result will be the columns that exist.
There is no way to do what you want, except for constructing an SQL string from the list of available columns, which can be got by querying information_schema.columns.
SQL statements are parsed before they are executed, and there is no conditional compilation or no short-circuiting, so you get an error if a non-existing column is referenced.

updating table rows in postgres using subquery with jooq

I would like to execute and update similar to this:
UPDATE dummy
SET customer=subquery.customer,
address=subquery.address,
partn=subquery.partn
FROM (SELECT address_id, customer, address, partn
FROM dummy) AS subquery
WHERE dummy.address_id=subquery.address_id;
Taken from this answer: https://stackoverflow.com/a/6258586/411965
I found this and wondered if this can auto converted to jooq fluent syntax.
What is the equivalent jooq query? specifically, how do I perform the outer when referencing the subquery?
Assuming you're using code generation, do it like this:
Table<?> subquery = table(
select(
DUMMY.ADDRESS_ID,
DUMMY.CUSTOMER,
DUMMY.ADDRESS,
DUMMY.PARTN
)
.from(DUMMY)
).as("subquery");
ctx.update(DUMMY)
.set(DUMMY.CUSTOMER, subquery.field(DUMMY.CUSTOMER))
.set(DUMMY.ADDRESS, subquery.field(DUMMY.ADDRESS))
.set(DUMMY.PARTN, subquery.field(DUMMY.PARTN))
.from(subquery)
.where(DUMMY.ADDRESS_ID.eq(subquery.field(DUMMY.ADDRESS_ID)))
.execute();
Of course, the query makes no sense it is, because you're just going to touch every row without modifying it, but since you copied the SQL from another answer, I'm assuming your subquery's dummy table is really something else.

Casting Integer to String in JPQL

I want to have a JPQL query that may look like:
entityManager.createQuery("Select a.* from A a WHERE CAST(a.num AS TEXT) LIKE '%345%' ", A.class);
where a.num is an integer. I want to cast this to String to use the LIKE criteria.
However above casting doesnt work in JPQL. Any idea about how can I implement this?
Could you be more specific, what your problem is? Do you have some kind of error or it the result of the query is just wrong?
Because this code works fine for me:
session.createQuery("from MyObject where CAST(id as text) like :id").setParameter("id", "%1").getResultList();
I am using Hibernate 5.2 and Postgresql 9.5.
Also, if you are having trouble understanding what goes wrong, you could try editing hibernate.cfg.xml or whatever configuration file you are using to make Hibernate show queries it sends, by doing something like this:
<property name="hibernate.show_sql">true</property>
I also have the same need. This should work with JPA 2.0 and Hibernate 5.0.2:
entityManager.createQuery(
"Select a.* from A a WHERE CONCAT(a.num, '') LIKE '%345%' ", A.class);
From hibernate document, "cast(... as ...)", where the second argument is the name of a Hibernate type. According list of Hibernate Types it should be string (case sensitive!).
So request should be:
entityManager.createQuery("select a.* from A a WHERE CAST(a.num AS string) LIKE '%345%' ", A.class);
Was taken and checked from Caused by: org.hibernate.QueryException: Could not resolve requested type for CAST : INT answer.
You can simply use CAST(num as string). It worked for me
Well you can use to_char() function in the select clause but, you will need to select all the a.num field separately and not with *.
And in postgresql you will need to specify a mask for to_char()function, so it would be to_char(field, mask), for example we can supply 'FM999999999999999999' as a mask to accept the maximum possible digits.
Your query would be something like this:
Select *, to_char(a.num, 'FM999999999999999999') as num from A a WHERE num LIKE '%345%'
You can take a look at Postgresql Data Type Formatting Functions for further details.
To write the query in your code with EntityManager you can create a native query using .createNativeQuery() method, this is how should be your code:
em.createNativeQuery("Select *, to_char(a.num, 'FM999999999999999999') as num from A a WHERE num LIKE '%345%'");
The correct query is :
entityManager.createQuery("Select a.* from A a WHERE CAST(a.num AS String) LIKE '%345%' ", A.class);

OpenJpa how to find length of string in JPQL

I am using
length(ze.string)>2 in openJpa query. but i am getting
SQLCODE=-440, SQLSTATE=42884, SQLERRMC=CHAR_LENGTH;FUNCTION, DRIVER=3.53.95 {prepstmnt 1776269692 SELECT t0.f1, t0.f2, t0.f3, t0.f4, t0.f5, t0.f6, t0.f7, t0.f8, t0.f9, t0.f10, t0.f11, t0.f12, t0.f13, t0.f14, t0.f15, t0.f16, t0.f17 FROM table t0 WHERE (t0.f1 = ? AND CHAR_LENGTH(?) > ? AND .....
In plain query when i do length operation i am getting record but using jpa its not working. I looked Here used size it doesn't work. and the field is varchar and db2. trying from past 1 hour.
DB2 requires use of the SQL function LENGTH, yet OpenJPA seems to be incorrectly converting your JPQL to use SQL function CHAR_LENGTH (hence the error message - not that DB2 gives out clear messages saying what is wrong, who knows what SQLCODE=-440 is without having to search!!).
Raise a bug on your JPA provider.
See https://www.ibm.com/support/knowledgecenter/SSEPGG_9.7.0/com.ibm.db2.luw.sql.ref.doc/doc/r0000818.html
You would need to give more details about your entity, persistence.xml, and query to get to the bottom or this. However, I do not see how OpenJPA would use CHAR_LENGTH instead of LENGTH for DB2. Let me explain. If you look at DBDictionary here:
https://svn.apache.org/viewvc/openjpa/branches/2.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java?view=markup
You can see it defines something called "stringLengthFunction" as follows:
public String stringLengthFunction = "CHAR_LENGTH({0})";
This is the string length function which should be used for each individual dictionary (i.e. Database config). However, for DB2, the AbstractDB2Dictionary, see here:
https://svn.apache.org/viewvc/openjpa/branches/2.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractDB2Dictionary.java?view=markup
overrides this as follows:
stringLengthFunction = "LENGTH({0})";
Given this, for DB2, LENGTH should be used. I took the following simple query:
"select me.id from MyEntity me where length(me.name)>2"
And executed it on OpenJPA using DB2, and I got this:
SELECT t0.ID FROM MYENTITY t0 WHERE (CAST(LENGTH(t0.ID) AS BIGINT) > CAST(? AS BIGINT)) [params=(long) 2]
Thanks,
Heath Thomann

JPQL / JPA query to order entities based on the greatest/maximum of two columns?

I need something similar to this SQL query:
SELECT * FROM foo f ORDER BY GREATEST(f.bar_date, f.baz_date)
As not all RDBMS systems support the GREATEST function, ideally I would like the JPA implementation to generate the correct SQL query for the underlying database. The databases that I am targetting are Oracle, SQL Server, and PostgreSQL.
JPQL allows the FUNCTION operator to call a database function.
Oracle and Postgres support GREATEST, I don't think SQL Server does, so for it you may be able to write your own function.
You could also use a CASE function with >.
To put this a little more concrete - you could do this in JPQL with the CASE statement, which is supported since JPA 2.0. I've omitted the _date suffixes for brevity.
SELECT * FROM foo f ORDER BY CASE WHEN f.bar > f.baz THEN f.bar ELSE f.baz END
I've used CASE function.
Via criteria builder it looks like:
CriteriaQuery<?> query = ...
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
query.orderBy(builder.selectCase().when(builder.greaterThan(pathToBarDate, pathToBazDate),pathToBarDate).otherwise(pathToBazDate));
In JPQL it should look like
ORDER BY
CASE WHEN (f.bar_date>f.baz_date) THEN f.bar_date
ELSE f.baz_date