From 065d9dc55535b9e1cc2a7962b92f86f9cad2f1d7 Mon Sep 17 00:00:00 2001 From: NPCRUS Date: Mon, 7 Apr 2025 14:54:56 +0200 Subject: [PATCH 1/2] . --- scalasql/query/src/Returning.scala | 11 ++++- scalasql/test/src/ConcreteTestSuites.scala | 12 +++++- .../EscapedTableNameReturningTests.scala | 43 +++++++++++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 scalasql/test/src/query/EscapedTableNameReturningTests.scala diff --git a/scalasql/query/src/Returning.scala b/scalasql/query/src/Returning.scala index daef3213..136eb4e5 100644 --- a/scalasql/query/src/Returning.scala +++ b/scalasql/query/src/Returning.scala @@ -54,7 +54,16 @@ object Returning { override def queryIsSingleRow = false private[scalasql] override def renderSql(ctx0: Context) = { - implicit val implicitCtx = Context.compute(ctx0, Nil, Some(returnable.table)) + val contextStage1: Context = Context.compute(ctx0, Nil, Some(returnable.table)) + + implicit val implicitCtx: Context = if (returnable.table.value.escape) { + contextStage1.withFromNaming( + contextStage1.fromNaming + .updated(returnable.table, Table.fullIdentifier(returnable.table.value)(contextStage1)) + ) + } else { + contextStage1 + } val prefix = Renderable.renderSql(returnable) val walked = qr.walkLabelsAndExprs(expr) diff --git a/scalasql/test/src/ConcreteTestSuites.scala b/scalasql/test/src/ConcreteTestSuites.scala index 81099425..3eb10c21 100644 --- a/scalasql/test/src/ConcreteTestSuites.scala +++ b/scalasql/test/src/ConcreteTestSuites.scala @@ -30,7 +30,8 @@ import query.{ GetGeneratedKeysTests, WithCteTests, SchemaTests, - EscapedTableNameTests + EscapedTableNameTests, + EscapedTableNameWithReturningTests } import scalasql.dialects.{ MySqlDialectTests, @@ -63,6 +64,9 @@ package postgres { object GetGeneratedKeysTests extends GetGeneratedKeysTests with PostgresSuite object SchemaTests extends SchemaTests with PostgresSuite object EscapedTableNameTests extends EscapedTableNameTests with PostgresSuite + object EscapedTableNameWithReturningTests + extends EscapedTableNameWithReturningTests + with PostgresSuite object SubQueryTests extends SubQueryTests with PostgresSuite object WithCteTests extends WithCteTests with PostgresSuite @@ -109,6 +113,9 @@ package hikari { object GetGeneratedKeysTests extends GetGeneratedKeysTests with HikariSuite object SchemaTests extends SchemaTests with HikariSuite object EscapedTableNameTests extends EscapedTableNameTests with HikariSuite + object EscapedTableNameWithReturningTests + extends EscapedTableNameWithReturningTests + with HikariSuite object SubQueryTests extends SubQueryTests with HikariSuite object WithCteTests extends WithCteTests with HikariSuite @@ -220,6 +227,9 @@ package sqlite { // Sqlite doesn't support schemas // object SchemaTests extends SchemaTests with SqliteSuite object EscapedTableNameTests extends EscapedTableNameTests with SqliteSuite + object EscapedTableNameWithReturningTests + extends EscapedTableNameWithReturningTests + with SqliteSuite object DataTypesTests extends datatypes.DataTypesTests with SqliteSuite object OptionalTests extends datatypes.OptionalTests with SqliteSuite diff --git a/scalasql/test/src/query/EscapedTableNameReturningTests.scala b/scalasql/test/src/query/EscapedTableNameReturningTests.scala new file mode 100644 index 00000000..38a1064a --- /dev/null +++ b/scalasql/test/src/query/EscapedTableNameReturningTests.scala @@ -0,0 +1,43 @@ +package scalasql.query + +import scalasql._ +import scalasql.core.JoinNullable +import sourcecode.Text +import utest._ +import utils.ScalaSqlSuite + +import java.time.LocalDate +import scalasql.core.Config +import scalasql.dialects.ReturningDialect + +trait EscapedTableNameWithReturningTests extends ScalaSqlSuite { + this: ReturningDialect => + + def description = """ + If your table name is a reserved sql world, e.g. `order`, you can specify this in your table definition with + `override def escape = true` + """ + + def tests = Tests { + val tableNameEscaped = dialectSelf.escape(Config.camelToSnake(Table.name(Select))) + + test("insert with returning") { + checker( + query = Text { + Select.insert + .values( + Select[Sc]( + id = 0, + name = "hello" + ) + ) + .returning(_.id) + }, + sql = + s"INSERT INTO $tableNameEscaped (id, name) VALUES (?, ?) RETURNING $tableNameEscaped.id AS res", + value = Seq(0), + docs = "" + ) + } + } +} From a8fa63cac04a0b45f668f2c071c942cfdc8e7314 Mon Sep 17 00:00:00 2001 From: NPCRUS Date: Mon, 7 Apr 2025 18:51:28 +0200 Subject: [PATCH 2/2] update reference --- docs/reference.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/docs/reference.md b/docs/reference.md index fec74c0b..7220e9b3 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -7061,6 +7061,41 @@ Select.insert.values( +## EscapedTableNameWithReturning + + If your table name is a reserved sql world, e.g. `order`, you can specify this in your table definition with + `override def escape = true` + +### EscapedTableNameWithReturning.insert with returning + + + +```scala +Select.insert + .values( + Select[Sc]( + id = 0, + name = "hello" + ) + ) + .returning(_.id) +``` + + +* + ```sql + INSERT INTO "select" (id, name) VALUES (?, ?) RETURNING "select".id AS res + ``` + + + +* + ```scala + Seq(0) + ``` + + + ## SubQuery Queries that explicitly use subqueries (e.g. for `JOIN`s) or require subqueries to preserve the Scala semantics of the various operators ### SubQuery.sortTakeJoin