diff --git a/sqlest/src/main/scala/sqlest/executor/Database.scala b/sqlest/src/main/scala/sqlest/executor/Database.scala index a69a61d..12a4ead 100644 --- a/sqlest/src/main/scala/sqlest/executor/Database.scala +++ b/sqlest/src/main/scala/sqlest/executor/Database.scala @@ -83,7 +83,7 @@ class Session(database: Database) extends Logging { def executeSelect[A](select: Select[_, _])(extractor: ResultSet => A): A = withConnection { connection => - val (preprocessedSelect, sql, argumentLists) = database.statementBuilder(select) + val (preprocessedSelect, sql, argumentLists, prettySql) = database.statementBuilder(select) try { val startTime = new DateTime val preparedStatement = prepareStatement(connection, preprocessedSelect, sql, argumentLists) @@ -92,7 +92,7 @@ class Session(database: Database) extends Logging { try { val result = extractor(resultSet) val endTime = new DateTime - logger.info(s"Ran sql in ${endTime.getMillis - startTime.getMillis}ms: ${logDetails(connection, sql, argumentLists)}") + logger.info(s"Ran sql in ${endTime.getMillis - startTime.getMillis}ms: ${logDetails(connection, prettySql, argumentLists)}") result } finally { try { @@ -177,11 +177,16 @@ class Session(database: Database) extends Logging { protected def logDetails(connection: Connection, sql: String, argumentLists: List[List[LiteralColumn[_]]]) = { val connectionLog = database.connectionDescription.map(connectionDescription => s", connection [${connectionDescription(connection)}]").getOrElse("") + val argumentsLog = if (argumentLists.size == 1) argumentLists.head.map(_.value).mkString(", ") else argumentLists.map(_.map(_.value).mkString("(", ", ", ")")).mkString(", ") - s"sql [$sql], arguments [$argumentsLog]${connectionLog}" + s"""sql [ + | + |$sql + | + |], arguments [$argumentsLog]${connectionLog}""".stripMargin } } @@ -265,14 +270,14 @@ case class Transaction(database: Database) extends Session(database) { def executeCommand(command: Command): Int = withConnection { connection => - val (preprocessedCommand, sql, argumentLists) = database.statementBuilder(command) + val (preprocessedCommand, sql, argumentLists, prettySql) = database.statementBuilder(command) val startTime = new DateTime try { val preparedStatement = prepareStatement(connection, preprocessedCommand, sql, argumentLists) try { val result = preparedStatement.executeBatch.sum val endTime = new DateTime - logger.info(s"Ran sql in ${endTime.getMillis - startTime.getMillis}ms: ${logDetails(connection, sql, argumentLists)}") + logger.info(s"Ran sql in ${endTime.getMillis - startTime.getMillis}ms: ${logDetails(connection, prettySql, argumentLists)}") result } finally { try { @@ -288,7 +293,7 @@ case class Transaction(database: Database) extends Session(database) { def executeInsertReturningKeys[T](command: Insert)(implicit columnType: ColumnType[T]): List[T] = withConnection { connection => - val (preprocessedCommand, sql, argumentLists) = database.statementBuilder(command) + val (preprocessedCommand, sql, argumentLists, prettySql) = database.statementBuilder(command) val startTime = new DateTime try { val preparedStatement = prepareStatement( @@ -303,7 +308,7 @@ case class Transaction(database: Database) extends Session(database) { val rs = preparedStatement.getGeneratedKeys val keys = IndexedExtractor[T](1).extractAll(ResultSetIterable(rs)) val endTime = new DateTime - logger.info(s"Ran sql in ${endTime.getMillis - startTime.getMillis}ms: ${logDetails(connection, sql, argumentLists)}") + logger.info(s"Ran sql in ${endTime.getMillis - startTime.getMillis}ms: ${logDetails(connection, prettySql, argumentLists)}") keys } finally { try { diff --git a/sqlest/src/main/scala/sqlest/sql/DB2StatementBuilder.scala b/sqlest/src/main/scala/sqlest/sql/DB2StatementBuilder.scala index 6636ae3..ae71ebb 100644 --- a/sqlest/src/main/scala/sqlest/sql/DB2StatementBuilder.scala +++ b/sqlest/src/main/scala/sqlest/sql/DB2StatementBuilder.scala @@ -56,12 +56,12 @@ trait DB2StatementBuilder extends base.StatementBuilder { case mappedColumnType: MappedColumnType[_, _] => castLiteralSql(mappedColumnType.baseColumnType) } - override def selectSql(select: Select[_, _ <: Relation]): String = { + override def selectSql(select: Select[_, _ <: Relation], indent: Int): String = { val offset = select.offset getOrElse 0L if (offset > 0L) { - rowNumberSelectSql(select, offset, select.limit) + rowNumberSelectSql(select, offset, select.limit, indent) } else { - super.selectSql(select) + super.selectSql(select, indent) } } @@ -71,40 +71,62 @@ trait DB2StatementBuilder extends base.StatementBuilder { override def selectOffsetSql(offset: Option[Long]): Option[String] = None - override def joinSql(relation: Relation): String = relation match { - case tableFunctionApplication: TableFunctionApplication[_] => "table(" + functionSql(tableFunctionApplication.tableName, tableFunctionApplication.parameterColumns.map(addTypingToSqlColumn)) + ") as " + identifierSql(tableFunctionApplication.tableAlias) - case TableFunctionFromSelect(select, alias) => "table(" + selectSql(select) + ") as " + identifierSql(alias) - case LeftExceptionJoin(left, right, condition) => joinSql(left) + " left exception join " + joinSql(right) + " on " + columnSql(condition) - case RightExceptionJoin(left, right, condition) => joinSql(left) + " right exception join " + joinSql(right) + " on " + columnSql(condition) - case _ => super.joinSql(relation) + override def joinSql(relation: Relation, indent: Int): String = relation match { + case tableFunctionApplication: TableFunctionApplication[_] => "table(" + functionSql(tableFunctionApplication.tableName, tableFunctionApplication.parameterColumns.map(addTypingToSqlColumn), indent) + ") as " + identifierSql(tableFunctionApplication.tableAlias) + case TableFunctionFromSelect(select, alias) => + "table(" + + onNewLine(selectSql(select, indent + TabWidth), indent + TabWidth) + + onNewLine(") as " + identifierSql(alias), indent) + case LeftExceptionJoin(left, right, condition) => + joinSql(left, indent) + + onNewLine("left exception join ", indent) + + joinSql(right, indent) + + onNewLine("on ", indent) + + columnSql(condition, indent) + case RightExceptionJoin(left, right, condition) => + joinSql(left, indent) + + onNewLine("right exception join ", indent) + + joinSql(right, indent) + + onNewLine("on ", indent) + + columnSql(condition, indent) + case _ => super.joinSql(relation, indent) } - def rowNumberSelectSql(select: Select[_, _ <: Relation], offset: Long, limit: Option[Long]): String = { + def rowNumberSelectSql(select: Select[_, _ <: Relation], offset: Long, limit: Option[Long], indent: Int): String = { + val orderBy = selectOrderBySql(select.orderBy, indent).getOrElse("") + val whatColumns = Seq(selectWhatSql(select.columns, indent + TabWidth), s"row_number() over ($orderBy) as rownum") + val whatSql = withLineBreaks(whatColumns, indent + (TabWidth * 2))("", ", ", "") + val subquery = Seq( - s"${selectWhatSql(select.columns)}, row_number() over (${selectOrderBySql(select.orderBy) getOrElse ""}) as rownum", - selectFromSql(select.from) + whatSql, + selectFromSql(select.from, indent + TabWidth) ) ++ Seq( - selectWhereSql(select.where), - selectGroupBySql(select.groupBy) - ).flatten mkString " " + selectWhereSql(select.where, indent + TabWidth), + selectGroupBySql(select.groupBy, indent + TabWidth) + ).flatten mkString (NewLine + padding(indent + TabWidth)) val what = - select.columns map (col => identifierSql(col.columnAlias)) mkString ", " + withLineBreaks(select.columns.map(col => identifierSql(col.columnAlias)), indent)("", ", ", "") val bounds = limit .map(limit => s"rownum between ? and ?") .getOrElse(s"rownum >= ?") - s"with subquery as ($subquery) select $what from subquery where $bounds" + s"with subquery as (" + + onNewLine(subquery, indent + TabWidth) + + onNewLine(")", indent) + + onNewLine(s"select $what", indent) + + onNewLine("from subquery", indent) + + onNewLine(s"where $bounds", indent) } - override def columnSql(column: Column[_]): String = + override def columnSql(column: Column[_], indent: Int): String = column match { case literalColumn: LiteralColumn[_] if literalColumn.columnType == BooleanColumnType => if (literalColumn.value == true) "(? = ?)" else "(? <> ?)" case constantColumn: ConstantColumn[_] if constantColumn.columnType == BooleanColumnType => if (constantColumn.value == true) "(0 = 0)" else "(0 <> 0)" - case _ => super.columnSql(column) + case _ => super.columnSql(column, indent) } override def selectArgs(select: Select[_, _ <: Relation]): List[LiteralColumn[_]] = { diff --git a/sqlest/src/main/scala/sqlest/sql/H2StatementBuilder.scala b/sqlest/src/main/scala/sqlest/sql/H2StatementBuilder.scala index 7770e72..84a87b5 100644 --- a/sqlest/src/main/scala/sqlest/sql/H2StatementBuilder.scala +++ b/sqlest/src/main/scala/sqlest/sql/H2StatementBuilder.scala @@ -19,9 +19,9 @@ package sqlest.sql import sqlest.ast._ trait H2StatementBuilder extends base.StatementBuilder { - override def groupSql(group: Group): String = group match { + override def groupSql(group: Group, indent: Int): String = group match { case group: FunctionGroup => throw new UnsupportedOperationException - case group => super.groupSql(group) + case group => super.groupSql(group, indent) } } diff --git a/sqlest/src/main/scala/sqlest/sql/base/BaseStatementBuilder.scala b/sqlest/src/main/scala/sqlest/sql/base/BaseStatementBuilder.scala index 0b31f79..014f99c 100644 --- a/sqlest/src/main/scala/sqlest/sql/base/BaseStatementBuilder.scala +++ b/sqlest/src/main/scala/sqlest/sql/base/BaseStatementBuilder.scala @@ -20,6 +20,10 @@ import sqlest.ast._ import sqlest.ast.operations.ColumnOperations._ trait BaseStatementBuilder { + val MaxWidth = 40 + val TabWidth = 4 + val NewLine = System.lineSeparator + def preprocess(operation: Operation): Operation = aliasColumnsFromSubselects(operation) @@ -61,95 +65,152 @@ trait BaseStatementBuilder { case Lateral(select: Select[_, _]) => List(select) ++ findSubselects(select.from) } - def columnAliasListSql(columns: Seq[Column[_]]): String = - columns.map(column => columnAliasSql(column)).mkString(", ") + def padding(indent: Int): String = " " * indent + + def onNewLine(str: String, indent: Int): String = + if (str.isEmpty) str + else NewLine + padding(indent) + str + + def withLineBreaks(strs: Seq[String], indent: Int)(initial: String, separator: String, terminator: String) = { + if (strs.isEmpty) + initial + terminator + else { + val first = initial + strs.head + + val (sql, _) = strs.tail.foldLeft((first, first.length)) { + case ((sql, len), next) => + val nextLen = next.length + val newLen = len + separator.length + nextLen + if (newLen <= MaxWidth) + (sql + separator + next, newLen) + else + (sql + separator + onNewLine(next, indent), indent + nextLen) + } + + sql + terminator + } + } + + def columnAliasListSql(columns: Seq[Column[_]], indent: Int): String = { + val columnList = columns.map(column => columnAliasSql(column, indent)) - def columnAliasSql(column: Column[_]): String = column match { + if (columnList.isEmpty) + "" + else + withLineBreaks(columnList, indent)("", ", ", "") + } + + def columnAliasSql(column: Column[_], indent: Int): String = column match { case column: TableColumn[_] => - columnSql(column) + " as " + + columnSql(column, indent) + " as " + identifierSql(column.columnAlias) case column: AliasColumn[_] => - columnSql(column) + " as " + + columnSql(column, indent) + " as " + identifierSql(column.columnAlias) case column => - columnSql(column) + columnSql(column, indent) } - def columnSql(column: Column[_]): String = - // findCellExtractorInRelation(column).getOrElse( + def columnSql(column: Column[_], indent: Int): String = column match { - case LiteralColumn(literal) => literalSql(literal) + case LiteralColumn(literal) => literalSql(literal, indent) case column: ConstantColumn[_] => constantSql(column.columnType, column.value) - case column: PrefixFunctionColumn[_] => prefixSql(column.name, column.parameter) - case column: InfixFunctionColumn[_] => infixSql(column.name, column.parameter1, column.parameter2) - case column: PostfixFunctionColumn[_] => postfixSql(column.name, column.parameter) - case column: DoubleInfixFunctionColumn[_] => doubleInfixSql(column.infix1, column.infix2, column.parameter1, column.parameter2, column.parameter3) - case SelectColumn(select) => "(" + selectSql(select) + ")" - case ExistsColumn(select) => "exists (" + selectSql(aliasColumnsFromSubselects(select).asInstanceOf[Select[_, _ <: Relation]]) + ")" - case NotExistsColumn(select) => "not exists (" + selectSql(aliasColumnsFromSubselects(select).asInstanceOf[Select[_, _ <: Relation]]) + ")" - case WindowFunctionColumn(partitionByColumns, orders) => windowFunctionSql(partitionByColumns, orders) - case column: ScalarFunctionColumn[_] => functionSql(column.name, column.parameters) + case column: PrefixFunctionColumn[_] => prefixSql(column.name, column.parameter, indent) + case column: InfixFunctionColumn[_] => infixSql(column.name, column.parameter1, column.parameter2, indent) + case column: PostfixFunctionColumn[_] => postfixSql(column.name, column.parameter, indent) + case column: DoubleInfixFunctionColumn[_] => doubleInfixSql(column.infix1, column.infix2, column.parameter1, column.parameter2, column.parameter3, indent) + case SelectColumn(select) => "(" + + onNewLine(selectSql(select, indent + TabWidth), indent + TabWidth) + + onNewLine(")", indent) + case ExistsColumn(select) => "exists (" + + onNewLine(selectSql(aliasColumnsFromSubselects(select).asInstanceOf[Select[_, _ <: Relation]], indent + TabWidth), indent + TabWidth) + + onNewLine(")", indent) + case NotExistsColumn(select) => "not exists (" + + onNewLine(selectSql(aliasColumnsFromSubselects(select).asInstanceOf[Select[_, _ <: Relation]], indent + TabWidth), indent + TabWidth) + + onNewLine(")", indent) + case WindowFunctionColumn(partitionByColumns, orders) => + windowFunctionSql(partitionByColumns, orders, indent) + case column: ScalarFunctionColumn[_] => functionSql(column.name, column.parameters, indent) case column: KeywordFunctionColumn[_] => column.name case column: TableColumn[_] => identifierSql(column.tableAlias) + "." + identifierSql(column.columnName) - case column: AliasColumn[_] => columnSql(column.column) + case column: AliasColumn[_] => columnSql(column.column, indent) case column: ReferenceColumn[_] => column.columnAlias - case column: CaseWhenColumn[_] => caseSql(column.whens, None) - case column: CaseWhenElseColumn[_] => caseSql(column.whens, Some(column.`else`)) - case column: CaseColumnColumn[_, _] => caseColumnSql(column.column, column.mappings, None) - case column: CaseColumnElseColumn[_, _] => caseColumnSql(column.column, column.mappings, Some(column.`else`)) + case column: CaseWhenColumn[_] => caseSql(column.whens, None, indent) + case column: CaseWhenElseColumn[_] => caseSql(column.whens, Some(column.`else`), indent) + case column: CaseColumnColumn[_, _] => caseColumnSql(column.column, column.mappings, None, indent) + case column: CaseColumnElseColumn[_, _] => caseColumnSql(column.column, column.mappings, Some(column.`else`), indent) } - def selectSql(select: Select[_, _ <: Relation]): String + def selectSql(select: Select[_, _ <: Relation], indent: Int): String + + def prefixSql(op: String, parameter: Column[_], indent: Int): String = + s"($op ${columnSql(parameter, indent)})" - def prefixSql(op: String, parameter: Column[_]): String = - s"($op ${columnSql(parameter)})" + def infixSql(op: String, parameter1: Column[_], parameter2: Column[_], indent: Int): String = + if (op.isEmpty) + s"(${columnSql(parameter1, indent)} ${columnSql(parameter2, indent)})" + else + s"(${columnSql(parameter1, indent)} $op ${columnSql(parameter2, indent)})" - def infixSql(op: String, parameter1: Column[_], parameter2: Column[_]): String = - s"(${columnSql(parameter1)} $op ${columnSql(parameter2)})" + def postfixSql(op: String, parameter: Column[_], indent: Int): String = + s"${columnSql(parameter, indent)} $op" - def postfixSql(op: String, parameter: Column[_]): String = - s"${columnSql(parameter)} $op" + def doubleInfixSql(op1: String, op2: String, parameter1: Column[_], parameter2: Column[_], parameter3: Column[_], indent: Int): String = + s"(${columnSql(parameter1, indent)} $op1 ${columnSql(parameter2, indent)} $op2 ${columnSql(parameter3, indent)})" - def doubleInfixSql(op1: String, op2: String, parameter1: Column[_], parameter2: Column[_], parameter3: Column[_]): String = - s"(${columnSql(parameter1)} $op1 ${columnSql(parameter2)} $op2 ${columnSql(parameter3)})" + def functionSql(op: String, parameters: Seq[Column[_]], indent: Int): String = { + val paramList = parameters.map(parameter => columnSql(parameter, indent)) + withLineBreaks(paramList, indent)(s"$op(", ", ", ")") + } - def functionSql(op: String, parameters: Seq[Column[_]]): String = - parameters.map(parameter => columnSql(parameter)).mkString(s"$op(", ", ", ")") + def windowFunctionSql(partitions: Seq[Column[_]], orders: Seq[Order], indent: Int) = { + val partitionList = partitions.map(column => columnSql(column, indent)) - def windowFunctionSql(partitionByColumns: Seq[Column[_]], orders: Seq[Order]) = { val partitionBy = - if (partitionByColumns.isEmpty) "" - else s"partition by ${partitionByColumns.map(column => columnSql(column)).mkString(", ")}" + if (partitionList.isEmpty) "" + else withLineBreaks(partitionList.tail, indent)(s"partition by ${partitionList.head}", ", ", "") + + val orderList = orders.map(order => orderSql(order, indent)) val orderBy = if (orders.isEmpty) "" - else s"order by ${orderListSql(orders)}" + else withLineBreaks(orderList.tail, indent)(s"order by ${orderList.head}", ", ", "") - (partitionBy + " " + orderBy).trim + List(partitionBy, orderBy).filterNot(_.isEmpty).mkString(" ") } - def orderListSql(orders: Seq[Order]) = - orders.map(order => orderSql(order)).mkString(", ") + def orderListSql(orders: Seq[Order], indent: Int) = { + val orderList = orders.map(order => orderSql(order, indent)) + if (orders.isEmpty) "" + else withLineBreaks(orderList, indent)("", ", ", "") + } - def groupListSql(groups: Seq[Group]) = - groups.map(group => groupSql(group)).mkString(", ") + def groupListSql(groups: Seq[Group], indent: Int) = { + val groupList = groups.map(group => groupSql(group, indent)) + if (groups.isEmpty) "" + else withLineBreaks(groupList, indent + TabWidth)("", ", ", "") + } - def orderSql(order: Order) = + def orderSql(order: Order, indent: Int) = if (order.ascending) - columnSql(order.column) + columnSql(order.column, indent) else - columnSql(order.column) + " desc" - - def groupSql(group: Group): String = group match { - case group: ColumnGroup => columnSql(group.column) - case group: TupleGroup => group.groups.map(group => groupSql(group)).mkString("(", ", ", ")") - case group: FunctionGroup => group.name + "(" + group.groups.map(group => groupSql(group)).mkString(", ") + ")" + columnSql(order.column, indent) + " desc" + + def groupSql(group: Group, indent: Int): String = group match { + case group: ColumnGroup => + columnSql(group.column, indent) + case group: TupleGroup => + val groupList = group.groups.map(group => groupSql(group, indent)) + withLineBreaks(groupList, indent + TabWidth)("(", ", ", ")") + case group: FunctionGroup => + val groupList = group.groups.map(group => groupSql(group, indent)) + withLineBreaks(groupList, indent + TabWidth)(group.name + "(", ", ", ")") } - def literalSql[A](literal: A) = - "?" + def literalSql[A](literal: A) = "?" def constantSql[A](columnType: ColumnType[A], value: A): String = columnType match { case BooleanColumnType => value.toString @@ -175,16 +236,24 @@ trait BaseStatementBuilder { def escapeSqlString(string: String) = string.replace("'", "''") - def caseSql(whens: List[When[_]], `else`: Option[Column[_]]) = { - val whenSql = whens.map(when => s"when ${columnSql(when.condition)} then ${columnSql(when.result)}").mkString(" ") - val elseSql = `else`.map(`else` => s"else ${columnSql(`else`)} ").getOrElse("") - s"case $whenSql ${elseSql}end" + def caseSql(whens: List[When[_]], `else`: Option[Column[_]], indent: Int) = { + val whenSql = whens.map(when => s"when ${columnSql(when.condition, indent + TabWidth)} then ${columnSql(when.result, indent)}").mkString(NewLine + padding(indent + TabWidth)) + val elseSql = `else`.map(`else` => s"else ${columnSql(`else`, indent + TabWidth)} ").getOrElse("") + + onNewLine(s"case", indent) + + onNewLine(whenSql, indent + TabWidth) + + onNewLine(elseSql, indent + TabWidth) + + onNewLine("end", indent) } - def caseColumnSql(column: Column[_], mappings: List[(Column[_], Column[_])], `else`: Option[Column[_]]) = { - val whenSql = mappings.map(mapping => s"when ${columnSql(mapping._1)} then ${columnSql(mapping._2)}").mkString(" ") - val elseSql = `else`.map(`else` => s"else ${columnSql(`else`)} ").getOrElse("") - s"case ${columnSql(column)} $whenSql ${elseSql}end" + def caseColumnSql(column: Column[_], mappings: List[(Column[_], Column[_])], `else`: Option[Column[_]], indent: Int) = { + val whenSql = mappings.map(mapping => s"when ${columnSql(mapping._1, indent)} then ${columnSql(mapping._2, indent)}").mkString(NewLine + padding(indent + TabWidth)) + val elseSql = `else`.map(`else` => s"else ${columnSql(`else`, indent)} ").getOrElse("") + + s"case ${columnSql(column, indent)}" + + onNewLine(whenSql, indent + TabWidth) + + onNewLine(elseSql, indent + TabWidth) + + onNewLine("end", indent) } // ------------------------------------------------- diff --git a/sqlest/src/main/scala/sqlest/sql/base/DeleteStatementBuilder.scala b/sqlest/src/main/scala/sqlest/sql/base/DeleteStatementBuilder.scala index 26b4dd6..e697f34 100644 --- a/sqlest/src/main/scala/sqlest/sql/base/DeleteStatementBuilder.scala +++ b/sqlest/src/main/scala/sqlest/sql/base/DeleteStatementBuilder.scala @@ -19,20 +19,19 @@ package sqlest.sql.base import sqlest.ast._ trait DeleteStatementBuilder extends BaseStatementBuilder { - def deleteSql(delete: Delete): String = { + def deleteSql(delete: Delete, indent: Int): String = { Seq( - "delete", - deleteFromSql(delete.from) + "delete " + deleteFromSql(delete.from) ) ++ Seq( - deleteWhereSql(delete.where) - ).flatten mkString ("", " ", "") + deleteWhereSql(delete.where, indent) + ).flatten mkString (NewLine + padding(indent)) } def deleteFromSql(from: Table): String = s"from ${identifierSql(from.tableName)}" - def deleteWhereSql(where: Option[Column[Boolean]]): Option[String] = - where map (where => s"where ${columnSql(where)}") + def deleteWhereSql(where: Option[Column[Boolean]], indent: Int): Option[String] = + where map (where => s"where ${columnSql(where, indent)}") // ------------------------------------------------- diff --git a/sqlest/src/main/scala/sqlest/sql/base/InsertStatementBuilder.scala b/sqlest/src/main/scala/sqlest/sql/base/InsertStatementBuilder.scala index a33e3d5..1abc527 100644 --- a/sqlest/src/main/scala/sqlest/sql/base/InsertStatementBuilder.scala +++ b/sqlest/src/main/scala/sqlest/sql/base/InsertStatementBuilder.scala @@ -21,21 +21,26 @@ import sqlest.ast._ trait InsertStatementBuilder extends BaseStatementBuilder { selectStatementBuilder: SelectStatementBuilder => - def insertSql(insert: Insert): String = insert match { + def insertSql(insert: Insert, indent: Int): String = insert match { case insert: InsertValues => - s"insert ${insertIntoSql(insert.into)} ${insertColumnsSql(insert.columns)} ${insertValuesSql(insert.columns)}" + val insertColumns = insertColumnsSql(insert.columns) + val insertValues = insertValuesSql(insert.columns) + withLineBreaks(insertColumns, indent + TabWidth)(s"insert ${insertIntoSql(insert.into)} (", ", ", ")") + + onNewLine(withLineBreaks(insertValues, indent + 7)(s"values (", ", ", ")"), indent) case InsertFromSelect(into, columns, select) => - s"insert ${insertIntoSql(into)} ${insertColumnsSql(columns)} ${selectStatementBuilder.selectSql(select)}" + val insertColumns = insertColumnsSql(columns) + val insertValues = insertValuesSql(columns) + withLineBreaks(insertColumns, indent + TabWidth)(s"insert ${insertIntoSql(into)} (", ", ", ")") + + onNewLine(selectStatementBuilder.selectSql(select, indent), indent) } def insertIntoSql(into: Table): String = s"into ${identifierSql(into.tableName)}" - def insertColumnsSql(columns: Seq[TableColumn[_]]): String = - columns map (column => identifierSql(column.columnName)) mkString ("(", ", ", ")") + def insertColumnsSql(columns: Seq[TableColumn[_]]): Seq[String] = + columns.map(column => identifierSql(column.columnName)) - def insertValuesSql(columns: Seq[TableColumn[_]]): String = - columns.map(_ => "?") mkString ("values (", ", ", ")") + def insertValuesSql(columns: Seq[TableColumn[_]]): Seq[String] = columns.map(_ => "?") // ------------------------------------------------- diff --git a/sqlest/src/main/scala/sqlest/sql/base/SelectStatementBuilder.scala b/sqlest/src/main/scala/sqlest/sql/base/SelectStatementBuilder.scala index c62febc..0e84394 100644 --- a/sqlest/src/main/scala/sqlest/sql/base/SelectStatementBuilder.scala +++ b/sqlest/src/main/scala/sqlest/sql/base/SelectStatementBuilder.scala @@ -19,46 +19,46 @@ package sqlest.sql.base import sqlest.ast._ trait SelectStatementBuilder extends BaseStatementBuilder { - def selectSql(select: Select[_, _ <: Relation]): String = { + def selectSql(select: Select[_, _ <: Relation], indent: Int): String = { Seq( - selectWhatSql(select.columns), - selectFromSql(select.from) + selectWhatSql(select.columns, indent), + selectFromSql(select.from, indent) ) ++ Seq( - selectWhereSql(select.where), - selectStartWithSql(select.startWith), - selectConnectBySql(select.connectBy), - selectGroupBySql(select.groupBy), - selectHavingSql(select.having), - selectOrderBySql(select.orderBy), + selectWhereSql(select.where, indent), + selectStartWithSql(select.startWith, indent), + selectConnectBySql(select.connectBy, indent), + selectGroupBySql(select.groupBy, indent), + selectHavingSql(select.having, indent), + selectOrderBySql(select.orderBy, indent), selectLimitSql(select.limit), selectOffsetSql(select.offset), - selectUnionSql(select.union) - ).flatten mkString (" ") + selectUnionSql(select.union, indent) + ).flatten mkString (NewLine + padding(indent)) } - def selectWhatSql(columns: Seq[Column[_]]): String = - s"select ${columnAliasListSql(columns)}" + def selectWhatSql(columns: Seq[Column[_]], indent: Int): String = + s"select ${columnAliasListSql(columns, indent + TabWidth)}" - def selectFromSql(from: Relation): String = - s"from ${joinSql(from)}" + def selectFromSql(from: Relation, indent: Int): String = + s"from ${joinSql(from, indent)}" - def selectWhereSql(where: Option[Column[Boolean]]): Option[String] = - where map (where => s"where ${columnSql(where)}") + def selectWhereSql(where: Option[Column[Boolean]], indent: Int): Option[String] = + where map (where => s"where ${columnSql(where, indent)}") - def selectStartWithSql(startWith: Option[Column[Boolean]]): Option[String] = - startWith map (startWith => s"start with ${columnSql(startWith)}") + def selectStartWithSql(startWith: Option[Column[Boolean]], indent: Int): Option[String] = + startWith map (startWith => s"start with ${columnSql(startWith, indent)}") - def selectConnectBySql(connectBy: Option[Column[Boolean]]): Option[String] = - connectBy map (connectBy => s"connect by ${columnSql(connectBy)}") + def selectConnectBySql(connectBy: Option[Column[Boolean]], indent: Int): Option[String] = + connectBy map (connectBy => s"connect by ${columnSql(connectBy, indent)}") - def selectGroupBySql(group: Seq[Group]): Option[String] = - if (group.isEmpty) None else Some(s"group by ${groupListSql(group)}") + def selectGroupBySql(group: Seq[Group], indent: Int): Option[String] = + if (group.isEmpty) None else Some(s"group by ${groupListSql(group, indent)}") - def selectHavingSql(having: Option[Column[Boolean]]): Option[String] = - having map (having => s"having ${columnSql(having)}") + def selectHavingSql(having: Option[Column[Boolean]], indent: Int): Option[String] = + having map (having => s"having ${columnSql(having, indent)}") - def selectOrderBySql(order: Seq[Order]): Option[String] = - if (order.isEmpty) None else Some(s"order by ${orderListSql(order)}") + def selectOrderBySql(order: Seq[Order], indent: Int): Option[String] = + if (order.isEmpty) None else Some(s"order by ${orderListSql(order, indent)}") def selectLimitSql(limit: Option[Long]): Option[String] = limit map (limit => s"limit ${literalSql(limit)}") @@ -66,35 +66,67 @@ trait SelectStatementBuilder extends BaseStatementBuilder { def selectOffsetSql(offset: Option[Long]): Option[String] = offset map (offset => s"offset ${literalSql(offset)}") - def selectUnionSql(union: Seq[Union[_]]): Option[String] = - if (union.isEmpty) None else + def selectUnionSql(union: Seq[Union[_]], indent: Int): Option[String] = + if (union.isEmpty) + None + else Some(union.map { - case Union(select, false) => s"union ${selectSql(select)}" - case Union(select, true) => s"union all ${selectSql(select)}" - }.mkString(" ")) + case Union(select, false) => s"union" + onNewLine(selectSql(select, indent), indent) + case Union(select, true) => s"union all" + onNewLine(selectSql(select, indent), indent) + }.mkString(NewLine + padding(indent))) - def joinSql(relation: Relation): String = relation match { + def joinSql(relation: Relation, indent: Int): String = relation match { case table: Table if table.tableName == table.tableAlias => identifierSql(table.tableName) case table: Table if table.tableName != table.tableAlias => identifierSql(table.tableName) + " as " + identifierSql(table.tableAlias) - case tableFunctionApplication: TableFunctionApplication[_] => functionSql(tableFunctionApplication.tableName, tableFunctionApplication.parameterColumns) + " as " + identifierSql(tableFunctionApplication.tableAlias) - case TableFunctionFromSelect(select, alias) => throw new UnsupportedOperationException - case LeftJoin(left, right, condition) => joinSql(left) + " left join " + joinSql(right) + " on " + columnSql(condition) - case LeftExceptionJoin(left, right, condition) => throw new UnsupportedOperationException - case RightJoin(left, right, condition) => joinSql(left) + " right join " + joinSql(right) + " on " + columnSql(condition) - case RightExceptionJoin(left, right, condition) => throw new UnsupportedOperationException - case InnerJoin(left, right, condition) => joinSql(left) + " inner join " + joinSql(right) + " on " + columnSql(condition) - case OuterJoin(left, right, condition) => joinSql(left) + " full outer join " + joinSql(right) + " on " + columnSql(condition) - case CrossJoin(left, right) => joinSql(left) + " cross join " + joinSql(right) - case select: Select[_, _] => subselectSql(select) - case Lateral(select: Select[_, _]) => "lateral " + subselectSql(select) + case tableFunctionApplication: TableFunctionApplication[_] => functionSql(tableFunctionApplication.tableName, tableFunctionApplication.parameterColumns, indent) + " as " + identifierSql(tableFunctionApplication.tableAlias) + case TableFunctionFromSelect(select, alias) => + throw new UnsupportedOperationException + case LeftJoin(left, right, condition) => + joinSql(left, indent) + + onNewLine("left join ", indent) + + joinSql(right, indent) + + onNewLine("on ", indent) + + columnSql(condition, indent) + case LeftExceptionJoin(left, right, condition) => + throw new UnsupportedOperationException + case RightJoin(left, right, condition) => + joinSql(left, indent) + + onNewLine("right join ", indent) + + joinSql(right, indent) + + onNewLine("on ", indent) + + columnSql(condition, indent) + case RightExceptionJoin(left, right, condition) => + throw new UnsupportedOperationException + case InnerJoin(left, right, condition) => + joinSql(left, indent) + + onNewLine("inner join ", indent) + + joinSql(right, indent) + + onNewLine("on ", indent) + + columnSql(condition, indent) + case OuterJoin(left, right, condition) => + joinSql(left, indent) + + onNewLine("full outer join ", indent) + + joinSql(right, indent) + + onNewLine("on ", indent) + + columnSql(condition, indent) + case CrossJoin(left, right) => + joinSql(left, indent) + + onNewLine("cross join ", indent) + + joinSql(right, indent) + case select: Select[_, _] => + subselectSql(select, indent) + case Lateral(select: Select[_, _]) => + "lateral " + subselectSql(select, indent) } - def subselectSql(select: Select[_, _ <: Relation]) = { + def subselectSql(select: Select[_, _ <: Relation], indent: Int) = { val alias = if (select.subselectAlias.isDefined) " as " + select.subselectAlias.get else "" - "(" + selectSql(select) + ")" + alias + "(" + + onNewLine(selectSql(select, indent + TabWidth), indent + TabWidth) + + onNewLine(")" + alias, indent) } // ------------------------------------------------- diff --git a/sqlest/src/main/scala/sqlest/sql/base/StatementBuilder.scala b/sqlest/src/main/scala/sqlest/sql/base/StatementBuilder.scala index a721ed8..c121aca 100644 --- a/sqlest/src/main/scala/sqlest/sql/base/StatementBuilder.scala +++ b/sqlest/src/main/scala/sqlest/sql/base/StatementBuilder.scala @@ -26,7 +26,9 @@ trait StatementBuilder extends BaseStatementBuilder def apply(operation: Operation) = { val preprocessedOperation = preprocess(operation) - (preprocessedOperation, sql(preprocessedOperation), argumentLists(preprocessedOperation)) + val rawSql = sql(preprocessedOperation) + val argLists = argumentLists(preprocessedOperation) + (preprocessedOperation, rawSql, argLists, prettySql(rawSql, argLists)) } def generateRawSql(operation: Operation): String = { @@ -39,11 +41,56 @@ trait StatementBuilder extends BaseStatementBuilder .mkString } + private def prettySql(sql: String, argumentLists: List[List[LiteralColumn[_]]]): String = { + def literals(argList: List[LiteralColumn[_]]) = argList.map { + case literal: LiteralColumn[a] => + constantSql(literal.columnType, literal.value) + } + + val frags = sql.split("\\?") + val fragLen = frags.length + + val firstArgs = argumentLists + .headOption + .toList + .flatMap(literals) + + val firstArgsSql = frags.zipAll(firstArgs, "", "").flatMap { + case (l, r) => Seq(l, r) + }.mkString + + val restArgLists = + if (firstArgs.isEmpty) Nil + else argumentLists + .drop(1) + .flatMap(literals) + .grouped(firstArgs.length) + .toList + + val restArgListsSql = restArgLists.map { argList => + withLineBreaks(argList, 7)("(", ", ", ")") + } + + val restArgsSql = + if (restArgListsSql.isEmpty) + "" + else restArgListsSql.mkString( + "," + NewLine + padding(7), + "," + NewLine + padding(7), + "" + ) + + if (restArgsSql.isEmpty) + firstArgsSql + else + firstArgsSql + restArgsSql + } + private def sql(operation: Operation): String = operation match { - case select: Select[_, _] => selectSql(select) - case insert: Insert => insertSql(insert) - case update: Update => updateSql(update) - case delete: Delete => deleteSql(delete) + case select: Select[_, _] => selectSql(select, 0) + case insert: Insert => insertSql(insert, 0) + case update: Update => updateSql(update, 0) + case delete: Delete => deleteSql(delete, 0) case other => sys.error("Unsupported operation type: " + other) } diff --git a/sqlest/src/main/scala/sqlest/sql/base/UpdateStatementBuilder.scala b/sqlest/src/main/scala/sqlest/sql/base/UpdateStatementBuilder.scala index 2386e64..fa4f0e8 100644 --- a/sqlest/src/main/scala/sqlest/sql/base/UpdateStatementBuilder.scala +++ b/sqlest/src/main/scala/sqlest/sql/base/UpdateStatementBuilder.scala @@ -19,23 +19,25 @@ package sqlest.sql.base import sqlest.ast._ trait UpdateStatementBuilder extends BaseStatementBuilder { - def updateSql(update: Update): String = { + def updateSql(update: Update, indent: Int): String = { Seq( updateTableSql(update.table), - updateSetSql(update.set) + updateSetSql(update.set, indent) ) ++ Seq( - updateWhereSql(update.where) - ).flatten mkString ("", " ", "") + updateWhereSql(update.where, indent) + ).flatten mkString (NewLine + padding(indent)) } def updateTableSql(table: Table): String = s"update ${identifierSql(table.tableName)}" - def updateSetSql(setters: Seq[Setter[_, _]]): String = - "set " + setters.map(setter => identifierSql(setter.column.columnName) + " = " + columnSql(setter.value)).mkString(", ") + def updateSetSql(setters: Seq[Setter[_, _]], indent: Int): String = { + val setterSql = setters.map(setter => identifierSql(setter.column.columnName) + " = " + columnSql(setter.value, indent)) + withLineBreaks(setterSql, indent + TabWidth)("set ", ", ", "") + } - def updateWhereSql(where: Option[Column[Boolean]]): Option[String] = - where map (where => s"where ${columnSql(where)}") + def updateWhereSql(where: Option[Column[Boolean]], indent: Int): Option[String] = + where map (where => s"where ${columnSql(where, indent)}") // ------------------------------------------------- diff --git a/sqlest/src/test/scala/sqlest/executor/ExecutorSpec.scala b/sqlest/src/test/scala/sqlest/executor/ExecutorSpec.scala index 311103b..93e4c92 100644 --- a/sqlest/src/test/scala/sqlest/executor/ExecutorSpec.scala +++ b/sqlest/src/test/scala/sqlest/executor/ExecutorSpec.scala @@ -303,7 +303,8 @@ class ExecutorSpec extends FlatSpec with Matchers { it should "generate raw SQL correctly" in { TestDatabase(testResultSet).statementBuilder.generateRawSql(optionInsertStatement) should equal( - "insert into three (col3, col4) values (1, null)" + """insert into three (col3, col4) + |values (1, null)""".stripMargin ) } @@ -313,7 +314,12 @@ class ExecutorSpec extends FlatSpec with Matchers { optionInsertStatement.execute } - testDatabase.preparedStatement.get.sql shouldBe "insert into three (col3, col4) values (?, ?)" + testDatabase.preparedStatement.get.sql shouldBe + """ + |insert into three (col3, col4) + |values (?, ?) + """.trim.stripMargin + testDatabase.preparedStatement.get.parameters shouldBe Map(1 -> 1, 2 -> null) } @@ -325,19 +331,33 @@ class ExecutorSpec extends FlatSpec with Matchers { it should "generate raw SQL correctly" in { TestDatabase(testResultSet).statementBuilder.generateRawSql(mappedOptionInsertStatement1) should equal( - "insert into six (trimmedString) values ('a')" + """ + |insert into six (trimmedString) + |values ('a') + """.trim.stripMargin ) testDatabase.statementBuilder.generateRawSql(mappedOptionInsertStatement2) should equal( - "insert into six (trimmedString) values ('')" + """ + |insert into six (trimmedString) + |values ('') + """.trim.stripMargin ) testDatabase.statementBuilder.generateRawSql(mappedOptionSelectStatement1) should equal( - "select six.zeroIsNoneDateTime as six_zeroIsNoneDateTime from six where (six.zeroIsNoneDateTime = 0)" + """ + |select six.zeroIsNoneDateTime as six_zeroIsNoneDateTime + |from six + |where (six.zeroIsNoneDateTime = 0) + """.trim.stripMargin ) testDatabase.statementBuilder.generateRawSql(mappedOptionSelectStatement2) should equal( - "select six.zeroIsNoneDateTime as six_zeroIsNoneDateTime from six where (six.zeroIsNoneDateTime = 20150101)" + """ + |select six.zeroIsNoneDateTime as six_zeroIsNoneDateTime + |from six + |where (six.zeroIsNoneDateTime = 20150101) + """.trim.stripMargin ) } @@ -348,14 +368,24 @@ class ExecutorSpec extends FlatSpec with Matchers { mappedOptionInsertStatement1.execute } - testDatabase.preparedStatement.get.sql shouldBe "insert into six (trimmedString) values (?)" + testDatabase.preparedStatement.get.sql shouldBe + """ + |insert into six (trimmedString) + |values (?) + """.trim.stripMargin + testDatabase.preparedStatement.get.parameters shouldBe Map(1 -> "a") testDatabase.withTransaction { implicit transaction => mappedOptionInsertStatement2.execute } - testDatabase.preparedStatement.get.sql shouldBe "insert into six (trimmedString) values (?)" + testDatabase.preparedStatement.get.sql shouldBe + """ + |insert into six (trimmedString) + |values (?) + """.trim.stripMargin + testDatabase.preparedStatement.get.parameters shouldBe Map(1 -> "") } diff --git a/sqlest/src/test/scala/sqlest/sql/BaseStatementBuilderSpec.scala b/sqlest/src/test/scala/sqlest/sql/BaseStatementBuilderSpec.scala index 71b9ba0..ce6ba43 100644 --- a/sqlest/src/test/scala/sqlest/sql/BaseStatementBuilderSpec.scala +++ b/sqlest/src/test/scala/sqlest/sql/BaseStatementBuilderSpec.scala @@ -23,13 +23,13 @@ import sqlest.ast._ trait BaseStatementBuilderSpec extends FlatSpec with Matchers { implicit class StringFormatOps(sql: String) { - def formatSql = sql.trim.stripMargin.split(scala.util.Properties.lineSeparator).map(_.trim).mkString(" ") + def formatSql = sql.trim.stripMargin.replaceAll("\\s+", " ") } implicit def statementBuilder: StatementBuilder def sql(operation: Operation) = { - val (_, generatedSql, parameters) = statementBuilder(operation) - (generatedSql, parameters.map(_.map(_.value))) + val (_, generatedSql, parameters, prettySql) = statementBuilder(operation) + (generatedSql.replaceAll("\\s+", " "), parameters.map(_.map(_.value))) } // Test data ---------------------------------- diff --git a/sqlest/src/test/scala/sqlest/sql/DB2StatementBuilderSpec.scala b/sqlest/src/test/scala/sqlest/sql/DB2StatementBuilderSpec.scala index b3f6afb..edac6df 100644 --- a/sqlest/src/test/scala/sqlest/sql/DB2StatementBuilderSpec.scala +++ b/sqlest/src/test/scala/sqlest/sql/DB2StatementBuilderSpec.scala @@ -51,10 +51,11 @@ class DB2StatementBuilderSpec extends BaseStatementBuilderSpec { .offset(20) } should equal( s""" - |with subquery as - |(select mytable.col1 as mytable_col1, mytable.col2 as mytable_col2, row_number() over () as rownum - |from mytable - |where (mytable.col1 = ?)) + |with subquery as ( + | select mytable.col1 as mytable_col1, mytable.col2 as mytable_col2, row_number() over () as rownum + | from mytable + | where (mytable.col1 = ?) + |) |select mytable_col1, mytable_col2 |from subquery |where rownum >= ? @@ -71,10 +72,12 @@ class DB2StatementBuilderSpec extends BaseStatementBuilderSpec { .page(2, 10) } should equal( s""" - |with subquery as - |(select mytable.col1 as mytable_col1, mytable.col2 as mytable_col2, row_number() over () as rownum - |from mytable - |where (mytable.col1 = ?)) + |with subquery as ( + | select mytable.col1 as mytable_col1, mytable.col2 as mytable_col2, + | row_number() over () as rownum + | from mytable + | where (mytable.col1 = ?) + |) |select mytable_col1, mytable_col2 |from subquery |where rownum between ? and ? @@ -92,10 +95,12 @@ class DB2StatementBuilderSpec extends BaseStatementBuilderSpec { .page(2, 10) } should equal( s""" - |with subquery as - |(select mytable.col1 as mytable_col1, mytable.col2 as mytable_col2, row_number() over (order by mytable.col1) as rownum - |from mytable - |where (mytable.col1 = ?)) + |with subquery as ( + | select mytable.col1 as mytable_col1, mytable.col2 as mytable_col2, + | row_number() over (order by mytable.col1) as rownum + | from mytable + | where (mytable.col1 = ?) + |) |select mytable_col1, mytable_col2 |from subquery |where rownum between ? and ? @@ -113,10 +118,12 @@ class DB2StatementBuilderSpec extends BaseStatementBuilderSpec { .page(15, 16) } should equal( s""" - |with subquery as - |(select 1 as a, sum(cast(? as integer)) as b, (3 + ?) as c, row_number() over (order by ?, ? desc) as rownum - |from one inner join two on ((? = ?) and (? <> ?)) - |where ((? = ?) and (? <> ?))) + |with subquery as ( + | select 1 as a, sum(cast(? as integer)) as b, (3 + ?) as c, + | row_number() over (order by ?, ? desc) as rownum + | from one inner join two on ((? = ?) and (? <> ?)) + | where ((? = ?) and (? <> ?)) + |) |select a, b, c |from subquery |where rownum between ? and ? @@ -147,7 +154,10 @@ class DB2StatementBuilderSpec extends BaseStatementBuilderSpec { } should equal( s""" |select one.col1 as one_col1, one.col2 as one_col2, two_col2, two_col3 - |from one left join table(select two.col2 as two_col2, two.col3 as two_col3 from two where (two.col2 = ?)) as testTableFunctionFromSelect + |from one left join table( + | select two.col2 as two_col2, two.col3 as two_col3 + | from two where (two.col2 = ?) + |) as testTableFunctionFromSelect |on (one.col2 = two_col2) """.formatSql, List(List("123")) diff --git a/sqlest/src/test/scala/sqlest/sql/InsertStatementBuilderSpec.scala b/sqlest/src/test/scala/sqlest/sql/InsertStatementBuilderSpec.scala index be1aebe..5fb584c 100644 --- a/sqlest/src/test/scala/sqlest/sql/InsertStatementBuilderSpec.scala +++ b/sqlest/src/test/scala/sqlest/sql/InsertStatementBuilderSpec.scala @@ -66,17 +66,23 @@ class InsertStatementBuilderSpec extends BaseStatementBuilderSpec { sql { insert .into(TableOne) - .columns(TableOne.col1, TableOne.col2) - .values(TableOne.col1 -> "a", TableOne.col2 -> "b") - .values(TableOne.col1 -> "c", TableOne.col2 -> "d") + .columns(TableOne.col1, TableOne.col2, TableOne.col1, TableOne.col2, TableOne.col1, TableOne.col2) + .values(TableOne.col1 -> "a", TableOne.col2 -> "b", TableOne.col1 -> "a", TableOne.col2 -> "b", TableOne.col1 -> "a", TableOne.col2 -> "b") + .values(TableOne.col1 -> "c", TableOne.col2 -> "d", TableOne.col1 -> "c", TableOne.col2 -> "d", TableOne.col1 -> "c", TableOne.col2 -> "d") + .values(TableOne.col1 -> "e", TableOne.col2 -> "f", TableOne.col1 -> "e", TableOne.col2 -> "f", TableOne.col1 -> "e", TableOne.col2 -> "f") + .values(TableOne.col1 -> "g", TableOne.col2 -> "h", TableOne.col1 -> "g", TableOne.col2 -> "h", TableOne.col1 -> "g", TableOne.col2 -> "h") } should equal( s""" |insert |into one - |(col1, col2) - |values (?, ?) + |(col1, col2, col1, col2, col1, col2) + |values (?, ?, ?, ?, ?, ?) """.formatSql, - List(List("a", "b"), List("c", "d")) + List( + List("a", "b", "a", "b", "a", "b"), + List("c", "d", "c", "d", "c", "d"), + List("e", "f", "e", "f", "e", "f"), + List("g", "h", "g", "h", "g", "h")) ) } diff --git a/sqlest/src/test/scala/sqlest/sql/SelectStatementBuilderSpec.scala b/sqlest/src/test/scala/sqlest/sql/SelectStatementBuilderSpec.scala index 6716cc2..35e8b87 100644 --- a/sqlest/src/test/scala/sqlest/sql/SelectStatementBuilderSpec.scala +++ b/sqlest/src/test/scala/sqlest/sql/SelectStatementBuilderSpec.scala @@ -383,7 +383,10 @@ class SelectStatementBuilderSpec extends BaseStatementBuilderSpec { s""" |select mytable.col1 as mytable_col1, mytable.col2 as mytable_col2 |from mytable - |where (mytable.col1 = (select mytable.col1 as mytable_col1 from mytable)) + |where (mytable.col1 = ( + | select mytable.col1 as mytable_col1 + | from mytable + |)) """.formatSql, List(Nil) ) @@ -436,9 +439,10 @@ class SelectStatementBuilderSpec extends BaseStatementBuilderSpec { } should equal( s""" |select mytable_col1, mytable_col2 - |from - | (select mytable.col1 as mytable_col1, mytable.col2 as mytable_col2 - | from mytable) as subselect + |from ( + | select mytable.col1 as mytable_col1, mytable.col2 as mytable_col2 + | from mytable + |) as subselect """.formatSql, List(Nil) ) @@ -454,12 +458,14 @@ class SelectStatementBuilderSpec extends BaseStatementBuilderSpec { } should equal( s""" |select mytable_col1, mytable_col2 - |from mytable - |cross join lateral - | (select mytable_col1, mytable_col2 - | from - | (select mytable.col1 as mytable_col1, mytable.col2 as mytable_col2 - | from mytable) as subselect2) as subselect1 + |from mytable + |cross join lateral ( + | select mytable_col1, mytable_col2 + | from ( + | select mytable.col1 as mytable_col1, mytable.col2 as mytable_col2 + | from mytable + | ) as subselect2 + |) as subselect1 """.formatSql, List(Nil) ) @@ -475,12 +481,14 @@ class SelectStatementBuilderSpec extends BaseStatementBuilderSpec { } should equal( s""" |select mytable.col1 as mytable_col1, mytable.col2 as mytable_col2 - |from mytable - |where exists - | (select mytable_col1, mytable_col2 - | from - | (select mytable.col1 as mytable_col1, mytable.col2 as mytable_col2 - | from mytable) as subselect2) + |from mytable + |where exists ( + | select mytable_col1, mytable_col2 + | from ( + | select mytable.col1 as mytable_col1, mytable.col2 as mytable_col2 + | from mytable + | ) as subselect2 + |) """.formatSql, List(Nil) ) @@ -496,12 +504,14 @@ class SelectStatementBuilderSpec extends BaseStatementBuilderSpec { } should equal( s""" |select mytable.col1 as mytable_col1, mytable.col2 as mytable_col2 - |from mytable - |where not exists - | (select mytable_col1, mytable_col2 - | from - | (select mytable.col1 as mytable_col1, mytable.col2 as mytable_col2 - | from mytable) as subselect2) + |from mytable + |where not exists ( + | select mytable_col1, mytable_col2 + | from ( + | select mytable.col1 as mytable_col1, mytable.col2 as mytable_col2 + | from mytable + | ) as subselect2 + |) """.formatSql, List(Nil) ) @@ -513,7 +523,7 @@ class SelectStatementBuilderSpec extends BaseStatementBuilderSpec { .from(MyTable) } should equal( s""" - |select (rownumber() over()) as rownumber + |select (rownumber() over()) as rownumber |from mytable """.formatSql, List(Nil) @@ -524,7 +534,7 @@ class SelectStatementBuilderSpec extends BaseStatementBuilderSpec { .from(MyTable) } should equal( s""" - |select (rownumber() over(partition by mytable.col1 order by mytable.col2)) as rownumber + |select (rownumber() over(partition by mytable.col1 order by mytable.col2)) as rownumber |from mytable """.formatSql, List(Nil) @@ -542,8 +552,11 @@ class SelectStatementBuilderSpec extends BaseStatementBuilderSpec { s""" |select mytable.col1 as mytable_col1 |from mytable - |inner join (select (rownumber() over(partition by mytable.col1 order by mytable.col2)) as rownumber from mytable) - | on (rownumber = 1) + |inner join ( + | select (rownumber() over(partition by mytable.col1 order by mytable.col2)) as rownumber + | from mytable + |) + |on (rownumber = 1) """.formatSql, List(Nil) )