ebean: RETURNING column name is quoted excessively
Expected behavior
- when
databaseConfig.platformConfig.allQuotedIntentifiersis false, column name shouldn’t be quoted, when true, column name should be quoted once
Actual behavior
- when
databaseConfig.platformConfig.allQuotedIntentifiersis false, column name is quoted, when true, column name is quoted thrice
Steps to reproduce
Create any entity (didn’t test with other entity yet, will try to create minimal example later), use postgres org.postgresql.Driver, turn on SQL logging, call Database.save(entity). This is especially problematic if you set the @Id column name to be upper-case (which we need because of other db backends), because in that case, when identifier quoting is off, it creates the columns in lower-case, but then it quotes the returning column name, so it tries to find the upper-cased name and fails. If you turn on the identifier quoting, it just fails completely, because the name is surrunded by """.
I’m using ebean version 12.16.1. This is the persistence configuration I’m using:
@Configuration
@Import(JacksonAutoConfiguration::class)
class EgjePersistenceConfiguration {
@Autowired
lateinit var objMapper: ObjectMapper
@Bean
@ConfigurationProperties(prefix = "datasource.egje")
fun egjeDataSourceConfig() = DataSourceConfig()
@Bean
@ConfigurationProperties(prefix = "database.egje")
fun egjeDatabaseConfig() = DatabaseConfig().apply {
name = "egje"
objectMapper = objMapper
isDefaultServer = false
dataSourceConfig = egjeDataSourceConfig()
platformConfig.isAllQuotedIdentifiers = true // or false
packages = listOf("cz.sentica.qwazar.kb.registries.person.egje")
}
@Bean
fun egjeDatabase(): Database = DatabaseFactory.create(egjeDatabaseConfig())
}
And the configuration:
database:
egje:
ddl-run: true
ddl-generate: true
datasource:
egje:
username: ${EGJEDB_USER:qwazar}
password: ${EGJEDB_PASS:qwazar}
url: jdbc:postgresql://${EGJEDB_HOST:postgres_egje}/${EGJEDB_NAME:egjedb}
driver: org.postgresql.Driver
The entity for which it failed:
@Entity
@DbName("egje")
@Table(name = "EA_EMPLOYEE")
class EgjePerson {
/** Technické ID - primární klíč */
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "EMPLOYEE_LLR_ID", nullable = false)
val id: Long = 0L
/** Osobní číslo - záznamy se stejným oscis se týkají té samé osoby */
@Column(name = "OSCIS", nullable = false)
var oscis: Int = 0
/** Pořadové číslo úvazku */
@Column(name = "LLR_SERIAL_NO", nullable = false)
val serialNumber: Int = 0
/** Příznak zda jde o hlavní (1) nebo vedlejší (0) úvazek */
@Column(name = "MAIN_FLG")
var mainFlag: Int? = null
/** Uživatelské jméno - username */
@Column(name = "LOGIN_NAME", length = 80)
var login: String? = null
@Column(name = "DOMAIN", length = 80)
var domain: String? = null
/** Kategorie úvazku */
@Column(name = "CATEGORY", length = 10, nullable = false)
var category: String = ""
/** Křestní jméno */
@Column(name = "FIRST_NAME", length = 30, nullable = false)
var firstName: String = ""
/** Příjmení */
@Column(name = "LAST_NAME", length = 40, nullable = false)
var lastName: String = ""
/** Datum ukončení vztahu */
@Column(name = "END_DATE_IN_ORG")
var endDate: LocalDate? = null
/** Emailová adresa */
@Column(name = "EMAIL", length = 250)
var email: String? = null
/** Telefonní číslo (na pevnou linku) */
@Column(name = "PHONE", length = 250)
var phone: String? = null
/** Číslo mobilního telefonu */
@Column(name = "MOBILE", length = 250)
var mobile: String? = null
/** Číslo organizační jednotky */
@Column(name = "ORG_UNIT_ID")
var orgUnitId: Int? = null
/** Příznak zda je o úvazek na centrále (1) nebo na pobočce (0) */
@Column(name = "IS_CKB")
var isCkbFlag: Int? = null
/** Firma - viz ciselnik [OrganizationCode] */
@Column(name = "ORGANIZATION_CODE", length = 4)
var organizationCode: String? = null
/** Název pracovní funkce */
@Column(name = "FUNCTION_NAME", length = 100)
var functionName: String? = null
/** Název pracovní funkce v anglickém jazyce */
@Column(name = "FUNCTION_NAME_EN", length = 100)
var functionNameEn: String? = null
/** Rotační skupina pro personal recovery účely - ABCD. */
@Column(name = "ROTATION_GROUP", length = 250)
var rotationGroup: String? = null
/** Cele jmeno */
val fullName = "$lastName $firstName"
override fun toString(): String {
return "<${this::class.simpleName} title=\"$firstName $lastName ($oscis)\" id=$id source=EGJE>"
}
override fun equals(other: Any?) = other is EgjePerson && oscis == other.oscis
override fun hashCode(): Int = oscis.hashCode()
}
and the error output in case of isAllQuotedIdentifiers = true (when set to false, the RETURNING column is only quoted once, but that’s not right either because it isn’t qouted when running the DDL, so the case differs)
2022-04-13 06:00:31.649 UTC [57] ERROR: column ""EMPLOYEE_LLR_ID"" does not exist at character 374
2022-04-13 06:00:31.649 UTC [57] HINT: Perhaps you meant to reference the column "EA_EMPLOYEE.EMPLOYEE_LLR_ID".
2022-04-13 06:00:31.649 UTC [57] STATEMENT: insert into "EA_EMPLOYEE" ("OSCIS", "LLR_SERIAL_NO", "MAIN_FLG", "LOGIN_NAME", "DOMAIN", "CATEGORY", "FIRST_NAME", "LAST_NAME", "END_DATE_IN_ORG", "EMAIL", "PHON
E", "MOBILE", "ORG_UNIT_ID", "IS_CKB", "ORGANIZATION_CODE", "FUNCTION_NAME", "FUNCTION_NAME_EN", "ROTATION_GROUP", full_name) values ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19)
RETURNING """EMPLOYEE_LLR_ID"""
There’s also one other strange problem you can notice here - why does it use the full_name as column? It’s not annotated with @Column. And it’s not quoted in the query even though quoting is on in this case.
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 15 (6 by maintainers)
Commits related to this issue
- #2647 - When Postgres + isAllQuotedIdentifiers true + using DataSourceConfig THEN `datasourceConfig.addProperty("quoteReturningIdentifiers", false);` I think there is not a case where we do NOT want ... — committed to ebean-orm/ebean by rbygrave 2 years ago
- Merge pull request #2681 from ebean-orm/feature/2647 #2647 - When Postgres + isAllQuotedIdentifiers true + using DataSourceConfig THEN `datasourceConfig.addProperty("quoteReturningIdentifiers", false... — committed to ebean-orm/ebean by rbygrave 2 years ago
Can confirm that after upgrading postgresql driver to v42.3 and adding
dataSourceConfig.addProperty("quoteReturningIdentifiers", false)the problem indeed goes away. Thank you so much for the help. And great job in general guys, I really love this ORM. Was using JPA before and never want to go back.@Incanus3 Yes, if you do not want
RETURNINGclause to be quoted, you have to set the datasource propertyquoteReturningIdentifierstofalseusingaddPropertybecause the default value in pgjdbc istrue.Yes, when ebean quotes everything, then the property must be false. Otherwise you can not save anything through ebean. So the PR is fine.
Nice. But I’d almost think you want this always on with postgre - if identifier quoting is off, why would you want to quote the returning ones?
On Tue, May 3, 2022, 3:39 AM Rob Bygrave @.***> wrote: