diff --git a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/Connection.scala b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/Connection.scala
index c912f38b6..0bee23c24 100644
--- a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/Connection.scala
+++ b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/Connection.scala
@@ -60,7 +60,7 @@ object Connection:
socketOptions: List[SocketOption] = defaultSocketOptions,
readTimeout: Duration = Duration.Inf,
allowPublicKeyRetrieval: Boolean = false,
- databaseTerm: Option[DatabaseMetaData.DatabaseTerm] = None
+ databaseTerm: Option[DatabaseMetaData.DatabaseTerm] = Some(DatabaseMetaData.DatabaseTerm.CATALOG)
): Tracer[F] ?=> Resource[F, LdbcConnection[F]] =
val logger: String => F[Unit] = s => Console[F].println(s"TLS: $s")
diff --git a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/ConnectionImpl.scala b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/ConnectionImpl.scala
index ce000fbd6..a3955029e 100644
--- a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/ConnectionImpl.scala
+++ b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/ConnectionImpl.scala
@@ -33,7 +33,7 @@ private[ldbc] case class ConnectionImpl[F[_]: Temporal: Tracer: Console: Exchang
readOnly: Ref[F, Boolean],
isAutoCommit: Ref[F, Boolean],
connectionClosed: Ref[F, Boolean],
- databaseTerm: Option[DatabaseMetaData.DatabaseTerm] = None
+ databaseTerm: Option[DatabaseMetaData.DatabaseTerm] = Some(DatabaseMetaData.DatabaseTerm.CATALOG)
)(using ev: MonadError[F, Throwable])
extends LdbcConnection[F]:
@@ -115,8 +115,12 @@ private[ldbc] case class ConnectionImpl[F[_]: Temporal: Tracer: Console: Exchang
else ev.unit
override def getCatalog(): F[String] =
- if databaseTerm.contains(DatabaseMetaData.DatabaseTerm.CATALOG) then getSchema()
- else ev.pure("")
+ if databaseTerm.contains(DatabaseMetaData.DatabaseTerm.CATALOG) then
+ for
+ statement <- createStatement()
+ result <- statement.executeQuery("SELECT DATABASE()")
+ yield Option(result.getString(1)).getOrElse("")
+ else ev.pure(null)
override def setTransactionIsolation(level: Int): F[Unit] =
level match
@@ -484,10 +488,12 @@ private[ldbc] case class ConnectionImpl[F[_]: Temporal: Tracer: Console: Exchang
override def setSchema(schema: String): F[Unit] = protocol.resetSequenceId *> protocol.comInitDB(schema)
override def getSchema(): F[String] =
- for
- statement <- createStatement()
- result <- statement.executeQuery("SELECT DATABASE()")
- yield Option(result.getString(1)).getOrElse("")
+ if databaseTerm.contains(DatabaseMetaData.DatabaseTerm.SCHEMA) then
+ for
+ statement <- createStatement()
+ result <- statement.executeQuery("SELECT DATABASE()")
+ yield Option(result.getString(1)).getOrElse("")
+ else ev.pure(null)
override def getStatistics: F[StatisticsPacket] = protocol.resetSequenceId *> protocol.comStatistics()
diff --git a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/DatabaseMetaDataImpl.scala b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/DatabaseMetaDataImpl.scala
index fc561ab79..047eb86a2 100644
--- a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/DatabaseMetaDataImpl.scala
+++ b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/DatabaseMetaDataImpl.scala
@@ -6,6 +6,8 @@
package ldbc.connector
+import java.util.{ Locale, StringTokenizer }
+
import scala.collection.immutable.{ ListMap, SortedMap }
import cats.*
@@ -26,6 +28,7 @@ import ldbc.connector.net.packet.response.*
import ldbc.connector.net.packet.request.*
import ldbc.connector.net.Protocol
import ldbc.connector.net.protocol.*
+import ldbc.connector.util.StringHelper
private[ldbc] case class DatabaseMetaDataImpl[F[_]: Temporal: Exchange: Tracer](
protocol: Protocol[F],
@@ -38,7 +41,8 @@ private[ldbc] case class DatabaseMetaDataImpl[F[_]: Temporal: Exchange: Tracer](
getProceduresReturnsFunctions: Boolean = true,
tinyInt1isBit: Boolean = true,
transformedBitIsBoolean: Boolean = false,
- yearIsDateType: Boolean = true
+ yearIsDateType: Boolean = true,
+ nullDatabaseMeansCurrent: Boolean = false
)(using ev: MonadError[F, Throwable])
extends DatabaseMetaDataImpl.StaticDatabaseMetaData[F]:
@@ -141,10 +145,10 @@ private[ldbc] case class DatabaseMetaDataImpl[F[_]: Temporal: Exchange: Tracer](
override def getProcedureTerm(): String = "PROCEDURE"
- override def getCatalogTerm(): String = databaseTerm.fold("") {
- case DatabaseMetaData.DatabaseTerm.SCHEMA => ""
- case DatabaseMetaData.DatabaseTerm.CATALOG => "CATALOG"
- }
+ override def getCatalogTerm(): String = databaseTerm match
+ case Some(DatabaseMetaData.DatabaseTerm.SCHEMA) => "CATALOG"
+ case Some(DatabaseMetaData.DatabaseTerm.CATALOG) => "database"
+ case None => "database"
override def supportsSchemasInDataManipulation(): Boolean = databaseTerm.fold(false) {
case DatabaseMetaData.DatabaseTerm.SCHEMA => true
@@ -171,10 +175,8 @@ private[ldbc] case class DatabaseMetaDataImpl[F[_]: Temporal: Exchange: Tracer](
case DatabaseMetaData.DatabaseTerm.CATALOG => false
}
- override def supportsCatalogsInDataManipulation(): Boolean = databaseTerm.fold(false) {
- case DatabaseMetaData.DatabaseTerm.SCHEMA => false
- case DatabaseMetaData.DatabaseTerm.CATALOG => true
- }
+ override def supportsCatalogsInDataManipulation(): Boolean =
+ databaseTerm.contains(DatabaseMetaData.DatabaseTerm.CATALOG)
override def supportsCatalogsInProcedureCalls(): Boolean = databaseTerm.fold(false) {
case DatabaseMetaData.DatabaseTerm.SCHEMA => false
@@ -191,17 +193,14 @@ private[ldbc] case class DatabaseMetaDataImpl[F[_]: Temporal: Exchange: Tracer](
case DatabaseMetaData.DatabaseTerm.CATALOG => true
}
- override def supportsCatalogsInPrivilegeDefinitions(): Boolean = databaseTerm.fold(false) {
- case DatabaseMetaData.DatabaseTerm.SCHEMA => false
- case DatabaseMetaData.DatabaseTerm.CATALOG => true
- }
+ override def supportsCatalogsInPrivilegeDefinitions(): Boolean =
+ databaseTerm.contains(DatabaseMetaData.DatabaseTerm.CATALOG)
override def getProcedures(
catalog: Option[String],
schemaPattern: Option[String],
procedureNamePattern: Option[String]
): F[ResultSet] =
-
val db = getDatabase(catalog, schemaPattern)
val sqlBuf = new StringBuilder(
@@ -221,7 +220,7 @@ private[ldbc] case class DatabaseMetaDataImpl[F[_]: Temporal: Exchange: Tracer](
val conditionBuf = new StringBuilder()
- if getProceduresReturnsFunctions then conditionBuf.append(" ROUTINE_TYPE = 'PROCEDURE'")
+ if !getProceduresReturnsFunctions then conditionBuf.append(" ROUTINE_TYPE = 'PROCEDURE'")
end if
if db.nonEmpty then
@@ -265,7 +264,6 @@ private[ldbc] case class DatabaseMetaDataImpl[F[_]: Temporal: Exchange: Tracer](
procedureNamePattern: Option[String],
columnNamePattern: Option[String]
): F[ResultSet] =
-
val db = getDatabase(catalog, schemaPattern)
val supportsFractSeconds = protocol.initialPacket.serverVersion.compare(Version(5, 6, 4)) >= 0
@@ -388,7 +386,7 @@ private[ldbc] case class DatabaseMetaDataImpl[F[_]: Temporal: Exchange: Tracer](
val conditionBuf = new StringBuilder()
- if getProceduresReturnsFunctions then conditionBuf.append(" ROUTINE_TYPE = 'PROCEDURE'")
+ if !getProceduresReturnsFunctions then conditionBuf.append(" ROUTINE_TYPE = 'PROCEDURE'")
end if
if db.nonEmpty then
@@ -476,7 +474,7 @@ private[ldbc] case class DatabaseMetaDataImpl[F[_]: Temporal: Exchange: Tracer](
sqlBuf.append(
if "information_schema".equalsIgnoreCase(dbValue) || "performance_schema".equalsIgnoreCase(
dbValue
- ) || !dbValue.contains("%")
+ ) || !StringHelper.hasWildcards(dbValue)
|| databaseTerm.contains(DatabaseMetaData.DatabaseTerm.CATALOG)
then " TABLE_SCHEMA = ?"
else " TABLE_SCHEMA LIKE ?"
@@ -487,7 +485,7 @@ private[ldbc] case class DatabaseMetaDataImpl[F[_]: Temporal: Exchange: Tracer](
case Some(tableName) =>
if db.nonEmpty then sqlBuf.append(" AND")
end if
- if tableName.contains("%") then sqlBuf.append(" TABLE_NAME LIKE ?")
+ if StringHelper.hasWildcards(tableName) then sqlBuf.append(" TABLE_NAME LIKE ?")
else sqlBuf.append(" TABLE_NAME = ?")
case None => ()
@@ -562,9 +560,8 @@ private[ldbc] case class DatabaseMetaDataImpl[F[_]: Temporal: Exchange: Tracer](
val db = getDatabase(catalog, schemaPattern)
val sqlBuf = new StringBuilder(
- if databaseTerm.contains(DatabaseMetaData.DatabaseTerm.SCHEMA) then
- "SELECT TABLE_CATALOG AS TABLE_CAT, TABLE_SCHEMA AS TABLE_SCHEM,"
- else "SELECT TABLE_SCHEMA AS TABLE_CAT, NULL AS TABLE_SCHEM,"
+ if databaseTerm.contains(DatabaseMetaData.DatabaseTerm.SCHEMA) then "SELECT TABLE_CATALOG, TABLE_SCHEMA,"
+ else "SELECT TABLE_SCHEMA, NULL,"
)
sqlBuf.append(" TABLE_NAME, COLUMN_NAME,")
@@ -687,58 +684,102 @@ private[ldbc] case class DatabaseMetaDataImpl[F[_]: Temporal: Exchange: Tracer](
val conditionBuf = new StringBuilder()
- db match
- case Some(dbValue) =>
- conditionBuf.append(
- if "information_schema".equalsIgnoreCase(dbValue) || "performance_schema".equalsIgnoreCase(
- dbValue
- ) || !dbValue.contains("%")
- || databaseTerm.contains(DatabaseMetaData.DatabaseTerm.SCHEMA)
- then " TABLE_SCHEMA = ?"
- else " TABLE_SCHEMA LIKE ?"
- )
- case None => ()
+ db.foreach(dbValue =>
+ conditionBuf.append(
+ if "information_schema".equalsIgnoreCase(dbValue) || "performance_schema".equalsIgnoreCase(
+ dbValue
+ ) || !StringHelper.hasWildcards(dbValue)
+ || databaseTerm.contains(DatabaseMetaData.DatabaseTerm.CATALOG)
+ then " TABLE_SCHEMA = ?"
+ else " TABLE_SCHEMA LIKE ?"
+ )
+ )
- tableName match
- case Some(tableNameValue) =>
- if conditionBuf.nonEmpty then conditionBuf.append(" AND")
- end if
- conditionBuf.append(if tableNameValue.contains("%") then " TABLE_NAME LIKE ?" else " TABLE_NAME = ?")
- case None => ()
+ tableName.foreach(name =>
+ if conditionBuf.nonEmpty then conditionBuf.append(" AND")
- columnNamePattern match
- case Some(columnName) =>
- if conditionBuf.nonEmpty then conditionBuf.append(" AND")
- end if
- conditionBuf.append(if columnName.contains("%") then " COLUMN_NAME LIKE ?" else " COLUMN_NAME = ?")
- case None => ()
+ conditionBuf.append(
+ if StringHelper.hasWildcards(name) then " TABLE_NAME LIKE ?"
+ else " TABLE_NAME = ?"
+ )
+ )
+
+ columnNamePattern.foreach(columnName =>
+ if conditionBuf.nonEmpty then conditionBuf.append(" AND")
+
+ conditionBuf.append(
+ if StringHelper.hasWildcards(columnName) then " COLUMN_NAME LIKE ?"
+ else " COLUMN_NAME = ?"
+ )
+ )
if conditionBuf.nonEmpty then sqlBuf.append(" WHERE")
end if
sqlBuf.append(conditionBuf)
- sqlBuf.append(" ORDER BY TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION")
- prepareMetaDataSafeStatement(sqlBuf.toString()).flatMap { preparedStatement =>
- val settings = (db, tableName, columnNamePattern) match
- case (Some(dbValue), Some(tableNameValue), Some(columnName)) =>
- preparedStatement.setString(1, dbValue) *> preparedStatement.setString(
- 2,
- tableNameValue
- ) *> preparedStatement.setString(3, columnName)
- case (Some(dbValue), Some(tableNameValue), None) =>
- preparedStatement.setString(1, dbValue) *> preparedStatement.setString(2, tableNameValue)
- case (Some(dbValue), None, Some(columnName)) =>
- preparedStatement.setString(1, dbValue) *> preparedStatement.setString(2, columnName)
- case (Some(dbValue), None, None) => preparedStatement.setString(1, dbValue)
- case (None, Some(tableNameValue), Some(columnName)) =>
- preparedStatement.setString(1, tableNameValue) *> preparedStatement.setString(2, columnName)
- case (None, Some(tableNameValue), None) => preparedStatement.setString(1, tableNameValue)
- case (None, None, Some(columnName)) => preparedStatement.setString(1, columnName)
- case (None, None, None) => ev.unit
-
- settings *> preparedStatement.executeQuery()
- }
+ sqlBuf.append(" ORDER BY TABLE_SCHEMA, TABLE_NAME, ORDINAL_POSITION")
+
+ prepareMetaDataSafeStatement(sqlBuf.toString())
+ .flatMap { preparedStatement =>
+ val settings = (db, tableName, columnNamePattern) match
+ case (Some(dbValue), Some(tableNameValue), Some(columnName)) =>
+ preparedStatement.setString(1, dbValue) *> preparedStatement.setString(
+ 2,
+ tableNameValue
+ ) *> preparedStatement.setString(3, columnName)
+ case (Some(dbValue), Some(tableNameValue), None) =>
+ preparedStatement.setString(1, dbValue) *> preparedStatement.setString(2, tableNameValue)
+ case (Some(dbValue), None, Some(columnName)) =>
+ preparedStatement.setString(1, dbValue) *> preparedStatement.setString(2, columnName)
+ case (Some(dbValue), None, None) => preparedStatement.setString(1, dbValue)
+ case (None, Some(tableNameValue), Some(columnName)) =>
+ preparedStatement.setString(1, tableNameValue) *> preparedStatement.setString(2, columnName)
+ case (None, Some(tableNameValue), None) => preparedStatement.setString(1, tableNameValue)
+ case (None, None, Some(columnName)) => preparedStatement.setString(1, columnName)
+ case (None, None, None) => ev.unit
+
+ settings *> preparedStatement.executeQuery()
+ }
+ .map { resultSet =>
+ ResultSetImpl(
+ Vector(
+ "TABLE_CAT",
+ "TABLE_SCHEM",
+ "TABLE_NAME",
+ "COLUMN_NAME",
+ "DATA_TYPE",
+ "TYPE_NAME",
+ "COLUMN_SIZE",
+ "BUFFER_LENGTH",
+ "DECIMAL_DIGITS",
+ "NUM_PREC_RADIX",
+ "NULLABLE",
+ "REMARKS",
+ "COLUMN_DEF",
+ "SQL_DATA_TYPE",
+ "SQL_DATETIME_SUB",
+ "CHAR_OCTET_LENGTH",
+ "ORDINAL_POSITION",
+ "IS_NULLABLE",
+ "SCOPE_CATALOG",
+ "SCOPE_SCHEMA",
+ "SCOPE_TABLE",
+ "SOURCE_DATA_TYPE",
+ "IS_AUTOINCREMENT",
+ "IS_GENERATEDCOLUMN"
+ ).map(value =>
+ new ColumnDefinitionPacket:
+ override def table: String = ""
+ override def name: String = value
+ override def columnType: ColumnDataType = ColumnDataType.MYSQL_TYPE_VARCHAR
+ override def flags: Seq[ColumnDefinitionFlags] = Seq.empty
+ ),
+ resultSet.asInstanceOf[ResultSetImpl].records,
+ serverVariables,
+ protocol.initialPacket.serverVersion
+ )
+ }
override def getColumnPrivileges(
catalog: Option[String],
@@ -794,7 +835,7 @@ private[ldbc] case class DatabaseMetaDataImpl[F[_]: Temporal: Exchange: Tracer](
val db = getDatabase(catalog, schemaPattern)
val sqlBuf = new StringBuilder(
- "SELECT db AS TABLE_SCHEM, table_name AS TABLE_NAME, grantor AS GRANTOR, CONCAT(user, '@', host) AS GRANTEE, table_priv AS PRIVILEGE FROM mysql.tables_priv"
+ "SELECT host,db,table_name,grantor,user,table_priv FROM mysql.tables_priv"
)
val conditionBuf = new StringBuilder()
@@ -816,16 +857,89 @@ private[ldbc] case class DatabaseMetaDataImpl[F[_]: Temporal: Exchange: Tracer](
sqlBuf.append(conditionBuf)
end if
- prepareMetaDataSafeStatement(sqlBuf.toString()).flatMap { preparedStatement =>
- val setting = (db, tableNamePattern) match
- case (Some(dbValue), Some(tableName)) =>
- preparedStatement.setString(1, dbValue) *> preparedStatement.setString(2, tableName)
- case (Some(dbValue), None) => preparedStatement.setString(1, dbValue)
- case (None, Some(tableName)) => preparedStatement.setString(1, tableName)
- case _ => ev.unit
+ prepareMetaDataSafeStatement(sqlBuf.toString())
+ .flatMap { preparedStatement =>
+ val setting = (db, tableNamePattern) match
+ case (Some(dbValue), Some(tableName)) =>
+ preparedStatement.setString(1, dbValue) *> preparedStatement.setString(2, tableName)
+ case (Some(dbValue), None) => preparedStatement.setString(1, dbValue)
+ case (None, Some(tableName)) => preparedStatement.setString(1, tableName)
+ case _ => ev.unit
- setting *> preparedStatement.executeQuery()
- }
+ setting *> preparedStatement.executeQuery()
+ }
+ .flatMap { resultSet =>
+
+ val keys = Vector.newBuilder[(Option[String], Option[String], Option[String], String, String)]
+ while resultSet.next() do
+ val host = Option(resultSet.getString(1))
+ val db = Option(resultSet.getString(2))
+ val table = Option(resultSet.getString(3))
+ val grantor = Option(resultSet.getString(4))
+ val user = Option(resultSet.getString(5)).getOrElse("%")
+
+ val fullUser = new StringBuilder(user)
+ host.foreach(h => fullUser.append("@").append(h))
+
+ Option(resultSet.getString(6)) match
+ case Some(value) =>
+ val allPrivileges = value.toUpperCase(Locale.ENGLISH)
+ val stringTokenizer = new StringTokenizer(allPrivileges, ",")
+
+ while stringTokenizer.hasMoreTokens do
+ val privilege = stringTokenizer.nextToken().trim
+
+ keys += ((db, table, grantor, fullUser.toString(), privilege))
+ end while
+
+ case None => // no privileges
+ end while
+
+ val records = keys
+ .result()
+ .traverse { (db, table, grantor, user, privilege) =>
+ val columnResults = getColumns(catalog, schemaPattern, table, None)
+ columnResults.map { columnResult =>
+ val records = Vector.newBuilder[ResultSetRowPacket]
+ while columnResult.next() do
+ val rows = Array(
+ if databaseTerm.contains(DatabaseMetaData.DatabaseTerm.SCHEMA) then Some("def") else db, // TABLE_CAT
+ if databaseTerm.contains(DatabaseMetaData.DatabaseTerm.SCHEMA) then db else None, // TABLE_SCHEM
+ table, // TABLE_NAME
+ grantor, // GRANTOR
+ Some(user), // GRANTEE
+ Some(privilege), // PRIVILEGE
+ None // IS_GRANTABLE
+ )
+ records += ResultSetRowPacket(rows)
+ records.result()
+ }
+ }
+ .map(_.flatten)
+
+ records.map { records =>
+ ResultSetImpl(
+ Vector(
+ "TABLE_CAT",
+ "TABLE_SCHEM",
+ "TABLE_NAME",
+ "GRANTOR",
+ "GRANTEE",
+ "PRIVILEGE",
+ "IS_GRANTABLE"
+ ).map { value =>
+ new ColumnDefinitionPacket:
+ override def table: String = ""
+ override def name: String = value
+ override def columnType: ColumnDataType = ColumnDataType.MYSQL_TYPE_VARCHAR
+ override def flags: Seq[ColumnDefinitionFlags] = Seq.empty
+ },
+ records,
+ serverVariables,
+ protocol.initialPacket.serverVersion
+ )
+ }
+ }
override def getBestRowIdentifier(
catalog: Option[String],
@@ -1172,6 +1286,7 @@ private[ldbc] case class DatabaseMetaDataImpl[F[_]: Temporal: Exchange: Tracer](
ResultSetRowPacket(getTypeInfo("MEDIUMBLOB")),
ResultSetRowPacket(getTypeInfo("LONGBLOB")),
ResultSetRowPacket(getTypeInfo("BLOB")),
+ ResultSetRowPacket(getTypeInfo("VECTOR")),
ResultSetRowPacket(getTypeInfo("VARBINARY")),
ResultSetRowPacket(getTypeInfo("TINYBLOB")),
ResultSetRowPacket(getTypeInfo("BINARY")),
@@ -1192,7 +1307,6 @@ private[ldbc] case class DatabaseMetaDataImpl[F[_]: Temporal: Exchange: Tracer](
ResultSetRowPacket(getTypeInfo("MEDIUMINT UNSIGNED")),
ResultSetRowPacket(getTypeInfo("SMALLINT")),
ResultSetRowPacket(getTypeInfo("SMALLINT UNSIGNED")),
- ResultSetRowPacket(getTypeInfo("YEAR")),
ResultSetRowPacket(getTypeInfo("FLOAT")),
ResultSetRowPacket(getTypeInfo("DOUBLE")),
ResultSetRowPacket(getTypeInfo("DOUBLE PRECISION")),
@@ -1203,6 +1317,7 @@ private[ldbc] case class DatabaseMetaDataImpl[F[_]: Temporal: Exchange: Tracer](
ResultSetRowPacket(getTypeInfo("TINYTEXT")),
ResultSetRowPacket(getTypeInfo("BOOL")),
ResultSetRowPacket(getTypeInfo("DATE")),
+ ResultSetRowPacket(getTypeInfo("YEAR")),
ResultSetRowPacket(getTypeInfo("TIME")),
ResultSetRowPacket(getTypeInfo("DATETIME")),
ResultSetRowPacket(getTypeInfo("TIMESTAMP"))
@@ -1506,7 +1621,7 @@ private[ldbc] case class DatabaseMetaDataImpl[F[_]: Temporal: Exchange: Tracer](
if tinyInt1isBit && !transformedBitIsBoolean then
sqlBuf.append(
- " WHEN (UPPER(DATA_TYPE)='TINYINT' AND LOCATE('ZEROFILL', UPPER(DTD_IDENTIFIER)) = 0) AND LOCATE('UNSIGNED', UPPER(DTD_IDENTIFIER)) = 0 AND LOCATE('(1)', DTD_IDENTIFIER) != 0 THEN 1"
+ " WHEN UPPER(DATA_TYPE)='TINYINT' AND LOCATE('ZEROFILL', UPPER(DTD_IDENTIFIER)) = 0 AND LOCATE('UNSIGNED', UPPER(DTD_IDENTIFIER)) = 0 AND LOCATE('(1)', DTD_IDENTIFIER) != 0 THEN 1"
)
sqlBuf.append(" WHEN UPPER(DATA_TYPE)='MEDIUMINT' AND LOCATE('UNSIGNED', UPPER(DTD_IDENTIFIER)) != 0 THEN 8")
@@ -1619,10 +1734,12 @@ private[ldbc] case class DatabaseMetaDataImpl[F[_]: Temporal: Exchange: Tracer](
)
protected def getDatabase(catalog: Option[String], schema: Option[String]): Option[String] =
- (databaseTerm, catalog, schema) match
- case (Some(DatabaseMetaData.DatabaseTerm.SCHEMA), None, value) => value.fold(database)(_.some)
- case (Some(DatabaseMetaData.DatabaseTerm.CATALOG), value, None) => value.fold(database)(_.some)
- case _ => database
+ databaseTerm.flatMap {
+ case DatabaseMetaData.DatabaseTerm.SCHEMA =>
+ if schema.nonEmpty && nullDatabaseMeansCurrent then database else schema
+ case DatabaseMetaData.DatabaseTerm.CATALOG =>
+ if catalog.nonEmpty && nullDatabaseMeansCurrent then database else catalog
+ }
/**
* Get a prepared statement to query information_schema tables.
@@ -1769,7 +1886,8 @@ private[ldbc] case class DatabaseMetaDataImpl[F[_]: Temporal: Exchange: Tracer](
case MysqlType.TINYBLOB | MysqlType.BLOB | MysqlType.MEDIUMBLOB | MysqlType.LONGBLOB | MysqlType.TINYTEXT |
MysqlType.TEXT | MysqlType.MEDIUMTEXT | MysqlType.LONGTEXT | MysqlType.JSON | MysqlType.BINARY |
MysqlType.VARBINARY | MysqlType.CHAR | MysqlType.VARCHAR | MysqlType.ENUM | MysqlType.SET | MysqlType.DATE |
- MysqlType.TIME | MysqlType.DATETIME | MysqlType.TIMESTAMP | MysqlType.GEOMETRY | MysqlType.UNKNOWN =>
+ MysqlType.TIME | MysqlType.DATETIME | MysqlType.TIMESTAMP | MysqlType.GEOMETRY | MysqlType.VECTOR |
+ MysqlType.UNKNOWN =>
Array(Some("'"), Some("'"))
case _ => Array(Some(""), Some(""))
) ++ Array(
@@ -1782,11 +1900,13 @@ private[ldbc] case class DatabaseMetaDataImpl[F[_]: Temporal: Exchange: Tracer](
Some("false"), // FIXED_PREC_SCALE
(
mysqlType match
- case MysqlType.BIGINT | MysqlType.BIGINT_UNSIGNED | MysqlType.BOOLEAN | MysqlType.DOUBLE |
- MysqlType.DOUBLE_UNSIGNED | MysqlType.FLOAT | MysqlType.FLOAT_UNSIGNED | MysqlType.INT |
+ case MysqlType.BIGINT | MysqlType.BIGINT_UNSIGNED | MysqlType.BOOLEAN | MysqlType.INT |
MysqlType.INT_UNSIGNED | MysqlType.MEDIUMINT | MysqlType.MEDIUMINT_UNSIGNED | MysqlType.SMALLINT |
MysqlType.SMALLINT_UNSIGNED | MysqlType.TINYINT | MysqlType.TINYINT_UNSIGNED =>
Some("true")
+ case MysqlType.DOUBLE | MysqlType.DOUBLE_UNSIGNED | MysqlType.FLOAT | MysqlType.FLOAT_UNSIGNED =>
+ val supportsAutoIncrement = protocol.initialPacket.serverVersion.compare(Version(8, 4, 0)) >= 0
+ if supportsAutoIncrement then Some("true") else Some("false")
case _ => Some("false")
), // AUTO_INCREMENT
Some(mysqlType.name) // LOCAL_TYPE_NAME
@@ -2166,7 +2286,7 @@ private[ldbc] object DatabaseMetaDataImpl:
override def getSearchStringEscape(): String = "\\"
- override def getExtraNameCharacters(): String = "#@"
+ override def getExtraNameCharacters(): String = "$"
override def supportsAlterTableWithAddColumn(): Boolean = true
@@ -2320,32 +2440,5 @@ private[ldbc] object DatabaseMetaDataImpl:
override def supportsResultSetHoldability(holdability: Int): Boolean =
holdability == ResultSet.HOLD_CURSORS_OVER_COMMIT
- override def locatorsUpdateCopy(): Boolean = false
+ override def locatorsUpdateCopy(): Boolean = true
end StaticDatabaseMetaData
-
- def apply[F[_]: Temporal: Exchange: Tracer](
- protocol: Protocol[F],
- serverVariables: Map[String, String],
- connectionClosed: Ref[F, Boolean],
- statementClosed: Ref[F, Boolean],
- resultSetClosed: Ref[F, Boolean],
- database: Option[String] = None,
- databaseTerm: Option[DatabaseMetaData.DatabaseTerm] = None,
- getProceduresReturnsFunctions: Boolean = true,
- tinyInt1isBit: Boolean = true,
- transformedBitIsBoolean: Boolean = false,
- yearIsDateType: Boolean = true
- )(using ev: MonadError[F, Throwable]): DatabaseMetaData[F] =
- new DatabaseMetaDataImpl[F](
- protocol,
- serverVariables,
- connectionClosed,
- statementClosed,
- resultSetClosed,
- database,
- databaseTerm,
- getProceduresReturnsFunctions,
- tinyInt1isBit,
- transformedBitIsBoolean,
- yearIsDateType
- )
diff --git a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/data/MysqlType.scala b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/data/MysqlType.scala
index 0b3ce7b1e..32af47969 100644
--- a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/data/MysqlType.scala
+++ b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/data/MysqlType.scala
@@ -610,6 +610,15 @@ enum MysqlType(
*/
case GEOMETRY extends MysqlType("GEOMETRY", Types.BINARY, 0, MysqlTypeVariables.IS_NOT_DECIMAL, 65535L, "")
+ /**
+ * VECTOR[(M)]
+ * A VECTOR column with a maximum length of 65,532 (16383 x 4) bytes. An optional length M can be given for this type to indicate the maximum number of
+ * entries in a VECTOR. M cannot exceed 16383. Each entry is a 4 Byte (single-precision) floating-point value.
+ *
+ * Protocol: FIELD_TYPE_VECTOR = 242
+ */
+ case VECTOR extends MysqlType("VECTOR", Types.LONGVARBINARY, 0, MysqlTypeVariables.IS_NOT_DECIMAL, 65532L, "[(M)]")
+
/**
* Fall-back type for those MySQL data types which c/J can't recognize.
* Handled the same as BLOB.
@@ -689,6 +698,7 @@ object MysqlType:
case name if name.contains("BLOB") => MysqlType.BLOB
case name if name.contains("TEXT") => MysqlType.TEXT
case name if name.contains("GEOM") | name.contains("POINT") | name.contains("POLYGON") => MysqlType.GEOMETRY
+ case name if name.contains("VECTOR") => MysqlType.VECTOR
case _ => MysqlType.UNKNOWN
/**
diff --git a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/util/StringHelper.scala b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/util/StringHelper.scala
index 830776891..2e1859da6 100644
--- a/module/ldbc-connector/shared/src/main/scala/ldbc/connector/util/StringHelper.scala
+++ b/module/ldbc-connector/shared/src/main/scala/ldbc/connector/util/StringHelper.scala
@@ -71,3 +71,14 @@ object StringHelper:
def getUniqueSavepointId: String =
val uuid = UUID.randomUUID().toString
uuid.replaceAll("-", "_")
+
+ /**
+ * Does the string contain wildcard symbols ('%' or '_'). Used in DatabaseMetaData.
+ *
+ * @param src
+ * string
+ * @return
+ * true if src contains wildcard symbols
+ */
+ def hasWildcards(src: String): Boolean =
+ indexOfIgnoreCase(0, src, "%") != -1 || indexOfIgnoreCase(0, src, "_") != -1
diff --git a/module/ldbc-connector/shared/src/test/scala/ldbc/connector/ConnectionTest.scala b/module/ldbc-connector/shared/src/test/scala/ldbc/connector/ConnectionTest.scala
index 5ed31c42e..1b49e5340 100644
--- a/module/ldbc-connector/shared/src/test/scala/ldbc/connector/ConnectionTest.scala
+++ b/module/ldbc-connector/shared/src/test/scala/ldbc/connector/ConnectionTest.scala
@@ -264,7 +264,7 @@ class ConnectionTest extends FTestPlatform:
assertIOBoolean(connection.use(_ => IO(true)))
}
- test("Schema change will change the currently connected Schema.") {
+ test("Catalog change will change the currently connected Catalog.") {
val connection = Connection[IO](
host = "127.0.0.1",
port = 13306,
@@ -276,7 +276,7 @@ class ConnectionTest extends FTestPlatform:
assertIO(
connection.use { conn =>
- conn.setSchema("world") *> conn.getSchema()
+ conn.setCatalog("world") *> conn.getCatalog()
},
"world"
)
@@ -884,7 +884,7 @@ class ConnectionTest extends FTestPlatform:
assertIO(
connection.use(_.getMetaData().map(_.getExtraNameCharacters())),
- "#@"
+ "$"
)
}
@@ -902,7 +902,7 @@ class ConnectionTest extends FTestPlatform:
connection.use { conn =>
for
metaData <- conn.getMetaData()
- resultSet <- metaData.getProcedures("def", "connector_test", "demoSp")
+ resultSet <- metaData.getProcedures(Some("connector_test"), None, Some("demoSp"))
yield
val builder = Vector.newBuilder[String]
while resultSet.next() do
@@ -934,7 +934,7 @@ class ConnectionTest extends FTestPlatform:
connection.use { conn =>
for
metaData <- conn.getMetaData()
- resultSet <- metaData.getProcedureColumns(Some("def"), Some("connector_test"), Some("demoSp"), None)
+ resultSet <- metaData.getProcedureColumns(Some("connector_test"), None, Some("demoSp"), None)
yield
val builder = Vector.newBuilder[String]
while resultSet.next() do
@@ -967,7 +967,7 @@ class ConnectionTest extends FTestPlatform:
connection.use { conn =>
for
metaData <- conn.getMetaData()
- resultSet <- metaData.getTables(None, Some("connector_test"), Some("all_types"), Array.empty[String])
+ resultSet <- metaData.getTables(Some("connector_test"), None, Some("all_types"), Array.empty[String])
yield
val builder = Vector.newBuilder[String]
while resultSet.next() do
@@ -1185,13 +1185,12 @@ class ConnectionTest extends FTestPlatform:
test("The result of retrieving table privileges information matches the specified value.") {
val connection = Connection[IO](
- host = "127.0.0.1",
- port = 13306,
- user = "ldbc",
- password = Some("password"),
- database = Some("connector_test"),
- ssl = SSL.Trusted,
- databaseTerm = Some(DatabaseMetaData.DatabaseTerm.SCHEMA)
+ host = "127.0.0.1",
+ port = 13306,
+ user = "ldbc",
+ password = Some("password"),
+ database = Some("connector_test"),
+ ssl = SSL.Trusted
)
assertIO(
@@ -1213,7 +1212,12 @@ class ConnectionTest extends FTestPlatform:
builder.result()
},
Vector(
- "Table Cat: null, Table Schem: connector_test, Table Name: privileges_table, Grantor: root@localhost, Grantee: ldbc@%, Privilege: Select,Insert, Is Grantable: null"
+ "Table Cat: connector_test, Table Schem: null, Table Name: privileges_table, Grantor: root@localhost, Grantee: ldbc@%, Privilege: SELECT, Is Grantable: null",
+ "Table Cat: connector_test, Table Schem: null, Table Name: privileges_table, Grantor: root@localhost, Grantee: ldbc@%, Privilege: SELECT, Is Grantable: null",
+ "Table Cat: connector_test, Table Schem: null, Table Name: privileges_table, Grantor: root@localhost, Grantee: ldbc@%, Privilege: SELECT, Is Grantable: null",
+ "Table Cat: connector_test, Table Schem: null, Table Name: privileges_table, Grantor: root@localhost, Grantee: ldbc@%, Privilege: INSERT, Is Grantable: null",
+ "Table Cat: connector_test, Table Schem: null, Table Name: privileges_table, Grantor: root@localhost, Grantee: ldbc@%, Privilege: INSERT, Is Grantable: null",
+ "Table Cat: connector_test, Table Schem: null, Table Name: privileges_table, Grantor: root@localhost, Grantee: ldbc@%, Privilege: INSERT, Is Grantable: null"
)
)
}
@@ -1499,6 +1503,7 @@ class ConnectionTest extends FTestPlatform:
"Type Name: MEDIUMBLOB, Data Type: -4, Precision: 16777215, Literal Prefix: ', Literal Suffix: ', Create Params: , Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: MEDIUMBLOB, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
"Type Name: LONGBLOB, Data Type: -4, Precision: 2147483647, Literal Prefix: ', Literal Suffix: ', Create Params: , Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: LONGBLOB, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
"Type Name: BLOB, Data Type: -4, Precision: 65535, Literal Prefix: ', Literal Suffix: ', Create Params: [(M)], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: BLOB, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: VECTOR, Data Type: -4, Precision: 65532, Literal Prefix: ', Literal Suffix: ', Create Params: [(M)], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: VECTOR, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
"Type Name: VARBINARY, Data Type: -3, Precision: 65535, Literal Prefix: ', Literal Suffix: ', Create Params: (M), Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: VARBINARY, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
"Type Name: TINYBLOB, Data Type: -3, Precision: 255, Literal Prefix: ', Literal Suffix: ', Create Params: , Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: TINYBLOB, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
"Type Name: BINARY, Data Type: -2, Precision: 255, Literal Prefix: ', Literal Suffix: ', Create Params: (M), Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: BINARY, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
@@ -1519,17 +1524,17 @@ class ConnectionTest extends FTestPlatform:
"Type Name: MEDIUMINT UNSIGNED, Data Type: 4, Precision: 8, Literal Prefix: , Literal Suffix: , Create Params: [(M)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: true, Fixed Prec Scale: false, Auto Increment: true, Local Type Name: MEDIUMINT UNSIGNED, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
"Type Name: SMALLINT, Data Type: 5, Precision: 5, Literal Prefix: , Literal Suffix: , Create Params: [(M)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: true, Local Type Name: SMALLINT, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
"Type Name: SMALLINT UNSIGNED, Data Type: 5, Precision: 5, Literal Prefix: , Literal Suffix: , Create Params: [(M)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: true, Fixed Prec Scale: false, Auto Increment: true, Local Type Name: SMALLINT UNSIGNED, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
- "Type Name: YEAR, Data Type: 91, Precision: 4, Literal Prefix: , Literal Suffix: , Create Params: [(4)], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: YEAR, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
- "Type Name: FLOAT, Data Type: 7, Precision: 12, Literal Prefix: , Literal Suffix: , Create Params: [(M,D)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: true, Local Type Name: FLOAT, Minimum Scale: -38, Maximum Scale: 38, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
- "Type Name: DOUBLE, Data Type: 8, Precision: 22, Literal Prefix: , Literal Suffix: , Create Params: [(M,D)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: true, Local Type Name: DOUBLE, Minimum Scale: -308, Maximum Scale: 308, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
- "Type Name: DOUBLE PRECISION, Data Type: 8, Precision: 22, Literal Prefix: , Literal Suffix: , Create Params: [(M,D)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: true, Local Type Name: DOUBLE, Minimum Scale: -308, Maximum Scale: 308, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
- "Type Name: REAL, Data Type: 8, Precision: 22, Literal Prefix: , Literal Suffix: , Create Params: [(M,D)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: true, Local Type Name: DOUBLE, Minimum Scale: -308, Maximum Scale: 308, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
- "Type Name: DOUBLE UNSIGNED, Data Type: 8, Precision: 22, Literal Prefix: , Literal Suffix: , Create Params: [(M,D)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: true, Fixed Prec Scale: false, Auto Increment: true, Local Type Name: DOUBLE UNSIGNED, Minimum Scale: -308, Maximum Scale: 308, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
- "Type Name: DOUBLE PRECISION UNSIGNED, Data Type: 8, Precision: 22, Literal Prefix: , Literal Suffix: , Create Params: [(M,D)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: true, Fixed Prec Scale: false, Auto Increment: true, Local Type Name: DOUBLE UNSIGNED, Minimum Scale: -308, Maximum Scale: 308, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: FLOAT, Data Type: 7, Precision: 12, Literal Prefix: , Literal Suffix: , Create Params: [(M,D)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: FLOAT, Minimum Scale: -38, Maximum Scale: 38, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: DOUBLE, Data Type: 8, Precision: 22, Literal Prefix: , Literal Suffix: , Create Params: [(M,D)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: DOUBLE, Minimum Scale: -308, Maximum Scale: 308, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: DOUBLE PRECISION, Data Type: 8, Precision: 22, Literal Prefix: , Literal Suffix: , Create Params: [(M,D)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: DOUBLE, Minimum Scale: -308, Maximum Scale: 308, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: REAL, Data Type: 8, Precision: 22, Literal Prefix: , Literal Suffix: , Create Params: [(M,D)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: DOUBLE, Minimum Scale: -308, Maximum Scale: 308, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: DOUBLE UNSIGNED, Data Type: 8, Precision: 22, Literal Prefix: , Literal Suffix: , Create Params: [(M,D)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: true, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: DOUBLE UNSIGNED, Minimum Scale: -308, Maximum Scale: 308, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: DOUBLE PRECISION UNSIGNED, Data Type: 8, Precision: 22, Literal Prefix: , Literal Suffix: , Create Params: [(M,D)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: true, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: DOUBLE UNSIGNED, Minimum Scale: -308, Maximum Scale: 308, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
"Type Name: VARCHAR, Data Type: 12, Precision: 65535, Literal Prefix: ', Literal Suffix: ', Create Params: (M) [CHARACTER SET charset_name] [COLLATE collation_name], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: VARCHAR, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
"Type Name: TINYTEXT, Data Type: 12, Precision: 255, Literal Prefix: ', Literal Suffix: ', Create Params: [CHARACTER SET charset_name] [COLLATE collation_name], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: TINYTEXT, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
"Type Name: BOOL, Data Type: 16, Precision: 3, Literal Prefix: , Literal Suffix: , Create Params: , Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: true, Local Type Name: BOOLEAN, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
"Type Name: DATE, Data Type: 91, Precision: 10, Literal Prefix: ', Literal Suffix: ', Create Params: , Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: DATE, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: YEAR, Data Type: 91, Precision: 4, Literal Prefix: , Literal Suffix: , Create Params: [(4)], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: YEAR, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
"Type Name: TIME, Data Type: 92, Precision: 16, Literal Prefix: ', Literal Suffix: ', Create Params: [(fsp)], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: TIME, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
"Type Name: DATETIME, Data Type: 93, Precision: 26, Literal Prefix: ', Literal Suffix: ', Create Params: [(fsp)], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: DATETIME, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
"Type Name: TIMESTAMP, Data Type: 93, Precision: 26, Literal Prefix: ', Literal Suffix: ', Create Params: [(fsp)], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: TIMESTAMP, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10"
diff --git a/module/ldbc-sql/src/main/scala/ldbc/sql/DatabaseMetaData.scala b/module/ldbc-sql/src/main/scala/ldbc/sql/DatabaseMetaData.scala
index d6f26e7b9..05c346ae8 100644
--- a/module/ldbc-sql/src/main/scala/ldbc/sql/DatabaseMetaData.scala
+++ b/module/ldbc-sql/src/main/scala/ldbc/sql/DatabaseMetaData.scala
@@ -1064,7 +1064,7 @@ trait DatabaseMetaData[F[_]]:
* Only procedure descriptions matching the schema and
* procedure name criteria are returned. They are ordered by
* PROCEDURE_CAT
, PROCEDURE_SCHEM
,
- * PROCEDURE_NAME
and SPECIFIC_ NAME
.
+ * PROCEDURE_NAME
and SPECIFIC_NAME
.
*
*
Each procedure description has the following columns:
*
diff --git a/tests/src/test/scala/ldbc/tests/ConnectionTest.scala b/tests/src/test/scala/ldbc/tests/ConnectionTest.scala
new file mode 100644
index 000000000..9bb8139c3
--- /dev/null
+++ b/tests/src/test/scala/ldbc/tests/ConnectionTest.scala
@@ -0,0 +1,883 @@
+/**
+ * Copyright (c) 2023-2024 by Takahiko Tominaga
+ * This software is licensed under the MIT License (MIT).
+ * For more information see LICENSE or https://opensource.org/licenses/MIT
+ */
+
+package ldbc.tests
+
+import com.mysql.cj.jdbc.MysqlDataSource
+
+import cats.effect.*
+
+import org.typelevel.otel4s.trace.Tracer
+
+import munit.*
+
+import ldbc.sql.*
+import ldbc.connector.SSL
+
+class LdbcConnectionTest extends ConnectionTest:
+ override def prefix: "ldbc" = "ldbc"
+
+ override def connection(databaseTerm: "SCHEMA" | "CATALOG" = "CATALOG"): Resource[IO, Connection[IO]] =
+ ldbc.connector.Connection[IO](
+ host = host,
+ port = port,
+ user = user,
+ password = Some(password),
+ database = Some(database),
+ ssl = SSL.Trusted,
+ databaseTerm = Some(databaseTerm match
+ case "SCHEMA" => DatabaseMetaData.DatabaseTerm.SCHEMA
+ case "CATALOG" => DatabaseMetaData.DatabaseTerm.CATALOG
+ )
+ )
+
+class JdbcConnectionTest extends ConnectionTest:
+
+ val ds = new MysqlDataSource()
+ ds.setServerName(host)
+ ds.setPortNumber(port)
+ ds.setDatabaseName(database)
+ ds.setUser(user)
+ ds.setPassword(password)
+
+ override def prefix: "jdbc" | "ldbc" = "jdbc"
+
+ override def connection(databaseTerm: "SCHEMA" | "CATALOG" = "CATALOG"): Resource[IO, Connection[IO]] =
+ ds.setDatabaseTerm(databaseTerm)
+ Resource.make(jdbc.connector.MysqlDataSource[IO](ds).getConnection)(_.close())
+
+trait ConnectionTest extends CatsEffectSuite:
+
+ given Tracer[IO] = Tracer.noop[IO]
+
+ protected val host: String = "127.0.0.1"
+ protected val port: Int = 13306
+ protected val user: String = "ldbc"
+ protected val password: String = "password"
+ protected val database: String = "connector_test"
+
+ def prefix: "jdbc" | "ldbc"
+ def connection(databaseTerm: "SCHEMA" | "CATALOG" = "CATALOG"): Resource[IO, Connection[IO]]
+
+ test("Catalog change will change the currently connected Catalog.") {
+ assertIO(
+ connection().use { conn =>
+ conn.setCatalog("world") *> conn.getCatalog()
+ },
+ "world"
+ )
+ }
+
+ test("The connection is valid.") {
+ assertIOBoolean(connection().use(_.isValid(0)))
+ }
+
+ test("The allProceduresAreCallable method of DatabaseMetaData is always false.") {
+ assertIOBoolean(connection().use(_.getMetaData().map(meta => !meta.allProceduresAreCallable())))
+ }
+
+ test("The allTablesAreSelectable method of DatabaseMetaData is always false.") {
+ assertIOBoolean(connection().use(_.getMetaData().map(meta => !meta.allTablesAreSelectable())))
+ }
+
+ test("The URL retrieved from DatabaseMetaData matches the specified value.") {
+ assertIO(
+ connection().use(_.getMetaData().map(_.getURL())),
+ "jdbc:mysql://127.0.0.1:13306/connector_test"
+ )
+ }
+
+ test("The User name retrieved from DatabaseMetaData matches the specified value.") {
+ assertIO(
+ connection().use(_.getMetaData().flatMap(_.getUserName())),
+ "ldbc@172.18.0.1"
+ )
+ }
+
+ test("The isReadOnly method of DatabaseMetaData is always false.") {
+ assertIOBoolean(connection().use(_.getMetaData().map(meta => !meta.isReadOnly())))
+ }
+
+ test("The nullsAreSortedHigh method of DatabaseMetaData is always false.") {
+ assertIOBoolean(connection().use(_.getMetaData().map(meta => !meta.nullsAreSortedHigh())))
+ }
+
+ test("The nullsAreSortedLow method of DatabaseMetaData is always true.") {
+ assertIOBoolean(connection().use(_.getMetaData().map(meta => meta.nullsAreSortedLow())))
+ }
+
+ test("The nullsAreSortedAtStart method of DatabaseMetaData is always false.") {
+ assertIOBoolean(connection().use(_.getMetaData().map(meta => !meta.nullsAreSortedAtStart())))
+ }
+
+ test("The nullsAreSortedAtEnd method of DatabaseMetaData is always false.") {
+ assertIOBoolean(connection().use(_.getMetaData().map(meta => !meta.nullsAreSortedAtEnd())))
+ }
+
+ test("The getDatabaseProductName method of DatabaseMetaData is always MySQL.") {
+ assertIO(
+ connection().use(_.getMetaData().map(_.getDatabaseProductName())),
+ "MySQL"
+ )
+ }
+
+ test("The Server version retrieved from DatabaseMetaData matches the specified value.") {
+ assertIO(
+ connection().use(_.getMetaData().map(_.getDatabaseProductVersion())),
+ "8.4.0"
+ )
+ }
+
+ test("The getDriverName method of DatabaseMetaData is always MySQL Connector/L.") {
+ assertIO(
+ connection().use(_.getMetaData().map(_.getDriverName())),
+ if prefix == "jdbc" then "MySQL Connector/J" else "MySQL Connector/L"
+ )
+ }
+
+ test("The Driver version retrieved from DatabaseMetaData matches the specified value.") {
+ assertIO(
+ connection().use(_.getMetaData().map(_.getDriverVersion())),
+ if prefix == "jdbc" then "mysql-connector-j-8.4.0 (Revision: 1c3f5c149e0bfe31c7fbeb24e2d260cd890972c4)"
+ else "ldbc-connector-0.3.0"
+ )
+ }
+
+ test("The usesLocalFiles method of DatabaseMetaData is always false.") {
+ assertIOBoolean(connection().use(_.getMetaData().map(meta => !meta.usesLocalFiles())))
+ }
+
+ test("The usesLocalFilePerTable method of DatabaseMetaData is always false.") {
+ assertIOBoolean(connection().use(_.getMetaData().map(meta => !meta.usesLocalFilePerTable())))
+ }
+
+ test("The supports Mixed Case Identifiers retrieved from DatabaseMetaData matches the specified value.") {
+ assertIOBoolean(connection().use(_.getMetaData().map(_.supportsMixedCaseIdentifiers())))
+ }
+
+ test("The storesUpperCaseIdentifiers method of DatabaseMetaData is always false.") {
+ assertIOBoolean(connection().use(_.getMetaData().map(meta => !meta.storesUpperCaseIdentifiers())))
+ }
+
+ test("The stores Lower Case Identifiers retrieved from DatabaseMetaData matches the specified value.") {
+ assertIOBoolean(connection().use(_.getMetaData().map(meta => !meta.storesLowerCaseIdentifiers())))
+ }
+
+ test("The stores Mixed Case Identifiers retrieved from DatabaseMetaData matches the specified value.") {
+ assertIOBoolean(connection().use(_.getMetaData().map(_.storesMixedCaseIdentifiers())))
+ }
+
+ test("The supports Mixed Case Quoted Identifiers retrieved from DatabaseMetaData matches the specified value.") {
+ assertIOBoolean(connection().use(_.getMetaData().map(_.supportsMixedCaseQuotedIdentifiers())))
+ }
+
+ test("The storesUpperCaseQuotedIdentifiers method of DatabaseMetaData is always true.") {
+ assertIOBoolean(connection().use(_.getMetaData().map(_.storesUpperCaseQuotedIdentifiers())))
+ }
+
+ test("The stores Lower Case Quoted Identifiers retrieved from DatabaseMetaData matches the specified value.") {
+ assertIOBoolean(connection().use(_.getMetaData().map(meta => !meta.storesLowerCaseQuotedIdentifiers())))
+ }
+
+ test("The stores Mixed Case Quoted Identifiers retrieved from DatabaseMetaData matches the specified value.") {
+ assertIOBoolean(connection().use(_.getMetaData().map(_.storesMixedCaseQuotedIdentifiers())))
+ }
+
+ test("The Identifier Quote String retrieved from DatabaseMetaData matches the specified value.") {
+ assertIO(
+ connection().use(_.getMetaData().map(_.getIdentifierQuoteString())),
+ "`"
+ )
+ }
+
+ test("The SQL Keywords retrieved from DatabaseMetaData matches the specified value.") {
+ assertIO(
+ connection().use(_.getMetaData().flatMap(_.getSQLKeywords())),
+ "ACCESSIBLE,ADD,ANALYZE,ASC,BEFORE,CASCADE,CHANGE,CONTINUE,DATABASE,DATABASES,DAY_HOUR,DAY_MICROSECOND,DAY_MINUTE,DAY_SECOND,DELAYED,DESC,DISTINCTROW,DIV,DUAL,ELSEIF,EMPTY,ENCLOSED,ESCAPED,EXIT,EXPLAIN,FIRST_VALUE,FLOAT4,FLOAT8,FORCE,FULLTEXT,GENERATED,GROUPS,HIGH_PRIORITY,HOUR_MICROSECOND,HOUR_MINUTE,HOUR_SECOND,IF,IGNORE,INDEX,INFILE,INT1,INT2,INT3,INT4,INT8,IO_AFTER_GTIDS,IO_BEFORE_GTIDS,ITERATE,JSON_TABLE,KEY,KEYS,KILL,LAG,LAST_VALUE,LEAD,LEAVE,LIMIT,LINEAR,LINES,LOAD,LOCK,LONG,LONGBLOB,LONGTEXT,LOOP,LOW_PRIORITY,MAXVALUE,MEDIUMBLOB,MEDIUMINT,MEDIUMTEXT,MIDDLEINT,MINUTE_MICROSECOND,MINUTE_SECOND,NO_WRITE_TO_BINLOG,NTH_VALUE,NTILE,OPTIMIZE,OPTIMIZER_COSTS,OPTION,OPTIONALLY,OUTFILE,PURGE,READ,READ_WRITE,REGEXP,RENAME,REPEAT,REPLACE,REQUIRE,RESIGNAL,RESTRICT,RLIKE,SCHEMA,SCHEMAS,SECOND_MICROSECOND,SEPARATOR,SHOW,SIGNAL,SPATIAL,SQL_BIG_RESULT,SQL_CALC_FOUND_ROWS,SQL_SMALL_RESULT,SSL,STARTING,STORED,STRAIGHT_JOIN,TERMINATED,TINYBLOB,TINYINT,TINYTEXT,UNDO,UNLOCK,UNSIGNED,USAGE,USE,UTC_DATE,UTC_TIME,UTC_TIMESTAMP,VARBINARY,VARCHARACTER,VIRTUAL,WHILE,WRITE,XOR,YEAR_MONTH,ZEROFILL"
+ )
+ }
+
+ test("The Numeric Functions retrieved from DatabaseMetaData matches the specified value.") {
+ assertIO(
+ connection().use(_.getMetaData().map(_.getNumericFunctions())),
+ "ABS,ACOS,ASIN,ATAN,ATAN2,BIT_COUNT,CEILING,COS,COT,DEGREES,EXP,FLOOR,LOG,LOG10,MAX,MIN,MOD,PI,POW,POWER,RADIANS,RAND,ROUND,SIN,SQRT,TAN,TRUNCATE"
+ )
+ }
+
+ test("The String Functions retrieved from DatabaseMetaData matches the specified value.") {
+ assertIO(
+ connection().use(_.getMetaData().map(_.getStringFunctions())),
+ "ASCII,BIN,BIT_LENGTH,CHAR,CHARACTER_LENGTH,CHAR_LENGTH,CONCAT,CONCAT_WS,CONV,ELT,EXPORT_SET,FIELD,FIND_IN_SET,HEX,INSERT,"
+ + "INSTR,LCASE,LEFT,LENGTH,LOAD_FILE,LOCATE,LOCATE,LOWER,LPAD,LTRIM,MAKE_SET,MATCH,MID,OCT,OCTET_LENGTH,ORD,POSITION,"
+ + "QUOTE,REPEAT,REPLACE,REVERSE,RIGHT,RPAD,RTRIM,SOUNDEX,SPACE,STRCMP,SUBSTRING,SUBSTRING,SUBSTRING,SUBSTRING,"
+ + "SUBSTRING_INDEX,TRIM,UCASE,UPPER"
+ )
+ }
+
+ test("The System Functions retrieved from DatabaseMetaData matches the specified value.") {
+ assertIO(
+ connection().use(_.getMetaData().map(_.getSystemFunctions())),
+ "DATABASE,USER,SYSTEM_USER,SESSION_USER,PASSWORD,ENCRYPT,LAST_INSERT_ID,VERSION"
+ )
+ }
+
+ test("The Time Date Functions retrieved from DatabaseMetaData matches the specified value.") {
+ assertIO(
+ connection().use(_.getMetaData().map(_.getTimeDateFunctions())),
+ "DAYOFWEEK,WEEKDAY,DAYOFMONTH,DAYOFYEAR,MONTH,DAYNAME,MONTHNAME,QUARTER,WEEK,YEAR,HOUR,MINUTE,SECOND,PERIOD_ADD,"
+ + "PERIOD_DIFF,TO_DAYS,FROM_DAYS,DATE_FORMAT,TIME_FORMAT,CURDATE,CURRENT_DATE,CURTIME,CURRENT_TIME,NOW,SYSDATE,"
+ + "CURRENT_TIMESTAMP,UNIX_TIMESTAMP,FROM_UNIXTIME,SEC_TO_TIME,TIME_TO_SEC"
+ )
+ }
+
+ test("The Search String Escape retrieved from DatabaseMetaData matches the specified value.") {
+ assertIO(
+ connection().use(_.getMetaData().map(_.getSearchStringEscape())),
+ "\\"
+ )
+ }
+
+ test("The Extra Name Characters retrieved from DatabaseMetaData matches the specified value.") {
+ assertIO(
+ connection().use(_.getMetaData().map(_.getExtraNameCharacters())),
+ "$"
+ )
+ }
+
+ test("The result of retrieving procedure information matches the specified value.") {
+ assertIO(
+ connection().use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getProcedures(Some("connector_test"), None, Some("demoSp"))
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val procedureCat = resultSet.getString("PROCEDURE_CAT")
+ val procedureSchem = resultSet.getString("PROCEDURE_SCHEM")
+ val procedureName = resultSet.getString("PROCEDURE_NAME")
+ val remarks = resultSet.getString("REMARKS")
+ val procedureType = resultSet.getString("PROCEDURE_TYPE")
+ builder += s"Procedure Catalog: $procedureCat, Procedure Schema: $procedureSchem, Procedure Name: $procedureName, Remarks: $remarks, Procedure Type: $procedureType"
+ builder.result()
+ },
+ Vector(
+ "Procedure Catalog: connector_test, Procedure Schema: null, Procedure Name: demoSp, Remarks: , Procedure Type: 1"
+ )
+ )
+ }
+
+ test("The result of retrieving procedure columns information matches the specified value.") {
+ assertIO(
+ connection().use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getProcedureColumns(Some("connector_test"), None, Some("demoSp"), None)
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val procedureCat = resultSet.getString("PROCEDURE_CAT")
+ val procedureSchem = resultSet.getString("PROCEDURE_SCHEM")
+ val procedureName = resultSet.getString("PROCEDURE_NAME")
+ val columnName = resultSet.getString("COLUMN_NAME")
+ val columnType = resultSet.getString("COLUMN_TYPE")
+ builder += s"Procedure Catalog: $procedureCat, Procedure Schema: $procedureSchem, Procedure Name: $procedureName, Column Name: $columnName, Column Type: $columnType"
+ builder.result()
+ },
+ Vector(
+ "Procedure Catalog: connector_test, Procedure Schema: null, Procedure Name: demoSp, Column Name: inputParam, Column Type: 1",
+ "Procedure Catalog: connector_test, Procedure Schema: null, Procedure Name: demoSp, Column Name: inOutParam, Column Type: 2"
+ )
+ )
+ }
+
+ test("The result of retrieving tables information matches the specified value.") {
+ assertIO(
+ connection().use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getTables(Some("connector_test"), None, Some("all_types"), Array.empty[String])
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val tableCat = resultSet.getString("TABLE_CAT")
+ val tableSchem = resultSet.getString("TABLE_SCHEM")
+ val tableName = resultSet.getString("TABLE_NAME")
+ val tableType = resultSet.getString("TABLE_TYPE")
+ val remarks = resultSet.getString("REMARKS")
+ val typeCat = resultSet.getString("TYPE_CAT")
+ val typeSchem = resultSet.getString("TYPE_SCHEM")
+ val typeName = resultSet.getString("TYPE_NAME")
+ val selfReferencingColName = resultSet.getString("SELF_REFERENCING_COL_NAME")
+ val refGeneration = resultSet.getString("REF_GENERATION")
+ builder += s"Table Catalog: $tableCat, Table Schema: $tableSchem, Table Name: $tableName, Table Type: $tableType, Remarks: $remarks, Type Catalog: $typeCat, Type Schema: $typeSchem, Type Name: $typeName, Self Referencing Column Name: $selfReferencingColName, Reference Generation: $refGeneration"
+ builder.result()
+ },
+ Vector(
+ "Table Catalog: connector_test, Table Schema: null, Table Name: all_types, Table Type: TABLE, Remarks: , Type Catalog: null, Type Schema: null, Type Name: null, Self Referencing Column Name: null, Reference Generation: null"
+ )
+ )
+ }
+
+ test("The result of retrieving schemas information matches the specified value.") {
+ assertIO(
+ connection("SCHEMA").use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getSchemas()
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val tableCatalog = resultSet.getString("TABLE_CATALOG")
+ val tableSchem = resultSet.getString("TABLE_SCHEM")
+ builder += s"Table Catalog: $tableCatalog, Table Schema: $tableSchem"
+ builder.result()
+ },
+ Vector(
+ "Table Catalog: def, Table Schema: benchmark",
+ "Table Catalog: def, Table Schema: connector_test",
+ "Table Catalog: def, Table Schema: information_schema",
+ "Table Catalog: def, Table Schema: mysql",
+ "Table Catalog: def, Table Schema: performance_schema",
+ "Table Catalog: def, Table Schema: sys",
+ "Table Catalog: def, Table Schema: world",
+ "Table Catalog: def, Table Schema: world2"
+ )
+ )
+ }
+
+ test("The result of retrieving catalogs information matches the specified value.") {
+ assertIO(
+ connection().use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getCatalogs()
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do builder += s"Table Catalog: ${ resultSet.getString("TABLE_CAT") }"
+ builder.result()
+ },
+ Vector(
+ "Table Catalog: benchmark",
+ "Table Catalog: connector_test",
+ "Table Catalog: information_schema",
+ "Table Catalog: mysql",
+ "Table Catalog: performance_schema",
+ "Table Catalog: sys",
+ "Table Catalog: world",
+ "Table Catalog: world2"
+ )
+ )
+ }
+
+ test("The result of retrieving tableTypes information matches the specified value.") {
+ assertIO(
+ connection().use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet = metaData.getTableTypes()
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do builder += s"Table Type: ${ resultSet.getString("TABLE_TYPE") }"
+ builder.result()
+ },
+ Vector(
+ "Table Type: LOCAL TEMPORARY",
+ "Table Type: SYSTEM TABLE",
+ "Table Type: SYSTEM VIEW",
+ "Table Type: TABLE",
+ "Table Type: VIEW"
+ )
+ )
+ }
+
+ test("The result of retrieving column privileges information matches the specified value.") {
+ assertIO(
+ connection().use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getColumnPrivileges(Some("connector_test"), None, Some("privileges_table"), None)
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val tableCat = resultSet.getString("TABLE_CAT")
+ val tableSchem = resultSet.getString("TABLE_SCHEM")
+ val tableName = resultSet.getString("TABLE_NAME")
+ val columnName = resultSet.getString("COLUMN_NAME")
+ val grantor = resultSet.getString("GRANTOR")
+ val grantee = resultSet.getString("GRANTEE")
+ val privilege = resultSet.getString("PRIVILEGE")
+ val isGrantable = resultSet.getString("IS_GRANTABLE")
+ builder += s"Table Cat: $tableCat, Table Schem: $tableSchem, Table Name: $tableName, Column Name: $columnName, Grantor: $grantor, Grantee: $grantee, Privilege: $privilege, Is Grantable: $isGrantable"
+ builder.result()
+ },
+ Vector(
+ "Table Cat: connector_test, Table Schem: null, Table Name: privileges_table, Column Name: c1, Grantor: null, Grantee: 'ldbc'@'%', Privilege: INSERT, Is Grantable: NO",
+ "Table Cat: connector_test, Table Schem: null, Table Name: privileges_table, Column Name: c1, Grantor: null, Grantee: 'ldbc'@'%', Privilege: SELECT, Is Grantable: NO",
+ "Table Cat: connector_test, Table Schem: null, Table Name: privileges_table, Column Name: c2, Grantor: null, Grantee: 'ldbc'@'%', Privilege: INSERT, Is Grantable: NO",
+ "Table Cat: connector_test, Table Schem: null, Table Name: privileges_table, Column Name: c2, Grantor: null, Grantee: 'ldbc'@'%', Privilege: SELECT, Is Grantable: NO"
+ )
+ )
+ }
+
+ test("The result of retrieving table privileges information matches the specified value.") {
+ assertIO(
+ connection().use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getTablePrivileges(None, None, Some("privileges_table"))
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val tableCat = resultSet.getString("TABLE_CAT")
+ val tableSchem = resultSet.getString("TABLE_SCHEM")
+ val tableName = resultSet.getString("TABLE_NAME")
+ val grantor = resultSet.getString("GRANTOR")
+ val grantee = resultSet.getString("GRANTEE")
+ val privilege = resultSet.getString("PRIVILEGE")
+ val isGrantable = resultSet.getString("IS_GRANTABLE")
+ builder += s"Table Cat: $tableCat, Table Schem: $tableSchem, Table Name: $tableName, Grantor: $grantor, Grantee: $grantee, Privilege: $privilege, Is Grantable: $isGrantable"
+ builder.result()
+ },
+ Vector(
+ "Table Cat: connector_test, Table Schem: null, Table Name: privileges_table, Grantor: root@localhost, Grantee: ldbc@%, Privilege: SELECT, Is Grantable: null",
+ "Table Cat: connector_test, Table Schem: null, Table Name: privileges_table, Grantor: root@localhost, Grantee: ldbc@%, Privilege: SELECT, Is Grantable: null",
+ "Table Cat: connector_test, Table Schem: null, Table Name: privileges_table, Grantor: root@localhost, Grantee: ldbc@%, Privilege: SELECT, Is Grantable: null",
+ "Table Cat: connector_test, Table Schem: null, Table Name: privileges_table, Grantor: root@localhost, Grantee: ldbc@%, Privilege: INSERT, Is Grantable: null",
+ "Table Cat: connector_test, Table Schem: null, Table Name: privileges_table, Grantor: root@localhost, Grantee: ldbc@%, Privilege: INSERT, Is Grantable: null",
+ "Table Cat: connector_test, Table Schem: null, Table Name: privileges_table, Grantor: root@localhost, Grantee: ldbc@%, Privilege: INSERT, Is Grantable: null"
+ )
+ )
+ }
+
+ test("The result of retrieving best row identifier information matches the specified value.") {
+ assertIO(
+ connection().use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getBestRowIdentifier(None, Some("connector_test"), "privileges_table", None, None)
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val scope = resultSet.getShort("SCOPE")
+ val columnName = resultSet.getString("COLUMN_NAME")
+ val dataType = resultSet.getInt("DATA_TYPE")
+ val typeName = resultSet.getString("TYPE_NAME")
+ val columnSize = resultSet.getInt("COLUMN_SIZE")
+ val bufferLength = resultSet.getInt("BUFFER_LENGTH")
+ val decimalDigits = resultSet.getShort("DECIMAL_DIGITS")
+ val pseudoColumn = resultSet.getShort("PSEUDO_COLUMN")
+ builder += s"Scope: $scope, Column Name: $columnName, Data Type: $dataType, Type Name: $typeName, Column Size: $columnSize, Buffer Length: $bufferLength, Decimal Digits: $decimalDigits, Pseudo Column: $pseudoColumn"
+ builder.result()
+ },
+ Vector(
+ "Scope: 2, Column Name: c1, Data Type: 4, Type Name: int, Column Size: 10, Buffer Length: 65535, Decimal Digits: 0, Pseudo Column: 1"
+ )
+ )
+ }
+
+ test("The result of retrieving version columns information matches the specified value.") {
+ assertIO(
+ connection().use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getVersionColumns(None, Some("connector_test"), "privileges_table")
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val scope = resultSet.getShort("SCOPE")
+ val columnName = resultSet.getString("COLUMN_NAME")
+ val dataType = resultSet.getInt("DATA_TYPE")
+ val typeName = resultSet.getString("TYPE_NAME")
+ val columnSize = resultSet.getInt("COLUMN_SIZE")
+ val bufferLength = resultSet.getInt("BUFFER_LENGTH")
+ val decimalDigits = resultSet.getShort("DECIMAL_DIGITS")
+ val pseudoColumn = resultSet.getShort("PSEUDO_COLUMN")
+ builder += s"Scope: $scope, Column Name: $columnName, Data Type: $dataType, Type Name: $typeName, Column Size: $columnSize, Buffer Length: $bufferLength, Decimal Digits: $decimalDigits, Pseudo Column: $pseudoColumn"
+ builder.result()
+ },
+ Vector(
+ "Scope: 0, Column Name: updated_at, Data Type: 93, Type Name: TIMESTAMP, Column Size: 19, Buffer Length: 65535, Decimal Digits: 0, Pseudo Column: 1"
+ )
+ )
+ }
+
+ test("The result of retrieving primary key information matches the specified value.") {
+ assertIO(
+ connection().use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getPrimaryKeys(Some("connector_test"), None, "privileges_table")
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val tableCat = resultSet.getString("TABLE_CAT")
+ val tableSchem = resultSet.getString("TABLE_SCHEM")
+ val tableName = resultSet.getString("TABLE_NAME")
+ val columnName = resultSet.getString("COLUMN_NAME")
+ val keySeq = resultSet.getShort("KEY_SEQ")
+ val pkName = resultSet.getString("PK_NAME")
+ builder += s"Table Cat: $tableCat, Table Schem: $tableSchem, Table Name: $tableName, Column Name: $columnName, Key Seq: $keySeq, PK Name: $pkName"
+ builder.result()
+ },
+ Vector(
+ "Table Cat: connector_test, Table Schem: null, Table Name: privileges_table, Column Name: c1, Key Seq: 1, PK Name: PRIMARY"
+ )
+ )
+ }
+
+ test("The result of retrieving imported key information matches the specified value.") {
+ assertIO(
+ connection().use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getImportedKeys(Some("world"), None, "city")
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val pktableCat = resultSet.getString("PKTABLE_CAT")
+ val pktableSchem = resultSet.getString("PKTABLE_SCHEM")
+ val pktableName = resultSet.getString("PKTABLE_NAME")
+ val pkcolumnName = resultSet.getString("PKCOLUMN_NAME")
+ val fktableCat = resultSet.getString("FKTABLE_CAT")
+ val fktableSchem = resultSet.getString("FKTABLE_SCHEM")
+ val fktableName = resultSet.getString("FKTABLE_NAME")
+ val fkcolumnName = resultSet.getString("FKCOLUMN_NAME")
+ val keySeq = resultSet.getShort("KEY_SEQ")
+ val updateRule = resultSet.getShort("UPDATE_RULE")
+ val deleteRule = resultSet.getShort("DELETE_RULE")
+ val fkName = resultSet.getString("FK_NAME")
+ val pkName = resultSet.getString("PK_NAME")
+ val deferrability = resultSet.getShort("DEFERRABILITY")
+ builder += s"PK Table Cat: $pktableCat, PK Table Schem: $pktableSchem, PK Table Name: $pktableName, PK Column Name: $pkcolumnName, FK Table Cat: $fktableCat, FK Table Schem: $fktableSchem, FK Table Name: $fktableName, FK Column Name: $fkcolumnName, Key Seq: $keySeq, Update Rule: $updateRule, Delete Rule: $deleteRule, FK Name: $fkName, PK Name: $pkName, Deferrability: $deferrability"
+ builder.result()
+ },
+ Vector(
+ "PK Table Cat: world, PK Table Schem: null, PK Table Name: country, PK Column Name: Code, FK Table Cat: world, FK Table Schem: null, FK Table Name: city, FK Column Name: CountryCode, Key Seq: 1, Update Rule: 1, Delete Rule: 1, FK Name: city_ibfk_1, PK Name: PRIMARY, Deferrability: 7"
+ )
+ )
+ }
+
+ test("The result of retrieving exported key information matches the specified value.") {
+ assertIO(
+ connection().use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getExportedKeys(Some("world"), None, "city")
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val pktableCat = resultSet.getString("PKTABLE_CAT")
+ val pktableSchem = resultSet.getString("PKTABLE_SCHEM")
+ val pktableName = resultSet.getString("PKTABLE_NAME")
+ val pkcolumnName = resultSet.getString("PKCOLUMN_NAME")
+ val fktableCat = resultSet.getString("FKTABLE_CAT")
+ val fktableSchem = resultSet.getString("FKTABLE_SCHEM")
+ val fktableName = resultSet.getString("FKTABLE_NAME")
+ val fkcolumnName = resultSet.getString("FKCOLUMN_NAME")
+ val keySeq = resultSet.getShort("KEY_SEQ")
+ val updateRule = resultSet.getShort("UPDATE_RULE")
+ val deleteRule = resultSet.getShort("DELETE_RULE")
+ val fkName = resultSet.getString("FK_NAME")
+ val pkName = resultSet.getString("PK_NAME")
+ val deferrability = resultSet.getShort("DEFERRABILITY")
+ builder += s"PK Table Cat: $pktableCat, PK Table Schem: $pktableSchem, PK Table Name: $pktableName, PK Column Name: $pkcolumnName, FK Table Cat: $fktableCat, FK Table Schem: $fktableSchem, FK Table Name: $fktableName, FK Column Name: $fkcolumnName, Key Seq: $keySeq, Update Rule: $updateRule, Delete Rule: $deleteRule, FK Name: $fkName, PK Name: $pkName, Deferrability: $deferrability"
+ builder.result()
+ },
+ Vector(
+ "PK Table Cat: world, PK Table Schem: null, PK Table Name: city, PK Column Name: ID, FK Table Cat: world, FK Table Schem: null, FK Table Name: government_office, FK Column Name: CityID, Key Seq: 1, Update Rule: 1, Delete Rule: 1, FK Name: government_office_ibfk_1, PK Name: PRIMARY, Deferrability: 7"
+ )
+ )
+ }
+
+ test("The result of retrieving cross reference information matches the specified value.") {
+ assertIO(
+ connection().use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <-
+ metaData.getCrossReference(Some("world"), None, "city", Some("world"), None, Some("government_office"))
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val pktableCat = resultSet.getString("PKTABLE_CAT")
+ val pktableSchem = resultSet.getString("PKTABLE_SCHEM")
+ val pktableName = resultSet.getString("PKTABLE_NAME")
+ val pkcolumnName = resultSet.getString("PKCOLUMN_NAME")
+ val fktableCat = resultSet.getString("FKTABLE_CAT")
+ val fktableSchem = resultSet.getString("FKTABLE_SCHEM")
+ val fktableName = resultSet.getString("FKTABLE_NAME")
+ val fkcolumnName = resultSet.getString("FKCOLUMN_NAME")
+ val keySeq = resultSet.getShort("KEY_SEQ")
+ val updateRule = resultSet.getShort("UPDATE_RULE")
+ val deleteRule = resultSet.getShort("DELETE_RULE")
+ val fkName = resultSet.getString("FK_NAME")
+ val pkName = resultSet.getString("PK_NAME")
+ val deferrability = resultSet.getShort("DEFERRABILITY")
+ builder += s"PK Table Cat: $pktableCat, PK Table Schem: $pktableSchem, PK Table Name: $pktableName, PK Column Name: $pkcolumnName, FK Table Cat: $fktableCat, FK Table Schem: $fktableSchem, FK Table Name: $fktableName, FK Column Name: $fkcolumnName, Key Seq: $keySeq, Update Rule: $updateRule, Delete Rule: $deleteRule, FK Name: $fkName, PK Name: $pkName, Deferrability: $deferrability"
+ builder.result()
+ },
+ Vector(
+ "PK Table Cat: world, PK Table Schem: null, PK Table Name: city, PK Column Name: ID, FK Table Cat: world, FK Table Schem: null, FK Table Name: government_office, FK Column Name: CityID, Key Seq: 1, Update Rule: 1, Delete Rule: 1, FK Name: government_office_ibfk_1, PK Name: PRIMARY, Deferrability: 7"
+ )
+ )
+ }
+
+ test("The result of retrieving type information matches the specified value.") {
+ assertIO(
+ connection().use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet = metaData.getTypeInfo()
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val typeName = resultSet.getString("TYPE_NAME")
+ val dataType = resultSet.getInt("DATA_TYPE")
+ val precision = resultSet.getInt("PRECISION")
+ val literalPrefix = resultSet.getString("LITERAL_PREFIX")
+ val literalSuffix = resultSet.getString("LITERAL_SUFFIX")
+ val createParams = resultSet.getString("CREATE_PARAMS")
+ val nullable = resultSet.getShort("NULLABLE")
+ val caseSensitive = resultSet.getBoolean("CASE_SENSITIVE")
+ val searchable = resultSet.getShort("SEARCHABLE")
+ val unsignedAttribute = resultSet.getBoolean("UNSIGNED_ATTRIBUTE")
+ val fixedPrecScale = resultSet.getBoolean("FIXED_PREC_SCALE")
+ val autoIncrement = resultSet.getBoolean("AUTO_INCREMENT")
+ val localTypeName = resultSet.getString("LOCAL_TYPE_NAME")
+ val minimumScale = resultSet.getShort("MINIMUM_SCALE")
+ val maximumScale = resultSet.getShort("MAXIMUM_SCALE")
+ val sqlDataType = resultSet.getShort("SQL_DATA_TYPE")
+ val sqlDatetimeSub = resultSet.getShort("SQL_DATETIME_SUB")
+ val numPrecRadix = resultSet.getShort("NUM_PREC_RADIX")
+ builder += s"Type Name: $typeName, Data Type: $dataType, Precision: $precision, Literal Prefix: $literalPrefix, Literal Suffix: $literalSuffix, Create Params: $createParams, Nullable: $nullable, Case Sensitive: $caseSensitive, Searchable: $searchable, Unsigned Attribute: $unsignedAttribute, Fixed Prec Scale: $fixedPrecScale, Auto Increment: $autoIncrement, Local Type Name: $localTypeName, Minimum Scale: $minimumScale, Maximum Scale: $maximumScale, SQL Data Type: $sqlDataType, SQL Datetime Sub: $sqlDatetimeSub, Num Prec Radix: $numPrecRadix"
+ builder.result()
+ },
+ Vector(
+ "Type Name: BIT, Data Type: -7, Precision: 1, Literal Prefix: , Literal Suffix: , Create Params: [(M)], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: BIT, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: TINYINT, Data Type: -6, Precision: 3, Literal Prefix: , Literal Suffix: , Create Params: [(M)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: true, Local Type Name: TINYINT, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: TINYINT UNSIGNED, Data Type: -6, Precision: 3, Literal Prefix: , Literal Suffix: , Create Params: [(M)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: true, Fixed Prec Scale: false, Auto Increment: true, Local Type Name: TINYINT UNSIGNED, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: BIGINT, Data Type: -5, Precision: 19, Literal Prefix: , Literal Suffix: , Create Params: [(M)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: true, Local Type Name: BIGINT, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: BIGINT UNSIGNED, Data Type: -5, Precision: 20, Literal Prefix: , Literal Suffix: , Create Params: [(M)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: true, Fixed Prec Scale: false, Auto Increment: true, Local Type Name: BIGINT UNSIGNED, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: LONG VARBINARY, Data Type: -4, Precision: 16777215, Literal Prefix: ', Literal Suffix: ', Create Params: , Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: MEDIUMBLOB, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: MEDIUMBLOB, Data Type: -4, Precision: 16777215, Literal Prefix: ', Literal Suffix: ', Create Params: , Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: MEDIUMBLOB, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: LONGBLOB, Data Type: -4, Precision: 2147483647, Literal Prefix: ', Literal Suffix: ', Create Params: , Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: LONGBLOB, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: BLOB, Data Type: -4, Precision: 65535, Literal Prefix: ', Literal Suffix: ', Create Params: [(M)], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: BLOB, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: VECTOR, Data Type: -4, Precision: 65532, Literal Prefix: ', Literal Suffix: ', Create Params: [(M)], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: VECTOR, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: VARBINARY, Data Type: -3, Precision: 65535, Literal Prefix: ', Literal Suffix: ', Create Params: (M), Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: VARBINARY, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: TINYBLOB, Data Type: -3, Precision: 255, Literal Prefix: ', Literal Suffix: ', Create Params: , Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: TINYBLOB, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: BINARY, Data Type: -2, Precision: 255, Literal Prefix: ', Literal Suffix: ', Create Params: (M), Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: BINARY, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: LONG VARCHAR, Data Type: -1, Precision: 16777215, Literal Prefix: ', Literal Suffix: ', Create Params: [CHARACTER SET charset_name] [COLLATE collation_name], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: MEDIUMTEXT, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: MEDIUMTEXT, Data Type: -1, Precision: 16777215, Literal Prefix: ', Literal Suffix: ', Create Params: [CHARACTER SET charset_name] [COLLATE collation_name], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: MEDIUMTEXT, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: LONGTEXT, Data Type: -1, Precision: 2147483647, Literal Prefix: ', Literal Suffix: ', Create Params: [CHARACTER SET charset_name] [COLLATE collation_name], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: LONGTEXT, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: TEXT, Data Type: -1, Precision: 65535, Literal Prefix: ', Literal Suffix: ', Create Params: [(M)] [CHARACTER SET charset_name] [COLLATE collation_name], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: TEXT, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: CHAR, Data Type: 1, Precision: 255, Literal Prefix: ', Literal Suffix: ', Create Params: [(M)] [CHARACTER SET charset_name] [COLLATE collation_name], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: CHAR, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: ENUM, Data Type: 1, Precision: 65535, Literal Prefix: ', Literal Suffix: ', Create Params: ('value1','value2',...) [CHARACTER SET charset_name] [COLLATE collation_name], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: ENUM, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: SET, Data Type: 1, Precision: 64, Literal Prefix: ', Literal Suffix: ', Create Params: ('value1','value2',...) [CHARACTER SET charset_name] [COLLATE collation_name], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: SET, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: DECIMAL, Data Type: 3, Precision: 65, Literal Prefix: , Literal Suffix: , Create Params: [(M[,D])] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: DECIMAL, Minimum Scale: -308, Maximum Scale: 308, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: NUMERIC, Data Type: 3, Precision: 65, Literal Prefix: , Literal Suffix: , Create Params: [(M[,D])] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: DECIMAL, Minimum Scale: -308, Maximum Scale: 308, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: INTEGER, Data Type: 4, Precision: 10, Literal Prefix: , Literal Suffix: , Create Params: [(M)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: true, Local Type Name: INT, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: INT, Data Type: 4, Precision: 10, Literal Prefix: , Literal Suffix: , Create Params: [(M)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: true, Local Type Name: INT, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: MEDIUMINT, Data Type: 4, Precision: 7, Literal Prefix: , Literal Suffix: , Create Params: [(M)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: true, Local Type Name: MEDIUMINT, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: INTEGER UNSIGNED, Data Type: 4, Precision: 10, Literal Prefix: , Literal Suffix: , Create Params: [(M)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: true, Fixed Prec Scale: false, Auto Increment: true, Local Type Name: INT UNSIGNED, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: INT UNSIGNED, Data Type: 4, Precision: 10, Literal Prefix: , Literal Suffix: , Create Params: [(M)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: true, Fixed Prec Scale: false, Auto Increment: true, Local Type Name: INT UNSIGNED, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: MEDIUMINT UNSIGNED, Data Type: 4, Precision: 8, Literal Prefix: , Literal Suffix: , Create Params: [(M)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: true, Fixed Prec Scale: false, Auto Increment: true, Local Type Name: MEDIUMINT UNSIGNED, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: SMALLINT, Data Type: 5, Precision: 5, Literal Prefix: , Literal Suffix: , Create Params: [(M)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: true, Local Type Name: SMALLINT, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: SMALLINT UNSIGNED, Data Type: 5, Precision: 5, Literal Prefix: , Literal Suffix: , Create Params: [(M)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: true, Fixed Prec Scale: false, Auto Increment: true, Local Type Name: SMALLINT UNSIGNED, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: FLOAT, Data Type: 7, Precision: 12, Literal Prefix: , Literal Suffix: , Create Params: [(M,D)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: FLOAT, Minimum Scale: -38, Maximum Scale: 38, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: DOUBLE, Data Type: 8, Precision: 22, Literal Prefix: , Literal Suffix: , Create Params: [(M,D)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: DOUBLE, Minimum Scale: -308, Maximum Scale: 308, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: DOUBLE PRECISION, Data Type: 8, Precision: 22, Literal Prefix: , Literal Suffix: , Create Params: [(M,D)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: DOUBLE, Minimum Scale: -308, Maximum Scale: 308, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: REAL, Data Type: 8, Precision: 22, Literal Prefix: , Literal Suffix: , Create Params: [(M,D)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: DOUBLE, Minimum Scale: -308, Maximum Scale: 308, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: DOUBLE UNSIGNED, Data Type: 8, Precision: 22, Literal Prefix: , Literal Suffix: , Create Params: [(M,D)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: true, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: DOUBLE UNSIGNED, Minimum Scale: -308, Maximum Scale: 308, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: DOUBLE PRECISION UNSIGNED, Data Type: 8, Precision: 22, Literal Prefix: , Literal Suffix: , Create Params: [(M,D)] [UNSIGNED] [ZEROFILL], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: true, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: DOUBLE UNSIGNED, Minimum Scale: -308, Maximum Scale: 308, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: VARCHAR, Data Type: 12, Precision: 65535, Literal Prefix: ', Literal Suffix: ', Create Params: (M) [CHARACTER SET charset_name] [COLLATE collation_name], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: VARCHAR, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: TINYTEXT, Data Type: 12, Precision: 255, Literal Prefix: ', Literal Suffix: ', Create Params: [CHARACTER SET charset_name] [COLLATE collation_name], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: TINYTEXT, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: BOOL, Data Type: 16, Precision: 3, Literal Prefix: , Literal Suffix: , Create Params: , Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: true, Local Type Name: BOOLEAN, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: DATE, Data Type: 91, Precision: 10, Literal Prefix: ', Literal Suffix: ', Create Params: , Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: DATE, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: YEAR, Data Type: 91, Precision: 4, Literal Prefix: , Literal Suffix: , Create Params: [(4)], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: YEAR, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: TIME, Data Type: 92, Precision: 16, Literal Prefix: ', Literal Suffix: ', Create Params: [(fsp)], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: TIME, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: DATETIME, Data Type: 93, Precision: 26, Literal Prefix: ', Literal Suffix: ', Create Params: [(fsp)], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: DATETIME, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10",
+ "Type Name: TIMESTAMP, Data Type: 93, Precision: 26, Literal Prefix: ', Literal Suffix: ', Create Params: [(fsp)], Nullable: 1, Case Sensitive: true, Searchable: 3, Unsigned Attribute: false, Fixed Prec Scale: false, Auto Increment: false, Local Type Name: TIMESTAMP, Minimum Scale: 0, Maximum Scale: 0, SQL Data Type: 0, SQL Datetime Sub: 0, Num Prec Radix: 10"
+ )
+ )
+ }
+
+ test("The result of retrieving index information matches the specified value.") {
+ assertIO(
+ connection().use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <-
+ metaData.getIndexInfo(Some("world"), None, Some("city"), true, true)
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val tableCat = resultSet.getString("TABLE_CAT")
+ val tableSchem = resultSet.getString("TABLE_SCHEM")
+ val tableName = resultSet.getString("TABLE_NAME")
+ val nonUnique = resultSet.getBoolean("NON_UNIQUE")
+ val indexQualifier = resultSet.getString("INDEX_QUALIFIER")
+ val INDEXNAME = resultSet.getString("INDEX_NAME")
+ val `type` = resultSet.getShort("TYPE")
+ val ordinalPosition = resultSet.getShort("ORDINAL_POSITION")
+ val columnName = resultSet.getString("COLUMN_NAME")
+ val ascOrDesc = resultSet.getString("ASC_OR_DESC")
+ val pages = resultSet.getLong("PAGES")
+ val filterCondition = resultSet.getString("FILTER_CONDITION")
+ builder += s"Table Cat: $tableCat, Table Schem: $tableSchem, Table Name: $tableName, Non Unique: $nonUnique, Index Qualifier: $indexQualifier, Index Name: $INDEXNAME, Type: ${ `type` }, Ordinal Position: $ordinalPosition, Column Name: $columnName, Asc Or Desc: $ascOrDesc, Pages: $pages, Filter Condition: $filterCondition"
+ builder.result()
+ },
+ Vector(
+ "Table Cat: world, Table Schem: null, Table Name: city, Non Unique: false, Index Qualifier: null, Index Name: PRIMARY, Type: 3, Ordinal Position: 1, Column Name: ID, Asc Or Desc: A, Pages: 0, Filter Condition: null"
+ )
+ )
+ }
+
+ test("The result of retrieving function information matches the specified value.") {
+ assertIO(
+ connection().use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getFunctions(Some("sys"), None, None)
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val functionCat = resultSet.getString("FUNCTION_CAT")
+ val functionSchem = resultSet.getString("FUNCTION_SCHEM")
+ val functionName = resultSet.getString("FUNCTION_NAME")
+ val functionType = resultSet.getShort("FUNCTION_TYPE")
+ val specificName = resultSet.getString("SPECIFIC_NAME")
+ builder += s"Function Cat: $functionCat, Function Schem: $functionSchem, Function Name: $functionName, Function Type: $functionType, Specific Name: $specificName"
+ builder.result()
+ },
+ Vector(
+ "Function Cat: sys, Function Schem: null, Function Name: extract_schema_from_file_name, Function Type: 1, Specific Name: extract_schema_from_file_name",
+ "Function Cat: sys, Function Schem: null, Function Name: extract_table_from_file_name, Function Type: 1, Specific Name: extract_table_from_file_name",
+ "Function Cat: sys, Function Schem: null, Function Name: format_bytes, Function Type: 1, Specific Name: format_bytes",
+ "Function Cat: sys, Function Schem: null, Function Name: format_path, Function Type: 1, Specific Name: format_path",
+ "Function Cat: sys, Function Schem: null, Function Name: format_statement, Function Type: 1, Specific Name: format_statement",
+ "Function Cat: sys, Function Schem: null, Function Name: format_time, Function Type: 1, Specific Name: format_time",
+ "Function Cat: sys, Function Schem: null, Function Name: list_add, Function Type: 1, Specific Name: list_add",
+ "Function Cat: sys, Function Schem: null, Function Name: list_drop, Function Type: 1, Specific Name: list_drop",
+ "Function Cat: sys, Function Schem: null, Function Name: ps_is_account_enabled, Function Type: 1, Specific Name: ps_is_account_enabled",
+ "Function Cat: sys, Function Schem: null, Function Name: ps_is_consumer_enabled, Function Type: 1, Specific Name: ps_is_consumer_enabled",
+ "Function Cat: sys, Function Schem: null, Function Name: ps_is_instrument_default_enabled, Function Type: 1, Specific Name: ps_is_instrument_default_enabled",
+ "Function Cat: sys, Function Schem: null, Function Name: ps_is_instrument_default_timed, Function Type: 1, Specific Name: ps_is_instrument_default_timed",
+ "Function Cat: sys, Function Schem: null, Function Name: ps_is_thread_instrumented, Function Type: 1, Specific Name: ps_is_thread_instrumented",
+ "Function Cat: sys, Function Schem: null, Function Name: ps_thread_account, Function Type: 1, Specific Name: ps_thread_account",
+ "Function Cat: sys, Function Schem: null, Function Name: ps_thread_id, Function Type: 1, Specific Name: ps_thread_id",
+ "Function Cat: sys, Function Schem: null, Function Name: ps_thread_stack, Function Type: 1, Specific Name: ps_thread_stack",
+ "Function Cat: sys, Function Schem: null, Function Name: ps_thread_trx_info, Function Type: 1, Specific Name: ps_thread_trx_info",
+ "Function Cat: sys, Function Schem: null, Function Name: quote_identifier, Function Type: 1, Specific Name: quote_identifier",
+ "Function Cat: sys, Function Schem: null, Function Name: sys_get_config, Function Type: 1, Specific Name: sys_get_config",
+ "Function Cat: sys, Function Schem: null, Function Name: version_major, Function Type: 1, Specific Name: version_major",
+ "Function Cat: sys, Function Schem: null, Function Name: version_minor, Function Type: 1, Specific Name: version_minor",
+ "Function Cat: sys, Function Schem: null, Function Name: version_patch, Function Type: 1, Specific Name: version_patch"
+ )
+ )
+ }
+
+ test("The result of retrieving function column information matches the specified value.") {
+ assertIO(
+ connection().use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getFunctionColumns(Some("sys"), None, None, Some("in_host"))
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val functionCat = resultSet.getString("FUNCTION_CAT")
+ val functionSchem = resultSet.getString("FUNCTION_SCHEM")
+ val functionName = resultSet.getString("FUNCTION_NAME")
+ val columnName = resultSet.getString("COLUMN_NAME")
+ val columnType = resultSet.getShort("COLUMN_TYPE")
+ val dataType = resultSet.getInt("DATA_TYPE")
+ val typeName = resultSet.getString("TYPE_NAME")
+ val precision = resultSet.getInt("PRECISION")
+ val length = resultSet.getInt("LENGTH")
+ val scale = resultSet.getShort("SCALE")
+ val radix = resultSet.getShort("RADIX")
+ val nullable = resultSet.getShort("NULLABLE")
+ val remarks = resultSet.getString("REMARKS")
+ val charOctetLength = resultSet.getInt("CHAR_OCTET_LENGTH")
+ val ordinalPosition = resultSet.getInt("ORDINAL_POSITION")
+ val isNullable = resultSet.getString("IS_NULLABLE")
+ val specificName = resultSet.getString("SPECIFIC_NAME")
+ builder += s"Function Cat: $functionCat, Function Schem: $functionSchem, Function Name: $functionName, Column Name: $columnName, Column Type: $columnType, Data Type: $dataType, Type Name: $typeName, Precision: $precision, Length: $length, Scale: $scale, Radix: $radix, Nullable: $nullable, Remarks: $remarks, Char Octet Length: $charOctetLength, Ordinal Position: $ordinalPosition, Is Nullable: $isNullable, Specific Name: $specificName"
+
+ builder.result()
+ },
+ Vector(
+ "Function Cat: sys, Function Schem: null, Function Name: extract_schema_from_file_name, Column Name: , Column Type: 4, Data Type: 12, Type Name: VARCHAR, Precision: 0, Length: 64, Scale: 0, Radix: 10, Nullable: 1, Remarks: null, Char Octet Length: 256, Ordinal Position: 0, Is Nullable: YES, Specific Name: extract_schema_from_file_name",
+ "Function Cat: sys, Function Schem: null, Function Name: extract_table_from_file_name, Column Name: , Column Type: 4, Data Type: 12, Type Name: VARCHAR, Precision: 0, Length: 64, Scale: 0, Radix: 10, Nullable: 1, Remarks: null, Char Octet Length: 256, Ordinal Position: 0, Is Nullable: YES, Specific Name: extract_table_from_file_name",
+ "Function Cat: sys, Function Schem: null, Function Name: format_bytes, Column Name: , Column Type: 4, Data Type: -1, Type Name: TEXT, Precision: 0, Length: 65535, Scale: 0, Radix: 10, Nullable: 1, Remarks: null, Char Octet Length: 65535, Ordinal Position: 0, Is Nullable: YES, Specific Name: format_bytes",
+ "Function Cat: sys, Function Schem: null, Function Name: format_path, Column Name: , Column Type: 4, Data Type: 12, Type Name: VARCHAR, Precision: 0, Length: 512, Scale: 0, Radix: 10, Nullable: 1, Remarks: null, Char Octet Length: 2048, Ordinal Position: 0, Is Nullable: YES, Specific Name: format_path",
+ "Function Cat: sys, Function Schem: null, Function Name: format_statement, Column Name: , Column Type: 4, Data Type: -1, Type Name: LONGTEXT, Precision: 0, Length: 2147483647, Scale: 0, Radix: 10, Nullable: 1, Remarks: null, Char Octet Length: 2147483647, Ordinal Position: 0, Is Nullable: YES, Specific Name: format_statement",
+ "Function Cat: sys, Function Schem: null, Function Name: format_time, Column Name: , Column Type: 4, Data Type: -1, Type Name: TEXT, Precision: 0, Length: 65535, Scale: 0, Radix: 10, Nullable: 1, Remarks: null, Char Octet Length: 65535, Ordinal Position: 0, Is Nullable: YES, Specific Name: format_time",
+ "Function Cat: sys, Function Schem: null, Function Name: list_add, Column Name: , Column Type: 4, Data Type: -1, Type Name: TEXT, Precision: 0, Length: 65535, Scale: 0, Radix: 10, Nullable: 1, Remarks: null, Char Octet Length: 65535, Ordinal Position: 0, Is Nullable: YES, Specific Name: list_add",
+ "Function Cat: sys, Function Schem: null, Function Name: list_drop, Column Name: , Column Type: 4, Data Type: -1, Type Name: TEXT, Precision: 0, Length: 65535, Scale: 0, Radix: 10, Nullable: 1, Remarks: null, Char Octet Length: 65535, Ordinal Position: 0, Is Nullable: YES, Specific Name: list_drop",
+ "Function Cat: sys, Function Schem: null, Function Name: ps_is_account_enabled, Column Name: , Column Type: 4, Data Type: 1, Type Name: ENUM, Precision: 0, Length: 3, Scale: 0, Radix: 10, Nullable: 1, Remarks: null, Char Octet Length: 12, Ordinal Position: 0, Is Nullable: YES, Specific Name: ps_is_account_enabled",
+ "Function Cat: sys, Function Schem: null, Function Name: ps_is_account_enabled, Column Name: in_host, Column Type: 1, Data Type: 12, Type Name: VARCHAR, Precision: 0, Length: 255, Scale: 0, Radix: 10, Nullable: 1, Remarks: null, Char Octet Length: 1020, Ordinal Position: 1, Is Nullable: YES, Specific Name: ps_is_account_enabled",
+ "Function Cat: sys, Function Schem: null, Function Name: ps_is_consumer_enabled, Column Name: , Column Type: 4, Data Type: 1, Type Name: ENUM, Precision: 0, Length: 3, Scale: 0, Radix: 10, Nullable: 1, Remarks: null, Char Octet Length: 12, Ordinal Position: 0, Is Nullable: YES, Specific Name: ps_is_consumer_enabled",
+ "Function Cat: sys, Function Schem: null, Function Name: ps_is_instrument_default_enabled, Column Name: , Column Type: 4, Data Type: 1, Type Name: ENUM, Precision: 0, Length: 3, Scale: 0, Radix: 10, Nullable: 1, Remarks: null, Char Octet Length: 12, Ordinal Position: 0, Is Nullable: YES, Specific Name: ps_is_instrument_default_enabled",
+ "Function Cat: sys, Function Schem: null, Function Name: ps_is_instrument_default_timed, Column Name: , Column Type: 4, Data Type: 1, Type Name: ENUM, Precision: 0, Length: 3, Scale: 0, Radix: 10, Nullable: 1, Remarks: null, Char Octet Length: 12, Ordinal Position: 0, Is Nullable: YES, Specific Name: ps_is_instrument_default_timed",
+ "Function Cat: sys, Function Schem: null, Function Name: ps_is_thread_instrumented, Column Name: , Column Type: 4, Data Type: 1, Type Name: ENUM, Precision: 0, Length: 7, Scale: 0, Radix: 10, Nullable: 1, Remarks: null, Char Octet Length: 28, Ordinal Position: 0, Is Nullable: YES, Specific Name: ps_is_thread_instrumented",
+ "Function Cat: sys, Function Schem: null, Function Name: ps_thread_account, Column Name: , Column Type: 4, Data Type: -1, Type Name: TEXT, Precision: 0, Length: 65535, Scale: 0, Radix: 10, Nullable: 1, Remarks: null, Char Octet Length: 65535, Ordinal Position: 0, Is Nullable: YES, Specific Name: ps_thread_account",
+ "Function Cat: sys, Function Schem: null, Function Name: ps_thread_id, Column Name: , Column Type: 4, Data Type: -5, Type Name: BIGINT UNSIGNED, Precision: 20, Length: 20, Scale: 0, Radix: 10, Nullable: 1, Remarks: null, Char Octet Length: 0, Ordinal Position: 0, Is Nullable: YES, Specific Name: ps_thread_id",
+ "Function Cat: sys, Function Schem: null, Function Name: ps_thread_stack, Column Name: , Column Type: 4, Data Type: -1, Type Name: LONGTEXT, Precision: 0, Length: 2147483647, Scale: 0, Radix: 10, Nullable: 1, Remarks: null, Char Octet Length: 2147483647, Ordinal Position: 0, Is Nullable: YES, Specific Name: ps_thread_stack",
+ "Function Cat: sys, Function Schem: null, Function Name: ps_thread_trx_info, Column Name: , Column Type: 4, Data Type: -1, Type Name: LONGTEXT, Precision: 0, Length: 2147483647, Scale: 0, Radix: 10, Nullable: 1, Remarks: null, Char Octet Length: 2147483647, Ordinal Position: 0, Is Nullable: YES, Specific Name: ps_thread_trx_info",
+ "Function Cat: sys, Function Schem: null, Function Name: quote_identifier, Column Name: , Column Type: 4, Data Type: -1, Type Name: TEXT, Precision: 0, Length: 65535, Scale: 0, Radix: 10, Nullable: 1, Remarks: null, Char Octet Length: 65535, Ordinal Position: 0, Is Nullable: YES, Specific Name: quote_identifier",
+ "Function Cat: sys, Function Schem: null, Function Name: sys_get_config, Column Name: , Column Type: 4, Data Type: 12, Type Name: VARCHAR, Precision: 0, Length: 128, Scale: 0, Radix: 10, Nullable: 1, Remarks: null, Char Octet Length: 512, Ordinal Position: 0, Is Nullable: YES, Specific Name: sys_get_config",
+ "Function Cat: sys, Function Schem: null, Function Name: version_major, Column Name: , Column Type: 4, Data Type: -6, Type Name: TINYINT UNSIGNED, Precision: 3, Length: 3, Scale: 0, Radix: 10, Nullable: 1, Remarks: null, Char Octet Length: 0, Ordinal Position: 0, Is Nullable: YES, Specific Name: version_major",
+ "Function Cat: sys, Function Schem: null, Function Name: version_minor, Column Name: , Column Type: 4, Data Type: -6, Type Name: TINYINT UNSIGNED, Precision: 3, Length: 3, Scale: 0, Radix: 10, Nullable: 1, Remarks: null, Char Octet Length: 0, Ordinal Position: 0, Is Nullable: YES, Specific Name: version_minor",
+ "Function Cat: sys, Function Schem: null, Function Name: version_patch, Column Name: , Column Type: 4, Data Type: -6, Type Name: TINYINT UNSIGNED, Precision: 3, Length: 3, Scale: 0, Radix: 10, Nullable: 1, Remarks: null, Char Octet Length: 0, Ordinal Position: 0, Is Nullable: YES, Specific Name: version_patch"
+ )
+ )
+ }
+
+ test("The result of retrieving columns information matches the specified value.") {
+ assertIO(
+ connection("SCHEMA").use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getColumns(None, None, Some("privileges_table"), None)
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val tableCat = resultSet.getString("TABLE_CAT")
+ val tableSchem = resultSet.getString("TABLE_SCHEM")
+ val tableName = resultSet.getString("TABLE_NAME")
+ val columnName = resultSet.getString("COLUMN_NAME")
+ val dataType = resultSet.getInt("DATA_TYPE")
+ val typeName = resultSet.getString("TYPE_NAME")
+ val columnSize = resultSet.getInt("COLUMN_SIZE")
+ val bufferLength = resultSet.getInt("BUFFER_LENGTH")
+ val decimalDigits = resultSet.getInt("DECIMAL_DIGITS")
+ val numPrecRadix = resultSet.getInt("NUM_PREC_RADIX")
+ val nullable = resultSet.getInt("NULLABLE")
+ val remarks = resultSet.getString("REMARKS")
+ val columnDef = resultSet.getString("COLUMN_DEF")
+ val sqlDataType = resultSet.getInt("SQL_DATA_TYPE")
+ val sqlDatetimeSub = resultSet.getInt("SQL_DATETIME_SUB")
+ val charOctetLength = resultSet.getInt("CHAR_OCTET_LENGTH")
+ val ordinalPosition = resultSet.getInt("ORDINAL_POSITION")
+ val isNullable = resultSet.getString("IS_NULLABLE")
+ val scopeCatalog = resultSet.getString("SCOPE_CATALOG")
+ val scopeSchema = resultSet.getString("SCOPE_SCHEMA")
+ val scopeTable = resultSet.getString("SCOPE_TABLE")
+ val sourceDataType = resultSet.getShort("SOURCE_DATA_TYPE")
+ val isAutoincrement = resultSet.getString("IS_AUTOINCREMENT")
+ val isGeneratedcolumn = resultSet.getString("IS_GENERATEDCOLUMN")
+ builder += s"Table Cat: $tableCat, Table Schem: $tableSchem, Table Name: $tableName, Column Name: $columnName, Data Type: $dataType, Type Name: $typeName, Column Size: $columnSize, Buffer Length: $bufferLength, Decimal Digits: $decimalDigits, Num Prec Radix: $numPrecRadix, Nullable: $nullable, Remarks: $remarks, Column Def: $columnDef, SQL Data Type: $sqlDataType, SQL Datetime Sub: $sqlDatetimeSub, Char Octet Length: $charOctetLength, Ordinal Position: $ordinalPosition, Is Nullable: $isNullable, Scope Catalog: $scopeCatalog, Scope Schema: $scopeSchema, Scope Table: $scopeTable, Source Data Type: $sourceDataType, Is Autoincrement: $isAutoincrement, Is Generatedcolumn: $isGeneratedcolumn"
+ builder.result()
+ },
+ Vector(
+ "Table Cat: def, Table Schem: connector_test, Table Name: privileges_table, Column Name: c1, Data Type: 4, Type Name: INT, Column Size: 10, Buffer Length: 65535, Decimal Digits: 0, Num Prec Radix: 10, Nullable: 0, Remarks: , Column Def: null, SQL Data Type: 0, SQL Datetime Sub: 0, Char Octet Length: 0, Ordinal Position: 1, Is Nullable: NO, Scope Catalog: null, Scope Schema: null, Scope Table: null, Source Data Type: 0, Is Autoincrement: NO, Is Generatedcolumn: NO",
+ "Table Cat: def, Table Schem: connector_test, Table Name: privileges_table, Column Name: c2, Data Type: 4, Type Name: INT, Column Size: 10, Buffer Length: 65535, Decimal Digits: 0, Num Prec Radix: 10, Nullable: 0, Remarks: , Column Def: null, SQL Data Type: 0, SQL Datetime Sub: 0, Char Octet Length: 0, Ordinal Position: 2, Is Nullable: NO, Scope Catalog: null, Scope Schema: null, Scope Table: null, Source Data Type: 0, Is Autoincrement: NO, Is Generatedcolumn: NO",
+ "Table Cat: def, Table Schem: connector_test, Table Name: privileges_table, Column Name: updated_at, Data Type: 93, Type Name: TIMESTAMP, Column Size: 19, Buffer Length: 65535, Decimal Digits: 0, Num Prec Radix: 10, Nullable: 0, Remarks: , Column Def: CURRENT_TIMESTAMP, SQL Data Type: 0, SQL Datetime Sub: 0, Char Octet Length: 0, Ordinal Position: 3, Is Nullable: NO, Scope Catalog: null, Scope Schema: null, Scope Table: null, Source Data Type: 0, Is Autoincrement: NO, Is Generatedcolumn: YES"
+ )
+ )
+ }
diff --git a/tests/src/test/scala/ldbc/tests/DatabaseMetaDataTest.scala b/tests/src/test/scala/ldbc/tests/DatabaseMetaDataTest.scala
new file mode 100644
index 000000000..6ed6d805c
--- /dev/null
+++ b/tests/src/test/scala/ldbc/tests/DatabaseMetaDataTest.scala
@@ -0,0 +1,2389 @@
+/**
+ * Copyright (c) 2023-2024 by Takahiko Tominaga
+ * This software is licensed under the MIT License (MIT).
+ * For more information see LICENSE or https://opensource.org/licenses/MIT
+ */
+
+package ldbc.tests
+
+import com.mysql.cj.jdbc.MysqlDataSource
+
+import cats.effect.*
+
+import org.typelevel.otel4s.trace.Tracer
+
+import munit.*
+
+import ldbc.sql.*
+import ldbc.connector.SSL
+
+class LdbcDatabaseMetaDataTest extends DatabaseMetaDataTest:
+ override def prefix: "ldbc" = "ldbc"
+
+ override def connection: Resource[IO, Connection[IO]] =
+ ldbc.connector.Connection[IO](
+ host = host,
+ port = port,
+ user = user,
+ password = Some(password),
+ database = Some(database),
+ ssl = SSL.Trusted
+ )
+
+class JdbcDatabaseMetaDataTest extends DatabaseMetaDataTest:
+
+ val ds = new MysqlDataSource()
+ ds.setServerName(host)
+ ds.setPortNumber(port)
+ ds.setDatabaseName(database)
+ ds.setUser(user)
+ ds.setPassword(password)
+
+ override def prefix: "jdbc" | "ldbc" = "jdbc"
+
+ override def connection: Resource[IO, Connection[IO]] =
+ Resource.make(jdbc.connector.MysqlDataSource[IO](ds).getConnection)(_.close())
+
+trait DatabaseMetaDataTest extends CatsEffectSuite:
+
+ given Tracer[IO] = Tracer.noop[IO]
+
+ protected val host: String = "127.0.0.1"
+ protected val port: Int = 13306
+ protected val user: String = "ldbc"
+ protected val password: String = "password"
+ protected val database: String = "connector_test"
+
+ def prefix: "jdbc" | "ldbc"
+ def connection: Resource[IO, Connection[IO]]
+
+ test(s"$prefix: allTablesAreSelectable") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.allTablesAreSelectable()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: getURL") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getURL()
+ },
+ s"jdbc:mysql://$host:$port/$database"
+ )
+ }
+
+ test(s"$prefix: getUserName") {
+ assertIO(
+ connection.use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ value <- metaData.getUserName()
+ yield value
+ },
+ s"$user@172.18.0.1"
+ )
+ }
+
+ test(s"$prefix: isReadOnly") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.isReadOnly()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: nullsAreSortedHigh") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.nullsAreSortedHigh()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: nullsAreSortedLow") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.nullsAreSortedLow()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: nullsAreSortedAtStart") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.nullsAreSortedAtStart()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: nullsAreSortedAtEnd") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.nullsAreSortedAtEnd()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: getDatabaseProductName") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getDatabaseProductName()
+ },
+ "MySQL"
+ )
+ }
+
+ test(s"$prefix: getDatabaseProductVersion") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getDatabaseProductVersion()
+ },
+ "8.4.0"
+ )
+ }
+
+ test(s"$prefix: getDriverName") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getDriverName()
+ },
+ if prefix == "ldbc" then "MySQL Connector/L" else "MySQL Connector/J"
+ )
+ }
+
+ test(s"$prefix: getDriverVersion") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getDriverVersion()
+ },
+ if prefix == "jdbc" then "mysql-connector-j-8.4.0 (Revision: 1c3f5c149e0bfe31c7fbeb24e2d260cd890972c4)"
+ else "ldbc-connector-0.3.0"
+ )
+ }
+
+ test(s"$prefix: getDriverMajorVersion") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getDriverMajorVersion()
+ },
+ if prefix == "jdbc" then 8 else 0
+ )
+ }
+
+ test(s"$prefix: getDriverMinorVersion") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getDriverMinorVersion()
+ },
+ if prefix == "jdbc" then 4 else 3
+ )
+ }
+
+ test(s"$prefix: usesLocalFiles") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.usesLocalFiles()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: usesLocalFilePerTable") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.usesLocalFilePerTable()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: supportsMixedCaseIdentifiers") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsMixedCaseIdentifiers()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: storesUpperCaseIdentifiers") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.storesUpperCaseIdentifiers()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: storesLowerCaseIdentifiers") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.storesLowerCaseIdentifiers()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: storesMixedCaseIdentifiers") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.storesMixedCaseIdentifiers()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsMixedCaseQuotedIdentifiers") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsMixedCaseQuotedIdentifiers()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: storesUpperCaseQuotedIdentifiers") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.storesUpperCaseQuotedIdentifiers()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: storesLowerCaseQuotedIdentifiers") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.storesLowerCaseQuotedIdentifiers()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: storesMixedCaseQuotedIdentifiers") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.storesMixedCaseQuotedIdentifiers()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: getIdentifierQuoteString") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getIdentifierQuoteString()
+ },
+ "`"
+ )
+ }
+
+ test(s"$prefix: getSQLKeywords") {
+ assertIO(
+ connection.use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ value <- metaData.getSQLKeywords()
+ yield value
+ },
+ "ACCESSIBLE,ADD,ANALYZE,ASC,BEFORE,CASCADE,CHANGE,CONTINUE,DATABASE,DATABASES,DAY_HOUR,DAY_MICROSECOND,DAY_MINUTE,DAY_SECOND,DELAYED,DESC,DISTINCTROW,DIV,DUAL,ELSEIF,EMPTY,ENCLOSED,ESCAPED,EXIT,EXPLAIN,FIRST_VALUE,FLOAT4,FLOAT8,FORCE,FULLTEXT,GENERATED,GROUPS,HIGH_PRIORITY,HOUR_MICROSECOND,HOUR_MINUTE,HOUR_SECOND,IF,IGNORE,INDEX,INFILE,INT1,INT2,INT3,INT4,INT8,IO_AFTER_GTIDS,IO_BEFORE_GTIDS,ITERATE,JSON_TABLE,KEY,KEYS,KILL,LAG,LAST_VALUE,LEAD,LEAVE,LIMIT,LINEAR,LINES,LOAD,LOCK,LONG,LONGBLOB,LONGTEXT,LOOP,LOW_PRIORITY,MAXVALUE,MEDIUMBLOB,MEDIUMINT,MEDIUMTEXT,MIDDLEINT,MINUTE_MICROSECOND,MINUTE_SECOND,NO_WRITE_TO_BINLOG,NTH_VALUE,NTILE,OPTIMIZE,OPTIMIZER_COSTS,OPTION,OPTIONALLY,OUTFILE,PURGE,READ,READ_WRITE,REGEXP,RENAME,REPEAT,REPLACE,REQUIRE,RESIGNAL,RESTRICT,RLIKE,SCHEMA,SCHEMAS,SECOND_MICROSECOND,SEPARATOR,SHOW,SIGNAL,SPATIAL,SQL_BIG_RESULT,SQL_CALC_FOUND_ROWS,SQL_SMALL_RESULT,SSL,STARTING,STORED,STRAIGHT_JOIN,TERMINATED,TINYBLOB,TINYINT,TINYTEXT,UNDO,UNLOCK,UNSIGNED,USAGE,USE,UTC_DATE,UTC_TIME,UTC_TIMESTAMP,VARBINARY,VARCHARACTER,VIRTUAL,WHILE,WRITE,XOR,YEAR_MONTH,ZEROFILL"
+ )
+ }
+
+ test(s"$prefix: getNumericFunctions") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getNumericFunctions()
+ },
+ "ABS,ACOS,ASIN,ATAN,ATAN2,BIT_COUNT,CEILING,COS,COT,DEGREES,EXP,FLOOR,LOG,LOG10,MAX,MIN,MOD,PI,POW,POWER,RADIANS,RAND,ROUND,SIN,SQRT,TAN,TRUNCATE"
+ )
+ }
+
+ test(s"$prefix: getStringFunctions") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getStringFunctions()
+ },
+ "ASCII,BIN,BIT_LENGTH,CHAR,CHARACTER_LENGTH,CHAR_LENGTH,CONCAT,CONCAT_WS,CONV,ELT,EXPORT_SET,FIELD,FIND_IN_SET,HEX,INSERT,INSTR,LCASE,LEFT,LENGTH,LOAD_FILE,LOCATE,LOCATE,LOWER,LPAD,LTRIM,MAKE_SET,MATCH,MID,OCT,OCTET_LENGTH,ORD,POSITION,QUOTE,REPEAT,REPLACE,REVERSE,RIGHT,RPAD,RTRIM,SOUNDEX,SPACE,STRCMP,SUBSTRING,SUBSTRING,SUBSTRING,SUBSTRING,SUBSTRING_INDEX,TRIM,UCASE,UPPER"
+ )
+ }
+
+ test(s"$prefix: getSystemFunctions") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getSystemFunctions()
+ },
+ "DATABASE,USER,SYSTEM_USER,SESSION_USER,PASSWORD,ENCRYPT,LAST_INSERT_ID,VERSION"
+ )
+ }
+
+ test(s"$prefix: getTimeDateFunctions") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getTimeDateFunctions()
+ },
+ "DAYOFWEEK,WEEKDAY,DAYOFMONTH,DAYOFYEAR,MONTH,DAYNAME,MONTHNAME,QUARTER,WEEK,YEAR,HOUR,MINUTE,SECOND,PERIOD_ADD,PERIOD_DIFF,TO_DAYS,FROM_DAYS,DATE_FORMAT,TIME_FORMAT,CURDATE,CURRENT_DATE,CURTIME,CURRENT_TIME,NOW,SYSDATE,CURRENT_TIMESTAMP,UNIX_TIMESTAMP,FROM_UNIXTIME,SEC_TO_TIME,TIME_TO_SEC"
+ )
+ }
+
+ test(s"$prefix: getSearchStringEscape") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getSearchStringEscape()
+ },
+ "\\"
+ )
+ }
+
+ test(s"$prefix: getExtraNameCharacters") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getExtraNameCharacters()
+ },
+ "$"
+ )
+ }
+
+ test(s"$prefix: supportsAlterTableWithAddColumn") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsAlterTableWithAddColumn()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsAlterTableWithDropColumn") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsAlterTableWithDropColumn()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsColumnAliasing") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsColumnAliasing()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: nullPlusNonNullIsNull") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.nullPlusNonNullIsNull()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsConvert") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsConvert()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: supportsTableCorrelationNames") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsTableCorrelationNames()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsDifferentTableCorrelationNames") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsDifferentTableCorrelationNames()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsExpressionsInOrderBy") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsExpressionsInOrderBy()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsOrderByUnrelated") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsOrderByUnrelated()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: supportsGroupBy") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsGroupBy()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsGroupByUnrelated") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsGroupByUnrelated()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsGroupByBeyondSelect") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsGroupByBeyondSelect()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsLikeEscapeClause") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsLikeEscapeClause()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsMultipleResultSets") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsMultipleResultSets()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsMultipleTransactions") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsMultipleTransactions()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsNonNullableColumns") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsNonNullableColumns()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsMinimumSQLGrammar") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsMinimumSQLGrammar()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsCoreSQLGrammar") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsCoreSQLGrammar()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsExtendedSQLGrammar") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsExtendedSQLGrammar()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: supportsANSI92EntryLevelSQL") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsANSI92EntryLevelSQL()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsANSI92IntermediateSQL") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsANSI92IntermediateSQL()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: supportsANSI92FullSQL") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsANSI92FullSQL()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: supportsIntegrityEnhancementFacility") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsIntegrityEnhancementFacility()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: supportsOuterJoins") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsOuterJoins()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsLimitedOuterJoins") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsLimitedOuterJoins()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: getSchemaTerm") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getSchemaTerm()
+ },
+ ""
+ )
+ }
+
+ test(s"$prefix: getProcedureTerm") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getProcedureTerm()
+ },
+ "PROCEDURE"
+ )
+ }
+
+ test(s"$prefix: getCatalogTerm") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getCatalogTerm()
+ },
+ "database"
+ )
+ }
+
+ test(s"$prefix: isCatalogAtStart") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.isCatalogAtStart()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: getCatalogSeparator") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getCatalogSeparator()
+ },
+ "."
+ )
+ }
+
+ test(s"$prefix: supportsSchemasInDataManipulation") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsSchemasInDataManipulation()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: supportsSchemasInProcedureCalls") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsSchemasInProcedureCalls()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: supportsSchemasInTableDefinitions") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsSchemasInTableDefinitions()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: supportsSchemasInIndexDefinitions") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsSchemasInIndexDefinitions()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: supportsSchemasInPrivilegeDefinitions") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsSchemasInPrivilegeDefinitions()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: supportsCatalogsInDataManipulation") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsCatalogsInDataManipulation()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsCatalogsInProcedureCalls") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsCatalogsInProcedureCalls()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsCatalogsInTableDefinitions") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsCatalogsInTableDefinitions()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsCatalogsInIndexDefinitions") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsCatalogsInIndexDefinitions()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsCatalogsInPrivilegeDefinitions") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsCatalogsInPrivilegeDefinitions()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsPositionedDelete") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsPositionedDelete()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: supportsPositionedUpdate") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsPositionedUpdate()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: supportsSelectForUpdate") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsSelectForUpdate()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsStoredProcedures") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsStoredProcedures()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsSubqueriesInComparisons") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsSubqueriesInComparisons()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsSubqueriesInExists") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsSubqueriesInExists()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsSubqueriesInIns") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsSubqueriesInIns()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsSubqueriesInQuantifieds") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsSubqueriesInQuantifieds()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsCorrelatedSubqueries") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsCorrelatedSubqueries()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsUnion") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsUnion()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsUnionAll") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsUnionAll()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsOpenCursorsAcrossCommit") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsOpenCursorsAcrossCommit()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: supportsOpenCursorsAcrossRollback") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsOpenCursorsAcrossRollback()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: supportsOpenStatementsAcrossCommit") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsOpenStatementsAcrossCommit()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: supportsOpenStatementsAcrossRollback") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsOpenStatementsAcrossRollback()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: getMaxBinaryLiteralLength") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getMaxBinaryLiteralLength()
+ },
+ 16777208
+ )
+ }
+
+ test(s"$prefix: getMaxCharLiteralLength") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getMaxCharLiteralLength()
+ },
+ 16777208
+ )
+ }
+
+ test(s"$prefix: getMaxColumnNameLength") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getMaxColumnNameLength()
+ },
+ 64
+ )
+ }
+
+ test(s"$prefix: getMaxColumnsInGroupBy") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getMaxColumnsInGroupBy()
+ },
+ 64
+ )
+ }
+
+ test(s"$prefix: getMaxColumnsInIndex") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getMaxColumnsInIndex()
+ },
+ 16
+ )
+ }
+
+ test(s"$prefix: getMaxColumnsInOrderBy") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getMaxColumnsInOrderBy()
+ },
+ 64
+ )
+ }
+
+ test(s"$prefix: getMaxColumnsInSelect") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getMaxColumnsInSelect()
+ },
+ 256
+ )
+ }
+
+ test(s"$prefix: getMaxColumnsInTable") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getMaxColumnsInTable()
+ },
+ 512
+ )
+ }
+
+ test(s"$prefix: getMaxConnections") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getMaxConnections()
+ },
+ 0
+ )
+ }
+
+ test(s"$prefix: getMaxCursorNameLength") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getMaxCursorNameLength()
+ },
+ 64
+ )
+ }
+
+ test(s"$prefix: getMaxIndexLength") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getMaxIndexLength()
+ },
+ 256
+ )
+ }
+
+ test(s"$prefix: getMaxSchemaNameLength") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getMaxSchemaNameLength()
+ },
+ 0
+ )
+ }
+
+ test(s"$prefix: getMaxProcedureNameLength") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getMaxProcedureNameLength()
+ },
+ 0
+ )
+ }
+
+ test(s"$prefix: getMaxCatalogNameLength") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getMaxCatalogNameLength()
+ },
+ 32
+ )
+ }
+
+ test(s"$prefix: getMaxRowSize") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getMaxRowSize()
+ },
+ 2147483639
+ )
+ }
+
+ test(s"$prefix: doesMaxRowSizeIncludeBlobs") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.doesMaxRowSizeIncludeBlobs()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: getMaxStatementLength") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getMaxStatementLength()
+ },
+ 65531
+ )
+ }
+
+ test(s"$prefix: getMaxStatements") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getMaxStatements()
+ },
+ 0
+ )
+ }
+
+ test(s"$prefix: getMaxTableNameLength") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getMaxTableNameLength()
+ },
+ 64
+ )
+ }
+
+ test(s"$prefix: getMaxTablesInSelect") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getMaxTablesInSelect()
+ },
+ 256
+ )
+ }
+
+ test(s"$prefix: getMaxUserNameLength") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getMaxUserNameLength()
+ },
+ 16
+ )
+ }
+
+ test(s"$prefix: getDefaultTransactionIsolation") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getDefaultTransactionIsolation()
+ },
+ 4
+ )
+ }
+
+ test(s"$prefix: supportsTransactions") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsTransactions()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsTransactionIsolationLevel") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsTransactionIsolationLevel(2)
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsDataDefinitionAndDataManipulationTransactions") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsDataDefinitionAndDataManipulationTransactions()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: supportsDataManipulationTransactionsOnly") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsDataManipulationTransactionsOnly()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: dataDefinitionCausesTransactionCommit") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.dataDefinitionCausesTransactionCommit()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: dataDefinitionIgnoredInTransactions") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.dataDefinitionIgnoredInTransactions()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: getProcedures") {
+ assertIO(
+ connection.use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getProcedures(None, None, None)
+ yield
+ val builder = List.newBuilder[String]
+ while resultSet.next() do
+ val procedureCat = resultSet.getString("PROCEDURE_CAT")
+ val procedureSchem = resultSet.getString("PROCEDURE_SCHEM")
+ val procedureName = resultSet.getString("PROCEDURE_NAME")
+ val procedureType = resultSet.getShort("PROCEDURE_TYPE")
+ val specificName = resultSet.getString("SPECIFIC_NAME")
+ builder += s"$procedureCat, $procedureSchem, $procedureName, $procedureType, $specificName"
+ builder.result()
+ },
+ List(
+ "connector_test, null, demoSp, 1, demoSp",
+ "connector_test, null, func1, 2, func1",
+ "connector_test, null, func2, 2, func2",
+ "connector_test, null, getPrice, 2, getPrice",
+ "connector_test, null, proc1, 1, proc1",
+ "connector_test, null, proc2, 1, proc2",
+ "connector_test, null, proc3, 1, proc3",
+ "connector_test, null, proc4, 1, proc4",
+ "sys, null, create_synonym_db, 1, create_synonym_db",
+ "sys, null, diagnostics, 1, diagnostics",
+ "sys, null, execute_prepared_stmt, 1, execute_prepared_stmt",
+ "sys, null, extract_schema_from_file_name, 2, extract_schema_from_file_name",
+ "sys, null, extract_table_from_file_name, 2, extract_table_from_file_name",
+ "sys, null, format_bytes, 2, format_bytes",
+ "sys, null, format_path, 2, format_path",
+ "sys, null, format_statement, 2, format_statement",
+ "sys, null, format_time, 2, format_time",
+ "sys, null, list_add, 2, list_add",
+ "sys, null, list_drop, 2, list_drop",
+ "sys, null, ps_is_account_enabled, 2, ps_is_account_enabled",
+ "sys, null, ps_is_consumer_enabled, 2, ps_is_consumer_enabled",
+ "sys, null, ps_is_instrument_default_enabled, 2, ps_is_instrument_default_enabled",
+ "sys, null, ps_is_instrument_default_timed, 2, ps_is_instrument_default_timed",
+ "sys, null, ps_is_thread_instrumented, 2, ps_is_thread_instrumented",
+ "sys, null, ps_setup_disable_background_threads, 1, ps_setup_disable_background_threads",
+ "sys, null, ps_setup_disable_consumer, 1, ps_setup_disable_consumer",
+ "sys, null, ps_setup_disable_instrument, 1, ps_setup_disable_instrument",
+ "sys, null, ps_setup_disable_thread, 1, ps_setup_disable_thread",
+ "sys, null, ps_setup_enable_background_threads, 1, ps_setup_enable_background_threads",
+ "sys, null, ps_setup_enable_consumer, 1, ps_setup_enable_consumer",
+ "sys, null, ps_setup_enable_instrument, 1, ps_setup_enable_instrument",
+ "sys, null, ps_setup_enable_thread, 1, ps_setup_enable_thread",
+ "sys, null, ps_setup_reload_saved, 1, ps_setup_reload_saved",
+ "sys, null, ps_setup_reset_to_default, 1, ps_setup_reset_to_default",
+ "sys, null, ps_setup_save, 1, ps_setup_save",
+ "sys, null, ps_setup_show_disabled, 1, ps_setup_show_disabled",
+ "sys, null, ps_setup_show_disabled_consumers, 1, ps_setup_show_disabled_consumers",
+ "sys, null, ps_setup_show_disabled_instruments, 1, ps_setup_show_disabled_instruments",
+ "sys, null, ps_setup_show_enabled, 1, ps_setup_show_enabled",
+ "sys, null, ps_setup_show_enabled_consumers, 1, ps_setup_show_enabled_consumers",
+ "sys, null, ps_setup_show_enabled_instruments, 1, ps_setup_show_enabled_instruments",
+ "sys, null, ps_statement_avg_latency_histogram, 1, ps_statement_avg_latency_histogram",
+ "sys, null, ps_thread_account, 2, ps_thread_account",
+ "sys, null, ps_thread_id, 2, ps_thread_id",
+ "sys, null, ps_thread_stack, 2, ps_thread_stack",
+ "sys, null, ps_thread_trx_info, 2, ps_thread_trx_info",
+ "sys, null, ps_trace_statement_digest, 1, ps_trace_statement_digest",
+ "sys, null, ps_trace_thread, 1, ps_trace_thread",
+ "sys, null, ps_truncate_all_tables, 1, ps_truncate_all_tables",
+ "sys, null, quote_identifier, 2, quote_identifier",
+ "sys, null, statement_performance_analyzer, 1, statement_performance_analyzer",
+ "sys, null, sys_get_config, 2, sys_get_config",
+ "sys, null, table_exists, 1, table_exists",
+ "sys, null, version_major, 2, version_major",
+ "sys, null, version_minor, 2, version_minor",
+ "sys, null, version_patch, 2, version_patch"
+ )
+ )
+ }
+
+ test(s"$prefix: getProcedureColumns") {
+ assertIO(
+ connection.use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getProcedureColumns(None, None, None, None)
+ yield
+ val builder = List.newBuilder[String]
+ while resultSet.next() do
+ val procedureCat = resultSet.getString("PROCEDURE_CAT")
+ val procedureSchem = resultSet.getString("PROCEDURE_SCHEM")
+ val procedureName = resultSet.getString("PROCEDURE_NAME")
+ val columnName = resultSet.getString("COLUMN_NAME")
+ val columnType = resultSet.getInt("COLUMN_TYPE")
+ val dataType = resultSet.getInt("DATA_TYPE")
+ val typeName = resultSet.getString("TYPE_NAME")
+ val precision = resultSet.getInt("PRECISION")
+ val length = resultSet.getInt("LENGTH")
+ val scale = resultSet.getInt("SCALE")
+ val radix = resultSet.getInt("RADIX")
+ val nullable = resultSet.getInt("NULLABLE")
+ val remarks = resultSet.getString("REMARKS")
+ val columnDef = resultSet.getString("COLUMN_DEF")
+ val sqlDataType = resultSet.getInt("SQL_DATA_TYPE")
+ val sqlDatetimeSub = resultSet.getInt("SQL_DATETIME_SUB")
+ val charOctetLength = resultSet.getInt("CHAR_OCTET_LENGTH")
+ val ordinalPosition = resultSet.getInt("ORDINAL_POSITION")
+ val isNullable = resultSet.getString("IS_NULLABLE")
+ builder += s"$procedureCat, $procedureSchem, $procedureName, $columnName, $columnType, $dataType, $typeName, $precision, $length, $scale, $radix, $nullable, $remarks, $columnDef, $sqlDataType, $sqlDatetimeSub, $charOctetLength, $ordinalPosition, $isNullable"
+ builder.result()
+ },
+ List(
+ "connector_test, null, demoSp, inputParam, 1, 12, VARCHAR, 0, 255, 0, 10, 1, null, null, 0, 0, 1020, 1, YES",
+ "connector_test, null, demoSp, inOutParam, 2, 4, INT, 10, 10, 0, 10, 1, null, null, 0, 0, 0, 2, YES",
+ "connector_test, null, func1, , 5, 4, INT, 10, 10, 0, 10, 1, null, null, 0, 0, 0, 0, YES",
+ "connector_test, null, func2, , 5, 12, VARCHAR, 0, 12, 0, 10, 1, null, null, 0, 0, 48, 0, YES",
+ "connector_test, null, getPrice, , 5, 4, INT, 10, 10, 0, 10, 1, null, null, 0, 0, 0, 0, YES",
+ "connector_test, null, getPrice, price, 1, 4, INT, 10, 10, 0, 10, 1, null, null, 0, 0, 0, 1, YES",
+ "connector_test, null, proc2, param, 1, 4, INT, 10, 10, 0, 10, 1, null, null, 0, 0, 0, 1, YES",
+ "connector_test, null, proc3, param1, 1, 4, INT, 10, 10, 0, 10, 1, null, null, 0, 0, 0, 1, YES",
+ "connector_test, null, proc3, param2, 1, 12, VARCHAR, 0, 8, 0, 10, 1, null, null, 0, 0, 32, 2, YES",
+ "connector_test, null, proc4, param1, 4, 4, INT, 10, 10, 0, 10, 1, null, null, 0, 0, 0, 1, YES",
+ "connector_test, null, proc4, param2, 4, 12, VARCHAR, 0, 8, 0, 10, 1, null, null, 0, 0, 32, 2, YES",
+ "sys, null, create_synonym_db, in_db_name, 1, 12, VARCHAR, 0, 64, 0, 10, 1, null, null, 0, 0, 256, 1, YES",
+ "sys, null, create_synonym_db, in_synonym, 1, 12, VARCHAR, 0, 64, 0, 10, 1, null, null, 0, 0, 256, 2, YES",
+ "sys, null, diagnostics, in_max_runtime, 1, 4, INT UNSIGNED, 10, 10, 0, 10, 1, null, null, 0, 0, 0, 1, YES",
+ "sys, null, diagnostics, in_interval, 1, 4, INT UNSIGNED, 10, 10, 0, 10, 1, null, null, 0, 0, 0, 2, YES",
+ "sys, null, diagnostics, in_auto_config, 1, 1, ENUM, 0, 7, 0, 10, 1, null, null, 0, 0, 28, 3, YES",
+ "sys, null, execute_prepared_stmt, in_query, 1, -1, LONGTEXT, 0, 2147483647, 0, 10, 1, null, null, 0, 0, 2147483647, 1, YES",
+ "sys, null, extract_schema_from_file_name, , 5, 12, VARCHAR, 0, 64, 0, 10, 1, null, null, 0, 0, 256, 0, YES",
+ "sys, null, extract_schema_from_file_name, path, 1, 12, VARCHAR, 0, 512, 0, 10, 1, null, null, 0, 0, 2048, 1, YES",
+ "sys, null, extract_table_from_file_name, , 5, 12, VARCHAR, 0, 64, 0, 10, 1, null, null, 0, 0, 256, 0, YES",
+ "sys, null, extract_table_from_file_name, path, 1, 12, VARCHAR, 0, 512, 0, 10, 1, null, null, 0, 0, 2048, 1, YES",
+ "sys, null, format_bytes, , 5, -1, TEXT, 0, 65535, 0, 10, 1, null, null, 0, 0, 65535, 0, YES",
+ "sys, null, format_bytes, bytes, 1, -1, TEXT, 0, 65535, 0, 10, 1, null, null, 0, 0, 65535, 1, YES",
+ "sys, null, format_path, , 5, 12, VARCHAR, 0, 512, 0, 10, 1, null, null, 0, 0, 2048, 0, YES",
+ "sys, null, format_path, in_path, 1, 12, VARCHAR, 0, 512, 0, 10, 1, null, null, 0, 0, 2048, 1, YES",
+ "sys, null, format_statement, , 5, -1, LONGTEXT, 0, 2147483647, 0, 10, 1, null, null, 0, 0, 2147483647, 0, YES",
+ "sys, null, format_statement, statement, 1, -1, LONGTEXT, 0, 2147483647, 0, 10, 1, null, null, 0, 0, 2147483647, 1, YES",
+ "sys, null, format_time, , 5, -1, TEXT, 0, 65535, 0, 10, 1, null, null, 0, 0, 65535, 0, YES",
+ "sys, null, format_time, picoseconds, 1, -1, TEXT, 0, 65535, 0, 10, 1, null, null, 0, 0, 65535, 1, YES",
+ "sys, null, list_add, , 5, -1, TEXT, 0, 65535, 0, 10, 1, null, null, 0, 0, 65535, 0, YES",
+ "sys, null, list_add, in_list, 1, -1, TEXT, 0, 65535, 0, 10, 1, null, null, 0, 0, 65535, 1, YES",
+ "sys, null, list_add, in_add_value, 1, -1, TEXT, 0, 65535, 0, 10, 1, null, null, 0, 0, 65535, 2, YES",
+ "sys, null, list_drop, , 5, -1, TEXT, 0, 65535, 0, 10, 1, null, null, 0, 0, 65535, 0, YES",
+ "sys, null, list_drop, in_list, 1, -1, TEXT, 0, 65535, 0, 10, 1, null, null, 0, 0, 65535, 1, YES",
+ "sys, null, list_drop, in_drop_value, 1, -1, TEXT, 0, 65535, 0, 10, 1, null, null, 0, 0, 65535, 2, YES",
+ "sys, null, ps_is_account_enabled, , 5, 1, ENUM, 0, 3, 0, 10, 1, null, null, 0, 0, 12, 0, YES",
+ "sys, null, ps_is_account_enabled, in_host, 1, 12, VARCHAR, 0, 255, 0, 10, 1, null, null, 0, 0, 1020, 1, YES",
+ "sys, null, ps_is_account_enabled, in_user, 1, 12, VARCHAR, 0, 32, 0, 10, 1, null, null, 0, 0, 128, 2, YES",
+ "sys, null, ps_is_consumer_enabled, , 5, 1, ENUM, 0, 3, 0, 10, 1, null, null, 0, 0, 12, 0, YES",
+ "sys, null, ps_is_consumer_enabled, in_consumer, 1, 12, VARCHAR, 0, 64, 0, 10, 1, null, null, 0, 0, 256, 1, YES",
+ "sys, null, ps_is_instrument_default_enabled, , 5, 1, ENUM, 0, 3, 0, 10, 1, null, null, 0, 0, 12, 0, YES",
+ "sys, null, ps_is_instrument_default_enabled, in_instrument, 1, 12, VARCHAR, 0, 128, 0, 10, 1, null, null, 0, 0, 512, 1, YES",
+ "sys, null, ps_is_instrument_default_timed, , 5, 1, ENUM, 0, 3, 0, 10, 1, null, null, 0, 0, 12, 0, YES",
+ "sys, null, ps_is_instrument_default_timed, in_instrument, 1, 12, VARCHAR, 0, 128, 0, 10, 1, null, null, 0, 0, 512, 1, YES",
+ "sys, null, ps_is_thread_instrumented, , 5, 1, ENUM, 0, 7, 0, 10, 1, null, null, 0, 0, 28, 0, YES",
+ "sys, null, ps_is_thread_instrumented, in_connection_id, 1, -5, BIGINT UNSIGNED, 20, 20, 0, 10, 1, null, null, 0, 0, 0, 1, YES",
+ "sys, null, ps_setup_disable_consumer, consumer, 1, 12, VARCHAR, 0, 128, 0, 10, 1, null, null, 0, 0, 512, 1, YES",
+ "sys, null, ps_setup_disable_instrument, in_pattern, 1, 12, VARCHAR, 0, 128, 0, 10, 1, null, null, 0, 0, 512, 1, YES",
+ "sys, null, ps_setup_disable_thread, in_connection_id, 1, -5, BIGINT, 19, 19, 0, 10, 1, null, null, 0, 0, 0, 1, YES",
+ "sys, null, ps_setup_enable_consumer, consumer, 1, 12, VARCHAR, 0, 128, 0, 10, 1, null, null, 0, 0, 512, 1, YES",
+ "sys, null, ps_setup_enable_instrument, in_pattern, 1, 12, VARCHAR, 0, 128, 0, 10, 1, null, null, 0, 0, 512, 1, YES",
+ "sys, null, ps_setup_enable_thread, in_connection_id, 1, -5, BIGINT, 19, 19, 0, 10, 1, null, null, 0, 0, 0, 1, YES",
+ "sys, null, ps_setup_reset_to_default, in_verbose, 1, -7, BIT, 1, 1, 0, 10, 1, null, null, 0, 0, 0, 1, YES",
+ "sys, null, ps_setup_save, in_timeout, 1, 4, INT, 10, 10, 0, 10, 1, null, null, 0, 0, 0, 1, YES",
+ "sys, null, ps_setup_show_disabled, in_show_instruments, 1, -7, BIT, 1, 1, 0, 10, 1, null, null, 0, 0, 0, 1, YES",
+ "sys, null, ps_setup_show_disabled, in_show_threads, 1, -7, BIT, 1, 1, 0, 10, 1, null, null, 0, 0, 0, 2, YES",
+ "sys, null, ps_setup_show_enabled, in_show_instruments, 1, -7, BIT, 1, 1, 0, 10, 1, null, null, 0, 0, 0, 1, YES",
+ "sys, null, ps_setup_show_enabled, in_show_threads, 1, -7, BIT, 1, 1, 0, 10, 1, null, null, 0, 0, 0, 2, YES",
+ "sys, null, ps_thread_account, , 5, -1, TEXT, 0, 65535, 0, 10, 1, null, null, 0, 0, 65535, 0, YES",
+ "sys, null, ps_thread_account, in_thread_id, 1, -5, BIGINT UNSIGNED, 20, 20, 0, 10, 1, null, null, 0, 0, 0, 1, YES",
+ "sys, null, ps_thread_id, , 5, -5, BIGINT UNSIGNED, 20, 20, 0, 10, 1, null, null, 0, 0, 0, 0, YES",
+ "sys, null, ps_thread_id, in_connection_id, 1, -5, BIGINT UNSIGNED, 20, 20, 0, 10, 1, null, null, 0, 0, 0, 1, YES",
+ "sys, null, ps_thread_stack, , 5, -1, LONGTEXT, 0, 2147483647, 0, 10, 1, null, null, 0, 0, 2147483647, 0, YES",
+ "sys, null, ps_thread_stack, thd_id, 1, -5, BIGINT UNSIGNED, 20, 20, 0, 10, 1, null, null, 0, 0, 0, 1, YES",
+ "sys, null, ps_thread_stack, debug, 1, -7, BIT, 1, 1, 0, 10, 1, null, null, 0, 0, 0, 2, YES",
+ "sys, null, ps_thread_trx_info, , 5, -1, LONGTEXT, 0, 2147483647, 0, 10, 1, null, null, 0, 0, 2147483647, 0, YES",
+ "sys, null, ps_thread_trx_info, in_thread_id, 1, -5, BIGINT UNSIGNED, 20, 20, 0, 10, 1, null, null, 0, 0, 0, 1, YES",
+ "sys, null, ps_trace_statement_digest, in_digest, 1, 12, VARCHAR, 0, 64, 0, 10, 1, null, null, 0, 0, 256, 1, YES",
+ "sys, null, ps_trace_statement_digest, in_runtime, 1, 4, INT, 10, 10, 0, 10, 1, null, null, 0, 0, 0, 2, YES",
+ "sys, null, ps_trace_statement_digest, in_interval, 1, 3, DECIMAL, 2, 2, 2, 10, 1, null, null, 0, 0, 0, 3, YES",
+ "sys, null, ps_trace_statement_digest, in_start_fresh, 1, -7, BIT, 1, 1, 0, 10, 1, null, null, 0, 0, 0, 4, YES",
+ "sys, null, ps_trace_statement_digest, in_auto_enable, 1, -7, BIT, 1, 1, 0, 10, 1, null, null, 0, 0, 0, 5, YES",
+ "sys, null, ps_trace_thread, in_thread_id, 1, -5, BIGINT UNSIGNED, 20, 20, 0, 10, 1, null, null, 0, 0, 0, 1, YES",
+ "sys, null, ps_trace_thread, in_outfile, 1, 12, VARCHAR, 0, 255, 0, 10, 1, null, null, 0, 0, 1020, 2, YES",
+ "sys, null, ps_trace_thread, in_max_runtime, 1, 3, DECIMAL, 20, 20, 2, 10, 1, null, null, 0, 0, 0, 3, YES",
+ "sys, null, ps_trace_thread, in_interval, 1, 3, DECIMAL, 20, 20, 2, 10, 1, null, null, 0, 0, 0, 4, YES",
+ "sys, null, ps_trace_thread, in_start_fresh, 1, -7, BIT, 1, 1, 0, 10, 1, null, null, 0, 0, 0, 5, YES",
+ "sys, null, ps_trace_thread, in_auto_setup, 1, -7, BIT, 1, 1, 0, 10, 1, null, null, 0, 0, 0, 6, YES",
+ "sys, null, ps_trace_thread, in_debug, 1, -7, BIT, 1, 1, 0, 10, 1, null, null, 0, 0, 0, 7, YES",
+ "sys, null, ps_truncate_all_tables, in_verbose, 1, -7, BIT, 1, 1, 0, 10, 1, null, null, 0, 0, 0, 1, YES",
+ "sys, null, quote_identifier, , 5, -1, TEXT, 0, 65535, 0, 10, 1, null, null, 0, 0, 65535, 0, YES",
+ "sys, null, quote_identifier, in_identifier, 1, -1, TEXT, 0, 65535, 0, 10, 1, null, null, 0, 0, 65535, 1, YES",
+ "sys, null, statement_performance_analyzer, in_action, 1, 1, ENUM, 0, 12, 0, 10, 1, null, null, 0, 0, 48, 1, YES",
+ "sys, null, statement_performance_analyzer, in_table, 1, 12, VARCHAR, 0, 129, 0, 10, 1, null, null, 0, 0, 516, 2, YES",
+ "sys, null, statement_performance_analyzer, in_views, 1, 1, SET, 0, 124, 0, 10, 1, null, null, 0, 0, 496, 3, YES",
+ "sys, null, sys_get_config, , 5, 12, VARCHAR, 0, 128, 0, 10, 1, null, null, 0, 0, 512, 0, YES",
+ "sys, null, sys_get_config, in_variable_name, 1, 12, VARCHAR, 0, 128, 0, 10, 1, null, null, 0, 0, 512, 1, YES",
+ "sys, null, sys_get_config, in_default_value, 1, 12, VARCHAR, 0, 128, 0, 10, 1, null, null, 0, 0, 512, 2, YES",
+ "sys, null, table_exists, in_db, 1, 12, VARCHAR, 0, 64, 0, 10, 1, null, null, 0, 0, 256, 1, YES",
+ "sys, null, table_exists, in_table, 1, 12, VARCHAR, 0, 64, 0, 10, 1, null, null, 0, 0, 256, 2, YES",
+ "sys, null, table_exists, out_exists, 4, 1, ENUM, 0, 10, 0, 10, 1, null, null, 0, 0, 40, 3, YES",
+ "sys, null, version_major, , 5, -6, TINYINT UNSIGNED, 3, 3, 0, 10, 1, null, null, 0, 0, 0, 0, YES",
+ "sys, null, version_minor, , 5, -6, TINYINT UNSIGNED, 3, 3, 0, 10, 1, null, null, 0, 0, 0, 0, YES",
+ "sys, null, version_patch, , 5, -6, TINYINT UNSIGNED, 3, 3, 0, 10, 1, null, null, 0, 0, 0, 0, YES"
+ )
+ )
+ }
+
+ test(s"$prefix: getTables") {
+ assertIO(
+ connection.use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getTables(Some("world"), None, None, Array.empty[String])
+ yield
+ val builder = List.newBuilder[String]
+ while resultSet.next() do
+ val tableCat = resultSet.getString("TABLE_CAT")
+ val tableSchem = resultSet.getString("TABLE_SCHEM")
+ val tableName = resultSet.getString("TABLE_NAME")
+ val tableType = resultSet.getString("TABLE_TYPE")
+ val remarks = resultSet.getString("REMARKS")
+ val typeCat = resultSet.getString("TYPE_CAT")
+ val typeSchem = resultSet.getString("TYPE_SCHEM")
+ val typeName = resultSet.getString("TYPE_NAME")
+ val selfReferencingColName = resultSet.getString("SELF_REFERENCING_COL_NAME")
+ val refGeneration = resultSet.getString("REF_GENERATION")
+ builder += s"$tableCat, $tableSchem, $tableName, $tableType, $remarks, $typeCat, $typeSchem, $typeName, $selfReferencingColName, $refGeneration"
+ builder.result()
+ },
+ List(
+ "world, null, city, TABLE, , null, null, null, null, null",
+ "world, null, country, TABLE, , null, null, null, null, null",
+ "world, null, countrylanguage, TABLE, , null, null, null, null, null",
+ "world, null, government_office, TABLE, , null, null, null, null, null"
+ )
+ )
+ }
+
+ test(s"$prefix: getSchemas") {
+ assertIO(
+ connection.use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getSchemas()
+ yield
+ val builder = List.newBuilder[String]
+ while resultSet.next() do builder += resultSet.getString("TABLE_SCHEM")
+ builder.result()
+ },
+ List.empty
+ )
+ }
+
+ test(s"$prefix: getCatalogs") {
+ assertIO(
+ connection.use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getCatalogs()
+ yield
+ val builder = List.newBuilder[String]
+ while resultSet.next() do builder += resultSet.getString("TABLE_CAT")
+ builder.result()
+ },
+ List("benchmark", "connector_test", "information_schema", "mysql", "performance_schema", "sys", "world", "world2")
+ )
+ }
+
+ test(s"$prefix: getTableTypes") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield
+ val resultSet = metaData.getTableTypes()
+ val builder = List.newBuilder[String]
+ while resultSet.next() do builder += resultSet.getString("TABLE_TYPE")
+ builder.result()
+ },
+ List(
+ "LOCAL TEMPORARY",
+ "SYSTEM TABLE",
+ "SYSTEM VIEW",
+ "TABLE",
+ "VIEW"
+ )
+ )
+ }
+
+ test(s"$prefix: getColumns") {
+ assertIO(
+ connection.use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getColumns(None, None, Some("tax"), None)
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val tableCat = resultSet.getString("TABLE_CAT")
+ val tableSchem = resultSet.getString("TABLE_SCHEM")
+ val tableName = resultSet.getString("TABLE_NAME")
+ val columnName = resultSet.getString("COLUMN_NAME")
+ val dataType = resultSet.getInt("DATA_TYPE")
+ val typeName = resultSet.getString("TYPE_NAME")
+ val columnSize = resultSet.getInt("COLUMN_SIZE")
+ val bufferLength = resultSet.getInt("BUFFER_LENGTH")
+ val decimalDigits = resultSet.getInt("DECIMAL_DIGITS")
+ val numPrecRadix = resultSet.getInt("NUM_PREC_RADIX")
+ val nullable = resultSet.getInt("NULLABLE")
+ val remarks = resultSet.getString("REMARKS")
+ val columnDef = resultSet.getString("COLUMN_DEF")
+ val sqlDataType = resultSet.getInt("SQL_DATA_TYPE")
+ val sqlDatetimeSub = resultSet.getInt("SQL_DATETIME_SUB")
+ val charOctetLength = resultSet.getInt("CHAR_OCTET_LENGTH")
+ val ordinalPosition = resultSet.getInt("ORDINAL_POSITION")
+ val isNullable = resultSet.getString("IS_NULLABLE")
+ val scopeCatalog = resultSet.getString("SCOPE_CATALOG")
+ val scopeSchema = resultSet.getString("SCOPE_SCHEMA")
+ val scopeTable = resultSet.getString("SCOPE_TABLE")
+ val sourceDataType = resultSet.getShort("SOURCE_DATA_TYPE")
+ val isAutoincrement = resultSet.getString("IS_AUTOINCREMENT")
+ builder += s"$tableCat, $tableSchem, $tableName, $columnName, $dataType, $typeName, $columnSize, $bufferLength, $decimalDigits, $numPrecRadix, $nullable, $remarks, $columnDef, $sqlDataType, $sqlDatetimeSub, $charOctetLength, $ordinalPosition, $isNullable, $scopeCatalog, $scopeSchema, $scopeTable, $sourceDataType, $isAutoincrement"
+ builder.result()
+ },
+ Vector(
+ "connector_test, null, tax, id, -5, BIGINT, 19, 65535, 0, 10, 0, , null, 0, 0, 0, 1, NO, null, null, null, 0, YES",
+ "connector_test, null, tax, value, 8, DOUBLE, 22, 65535, 0, 10, 0, , null, 0, 0, 0, 2, NO, null, null, null, 0, NO",
+ "connector_test, null, tax, start_date, 91, DATE, 10, 65535, 0, 10, 0, , null, 0, 0, 0, 3, NO, null, null, null, 0, NO"
+ )
+ )
+ }
+
+ test(s"$prefix: getColumnPrivileges") {
+ assertIO(
+ connection.use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getColumnPrivileges(Some("connector_test"), None, Some("tax"), Some("id"))
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val tableCat = resultSet.getString("TABLE_CAT")
+ val tableSchem = resultSet.getString("TABLE_SCHEM")
+ val tableName = resultSet.getString("TABLE_NAME")
+ val columnName = resultSet.getString("COLUMN_NAME")
+ val grantor = resultSet.getString("GRANTOR")
+ val grantee = resultSet.getString("GRANTEE")
+ val privilege = resultSet.getString("PRIVILEGE")
+ val isGrantable = resultSet.getString("IS_GRANTABLE")
+ builder += s"$tableCat, $tableSchem, $tableName, $columnName, $grantor, $grantee, $privilege, $isGrantable"
+ builder.result()
+ },
+ Vector()
+ )
+ }
+
+ test(s"$prefix: getTablePrivileges") {
+ assertIO(
+ connection.use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getTablePrivileges(None, None, Some("tax"))
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val tableCat = resultSet.getString("TABLE_CAT")
+ val tableSchem = resultSet.getString("TABLE_SCHEM")
+ val tableName = resultSet.getString("TABLE_NAME")
+ val grantor = resultSet.getString("GRANTOR")
+ val grantee = resultSet.getString("GRANTEE")
+ val privilege = resultSet.getString("PRIVILEGE")
+ val isGrantable = resultSet.getString("IS_GRANTABLE")
+ builder += s"$tableCat, $tableSchem, $tableName, $grantor, $grantee, $privilege, $isGrantable"
+ builder.result()
+ },
+ Vector.empty
+ )
+ }
+
+ test(s"$prefix: getBestRowIdentifier") {
+ assertIO(
+ connection.use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getBestRowIdentifier(None, None, "tax", Some(1), Some(true))
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val scope = resultSet.getShort("SCOPE")
+ val columnName = resultSet.getString("COLUMN_NAME")
+ val dataType = resultSet.getInt("DATA_TYPE")
+ val typeName = resultSet.getString("TYPE_NAME")
+ val columnSize = resultSet.getInt("COLUMN_SIZE")
+ val bufferLength = resultSet.getInt("BUFFER_LENGTH")
+ val decimalDigits = resultSet.getShort("DECIMAL_DIGITS")
+ val pseudoColumn = resultSet.getShort("PSEUDO_COLUMN")
+ builder += s"$scope, $columnName, $dataType, $typeName, $columnSize, $bufferLength, $decimalDigits, $pseudoColumn"
+ builder.result()
+ },
+ Vector("2, id, -5, bigint, 19, 65535, 0, 1")
+ )
+ }
+
+ test(s"$prefix: getVersionColumns") {
+ assertIO(
+ connection.use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getVersionColumns(None, None, "tax")
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val scope = resultSet.getShort("SCOPE")
+ val columnName = resultSet.getString("COLUMN_NAME")
+ val dataType = resultSet.getInt("DATA_TYPE")
+ val typeName = resultSet.getString("TYPE_NAME")
+ val columnSize = resultSet.getInt("COLUMN_SIZE")
+ val bufferLength = resultSet.getInt("BUFFER_LENGTH")
+ val decimalDigits = resultSet.getShort("DECIMAL_DIGITS")
+ val pseudoColumn = resultSet.getShort("PSEUDO_COLUMN")
+ builder += s"$scope, $columnName, $dataType, $typeName, $columnSize, $bufferLength, $decimalDigits, $pseudoColumn"
+ builder.result()
+ },
+ Vector()
+ )
+ }
+
+ test(s"$prefix: getPrimaryKeys") {
+ assertIO(
+ connection.use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getPrimaryKeys(None, None, "tax")
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val tableCat = resultSet.getString("TABLE_CAT")
+ val tableSchem = resultSet.getString("TABLE_SCHEM")
+ val tableName = resultSet.getString("TABLE_NAME")
+ val columnName = resultSet.getString("COLUMN_NAME")
+ val keySeq = resultSet.getShort("KEY_SEQ")
+ val pkName = resultSet.getString("PK_NAME")
+ builder += s"$tableCat, $tableSchem, $tableName, $columnName, $keySeq, $pkName"
+ builder.result()
+ },
+ Vector("connector_test, null, tax, id, 1, PRIMARY")
+ )
+ }
+
+ test(s"$prefix: getImportedKeys") {
+ assertIO(
+ connection.use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getImportedKeys(None, None, "tax")
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val pkTableCat = resultSet.getString("PKTABLE_CAT")
+ val pkTableSchem = resultSet.getString("PKTABLE_SCHEM")
+ val pkTableName = resultSet.getString("PKTABLE_NAME")
+ val pkColumnName = resultSet.getString("PKCOLUMN_NAME")
+ val fkTableCat = resultSet.getString("FKTABLE_CAT")
+ val fkTableSchem = resultSet.getString("FKTABLE_SCHEM")
+ val fkTableName = resultSet.getString("FKTABLE_NAME")
+ val fkColumnName = resultSet.getString("FKCOLUMN_NAME")
+ val keySeq = resultSet.getShort("KEY_SEQ")
+ val updateRule = resultSet.getShort("UPDATE_RULE")
+ val deleteRule = resultSet.getShort("DELETE_RULE")
+ val fkName = resultSet.getString("FK_NAME")
+ val pkName = resultSet.getString("PK_NAME")
+ val deferrability = resultSet.getShort("DEFERRABILITY")
+ builder += s"$pkTableCat, $pkTableSchem, $pkTableName, $pkColumnName, $fkTableCat, $fkTableSchem, $fkTableName, $fkColumnName, $keySeq, $updateRule, $deleteRule, $fkName, $pkName, $deferrability"
+ builder.result()
+ },
+ Vector()
+ )
+ }
+
+ test(s"$prefix: getExportedKeys") {
+ assertIO(
+ connection.use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getExportedKeys(None, None, "tax")
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val pkTableCat = resultSet.getString("PKTABLE_CAT")
+ val pkTableSchem = resultSet.getString("PKTABLE_SCHEM")
+ val pkTableName = resultSet.getString("PKTABLE_NAME")
+ val pkColumnName = resultSet.getString("PKCOLUMN_NAME")
+ val fkTableCat = resultSet.getString("FKTABLE_CAT")
+ val fkTableSchem = resultSet.getString("FKTABLE_SCHEM")
+ val fkTableName = resultSet.getString("FKTABLE_NAME")
+ val fkColumnName = resultSet.getString("FKCOLUMN_NAME")
+ val keySeq = resultSet.getShort("KEY_SEQ")
+ val updateRule = resultSet.getShort("UPDATE_RULE")
+ val deleteRule = resultSet.getShort("DELETE_RULE")
+ val fkName = resultSet.getString("FK_NAME")
+ val pkName = resultSet.getString("PK_NAME")
+ val deferrability = resultSet.getShort("DEFERRABILITY")
+ builder += s"$pkTableCat, $pkTableSchem, $pkTableName, $pkColumnName, $fkTableCat, $fkTableSchem, $fkTableName, $fkColumnName, $keySeq, $updateRule, $deleteRule, $fkName, $pkName, $deferrability"
+ builder.result()
+ },
+ Vector()
+ )
+ }
+
+ test(s"$prefix: getCrossReference") {
+ assertIO(
+ connection.use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getCrossReference(None, None, "tax", None, None, Some("film"))
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val pkTableCat = resultSet.getString("PKTABLE_CAT")
+ val pkTableSchem = resultSet.getString("PKTABLE_SCHEM")
+ val pkTableName = resultSet.getString("PKTABLE_NAME")
+ val pkColumnName = resultSet.getString("PKCOLUMN_NAME")
+ val fkTableCat = resultSet.getString("FKTABLE_CAT")
+ val fkTableSchem = resultSet.getString("FKTABLE_SCHEM")
+ val fkTableName = resultSet.getString("FKTABLE_NAME")
+ val fkColumnName = resultSet.getString("FKCOLUMN_NAME")
+ val keySeq = resultSet.getShort("KEY_SEQ")
+ val updateRule = resultSet.getShort("UPDATE_RULE")
+ val deleteRule = resultSet.getShort("DELETE_RULE")
+ val fkName = resultSet.getString("FK_NAME")
+ val pkName = resultSet.getString("PK_NAME")
+ val deferrability = resultSet.getShort("DEFERRABILITY")
+ builder += s"$pkTableCat, $pkTableSchem, $pkTableName, $pkColumnName, $fkTableCat, $fkTableSchem, $fkTableName, $fkColumnName, $keySeq, $updateRule, $deleteRule, $fkName, $pkName, $deferrability"
+ builder.result()
+ },
+ Vector()
+ )
+ }
+
+ test(s"$prefix: getIndexInfo") {
+ assertIO(
+ connection.use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getIndexInfo(None, None, Some("tax"), false, false)
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val tableCat = resultSet.getString("TABLE_CAT")
+ val tableSchem = resultSet.getString("TABLE_SCHEM")
+ val tableName = resultSet.getString("TABLE_NAME")
+ val nonUnique = resultSet.getBoolean("NON_UNIQUE")
+ val indexQualifier = resultSet.getString("INDEX_QUALIFIER")
+ val indexName = resultSet.getString("INDEX_NAME")
+ val typed = resultSet.getShort("TYPE")
+ val ordinalPosition = resultSet.getInt("ORDINAL_POSITION")
+ val columnName = resultSet.getString("COLUMN_NAME")
+ val ascOrDesc = resultSet.getString("ASC_OR_DESC")
+ val cardinality = resultSet.getInt("CARDINALITY")
+ val pages = resultSet.getInt("PAGES")
+ val filterCondition = resultSet.getString("FILTER_CONDITION")
+ builder += s"$tableCat, $tableSchem, $tableName, $nonUnique, $indexQualifier, $indexName, $typed, $ordinalPosition, $columnName, $ascOrDesc, $cardinality, $pages, $filterCondition"
+ builder.result()
+ },
+ Vector(
+ "connector_test, null, tax, false, null, PRIMARY, 3, 1, id, A, 3, 0, null"
+ )
+ )
+ }
+
+ test(s"$prefix: supportsResultSetType") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsResultSetType(ResultSet.TYPE_FORWARD_ONLY)
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsResultSetConcurrency") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsResultSetConcurrency(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: ownUpdatesAreVisible") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.ownUpdatesAreVisible(ResultSet.TYPE_FORWARD_ONLY)
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: ownDeletesAreVisible") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.ownDeletesAreVisible(ResultSet.TYPE_FORWARD_ONLY)
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: ownInsertsAreVisible") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.ownInsertsAreVisible(ResultSet.TYPE_FORWARD_ONLY)
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: othersUpdatesAreVisible") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.othersUpdatesAreVisible(ResultSet.TYPE_FORWARD_ONLY)
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: othersDeletesAreVisible") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.othersDeletesAreVisible(ResultSet.TYPE_FORWARD_ONLY)
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: othersInsertsAreVisible") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.othersInsertsAreVisible(ResultSet.TYPE_FORWARD_ONLY)
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: updatesAreDetected") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.updatesAreDetected(ResultSet.TYPE_FORWARD_ONLY)
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: deletesAreDetected") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.deletesAreDetected(ResultSet.TYPE_FORWARD_ONLY)
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: insertsAreDetected") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.insertsAreDetected(ResultSet.TYPE_FORWARD_ONLY)
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: supportsBatchUpdates") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsBatchUpdates()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: getUDTs") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield
+ val resultSet = metaData.getUDTs(None, None, None, Array.empty[Int])
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val typeCat = resultSet.getString("TYPE_CAT")
+ val typeSchem = resultSet.getString("TYPE_SCHEM")
+ val typeName = resultSet.getString("TYPE_NAME")
+ val className = resultSet.getString("CLASS_NAME")
+ val dataType = resultSet.getInt("DATA_TYPE")
+ val remarks = resultSet.getString("REMARKS")
+ val baseType = resultSet.getShort("BASE_TYPE")
+ builder += s"$typeCat, $typeSchem, $typeName, $className, $dataType, $remarks, $baseType"
+ builder.result()
+ },
+ Vector()
+ )
+ }
+
+ test(s"$prefix: supportsSavepoints") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsSavepoints()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsNamedParameters") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsNamedParameters()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: supportsMultipleOpenResults") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsMultipleOpenResults()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsGetGeneratedKeys") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsGetGeneratedKeys()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: getSuperTypes") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield
+ val resultSet = metaData.getSuperTypes(None, None, None)
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val typeCat = resultSet.getString("TYPE_CAT")
+ val typeSchem = resultSet.getString("TYPE_SCHEM")
+ val typeName = resultSet.getString("TYPE_NAME")
+ val superTypeCat = resultSet.getString("SUPERTYPE_CAT")
+ val superTypeSchem = resultSet.getString("SUPERTYPE_SCHEM")
+ val superTypeName = resultSet.getString("SUPERTYPE_NAME")
+ builder += s"$typeCat, $typeSchem, $typeName, $superTypeCat, $superTypeSchem, $superTypeName"
+ builder.result()
+ },
+ Vector()
+ )
+ }
+
+ test(s"$prefix: getSuperTables") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield
+ val resultSet = metaData.getSuperTables(None, None, None)
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val tableCat = resultSet.getString("TABLE_CAT")
+ val tableSchem = resultSet.getString("TABLE_SCHEM")
+ val tableName = resultSet.getString("TABLE_NAME")
+ val superTableName = resultSet.getString("SUPERTABLE_NAME")
+ builder += s"$tableCat, $tableSchem, $tableName, $superTableName"
+ builder.result()
+ },
+ Vector()
+ )
+ }
+
+ test(s"$prefix: getAttributes") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield
+ val resultSet = metaData.getAttributes(None, None, None, None)
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val typeName = resultSet.getString("TYPE_NAME")
+ val attributeName = resultSet.getString("ATTR_NAME")
+ val attributeType = resultSet.getString("DATA_TYPE")
+ val attributeTypeName = resultSet.getString("ATTR_TYPE_NAME")
+ val attributeSize = resultSet.getInt("ATTR_SIZE")
+ val decimalDigits = resultSet.getInt("DECIMAL_DIGITS")
+ val numPrecRadix = resultSet.getInt("NUM_PREC_RADIX")
+ val nullable = resultSet.getInt("NULLABLE")
+ val remarks = resultSet.getString("REMARKS")
+ val attrDef = resultSet.getString("ATTR_DEF")
+ val sqlDataType = resultSet.getInt("SQL_DATA_TYPE")
+ val sqlDateTimeSub = resultSet.getInt("SQL_DATETIME_SUB")
+ val charOctetLength = resultSet.getInt("CHAR_OCTET_LENGTH")
+ val ordinalPosition = resultSet.getInt("ORDINAL_POSITION")
+ val isNullable = resultSet.getString("IS_NULLABLE")
+ builder += s"$typeName, $attributeName, $attributeType, $attributeTypeName, $attributeSize, $decimalDigits, $numPrecRadix, $nullable, $remarks, $attrDef, $sqlDataType, $sqlDateTimeSub, $charOctetLength, $ordinalPosition, $isNullable"
+ builder.result()
+ },
+ Vector()
+ )
+ }
+
+ test(s"$prefix: supportsResultSetHoldability") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsResultSetHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT)
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: getResultSetHoldability") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getResultSetHoldability()
+ },
+ 1
+ )
+ }
+
+ test(s"$prefix: getDatabaseMajorVersion") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getDatabaseMajorVersion()
+ },
+ 8
+ )
+ }
+
+ test(s"$prefix: getDatabaseMinorVersion") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getDatabaseMinorVersion()
+ },
+ 4
+ )
+ }
+
+ test(s"$prefix: getJDBCMajorVersion") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getJDBCMajorVersion()
+ },
+ if prefix == "jdbc" then 4 else 0
+ )
+ }
+
+ test(s"$prefix: getJDBCMinorVersion") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getJDBCMinorVersion()
+ },
+ if prefix == "jdbc" then 2 else 3
+ )
+ }
+
+ test(s"$prefix: getSQLStateType") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getSQLStateType()
+ },
+ 2
+ )
+ }
+
+ test(s"$prefix: locatorsUpdateCopy") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.locatorsUpdateCopy()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: supportsStatementPooling") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsStatementPooling()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: getRowIdLifetime") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getRowIdLifetime()
+ },
+ RowIdLifetime.ROWID_UNSUPPORTED
+ )
+ }
+
+ test(s"$prefix: getSchemas") {
+ assertIO(
+ connection.use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getSchemas(None, None)
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val tableSchem = resultSet.getString("TABLE_SCHEM")
+ val tableCatalog = resultSet.getString("TABLE_CATALOG")
+ builder += s"$tableSchem, $tableCatalog"
+ builder.result()
+ },
+ Vector()
+ )
+ }
+
+ test(s"$prefix: supportsStoredFunctionsUsingCallSyntax") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsStoredFunctionsUsingCallSyntax()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: autoCommitFailureClosesAllResultSets") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.autoCommitFailureClosesAllResultSets()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: getClientInfoProperties") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield
+ val resultSet = metaData.getClientInfoProperties()
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val name = resultSet.getString("NAME")
+ val maxLen = resultSet.getInt("MAX_LEN")
+ val defaultValue = resultSet.getString("DEFAULT_VALUE")
+ val description = resultSet.getString("DESCRIPTION")
+ builder += s"$name, $maxLen, $defaultValue, $description"
+ builder.result()
+ },
+ Vector()
+ )
+ }
+
+ test(s"$prefix: getFunctions") {
+ assertIO(
+ connection.use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getFunctions(None, None, None)
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val functionCat = resultSet.getString("FUNCTION_CAT")
+ val functionSchem = resultSet.getString("FUNCTION_SCHEM")
+ val functionName = resultSet.getString("FUNCTION_NAME")
+ val functionType = resultSet.getInt("FUNCTION_TYPE")
+ val specificName = resultSet.getString("SPECIFIC_NAME")
+ builder += s"$functionCat, $functionSchem, $functionName, $functionType, $specificName"
+ builder.result()
+ },
+ Vector(
+ "connector_test, null, func1, 1, func1",
+ "connector_test, null, func2, 1, func2",
+ "connector_test, null, getPrice, 1, getPrice",
+ "sys, null, extract_schema_from_file_name, 1, extract_schema_from_file_name",
+ "sys, null, extract_table_from_file_name, 1, extract_table_from_file_name",
+ "sys, null, format_bytes, 1, format_bytes",
+ "sys, null, format_path, 1, format_path",
+ "sys, null, format_statement, 1, format_statement",
+ "sys, null, format_time, 1, format_time",
+ "sys, null, list_add, 1, list_add",
+ "sys, null, list_drop, 1, list_drop",
+ "sys, null, ps_is_account_enabled, 1, ps_is_account_enabled",
+ "sys, null, ps_is_consumer_enabled, 1, ps_is_consumer_enabled",
+ "sys, null, ps_is_instrument_default_enabled, 1, ps_is_instrument_default_enabled",
+ "sys, null, ps_is_instrument_default_timed, 1, ps_is_instrument_default_timed",
+ "sys, null, ps_is_thread_instrumented, 1, ps_is_thread_instrumented",
+ "sys, null, ps_thread_account, 1, ps_thread_account",
+ "sys, null, ps_thread_id, 1, ps_thread_id",
+ "sys, null, ps_thread_stack, 1, ps_thread_stack",
+ "sys, null, ps_thread_trx_info, 1, ps_thread_trx_info",
+ "sys, null, quote_identifier, 1, quote_identifier",
+ "sys, null, sys_get_config, 1, sys_get_config",
+ "sys, null, version_major, 1, version_major",
+ "sys, null, version_minor, 1, version_minor",
+ "sys, null, version_patch, 1, version_patch"
+ )
+ )
+ }
+
+ test(s"$prefix: getFunctionColumns") {
+ assertIO(
+ connection.use { conn =>
+ for
+ metaData <- conn.getMetaData()
+ resultSet <- metaData.getFunctionColumns(None, None, None, None)
+ yield
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val functionCat = resultSet.getString("FUNCTION_CAT")
+ val functionSchem = resultSet.getString("FUNCTION_SCHEM")
+ val functionName = resultSet.getString("FUNCTION_NAME")
+ val columnName = resultSet.getString("COLUMN_NAME")
+ val columnType = resultSet.getInt("COLUMN_TYPE")
+ val dataType = resultSet.getInt("DATA_TYPE")
+ val typeName = resultSet.getString("TYPE_NAME")
+ val precision = resultSet.getInt("PRECISION")
+ val length = resultSet.getInt("LENGTH")
+ val scale = resultSet.getInt("SCALE")
+ val radix = resultSet.getInt("RADIX")
+ val nullable = resultSet.getInt("NULLABLE")
+ val remarks = resultSet.getString("REMARKS")
+ val charOctetLength = resultSet.getInt("CHAR_OCTET_LENGTH")
+ val ordinalPosition = resultSet.getInt("ORDINAL_POSITION")
+ val isNullable = resultSet.getString("IS_NULLABLE")
+ builder += s"$functionCat, $functionSchem, $functionName, $columnName, $columnType, $dataType, $typeName, $precision, $length, $scale, $radix, $nullable, $remarks, $charOctetLength, $ordinalPosition, $isNullable"
+ builder.result()
+ },
+ Vector(
+ "connector_test, null, func1, , 4, 4, INT, 10, 10, 0, 10, 1, null, 0, 0, YES",
+ "connector_test, null, func2, , 4, 12, VARCHAR, 0, 12, 0, 10, 1, null, 48, 0, YES",
+ "connector_test, null, getPrice, , 4, 4, INT, 10, 10, 0, 10, 1, null, 0, 0, YES",
+ "connector_test, null, getPrice, price, 1, 4, INT, 10, 10, 0, 10, 1, null, 0, 1, YES",
+ "sys, null, extract_schema_from_file_name, , 4, 12, VARCHAR, 0, 64, 0, 10, 1, null, 256, 0, YES",
+ "sys, null, extract_schema_from_file_name, path, 1, 12, VARCHAR, 0, 512, 0, 10, 1, null, 2048, 1, YES",
+ "sys, null, extract_table_from_file_name, , 4, 12, VARCHAR, 0, 64, 0, 10, 1, null, 256, 0, YES",
+ "sys, null, extract_table_from_file_name, path, 1, 12, VARCHAR, 0, 512, 0, 10, 1, null, 2048, 1, YES",
+ "sys, null, format_bytes, , 4, -1, TEXT, 0, 65535, 0, 10, 1, null, 65535, 0, YES",
+ "sys, null, format_bytes, bytes, 1, -1, TEXT, 0, 65535, 0, 10, 1, null, 65535, 1, YES",
+ "sys, null, format_path, , 4, 12, VARCHAR, 0, 512, 0, 10, 1, null, 2048, 0, YES",
+ "sys, null, format_path, in_path, 1, 12, VARCHAR, 0, 512, 0, 10, 1, null, 2048, 1, YES",
+ "sys, null, format_statement, , 4, -1, LONGTEXT, 0, 2147483647, 0, 10, 1, null, 2147483647, 0, YES",
+ "sys, null, format_statement, statement, 1, -1, LONGTEXT, 0, 2147483647, 0, 10, 1, null, 2147483647, 1, YES",
+ "sys, null, format_time, , 4, -1, TEXT, 0, 65535, 0, 10, 1, null, 65535, 0, YES",
+ "sys, null, format_time, picoseconds, 1, -1, TEXT, 0, 65535, 0, 10, 1, null, 65535, 1, YES",
+ "sys, null, list_add, , 4, -1, TEXT, 0, 65535, 0, 10, 1, null, 65535, 0, YES",
+ "sys, null, list_add, in_list, 1, -1, TEXT, 0, 65535, 0, 10, 1, null, 65535, 1, YES",
+ "sys, null, list_add, in_add_value, 1, -1, TEXT, 0, 65535, 0, 10, 1, null, 65535, 2, YES",
+ "sys, null, list_drop, , 4, -1, TEXT, 0, 65535, 0, 10, 1, null, 65535, 0, YES",
+ "sys, null, list_drop, in_list, 1, -1, TEXT, 0, 65535, 0, 10, 1, null, 65535, 1, YES",
+ "sys, null, list_drop, in_drop_value, 1, -1, TEXT, 0, 65535, 0, 10, 1, null, 65535, 2, YES",
+ "sys, null, ps_is_account_enabled, , 4, 1, ENUM, 0, 3, 0, 10, 1, null, 12, 0, YES",
+ "sys, null, ps_is_account_enabled, in_host, 1, 12, VARCHAR, 0, 255, 0, 10, 1, null, 1020, 1, YES",
+ "sys, null, ps_is_account_enabled, in_user, 1, 12, VARCHAR, 0, 32, 0, 10, 1, null, 128, 2, YES",
+ "sys, null, ps_is_consumer_enabled, , 4, 1, ENUM, 0, 3, 0, 10, 1, null, 12, 0, YES",
+ "sys, null, ps_is_consumer_enabled, in_consumer, 1, 12, VARCHAR, 0, 64, 0, 10, 1, null, 256, 1, YES",
+ "sys, null, ps_is_instrument_default_enabled, , 4, 1, ENUM, 0, 3, 0, 10, 1, null, 12, 0, YES",
+ "sys, null, ps_is_instrument_default_enabled, in_instrument, 1, 12, VARCHAR, 0, 128, 0, 10, 1, null, 512, 1, YES",
+ "sys, null, ps_is_instrument_default_timed, , 4, 1, ENUM, 0, 3, 0, 10, 1, null, 12, 0, YES",
+ "sys, null, ps_is_instrument_default_timed, in_instrument, 1, 12, VARCHAR, 0, 128, 0, 10, 1, null, 512, 1, YES",
+ "sys, null, ps_is_thread_instrumented, , 4, 1, ENUM, 0, 7, 0, 10, 1, null, 28, 0, YES",
+ "sys, null, ps_is_thread_instrumented, in_connection_id, 1, -5, BIGINT UNSIGNED, 20, 20, 0, 10, 1, null, 0, 1, YES",
+ "sys, null, ps_thread_account, , 4, -1, TEXT, 0, 65535, 0, 10, 1, null, 65535, 0, YES",
+ "sys, null, ps_thread_account, in_thread_id, 1, -5, BIGINT UNSIGNED, 20, 20, 0, 10, 1, null, 0, 1, YES",
+ "sys, null, ps_thread_id, , 4, -5, BIGINT UNSIGNED, 20, 20, 0, 10, 1, null, 0, 0, YES",
+ "sys, null, ps_thread_id, in_connection_id, 1, -5, BIGINT UNSIGNED, 20, 20, 0, 10, 1, null, 0, 1, YES",
+ "sys, null, ps_thread_stack, , 4, -1, LONGTEXT, 0, 2147483647, 0, 10, 1, null, 2147483647, 0, YES",
+ "sys, null, ps_thread_stack, thd_id, 1, -5, BIGINT UNSIGNED, 20, 20, 0, 10, 1, null, 0, 1, YES",
+ "sys, null, ps_thread_stack, debug, 1, -7, BIT, 1, 1, 0, 10, 1, null, 0, 2, YES",
+ "sys, null, ps_thread_trx_info, , 4, -1, LONGTEXT, 0, 2147483647, 0, 10, 1, null, 2147483647, 0, YES",
+ "sys, null, ps_thread_trx_info, in_thread_id, 1, -5, BIGINT UNSIGNED, 20, 20, 0, 10, 1, null, 0, 1, YES",
+ "sys, null, quote_identifier, , 4, -1, TEXT, 0, 65535, 0, 10, 1, null, 65535, 0, YES",
+ "sys, null, quote_identifier, in_identifier, 1, -1, TEXT, 0, 65535, 0, 10, 1, null, 65535, 1, YES",
+ "sys, null, sys_get_config, , 4, 12, VARCHAR, 0, 128, 0, 10, 1, null, 512, 0, YES",
+ "sys, null, sys_get_config, in_variable_name, 1, 12, VARCHAR, 0, 128, 0, 10, 1, null, 512, 1, YES",
+ "sys, null, sys_get_config, in_default_value, 1, 12, VARCHAR, 0, 128, 0, 10, 1, null, 512, 2, YES",
+ "sys, null, version_major, , 4, -6, TINYINT UNSIGNED, 3, 3, 0, 10, 1, null, 0, 0, YES",
+ "sys, null, version_minor, , 4, -6, TINYINT UNSIGNED, 3, 3, 0, 10, 1, null, 0, 0, YES",
+ "sys, null, version_patch, , 4, -6, TINYINT UNSIGNED, 3, 3, 0, 10, 1, null, 0, 0, YES"
+ )
+ )
+ }
+
+ test(s"$prefix: getPseudoColumns") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield
+ val resultSet = metaData.getPseudoColumns(None, None, None, None)
+ val builder = Vector.newBuilder[String]
+ while resultSet.next() do
+ val tableCat = resultSet.getString("TABLE_CAT")
+ val tableSchem = resultSet.getString("TABLE_SCHEM")
+ val tableName = resultSet.getString("TABLE_NAME")
+ val columnName = resultSet.getString("COLUMN_NAME")
+ val dataType = resultSet.getInt("DATA_TYPE")
+ val columnSize = resultSet.getInt("COLUMN_SIZE")
+ val decimalDigits = resultSet.getInt("DECIMAL_DIGITS")
+ val numPrecRadix = resultSet.getInt("NUM_PREC_RADIX")
+ val columnUsage = resultSet.getString("COLUMN_USAGE")
+ val remarks = resultSet.getString("REMARKS")
+ val charOctetLength = resultSet.getInt("CHAR_OCTET_LENGTH")
+ val isNullable = resultSet.getInt("IS_NULLABLE")
+ builder += s"$tableCat, $tableSchem, $tableName, $columnName, $dataType, $columnSize, $decimalDigits, $numPrecRadix, $columnUsage, $remarks, $charOctetLength, $isNullable"
+ builder.result()
+ },
+ Vector()
+ )
+ }
+
+ test(s"$prefix: generatedKeyAlwaysReturned") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.generatedKeyAlwaysReturned()
+ },
+ true
+ )
+ }
+
+ test(s"$prefix: getMaxLogicalLobSize") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.getMaxLogicalLobSize()
+ },
+ 0L
+ )
+ }
+
+ test(s"$prefix: supportsRefCursors") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsRefCursors()
+ },
+ false
+ )
+ }
+
+ test(s"$prefix: supportsSharding") {
+ assertIO(
+ connection.use { conn =>
+ for metaData <- conn.getMetaData()
+ yield metaData.supportsSharding()
+ },
+ false
+ )
+ }