-
Notifications
You must be signed in to change notification settings - Fork 697
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
support for native sql? #118
Comments
Hi @mvysny , thank you for warm words. About "native sql", you might try something like this: TransactionManager.current().exec("select u.name, c.name from user u inner join city c where blah blah") { rs ->
val result = arrayListOf<Pair<String, String>>()
while (rs.next()) {
result += rs.getString("u.name") to rs.getString("c.name")
}
result
}.forEeach { ... } or more generic fun <T:Any> String.execAndMap(transform : (ResultSet) -> T) : List<T> {
val result = arrayListOf<T>()
TransactionManager.current().exec("") { rs ->
while (rs.next()) {
result += transform(rs)
}
}
return result
}
"select u.name, c.name from user u inner join city c where blah blah".execAndMap { rs ->
rs.getString("u.name") to rs.getString("c.name")
} |
Hi @Tapac, thanks for the example. I think, however, there is a small error in the more generic one. The line
should be
in my opinion. |
@istvanszoboszlai you are right! To be honest I don't ran this code, so it not surprise that it contains bug:D Glad you find it. |
How can you prevent SQL injection if you use this approach, just passing in a raw string? |
@jsonbrooks , do not use user-provided data in such queries? |
It just seems like a very common use case to me if you do need custom native queries. Would it be possible to expose an exec method with a PreparedStatement as input instead? |
@jsonbrooks Also, it's not so hard to make such function and place it locally: fun Transaction.exec(sql: String, body: PreparedStatement.() -> Unit) : ResultSet? {
return connection.prepareStatement(sql).apply(body).run {
if (sql.toLowerCase().startsWith("select "))
executeQuery()
else {
executeUpdate()
resultSet
}
}
}
|
Would it be possible to define triggers in this way? |
@AdityaAnand1 , yes if you provide raw SQL with complete trigger creation text |
Wow, @Tapac, does it mean that you already work on adding support for async drivers? |
@istvanszoboszlai , yes, I have a plan to try support async drivers, but not sure how it should be implemented without making every function |
Excuse me. I don't know why show me the code as follows: My exposed version: <jetbrains.exposed.version>0.16.1</jetbrains.exposed.version> |
My solution: |
If you want to use ResultRow, (with the help of given code samples) we can perform transformation like below. fun FieldSet.nativeSelect(query: String): List<ResultRow> {
val fieldsIndex = realFields.toSet().mapIndexed { index, expression -> expression to index }.toMap()
val resultRows = mutableListOf<ResultRow>()
TransactionManager.current().exec(query) { resultSet ->
while (resultSet.next()) {
resultRows.add(ResultRow.create(resultSet, fieldsIndex))
}
}
return resultRows
}
private fun getResultRows(): List<ResultRow> {
val query = "..."
return SampleTable.nativeSelect(query)
} The only possible problem is // another alternative
// global object
val sampleTableFieldsIndex = SampleTable.realFields.toSet().mapIndexed { index, expression -> expression to index }.toMap()
fun nativeSelect(query: String, fieldsIndex: Map<Expression<*>, Int>): List<ResultRow> {
val resultRows = mutableListOf<ResultRow>()
TransactionManager.current().exec(query) { resultSet ->
while (resultSet.next()) {
resultRows.add(ResultRow.create(resultSet, fieldsIndex))
}
}
return resultRows
}
private fun getResultRows(): List<ResultRow> {
val query = "..."
return nativeSelect(query, sampleTableFieldsIndex)
} |
@akifb big thanks for after the some investigation I figured out that this code works only if you keep the order of columns in select query the same as in indexed query structure (that you use for mapping) based on this topic: https://stackoverflow.com/questions/62786434/how-to-convert-kotline-exposed-resultset-to-entity
So my final code looks like that:
|
@jsonbrooks Did you ever find a way to get |
Exposed looks great! Yet at some point I fear that some complex queries will not be representable by Kotlin magic. And, frankly,
Is too high-level magic for my tired brain :-)
I would prefer something like this for complex queries (you know one of those queries hand-tuned for perfection, which runs only 5 hours instead of 10 weeks):
Anyway, thanks for a fresh wind in the stale waters of JPA ;) It's good to have a framework where I can represent tables with objects, but without the 1st level cache/LazyInitializationException/other goodies from the JPA world. Yet, I want to be in charge of creating/migrating tables (of the DDL), and of queries more complex than "gimme all users in this city".
The text was updated successfully, but these errors were encountered: