diff --git a/src/main/scala/dev/mongocamp/driver/mongodb/jdbc/resultSet/MongoDbResultSet.scala b/src/main/scala/dev/mongocamp/driver/mongodb/jdbc/resultSet/MongoDbResultSet.scala index 6bc4d390..adaa69a4 100644 --- a/src/main/scala/dev/mongocamp/driver/mongodb/jdbc/resultSet/MongoDbResultSet.scala +++ b/src/main/scala/dev/mongocamp/driver/mongodb/jdbc/resultSet/MongoDbResultSet.scala @@ -18,11 +18,13 @@ import javax.sql.rowset.serial.SerialBlob import scala.util.Try import java.nio.charset.StandardCharsets -class MongoDbResultSet(collectionDao: MongoDAO[Document], data: List[Document], queryTimeOut: Int) extends ResultSet with MongoJdbcCloseable { +class MongoDbResultSet(collectionDao: MongoDAO[Document], data: List[Document], queryTimeOut: Int, keySet: List[String] = List.empty) + extends ResultSet + with MongoJdbcCloseable { private var currentRow: Document = _ private var index: Int = 0 - private lazy val metaData = new MongoDbResultSetMetaData(collectionDao, data) + private lazy val metaData = new MongoDbResultSetMetaData(collectionDao, data, keySet) def getDocument: Document = currentRow diff --git a/src/main/scala/dev/mongocamp/driver/mongodb/jdbc/resultSet/MongoDbResultSetMetaData.scala b/src/main/scala/dev/mongocamp/driver/mongodb/jdbc/resultSet/MongoDbResultSetMetaData.scala index 034e5fd9..85e35c3b 100644 --- a/src/main/scala/dev/mongocamp/driver/mongodb/jdbc/resultSet/MongoDbResultSetMetaData.scala +++ b/src/main/scala/dev/mongocamp/driver/mongodb/jdbc/resultSet/MongoDbResultSetMetaData.scala @@ -10,6 +10,7 @@ import java.sql.{ ResultSetMetaData, SQLException } class MongoDbResultSetMetaData extends ResultSetMetaData { private var document: Document = _ private var collectionDao: MongoDAO[Document] = _ + private var keySet: List[String] = List.empty def this(dao: MongoDAO[Document]) = { this() @@ -31,6 +32,14 @@ class MongoDbResultSetMetaData extends ResultSetMetaData { this.collectionDao = dao } + def this(dao: MongoDAO[Document], data: List[Document], keySet: List[String]) = { + this() + val row: Document = extractDocumentFromDataList(data) + this.document = row + this.collectionDao = dao + this.keySet = keySet + } + private def extractDocumentFromDataList(data: List[Document]) = { var row = data.headOption.getOrElse(throw new SQLException("No data in ResultSet")).copy() val distinctKeys = data.flatMap(_.keys).distinct @@ -59,7 +68,14 @@ class MongoDbResultSetMetaData extends ResultSetMetaData { override def getColumnDisplaySize(column: Int): Int = Int.MaxValue - override def getColumnLabel(column: Int): String = document.keys.toList(column - 1) + override def getColumnLabel(column: Int): String = { + val keys : Iterable[String] =if (keySet.nonEmpty) { + keySet + } else { + document.keys + } + keys.toList(column - 1) + } override def getColumnName(column: Int): String = getColumnLabel(column) diff --git a/src/main/scala/dev/mongocamp/driver/mongodb/jdbc/statement/MongoPreparedStatement.scala b/src/main/scala/dev/mongocamp/driver/mongodb/jdbc/statement/MongoPreparedStatement.scala index e83d68a3..d58751d1 100644 --- a/src/main/scala/dev/mongocamp/driver/mongodb/jdbc/statement/MongoPreparedStatement.scala +++ b/src/main/scala/dev/mongocamp/driver/mongodb/jdbc/statement/MongoPreparedStatement.scala @@ -78,7 +78,7 @@ case class MongoPreparedStatement(connection: MongoJdbcConnection) extends Calla var response = queryHolder.run(connection.getDatabaseProvider).results(getQueryTimeout) if (response.isEmpty && queryHolder.hasFunctionCallInSelect) { val emptyDocument = mutable.Map[String, Any]() - queryHolder.getKeysForEmptyDocument.foreach(key => emptyDocument.put(key, null)) + queryHolder.getKeysFromSelect.foreach(key => emptyDocument.put(key, null)) val doc = Converter.toDocument(emptyDocument.toMap) response = Seq(doc) } @@ -89,7 +89,7 @@ case class MongoPreparedStatement(connection: MongoJdbcConnection) extends Calla newDoc }) } - val resultSet = new MongoDbResultSet(collectionName.orNull, response.toList, getQueryTimeout) + val resultSet = new MongoDbResultSet(collectionName.orNull, response.toList, getQueryTimeout, queryHolder.getKeysFromSelect) _lastResultSet = resultSet resultSet } diff --git a/src/main/scala/dev/mongocamp/driver/mongodb/sql/MongoSqlQueryHolder.scala b/src/main/scala/dev/mongocamp/driver/mongodb/sql/MongoSqlQueryHolder.scala index e9988537..b4066827 100644 --- a/src/main/scala/dev/mongocamp/driver/mongodb/sql/MongoSqlQueryHolder.scala +++ b/src/main/scala/dev/mongocamp/driver/mongodb/sql/MongoSqlQueryHolder.scala @@ -7,11 +7,11 @@ import dev.mongocamp.driver.mongodb.database.DatabaseProvider.CollectionSeparato import dev.mongocamp.driver.mongodb.exception.SqlCommandNotSupportedException import dev.mongocamp.driver.mongodb.sql.SQLCommandType.SQLCommandType import net.sf.jsqlparser.expression.operators.arithmetic.Concat -import net.sf.jsqlparser.expression.operators.conditional.{AndExpression, OrExpression} +import net.sf.jsqlparser.expression.operators.conditional.{ AndExpression, OrExpression } import net.sf.jsqlparser.expression.operators.relational._ -import net.sf.jsqlparser.expression.{ArrayConstructor, Expression, NotExpression, SignedExpression} -import net.sf.jsqlparser.parser.{CCJSqlParser, StreamProvider} -import net.sf.jsqlparser.schema.{Column, Table} +import net.sf.jsqlparser.expression.{ ArrayConstructor, Expression, NotExpression, SignedExpression } +import net.sf.jsqlparser.parser.{ CCJSqlParser, StreamProvider } +import net.sf.jsqlparser.schema.{ Column, Table } import net.sf.jsqlparser.statement.alter.Alter import net.sf.jsqlparser.statement.create.index.CreateIndex import net.sf.jsqlparser.statement.create.table.CreateTable @@ -19,15 +19,15 @@ import net.sf.jsqlparser.statement.delete.Delete import net.sf.jsqlparser.statement.drop.Drop import net.sf.jsqlparser.statement.execute.Execute import net.sf.jsqlparser.statement.insert.Insert -import net.sf.jsqlparser.statement.select.{FromItem, PlainSelect, Select, SelectItem} +import net.sf.jsqlparser.statement.select.{ FromItem, PlainSelect, Select, SelectItem } import net.sf.jsqlparser.statement.show.ShowTablesStatement import net.sf.jsqlparser.statement.truncate.Truncate import net.sf.jsqlparser.statement.update.Update -import net.sf.jsqlparser.statement.{ShowStatement, Statement} +import net.sf.jsqlparser.statement.{ ShowStatement, Statement } import org.bson.conversions.Bson import org.mongodb.scala.model.IndexOptions import org.mongodb.scala.model.Sorts.ascending -import org.mongodb.scala.{Document, Observable, SingleObservable} +import org.mongodb.scala.{ Document, Observable, SingleObservable } import java.sql.SQLException import java.util.Date @@ -48,7 +48,7 @@ class MongoSqlQueryHolder { private var indexOptions: Option[IndexOptions] = None private var callFunction: Option[String] = None private var keepOneDocument: Boolean = false - private val keysForEmptyDocument: mutable.Set[String] = mutable.Set.empty + private val keysFromSelect: mutable.ListBuffer[String] = mutable.ListBuffer.empty def this(statement: net.sf.jsqlparser.statement.Statement) = { this() @@ -211,7 +211,7 @@ class MongoSqlQueryHolder { } } - def getKeysForEmptyDocument: Set[String] = keysForEmptyDocument.toSet + def getKeysFromSelect: List[String] = keysFromSelect.toList def hasFunctionCallInSelect: Boolean = keepOneDocument @@ -235,7 +235,7 @@ class MongoSqlQueryHolder { case e: net.sf.jsqlparser.expression.TimeValue => e.getValue case e: net.sf.jsqlparser.expression.TimestampValue => e.getValue case _: net.sf.jsqlparser.expression.NullValue => null - case e: Concat => Map("$concat" -> List(convertValue(e.getLeftExpression), convertValue(e.getRightExpression))) + case e: Concat => Map("$concat" -> List(convertValue(e.getLeftExpression), convertValue(e.getRightExpression))) case t: net.sf.jsqlparser.expression.TimeKeyExpression => t.getStringValue.toUpperCase match { case "CURRENT_TIMESTAMP" => new Date() @@ -343,6 +343,14 @@ class MongoSqlQueryHolder { if (classOf[net.sf.jsqlparser.expression.Function].isAssignableFrom(sI.getExpression.getClass)) { keepOneDocument = maybeDistinct.isEmpty } + sI match { + case se: SelectItem[Expression] => + val expressionName = se.getExpression.toString + val keyFromSelect = Option(se.getAlias).map(_.getName).getOrElse(expressionName) + if (keyFromSelect != "*") { + keysFromSelect += keyFromSelect + } + } }) val aliasList = ArrayBuffer[String]() sqlCommandType = SQLCommandType.Select @@ -496,7 +504,6 @@ class MongoSqlQueryHolder { val expression = if (functionName.equalsIgnoreCase(espr.last)) Map("$first" -> espr.last) else Map(functionName -> espr.last) group += expressionName -> expression } - keysForEmptyDocument += Option(se.getAlias).map(_.getName).getOrElse(expressionName) } val groupMap = Map("_id" -> idGroupMap) ++ group.toMap diff --git a/src/test/scala/dev/mongocamp/driver/mongodb/jdbc/LiquibaseJdbcSuite.scala b/src/test/scala/dev/mongocamp/driver/mongodb/jdbc/LiquibaseJdbcSuite.scala index d065a0ca..bad72561 100644 --- a/src/test/scala/dev/mongocamp/driver/mongodb/jdbc/LiquibaseJdbcSuite.scala +++ b/src/test/scala/dev/mongocamp/driver/mongodb/jdbc/LiquibaseJdbcSuite.scala @@ -1,6 +1,7 @@ package dev.mongocamp.driver.mongodb.jdbc import com.typesafe.scalalogging.LazyLogging +import dev.mongocamp.driver.mongodb.test.TestDatabase import liquibase.database.jvm.JdbcConnection import liquibase.exception.LiquibaseException import liquibase.resource.ClassLoaderResourceAccessor @@ -11,26 +12,29 @@ import scala.language.implicitConversions class LiquibaseJdbcSuite extends BaseJdbcSuite with LazyLogging { + override def beforeAll(): Unit = { + TestDatabase.provider.dropDatabase("mongocamp-unit-test") + super.beforeAll() + } + test("Jdbc Connection should migrate database with liquibase") { val jdbcConnection = new JdbcConnection(connection) val liquibase: Liquibase = new Liquibase("liquibase/changelog.xml", new ClassLoaderResourceAccessor(), jdbcConnection) val contexts = new Contexts() val unrunChangesets = liquibase.listUnrunChangeSets(contexts, new LabelExpression()) val changes = unrunChangesets.asScala.toList - if (changes.isEmpty) { - logger.info("liquibase - nothing to update") - assert(true) - } + assert(changes.nonEmpty) logger.info("liquibase - %s changesets to update".format(changes)) try { liquibase.update(contexts) - assert(true) } catch { case e: LiquibaseException => logger.error(e.getMessage, e) assert(false) } + val unrunChangesetsAfter = liquibase.listUnrunChangeSets(contexts, new LabelExpression()) + assert(unrunChangesetsAfter.asScala.nonEmpty) } } diff --git a/src/test/scala/dev/mongocamp/driver/mongodb/jdbc/SelectJDBCSuite.scala b/src/test/scala/dev/mongocamp/driver/mongodb/jdbc/SelectJDBCSuite.scala index fc304098..ff8c4c01 100644 --- a/src/test/scala/dev/mongocamp/driver/mongodb/jdbc/SelectJDBCSuite.scala +++ b/src/test/scala/dev/mongocamp/driver/mongodb/jdbc/SelectJDBCSuite.scala @@ -11,6 +11,11 @@ class SelectJDBCSuite extends BaseJdbcSuite { var i = 0 val arrayBuffer = ArrayBuffer[ResultSet]() while (result.next()) { + assertEquals(result.getLong(1),result.getLong("id")) + assertEquals(result.getString(2),result.getString("guid")) + assertEquals(result.getString(3),result.getString("name")) + assertEquals(result.getInt(4),result.getInt("age")) + assertEquals(result.getDouble(5),result.getDouble("balance")) i += 1 arrayBuffer += result } diff --git a/src/test/scala/dev/mongocamp/driver/mongodb/sql/SelectSqlSuite.scala b/src/test/scala/dev/mongocamp/driver/mongodb/sql/SelectSqlSuite.scala index 78dbe4e2..db92379b 100644 --- a/src/test/scala/dev/mongocamp/driver/mongodb/sql/SelectSqlSuite.scala +++ b/src/test/scala/dev/mongocamp/driver/mongodb/sql/SelectSqlSuite.scala @@ -53,7 +53,7 @@ class SelectSqlSuite extends BasePersonSuite { val selectResponse = queryConverter.run(TestDatabase.provider).resultList() assertEquals(selectResponse.head.getInteger("anz").toInt, 99) assertEquals(queryConverter.getCollection, "people") - assertEquals(queryConverter.getKeysForEmptyDocument, Set("anz")) + assertEquals(queryConverter.getKeysFromSelect, List("anz")) assertEquals(queryConverter.hasFunctionCallInSelect, true) }