I'm using DBeaver to write script for my PostgreSQL database.
I have a PostgreSQL DB with Tables autogenerated by C#/EFCore (Microsoft ORM) - I receive SQL Error [42P01] if I don't add double quotes around table names when I cut and paste my ORM queries to DBeaver. I got [42703] for fields without double quotes. I do not have to add double quotes in C# code but it appears to be required in DBeaver?
example:
select * from Dnp3PropertyBase => SQL Error [42P01]
select * from "Dnp3PropertyBase" => OK, all results shown...
Does anybody know if I can change a parameter in DBeaver somewhere in order to enter table names and fields without double quotes?
Note: Using DBeaver 22.3.2 (latest on 2023-01-11)
Update After reading: Postgresql tables exists, but getting "relation does not exist" when querying
show search_path => public, public, "$user"
SELECT * FROM information_schema.tables => All tables are in public schema
SELECT * FROM information_schema.columns => All columns are in public schema
Question: How to be able to cut and paste my EFCore generated queries from Visual Studio output window to DBeaver query without having any errors regarding table names and field names?
First let me copy #a_horse_with_no_name comment:
Unquoted names are folded to lower case in Postgres (and to uppercase
in Oracle, DB2, Firebird, and many others). So SomeTable is in fact
stored as sometable (or SOMETABLE). However quoted identifiers have to
preserve the case and are case sensitive then. So "SomeTable" is
stored as SomeTable
Many peoples recommended me to go with snake case which I didn't want to go with initialy because all tables were auto generated by EF Core (Microsoft C# ORM). I told myself that Microsoft would do standard things. Microsoft use the exact "class" name in code as the table name , by default. That appears to me very logical in order to stay coherent and apply the same rules everywhere. C# recommended to use Camel case for classes so each table names end by default in Camel case instead of snake case.
PostgreSQL seems to promote users to use snake casing because they lower case every non double quoted names. According to a_horse_with_no_name, and I think the same, only PostgreSQL has the behavior of lower casing down every table names and field names which are not double quoted in SQL script. That behavior (changing casing for non double quoted names) appears to me as being very limitative. It also has hidden effect that could be hard to find for non initiated peoples coming from other DB world.
According to PostgreSQL doc, they recommend to use nuget package (.UseSnakeCaseNamingConvention()). It probably works fine for TPH (table per hierarchy) which is recommended by Microsoft for performance. But it does not works for table name for TPC (table per class) because of actual bugs in EFCore 7 (see Github project).
I received that message at the end of "update-database":
Both 'WindTurbine' and 'ResourceGenerator' are mapped to the table
'resource_generator'. All the entity types in a non-TPH hierarchy (one
that doesn't have a discriminator) must be mapped to different tables.
See https://go.microsoft.com/fwlink/?linkid=2130430 for more
information.
PostgreSQL doc : TPH supported OK but not for table in TPC (2023-01-12). I use TPC then I had to force each table name directly through TableAttribute.
My solution For table name, I use snake casing by manually add a "Table" attribute to each of my classes with the proper name like this sample:
[Table("water_turbine")]
public class WaterTurbine : ResourceGenerator
For fields, I use the EFCore.NamingConventions NugetPackage which works fine for fields names. Don't forget that if you have 2 classes mapped to the same object, it is because you are using TPC and did not force table name through TableAttribute.
This way all my table and fields names are snake casing and I can cut and paste any query dumped in my debugger directly in any SQL script window of DBeaver (or any SQL tool).
I'm fairly new to using log analytics and not very familiar with the KQL language yet for queries.
I'm trying to do a query that will get the objectID value out of what appears to be a multi-valued property from the query. When I do a standard search to list the results in a table one of the columns is Properties, and the objectID is within that property column.
Not sure how to go about doing this so the results just show the objectID.
It would have helped to see your initial kusto query included in the question.
Nevertheless, you can use the project operator of KQL to extract the ObjectId as:
T
| ..<the rest of your query>..
| project Properties.ObjectId
where T is the table you are trying to query.
Here are some resources for you to get started with Kusto Query Language:
Getting started with Kusto
Write queries for Azure Data Explorer
Kusto Query Language (KQL) from Scratch
tl;dr: Hibernate automatically generates SQL table aliases in its queries like jurisdicti4_ or this_. Here's an example query:
SELECT
this_.id AS id2_6_3_,
this_.a_table_column AS a_table_column3_6_3_,
jurisdicti4_.b_table_column AS b_table_column4_6_3_,
FROM
app_table_a this_
LEFT OUTER JOIN jurisdiction jurisdicti4_ ON this_.jurisdiction = jurisdicti4_.name
WHERE
this_.a_table_column = ?
I'm using the Hibernate Criteria API to add some hints that need reference the SQL aliases in the query, so I need to know how to either:
specify the SQL table aliases Hibernate will use in its queries (e.g. tell it to use juris instead of jurisdicti4_ for jurisdiction, or
get hibernate to tell me the exact SQL table alias it will use for a particular table or entity (e.g. be told the alias in the query for jurisdiction will be jurisdicti4_.
Full story:
I've inherited a Java app with an Oracle DB that uses Hibernate 4.3.8 and the Hibernate Criteria API to generate some complicated search queries. It recently ran into a severe SQL performance problem that will require us to start to include hints these queries. However, we use Oracle, and its index hints are in the form of:
/*+ index (TABLE_ALIAS INDEX_NAME) */
I've successfully added the needed hints using Criteria.addHint(...), however I've had to hardcode the Hibernate-generated TABLE_ALIAS in the hint string. I'm concerned that over time, the aliases may change, so I want to either control how they're generated or be able to retrieve their values to use when adding the SQL hint.
Edit: This website describes the Hibernate SQL alias generation process: https://prismoskills.appspot.com/lessons/Hibernate/Chapter_23_-_Hibernate_alias_names.jsp
I've found that I have partial control of the SQL aliases when I programmatically set up the join like this: criteria.createAlias(associationPath, alias). The alias value I pass seems to be used as the first part of the SQL alias for the table. However, Hibernate appends some kind of generated table ID integer to that, so I'd get something like myalias4_ in the generated SQL. Also, this only seems to work in joins I setup myself in the criteria. Hibernate will often add its own based on the mappings, and I'm not sure how get this same level of partial control over those.
Perfectly fine ms-sql statement
SELECT distinct ProductLineCode ,
(SELECT CAST(ItemName + ', ' AS VARCHAR(MAX)) FROM Product spt
where spt.ProductLineCode = pt.ProductLineCode FOR XML PATH (''))
as ItemNames FROM Product pt where ProductLineCode is not null
cause error when executed as native query in hibernate.
org.hibernate.MappingException: No Dialect mapping for JDBC type: -16
I guess that JDBC type: -16 is boolean but that says me nothing. Product table has xml mapping and works well for months.
Could you please guide me what to try next?
You might as advised in comments be able to get something similar to work by changing the types in the sql.
But if that doesn't bring success, you might also be able to tell hibernate how to deal with this type by changing the Dialect class used by your application, possibly even extending the one currently used and adding a registration for the missing type.
It appears that your missing type mapping is for the type java.sql.Types.LONGNVARCHAR (by code grep, the value is -16), so a Dialect extension with a call something like
registerColumnType( Types.LONGNVARCHAR, "text" );
in the constructor may convince hibernate to treat this field as text.
If you do this you'll have to change the configuration to use your dialect by modifying the line
<property name="dialect">org.hibernate.dialect.SQLServer2012Dialect</property>
to use your own dialect class. (Note: the class in there is just a guess at what you might have there now.)
It's also possible that you just have hibernate using the wrong dialect for your DB, in which case just changing the configuration to the appropriate one would be better.
It's rarely necessary to use a custom Dialect, but this may be one of those times.
May I know how can I get the sql from a JPA query? or let's say, convert the JPA query to a SQL string? Thank you very much!
For Eclipselink: you can extract the SQL the following way:
query.unwrap(EJBQueryImpl.class).getDatabaseQuery().getSQLString()
It works only after the query has been executed.
If you only want to know how your JPQL or Criteria Query gets translated to the SQL dialect of your database you can enable fine grained logging in the persistence xml and then look into your log files.
The property name and value depends on your JPA implementation. Here is an example of the relevant part of persistence.xml for EclipseLink:
<properties>
<property name="eclipselink.logging.level" value="FINEST"/>
</properties>
JPA Specification
While there is not standard JPA functionality to achieve this goal, you can still extract the SQL query from a JPQL or Criteria API Query using the JPA provider-specific API.
Hibernate Types
Starting with the 2.9.11 version, the Hibernate Types open-source project offers the SQLExtractor utility that allows you to get the SQL query from any JPQL or Criteria API query, no matter you are using Hibernate 5.4, 5.3, 5.2, 5.1, 5.0, 4.3, 4.2, or 4.1.
Get the SQL statement from a JPQL Query
Let's assume we have the following JPQL query:
Query jpql = entityManager.createQuery("""
select
YEAR(p.createdOn) as year,
count(p) as postCount
from
Post p
group by
YEAR(p.createdOn)
""", Tuple.class
);
With Hibernate Types, extracting the Hibernate-generated SQL query is as simple as that:
String sql = SQLExtractor.from(jpql);
And, if we log the extracted SQL query:
LOGGER.info("""
The JPQL query: [
{}
]
generates the following SQL query: [
{}
]
""",
jpql.unwrap(org.hibernate.query.Query.class).getQueryString(),
sql
);
We get the following output:
- The JPQL query: [
select
YEAR(p.createdOn) as year,
count(p) as postCount
from
Post p
group by
YEAR(p.createdOn)
]
generates the following SQL query: [
SELECT
extract(YEAR FROM sqlextract0_.created_on) AS col_0_0_,
count(sqlextract0_.id) AS col_1_0_
FROM
post p
GROUP BY
extract(YEAR FROM p.created_on)
]
Notice that we unwrapped the JPA Query to the Hibernate org.hibernate.query.Query interface which provided the getQueryString method we can use to log the associated JPQL query string.
Get the SQL statement from a JPA Criteria API Query
The SQLExtractor is not limited to JPQL queries. You can use it with Criteria API queries as well, as illustrated by the following example:
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<PostComment> criteria = builder.createQuery(PostComment.class);
Root<PostComment> postComment = criteria.from(PostComment.class);
Join<PostComment, Post> post = postComment.join("post");
criteria.where(
builder.like(post.get("title"), "%Java%")
);
criteria.orderBy(
builder.asc(postComment.get("id"))
);
Query criteriaQuery = entityManager.createQuery(criteria);
String sql = SQLExtractor.from(criteriaQuery);
assertNotNull(sql);
LOGGER.info("""
The Criteria API, compiled to this JPQL query: [
{}
]
generates the following SQL query: [
{}
]
""",
jpql.unwrap(org.hibernate.query.Query.class).getQueryString(),
sql
);
When running the above test case, we get the following SQL query:
- The Criteria API, compiled to this JPQL query: [
select
pc
from
PostComment as pc
inner join
pc.post as p
where
p.title like :param0
order by
pc.id asc
]
generates the following SQL query: [
SELECT
pc.id AS id1_1_,
pc.post_id AS post_id3_1_,
pc.review AS review2_1_
FROM
post_comment pc
INNER JOIN
post p ON pc.post_id=p.id
WHERE
p.title LIKE ?
ORDER BY
pc.id ASC
]
The Criteria API is first compiled to a JPQL query, as illustrated by the getQueryString() method call.
The intermediary JPQL query is further translated to an SQL query, which is properly resolved by the SQLExtractor utility.
Following Karol's answer - It is possible to retrieve the SQL before executing the statement in EclipseLink :
Session session = em.unwrap(JpaEntityManager.class).getActiveSession();
DatabaseQuery databaseQuery = query.unwrap(EJBQueryImpl.class).getDatabaseQuery();
databaseQuery.prepareCall(session, new DatabaseRecord());
Record r = databaseQuery.getTranslationRow();
String bound = databaseQuery.getTranslatedSQLString(session, r);
String sqlString = databaseQuery.getSQLString();
To retrieve the SQL String During/After execution it is probably best to do so using persistence properties rather than in-code :
<property name="eclipselink.logging.parameters" value="true"/>
<property name="eclipselink.logging.level" value="FINE"/>
Beside enabling the logging like #Matt Handy mentioned it is also possible to get the SQL String for a specific query with eclipselink at runtime as described here.
Using Hibernate as a provider you can enable the following properties:
hibernate.show_sql
Write all SQL statements to console. This is an alternative to setting the log category org.hibernate.SQL to debug. (e.g. true | false)
hibernate.format_sql
Pretty print the SQL in the log and console. (e.g. true | false)
Or, as stated above you can enable logging to the debug level for the logger
org.hibernate.SQL
Log all SQL DML statements as they are executed
You are probably interested if there's a way to 'extract' JPQL string (either with placeholders for params, or final JPQL after params are filled-in) out of javax.persistence.Query (one of it's possible subclasses to be more precise),- in this case it's not possible according to JPA specification contract. However, this hypothetically might be possible by JPA implementation (e.g., NamedQueryImpl could have #toJPQLString(), which you could access via casting), but I doubt about that.
And even if it's possible I don't think it's a good code performing such manipulations. I would suggest finding another design solutions (and for that you could specify what kind of actual problem do you have). E.g., if you are building your queries dynamically, JPA Criteria API could be used for that, and along with 'building' JPA query, you could maintain your internal data structure reflecting the logic of your query.
This blog contains instructions: http://narcanti.keyboardsamurais.de/hibernate-hql-to-sql-translation.html
You could use p6spy. At the following link there are instructions for its operation:
https://p6spy.readthedocs.io/en/latest/install.html