Skip to content

Commit

Permalink
Support schema name (#57)
Browse files Browse the repository at this point in the history
Hello folks, here I tried to add support for `schemaName` into `INSERT`,
`UPDATE`, `DELETE` and some sub variants of those. I feel 90% confused
about most of the stuff I see in the repo so far, but I wanted to start
somewhere, so I can gradually get a better understanding of what's going
on.

Here I implemented a `Table.resolve` function that should make a fully
qualified table name + schema if present + apply mapping from config,
maybe it can also be used further for #53
I also thought it's a good idea whenever `Table.Base` becomes `String`
to be used as a fully qualified name to not do any further processing
and mapping of this string
 Fixes #54

---------

Co-authored-by: nikitaglushchenko <[email protected]>
  • Loading branch information
NPCRUS and nikitaglushchenko authored Jan 8, 2025
1 parent 4213f04 commit ba5710e
Show file tree
Hide file tree
Showing 9 changed files with 323 additions and 33 deletions.
180 changes: 179 additions & 1 deletion docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -6276,7 +6276,7 @@ Buyer.select
## Schema
Additional tests to ensure schema mapping produces valid SQL
### Schema.schema
### Schema.schema.select
If your table belongs to a schema other than the default schema of your database,
you can specify this in your table definition with table.schemaName
Expand Down Expand Up @@ -6305,6 +6305,184 @@ Invoice.select
### Schema.schema.insert.columns
If your table belongs to a schema other than the default schema of your database,
you can specify this in your table definition with table.schemaName
```scala
Invoice.insert.columns(
_.total := 200.3,
_.vendor_name := "Huawei"
)
```
*
```sql
INSERT INTO otherschema.invoice (total, vendor_name) VALUES (?, ?)
```
*
```scala
1
```
### Schema.schema.insert.values
If your table belongs to a schema other than the default schema of your database,
you can specify this in your table definition with table.schemaName
```scala
Invoice.insert
.values(
Invoice[Sc](
id = 0,
total = 200.3,
vendor_name = "Huawei"
)
)
.skipColumns(_.id)
```
*
```sql
INSERT INTO otherschema.invoice (total, vendor_name) VALUES (?, ?)
```
*
```scala
1
```
### Schema.schema.update
If your table belongs to a schema other than the default schema of your database,
you can specify this in your table definition with table.schemaName
```scala
Invoice
.update(_.id === 1)
.set(
_.total := 200.3,
_.vendor_name := "Huawei"
)
```
*
```sql
UPDATE otherschema.invoice
SET
total = ?,
vendor_name = ?
WHERE
(invoice.id = ?)
```
*
```scala
1
```
### Schema.schema.delete
If your table belongs to a schema other than the default schema of your database,
you can specify this in your table definition with table.schemaName
```scala
Invoice.delete(_.id === 1)
```
*
```sql
DELETE FROM otherschema.invoice WHERE (invoice.id = ?)
```
*
```scala
1
```
### Schema.schema.insert into
If your table belongs to a schema other than the default schema of your database,
you can specify this in your table definition with table.schemaName
```scala
Invoice.insert.select(
i => (i.total, i.vendor_name),
Invoice.select.map(i => (i.total, i.vendor_name))
)
```
*
```sql
INSERT INTO
otherschema.invoice (total, vendor_name)
SELECT
invoice0.total AS res_0,
invoice0.vendor_name AS res_1
FROM
otherschema.invoice invoice0
```
*
```scala
4
```
### Schema.schema.join
If your table belongs to a schema other than the default schema of your database,
you can specify this in your table definition with table.schemaName
```scala
Invoice.select.join(Invoice)(_.id `=` _.id).map(_._1.id)
```
*
```sql
SELECT
invoice0.id AS res
FROM
otherschema.invoice invoice0
JOIN otherschema.invoice invoice1 ON (invoice0.id = invoice1.id)
```
*
```scala
Seq(2, 3, 4, 5, 6, 7, 8, 9)
```
## 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
Expand Down
4 changes: 2 additions & 2 deletions scalasql/query/src/Delete.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ object Delete {
}

class Renderer(table: TableRef, expr: Expr[Boolean], prevContext: Context) {
lazy val tableNameStr =
SqlStr.raw(prevContext.config.tableNameMapper(Table.name(table.value)))
implicit val implicitCtx: Context = Context.compute(prevContext, Nil, Some(table))
lazy val tableNameStr =
SqlStr.raw(Table.resolve(table.value))

def render() = sql"DELETE FROM $tableNameStr WHERE $expr"
}
Expand Down
7 changes: 2 additions & 5 deletions scalasql/query/src/From.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,8 @@ class TableRef(val value: Table.Base) extends From {
def fromExprAliases(prevContext: Context): Seq[(Expr.Identity, SqlStr)] = Nil

def renderSql(name: SqlStr, prevContext: Context, liveExprs: LiveExprs) = {
val schemaStr = value.schemaName match {
case "" => ""
case str => s"$str."
}
SqlStr.raw(schemaStr + prevContext.config.tableNameMapper(Table.name(value))) + sql" " + name
val resolvedTable = Table.resolve(value)(prevContext)
SqlStr.raw(resolvedTable + sql" " + name)
}
}

Expand Down
4 changes: 2 additions & 2 deletions scalasql/query/src/InsertColumns.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ object InsertColumns {
protected def expr: V[Column] = WithSqlExpr.get(insert)

private[scalasql] override def renderSql(ctx: Context) =
new Renderer(columns, ctx, valuesLists, Table.name(table.value)).render()
new Renderer(columns, ctx, valuesLists, Table.resolve(table.value)(ctx)).render()

override protected def queryConstruct(args: Queryable.ResultSetIterator): Int =
args.get(IntType)
Expand All @@ -48,7 +48,7 @@ object InsertColumns {
SqlStr.commaSep
)
def render() = {
sql"INSERT INTO ${SqlStr.raw(ctx.config.tableNameMapper(tableName))} ($columns) VALUES $values"
sql"INSERT INTO ${SqlStr.raw(tableName)} ($columns) VALUES $values"
}
}
}
4 changes: 2 additions & 2 deletions scalasql/query/src/InsertSelect.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ object InsertSelect {
def table = insert.table

private[scalasql] override def renderSql(ctx: Context) =
new Renderer(select, select.qr.walkExprs(columns), ctx, Table.name(table.value))
new Renderer(select, select.qr.walkExprs(columns), ctx, Table.resolve(table.value)(ctx))
.render()

override protected def queryConstruct(args: Queryable.ResultSetIterator): Int =
Expand All @@ -45,7 +45,7 @@ object InsertSelect {

lazy val selectSql = Renderable.renderSql(select).withCompleteQuery(false)

lazy val tableNameStr = SqlStr.raw(ctx.config.tableNameMapper(tableName))
lazy val tableNameStr = SqlStr.raw(tableName)
def render() = sql"INSERT INTO $tableNameStr ($columns) $selectSql"
}
}
4 changes: 2 additions & 2 deletions scalasql/query/src/InsertValues.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ object InsertValues {

override private[scalasql] def renderSql(ctx: Context): SqlStr = {
new Renderer(
Table.name(insert.table.value),
Table.resolve(insert.table.value)(ctx),
Table.labels(insert.table.value),
values,
qr,
Expand Down Expand Up @@ -75,7 +75,7 @@ object InsertValues {
lazy val values = SqlStr.join(valuesSqls, SqlStr.commaSep)

def render() = {
sql"INSERT INTO ${SqlStr.raw(ctx.config.tableNameMapper(tableName))} ($columns) VALUES $values"
sql"INSERT INTO ${SqlStr.raw(tableName)} ($columns) VALUES $values"
}
}
}
8 changes: 8 additions & 0 deletions scalasql/query/src/Table.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package scalasql.query

import scalasql.core.{DialectTypeMappers, Sc, Queryable, Expr}
import scalasql.core.Context

/**
* In-code representation of a SQL table, associated with a given `case class` [[V]].
Expand Down Expand Up @@ -49,6 +50,13 @@ object Table {
def name(t: Table.Base) = t.tableName
def labels(t: Table.Base) = t.tableLabels
def columnNameOverride[V[_[_]]](t: Table.Base)(s: String) = t.tableColumnNameOverride(s)
def resolve(t: Table.Base)(implicit context: Context) = {
val mappedTableName = context.config.tableNameMapper(t.tableName)
t.schemaName match {
case "" => mappedTableName
case str => s"$str." + mappedTableName
}
}
trait Base {

/**
Expand Down
2 changes: 1 addition & 1 deletion scalasql/query/src/Update.scala
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ object Update {
implicit lazy val implicitCtx: Context = Context.compute(prevContext, froms, Some(table))

lazy val tableName =
SqlStr.raw(implicitCtx.config.tableNameMapper(Table.name(table.value)))
SqlStr.raw(Table.resolve(table.value))

lazy val updateList = set0.map { case assign =>
val kStr = SqlStr.raw(prevContext.config.columnNameMapper(assign.column.name))
Expand Down
Loading

0 comments on commit ba5710e

Please sign in to comment.