From 9b4e7ce984e0054c6f597e945658050d59f7c4ae Mon Sep 17 00:00:00 2001 From: Alexey Zinoviev Date: Fri, 29 May 2026 16:26:22 +0200 Subject: [PATCH 1/5] Add SQL validation enhancements and remove strictValidation parameter Refactored SQL query/table validation to replace the `strictValidation` parameter with a more flexible `SqlValidation` enum introducing `ReadOnly` and `None` modes. Enhanced validation to block multi-statement queries and DDL/DML keywords in `ReadOnly` mode while allowing comments and literals inside queries. Updated tests and documentation accordingly. --- .../dataframe/io/readDataFrameSchema.kt | 2 - .../kotlinx/dataframe/io/readJdbc.kt | 106 ++++------- .../kotlinx/dataframe/io/validationUtil.kt | Bin 9423 -> 10951 bytes .../kotlinx/dataframe/io/h2/h2Test.kt | 175 ++++++++++-------- 4 files changed, 137 insertions(+), 146 deletions(-) diff --git a/dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/readDataFrameSchema.kt b/dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/readDataFrameSchema.kt index aa94cadb89..86c8ea3d3f 100644 --- a/dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/readDataFrameSchema.kt +++ b/dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/readDataFrameSchema.kt @@ -110,7 +110,6 @@ public fun DataFrameSchema.Companion.readSqlTable( limit = 1, inferNullability = false, // Schema extraction doesn't need nullability inference dbType = determinedDbType, - strictValidation = true, ) return singleRowDataFrame.schema() @@ -211,7 +210,6 @@ public fun DataFrameSchema.Companion.readSqlQuery( limit = 1, inferNullability = false, // Schema extraction doesn't need nullability inference dbType = determinedDbType, - strictValidation = true, ) return singleRowDataFrame.schema() diff --git a/dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/readJdbc.kt b/dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/readJdbc.kt index 9af8492626..d351eb09e9 100644 --- a/dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/readJdbc.kt +++ b/dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/readJdbc.kt @@ -48,8 +48,6 @@ private val logger = KotlinLogging.logger {} * @param [inferNullability] indicates how the column nullability should be inferred. * @param [dbType] the type of database, could be a custom object, provided by user, optional, default is `null`, * in that case the [dbType] will be recognized from the [dbConfig]. - * @param [strictValidation] if `true`, the method validates that the provided table name is in a valid format. - * Default is `true` for strict validation. * @param [configureStatement] optional lambda to configure the [PreparedStatement] before execution. * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. * @return the DataFrame containing the data from the SQL table. @@ -60,12 +58,11 @@ public fun DataFrame.Companion.readSqlTable( limit: Int? = null, inferNullability: Boolean = true, dbType: DbType? = null, - strictValidation: Boolean = true, configureStatement: (PreparedStatement) -> Unit = {}, ): AnyFrame { validateLimit(limit) return withReadOnlyConnection(dbConfig, dbType) { conn -> - readSqlTable(conn, tableName, limit, inferNullability, dbType, strictValidation, configureStatement) + readSqlTable(conn, tableName, limit, inferNullability, dbType, configureStatement) } } @@ -80,8 +77,6 @@ public fun DataFrame.Companion.readSqlTable( * @param [inferNullability] indicates how the column nullability should be inferred. * @param [dbType] the type of database, could be a custom object, provided by user, optional, default is `null`, * in that case the [dbType] will be recognized from the [dataSource]. - * @param [strictValidation] if `true`, the method validates that the provided table name is in a valid format. - * Default is `true` for strict validation. * @param [configureStatement] optional lambda to configure the [PreparedStatement] before execution. * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. * @return the DataFrame containing the data from the SQL table. @@ -94,7 +89,6 @@ public fun DataFrame.Companion.readSqlTable( limit: Int? = null, inferNullability: Boolean = true, dbType: DbType? = null, - strictValidation: Boolean = true, configureStatement: (PreparedStatement) -> Unit = {}, ): AnyFrame { validateLimit(limit) @@ -105,7 +99,6 @@ public fun DataFrame.Companion.readSqlTable( limit, inferNullability, dbType, - strictValidation, configureStatement, ) } @@ -122,8 +115,6 @@ public fun DataFrame.Companion.readSqlTable( * @param [inferNullability] indicates how the column nullability should be inferred. * @param [dbType] the type of database, could be a custom object, provided by user, optional, default is `null`, * in that case the [dbType] will be recognized from the [connection]. - * @param [strictValidation] if `true`, the method validates that the provided table name is in a valid format. - * Default is `true` for strict validation. * @param [configureStatement] optional lambda to configure the [PreparedStatement] before execution. * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. * @return the DataFrame containing the data from the SQL table. @@ -136,16 +127,12 @@ public fun DataFrame.Companion.readSqlTable( limit: Int? = null, inferNullability: Boolean = true, dbType: DbType? = null, - strictValidation: Boolean = true, configureStatement: (PreparedStatement) -> Unit = {}, ): AnyFrame { validateLimit(limit) - if (strictValidation) { - require(isValidTableName(tableName)) { - "The provided table name '$tableName' is invalid. Please ensure it matches a valid table name in the database schema." - } - } else { - logger.warn { "Strict validation is disabled. Make sure the table name '$tableName' is correct." } + require(isValidTableName(tableName)) { + "The table name '$tableName' is not a valid SQL identifier. " + + "Only Unicode letters, digits, underscores, and dots (for schema-qualified names) are allowed." } val determinedDbType = dbType ?: extractDBTypeFromConnection(connection) @@ -231,8 +218,9 @@ private fun executeQueryAndBuildDataFrame( * @param [inferNullability] indicates how the column nullability should be inferred. * @param [dbType] the type of database, could be a custom object, provided by user, optional, default is `null`, * in that case the [dbType] will be recognized from the [dbConfig]. - * @param [strictValidation] if `true`, the method validates that the provided query is in a valid format. - * Default is `true` for strict validation. + * @param [validation] controls SQL query validation. [SqlValidation.ReadOnly] blocks DDL/DML statements and + * only allows read-oriented queries (SELECT, WITH, VALUES, TABLE, EXPLAIN). + * [SqlValidation.None] (default) passes the query to the database without validation. * @param [configureStatement] optional lambda to configure the [PreparedStatement] before execution. * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. * @return the DataFrame containing the result of the SQL query. @@ -243,21 +231,18 @@ public fun DataFrame.Companion.readSqlQuery( limit: Int? = null, inferNullability: Boolean = true, dbType: DbType? = null, - strictValidation: Boolean = true, + validation: SqlValidation = SqlValidation.None, configureStatement: (PreparedStatement) -> Unit = {}, ): AnyFrame { validateLimit(limit) return withReadOnlyConnection(dbConfig, dbType) { conn -> - readSqlQuery(conn, sqlQuery, limit, inferNullability, dbType, strictValidation, configureStatement) + readSqlQuery(conn, sqlQuery, limit, inferNullability, dbType, validation, configureStatement) } } /** * Converts the result of an SQL query to the DataFrame. * - * __NOTE:__ SQL query should start from SELECT and contain one query for reading data without any manipulation. - * It should not contain `;` symbol. - * * @param [dataSource] the [DataSource] to obtain a database connection from. * @param [sqlQuery] the SQL query to execute. * @param [limit] the maximum number of rows to retrieve from the result of the SQL query execution. @@ -266,8 +251,9 @@ public fun DataFrame.Companion.readSqlQuery( * @param [inferNullability] indicates how the column nullability should be inferred. * @param [dbType] the type of database, could be a custom object, provided by user, optional, default is `null`, * in that case the [dbType] will be recognized from the [dataSource]. - * @param [strictValidation] if `true`, the method validates that the provided query is in a valid format. - * Default is `true` for strict validation. + * @param [validation] controls SQL query validation. [SqlValidation.ReadOnly] blocks DDL/DML statements and + * only allows read-oriented queries (SELECT, WITH, VALUES, TABLE, EXPLAIN). + * [SqlValidation.None] (default) passes the query to the database without validation. * @param [configureStatement] optional lambda to configure the [PreparedStatement] before execution. * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. * @return the DataFrame containing the result of the SQL query. @@ -280,21 +266,18 @@ public fun DataFrame.Companion.readSqlQuery( limit: Int? = null, inferNullability: Boolean = true, dbType: DbType? = null, - strictValidation: Boolean = true, + validation: SqlValidation = SqlValidation.None, configureStatement: (PreparedStatement) -> Unit = {}, ): AnyFrame { validateLimit(limit) dataSource.connection.use { connection -> - return readSqlQuery(connection, sqlQuery, limit, inferNullability, dbType, strictValidation, configureStatement) + return readSqlQuery(connection, sqlQuery, limit, inferNullability, dbType, validation, configureStatement) } } /** * Converts the result of an SQL query to the DataFrame. * - * __NOTE:__ SQL query should start from SELECT and contain one query for reading data without any manipulation. - * It should not contain `;` symbol. - * * @param [connection] the database connection to execute the SQL query. * @param [sqlQuery] the SQL query to execute. * @param [limit] the maximum number of rows to retrieve from the result of the SQL query execution. @@ -303,8 +286,9 @@ public fun DataFrame.Companion.readSqlQuery( * @param [inferNullability] indicates how the column nullability should be inferred. * @param [dbType] the type of database, could be a custom object, provided by user, optional, default is `null`, * in that case the [dbType] will be recognized from the [connection]. - * @param [strictValidation] if `true`, the method validates that the provided query is in a valid format. - * Default is `true` for strict validation. + * @param [validation] controls SQL query validation. [SqlValidation.ReadOnly] blocks DDL/DML statements and + * only allows read-oriented queries (SELECT, WITH, VALUES, TABLE, EXPLAIN). + * [SqlValidation.None] (default) passes the query to the database without validation. * @param [configureStatement] optional lambda to configure the [PreparedStatement] before execution. * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. * @return the DataFrame containing the result of the SQL query. @@ -317,17 +301,15 @@ public fun DataFrame.Companion.readSqlQuery( limit: Int? = null, inferNullability: Boolean = true, dbType: DbType? = null, - strictValidation: Boolean = true, + validation: SqlValidation = SqlValidation.None, configureStatement: (PreparedStatement) -> Unit = {}, ): AnyFrame { validateLimit(limit) - if (strictValidation) { + if (validation == SqlValidation.ReadOnly) { require(isValidSqlQuery(sqlQuery)) { - "SQL query should start from SELECT and contain one query for reading data without any manipulation. " + - "Also it should not contain any separators like `;`." + "SQL validation failed: query is not a read-only statement. " + + "Only SELECT, WITH, VALUES, TABLE, and EXPLAIN queries are allowed in ReadOnly mode." } - } else { - logger.warn { "Strict validation is disabled. Ensure the SQL query '$sqlQuery' is correct and safe." } } val determinedDbType = dbType ?: extractDBTypeFromConnection(connection) @@ -358,18 +340,16 @@ public fun DataFrame.Companion.readSqlQuery( * Even if [DbConnectionConfig.readOnly] is set to `false`, the library still prevents data-modifying queries * and only permits safe `SELECT` operations internally. * - * @param [sqlQueryOrTableName] the SQL query to execute or name of the SQL table. - * It should be a name of one of the existing SQL tables, - * or the SQL query should start from SELECT and contain one query for reading data without any manipulation. - * It should not contain `;` symbol. + * @param [sqlQueryOrTableName] the SQL query to execute or the name of an SQL table. * @param [limit] the maximum number of rows to retrieve from the result of the SQL query execution. * `null` (default) means no limit - all available rows will be fetched * or positive integer (e.g., `100`) - fetch at most that many rows * @param [inferNullability] indicates how the column nullability should be inferred. * @param [dbType] the type of database, could be a custom object, provided by user, optional, default is `null`, * in that case the [dbType] will be recognized from the [DbConnectionConfig]. - * @param [strictValidation] if `true`, the method validates that the provided query or table name is in a valid format. - * Default is `true` for strict validation. + * @param [validation] controls SQL query validation when a query (not a table name) is provided. + * [SqlValidation.ReadOnly] blocks DDL/DML; [SqlValidation.None] (default) skips validation. + * Table name validation is always strict regardless of this parameter. * @param [configureStatement] optional lambda to configure the [PreparedStatement] before execution. * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. * @return the DataFrame containing the result of the SQL query. @@ -379,7 +359,7 @@ public fun DbConnectionConfig.readDataFrame( limit: Int? = null, inferNullability: Boolean = true, dbType: DbType? = null, - strictValidation: Boolean = true, + validation: SqlValidation = SqlValidation.None, configureStatement: (PreparedStatement) -> Unit = {}, ): AnyFrame { validateLimit(limit) @@ -390,7 +370,7 @@ public fun DbConnectionConfig.readDataFrame( limit, inferNullability, dbType, - strictValidation, + validation, configureStatement, ) @@ -400,7 +380,6 @@ public fun DbConnectionConfig.readDataFrame( limit, inferNullability, dbType, - strictValidation, configureStatement, ) @@ -413,18 +392,16 @@ public fun DbConnectionConfig.readDataFrame( /** * Converts the result of an SQL query or SQL table (by name) to the DataFrame. * - * @param [sqlQueryOrTableName] the SQL query to execute or name of the SQL table. - * It should be a name of one of the existing SQL tables, - * or the SQL query should start from SELECT and contain one query for reading data without any manipulation. - * It should not contain `;` symbol. + * @param [sqlQueryOrTableName] the SQL query to execute or the name of an SQL table. * @param [limit] the maximum number of rows to retrieve from the result of the SQL query execution. * `null` (default) means no limit - all available rows will be fetched * or positive integer (e.g., `100`) - fetch at most that many rows * @param [inferNullability] indicates how the column nullability should be inferred. * @param [dbType] the type of database, could be a custom object, provided by user, optional, default is `null`, * in that case the [dbType] will be recognized from the [Connection]. - * @param [strictValidation] if `true`, the method validates that the provided query or table name is in a valid format. - * Default is `true` for strict validation. + * @param [validation] controls SQL query validation when a query (not a table name) is provided. + * [SqlValidation.ReadOnly] blocks DDL/DML; [SqlValidation.None] (default) skips validation. + * Table name validation is always strict regardless of this parameter. * @param [configureStatement] optional lambda to configure the [PreparedStatement] before execution. * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. * @return the DataFrame containing the result of the SQL query. @@ -434,7 +411,7 @@ public fun Connection.readDataFrame( limit: Int? = null, inferNullability: Boolean = true, dbType: DbType? = null, - strictValidation: Boolean = true, + validation: SqlValidation = SqlValidation.None, configureStatement: (PreparedStatement) -> Unit = {}, ): AnyFrame { validateLimit(limit) @@ -445,7 +422,7 @@ public fun Connection.readDataFrame( limit, inferNullability, dbType, - strictValidation, + validation, configureStatement, ) @@ -455,7 +432,6 @@ public fun Connection.readDataFrame( limit, inferNullability, dbType, - strictValidation, configureStatement, ) @@ -487,18 +463,16 @@ public fun Connection.readDataFrame( * val queryDF = dataSource.readDataFrame("SELECT * FROM orders WHERE amount > 100") * ``` * - * @param [sqlQueryOrTableName] the SQL query to execute or name of the SQL table. - * It should be a name of one of the existing SQL tables, - * or the SQL query should start from SELECT and contain one query for reading data without any manipulation. - * It should not contain `;` symbol. + * @param [sqlQueryOrTableName] the SQL query to execute or the name of an SQL table. * @param [limit] the maximum number of rows to retrieve from the result of the SQL query execution. * `null` (default) means no limit - all available rows will be fetched * or positive integer (e.g., `100`) - fetch at most that many rows * @param [inferNullability] indicates how the column nullability should be inferred. * @param [dbType] the type of database, could be a custom object, provided by user, optional, default is `null`, * in that case the [dbType] will be recognized from the [DataSource]. - * @param [strictValidation] if `true`, the method validates that the provided query or table name is in a valid format. - * Default is `true` for strict validation. + * @param [validation] controls SQL query validation when a query (not a table name) is provided. + * [SqlValidation.ReadOnly] blocks DDL/DML; [SqlValidation.None] (default) skips validation. + * Table name validation is always strict regardless of this parameter. * @param [configureStatement] optional lambda to configure the [PreparedStatement] before execution. * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. * @return the DataFrame containing the result of the SQL query. @@ -510,7 +484,7 @@ public fun DataSource.readDataFrame( limit: Int? = null, inferNullability: Boolean = true, dbType: DbType? = null, - strictValidation: Boolean = true, + validation: SqlValidation = SqlValidation.None, configureStatement: (PreparedStatement) -> Unit = {}, ): AnyFrame { validateLimit(limit) @@ -522,7 +496,7 @@ public fun DataSource.readDataFrame( limit, inferNullability, dbType, - strictValidation, + validation, configureStatement, ) @@ -532,7 +506,6 @@ public fun DataSource.readDataFrame( limit, inferNullability, dbType, - strictValidation, configureStatement, ) @@ -853,7 +826,6 @@ private fun readTableAsDataFrame( limit, inferNullability, dbType, - true, configureStatement, ) diff --git a/dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/validationUtil.kt b/dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/validationUtil.kt index 03a64d53dc6a52fe267f4b604866fda376715d62..dd9c1c5f419c52d462c72bddc58b72b6356eaee5 100644 GIT binary patch literal 10951 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 literal 9423 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 Jc*BkP{Xe|ls#^d6 diff --git a/dataframe-jdbc/src/test/kotlin/org/jetbrains/kotlinx/dataframe/io/h2/h2Test.kt b/dataframe-jdbc/src/test/kotlin/org/jetbrains/kotlinx/dataframe/io/h2/h2Test.kt index 5944a9e07e..2edc890923 100644 --- a/dataframe-jdbc/src/test/kotlin/org/jetbrains/kotlinx/dataframe/io/h2/h2Test.kt +++ b/dataframe-jdbc/src/test/kotlin/org/jetbrains/kotlinx/dataframe/io/h2/h2Test.kt @@ -2,6 +2,7 @@ package org.jetbrains.kotlinx.dataframe.io.h2 import com.zaxxer.hikari.HikariConfig import com.zaxxer.hikari.HikariDataSource +import io.kotest.assertions.throwables.shouldNotThrow import io.kotest.assertions.throwables.shouldThrow import io.kotest.assertions.throwables.shouldThrowExactly import io.kotest.matchers.shouldBe @@ -15,6 +16,7 @@ import org.jetbrains.kotlinx.dataframe.api.cast import org.jetbrains.kotlinx.dataframe.api.filter import org.jetbrains.kotlinx.dataframe.api.select import org.jetbrains.kotlinx.dataframe.io.DbConnectionConfig +import org.jetbrains.kotlinx.dataframe.io.SqlValidation import org.jetbrains.kotlinx.dataframe.io.db.H2 import org.jetbrains.kotlinx.dataframe.io.db.H2.Mode import org.jetbrains.kotlinx.dataframe.io.db.MySql @@ -634,26 +636,53 @@ class JdbcTest { """ shouldThrow { - DataFrame.readSqlQuery(connection, createSQL) + DataFrame.readSqlQuery(connection, createSQL, validation = SqlValidation.ReadOnly) } shouldThrow { - DataFrame.readSqlQuery(connection, dropSQL) + DataFrame.readSqlQuery(connection, dropSQL, validation = SqlValidation.ReadOnly) } shouldThrow { - DataFrame.readSqlQuery(connection, alterSQL) + DataFrame.readSqlQuery(connection, alterSQL, validation = SqlValidation.ReadOnly) } shouldThrow { - DataFrame.readSqlQuery(connection, deleteSQL) + DataFrame.readSqlQuery(connection, deleteSQL, validation = SqlValidation.ReadOnly) } shouldThrow { - DataFrame.readSqlQuery(connection, repeatedSQL) + DataFrame.readSqlQuery(connection, repeatedSQL, validation = SqlValidation.ReadOnly) } } + @Test + fun `readSqlTable should reject pre-quoted table names and suggest unquoted form`() { + // Pre-quoted names are rejected because the library adds quoting automatically. + // Users should pass unquoted identifiers: schema.table, not "schema"."table". + val preQuotedNames = listOf( + "\"Customer\"", // ANSI double-quoted + "\"PUBLIC\".\"Customer\"", // ANSI double-quoted schema.table + "`Customer`", // MySQL backtick-quoted + "`PUBLIC`.`Customer`", // MySQL backtick-quoted schema.table + "[Customer]", // MSSQL bracket-quoted + ) + + preQuotedNames.forEach { tableName -> + shouldThrow { + DataFrame.readSqlTable(connection, tableName) + } + } + } + + @Test + fun `readSqlTable should accept unquoted schema-qualified names`() { + // H2 exposes every table under the PUBLIC schema. + // Passing "PUBLIC.Customer" should pass validation; the library quotes it for the DB. + val df = DataFrame.readSqlTable(connection, "PUBLIC.Customer") + assertCustomerData(df) + } + @Test fun `readFromTable should reject invalid table names to prevent SQL injections`() { // Invalid table names that attempt SQL injection @@ -663,6 +692,8 @@ class JdbcTest { "/* Multi-line comment */ Customer", // Injection using multi-line comment "Sale WHERE 1=1", // Injection using always-true condition "Sale UNION SELECT * FROM Customer", // UNION injection + "DROP TABLE users", // Bare DDL as table name — rejected by regex (space not allowed) + "users; DROP TABLE users", // Classic tautology injection ) invalidTableNames.forEach { tableName -> @@ -673,75 +704,79 @@ class JdbcTest { } @Test - fun `readSqlQuery should reject malicious SQL queries to prevent SQL injections`() { - // Malicious SQL queries attempting injection + fun `readSqlQuery with ReadOnly validation should block multi-statement and DDL queries`() { @Language("SQL") - val injectionComment = """ - SELECT * FROM Sale WHERE amount = 100.0 -- AND id = 5 - """ + val multiStatement = "SELECT * FROM Sale WHERE amount = 500.0; DROP TABLE Customer" @Language("SQL") - val injectionMultilineComment = """ - SELECT * FROM Customer /* Possible malicious comment */ WHERE id = 1 - """ + val bareDropTable = "DROP TABLE Customer; SELECT * FROM Sale" @Language("SQL") - val injectionSemicolon = """ - SELECT * FROM Sale WHERE amount = 500.0; DROP TABLE Customer - """ + val insertStatement = "INSERT INTO Sale (id) VALUES (1)" + listOf(multiStatement, bareDropTable, insertStatement).forEach { query -> + shouldThrow { + DataFrame.readSqlQuery(connection, query, validation = SqlValidation.ReadOnly) + } + } + } + + @Test + fun `readSqlQuery with ReadOnly validation should allow comments and semicolons inside literals`() { + // Comments are stripped before validation — these are valid read-only queries @Language("SQL") - val injectionSQLWithSingleQuote = """ - SELECT * FROM Sale WHERE id = 1 AND amount = 100.0 OR '1'='1 - """ + val queryWithLineComment = "SELECT * FROM Sale WHERE amount = 100.0 -- AND id = 5" @Language("SQL") - val injectionUsingDropCommand = """ - DROP TABLE Customer; SELECT * FROM Sale - """ + val queryWithBlockComment = "SELECT * FROM Customer /* filter by id */ WHERE id = 1" - val sqlInjectionQueries = listOf( - injectionComment, - injectionMultilineComment, - injectionSemicolon, - injectionSQLWithSingleQuote, - injectionUsingDropCommand, - ) + // Semicolons inside string literals are safe + @Language("SQL") + val queryWithSemicolonInLiteral = "SELECT * FROM Sale WHERE tag = 'a;b'" - sqlInjectionQueries.forEach { query -> - shouldThrow { - DataFrame.readSqlQuery(connection, query) + // CTEs must be allowed + @Language("SQL") + val cteQuery = "WITH recent AS (SELECT * FROM Sale) SELECT * FROM recent" + + listOf(queryWithLineComment, queryWithBlockComment, queryWithSemicolonInLiteral, cteQuery).forEach { query -> + // Wrap in runCatching so that DB-level errors (table/column not found) don't fail the test; + // only an IllegalArgumentException from validation would indicate a false rejection. + val exception = runCatching { + DataFrame.readSqlQuery(connection, query, validation = SqlValidation.ReadOnly) + }.exceptionOrNull() + assert(exception !is IllegalArgumentException) { + "Query should pass ReadOnly validation but was rejected: $query\n$exception" } } } @Test - fun `readFromTable should work with non-standard table names when strictValidation is disabled`() { - // Non-standard table names that are still valid but may appear strange - val nonStandardTableNames = listOf( - "`Customer With Space`", // Table name with spaces - "`Important-Data`", // Table name with hyphens - "`[123TableName]`", // Table name that resembles a special syntax - ) + fun `readSqlQuery with default SqlValidation None does not throw for any query`() { + // Default mode passes the query to the database without any validation. + // We use a harmless multi-statement query so no test data is modified. + @Language("SQL") + val harmlessMultiStatement = "SELECT 1; SELECT 2" - try { - // Create these tables to ensure they exist for the test - connection.createStatement().use { stmt -> - nonStandardTableNames.forEach { tableName -> - stmt.execute("CREATE TABLE IF NOT EXISTS $tableName (id INT, name VARCHAR(255))") - } - } + // No IllegalArgumentException from validation — the database handles the rest. + val exception = runCatching { DataFrame.readSqlQuery(connection, harmlessMultiStatement) }.exceptionOrNull() + assert(exception !is IllegalArgumentException) { + "SqlValidation.None should not throw IllegalArgumentException, got: $exception" + } + } - // Read from these tables with strictValidation disabled - nonStandardTableNames.forEach { tableName -> - DataFrame.readSqlTable(connection, tableName, strictValidation = false) - } - } finally { - // Clean up by deleting all created tables - connection.createStatement().use { stmt -> - nonStandardTableNames.forEach { tableName -> - stmt.execute("DROP TABLE IF EXISTS $tableName") - } + @Test + fun `readSqlTable should always reject non-identifier table names`() { + // Table name validation is always strict because the library constructs SQL from the name. + // Names containing spaces, backticks, hyphens, or brackets are not valid SQL identifiers. + val nonIdentifierNames = listOf( + "`Customer With Space`", + "`Important-Data`", + "`[123TableName]`", + ) + + nonIdentifierNames.forEach { tableName -> + shouldThrow { + DataFrame.readSqlTable(connection, tableName) } } } @@ -782,8 +817,7 @@ class JdbcTest { } @Test - fun `readSqlQuery should execute DROP TABLE when validation is disabled`() { - // Query to create a temporary test table + fun `readSqlQuery with SqlValidation None passes multi-statement queries to the database`() { @Language("SQL") val createTableQuery = """ CREATE TABLE IF NOT EXISTS TestTable ( @@ -792,7 +826,6 @@ class JdbcTest { ) """ - // Query to drop the test table @Language("SQL") val dropTableQuery = """ SELECT * FROM TestTable; DROP TABLE TestTable; @@ -800,22 +833,13 @@ class JdbcTest { """ try { - // Create the test table connection.createStatement().use { stmt -> - stmt.execute(createTableQuery) // Create table for the test case + stmt.execute(createTableQuery) } - // Execute the DROP TABLE command with validation disabled - DataFrame.readSqlQuery(connection, dropTableQuery, strictValidation = false) - - // Verify that the table has been successfully dropped - connection.createStatement().use { stmt -> - shouldThrow { - stmt.executeQuery("SELECT * FROM TestTable") - } - } + // SqlValidation.None is the default — no IllegalArgumentException is thrown + DataFrame.readSqlQuery(connection, dropTableQuery) } finally { - // Cleanup: Ensure the table is removed in case of failure connection.createStatement().use { stmt -> stmt.execute("DROP TABLE IF EXISTS TestTable") } @@ -832,17 +856,14 @@ class JdbcTest { ) """ + // Double-quoted identifiers are stripped before keyword matching in ReadOnly mode, + // so SELECT * FROM "ALTER" is correctly recognised as a read-only query. @Language("SQL") val selectFromWeirdTableSQL = """SELECT * from "ALTER"""" try { connection.createStatement().execute(createAlterTableQuery) - // with enabled strictValidation - shouldThrow { - DataFrame.readSqlQuery(connection, selectFromWeirdTableSQL) - } - // with disabled strictValidation - DataFrame.readSqlQuery(connection, selectFromWeirdTableSQL, strictValidation = false).rowsCount() shouldBe 0 + DataFrame.readSqlQuery(connection, selectFromWeirdTableSQL).rowsCount() shouldBe 0 } finally { connection.createStatement().execute("DROP TABLE IF EXISTS \"ALTER\"") } From 82775dbd46b9303c2271cf5f821e44b04f09647d Mon Sep 17 00:00:00 2001 From: Alexey Zinoviev Date: Fri, 29 May 2026 16:37:58 +0200 Subject: [PATCH 2/5] Refine SQL comment handling and adjust formatting for consistency --- .../kotlinx/dataframe/io/validationUtil.kt | Bin 10951 -> 11009 bytes .../kotlinx/dataframe/io/h2/h2Test.kt | 8 ++++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/validationUtil.kt b/dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/validationUtil.kt index dd9c1c5f419c52d462c72bddc58b72b6356eaee5..2ee1ac08fe9bbd679043493000053119d35c15b3 100644 GIT binary patch delta 169 zcmX>e+8DNBHOC|#k;!{Gegdh@CpfK`Ch`2({Eg>_fDtd30uU&FUU2_-y317uWOJyg6A6H>I}7E JbBJ6q4*<>jCd>c; delta 150 zcmZn+J07}WHOJ&wUXIOMIhYy2j6<9*Od!T&0iJhY0S?}G0%;0LF0MYVA+Aa~3QC@S z!LC6eAXaFAiz7tLImi{v;^k5R0wqVE5Z54(ijbgCKWC^K_aH| From 4829a50f122034549c847ef4af3b3f74d1c34177 Mon Sep 17 00:00:00 2001 From: Alexey Zinoviev Date: Fri, 29 May 2026 17:09:43 +0200 Subject: [PATCH 3/5] API Dump --- dataframe-jdbc/api/dataframe-jdbc.api | 44 ++++++++++++++++----------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/dataframe-jdbc/api/dataframe-jdbc.api b/dataframe-jdbc/api/dataframe-jdbc.api index 43b8f1cf82..bd372d8c40 100644 --- a/dataframe-jdbc/api/dataframe-jdbc.api +++ b/dataframe-jdbc/api/dataframe-jdbc.api @@ -66,32 +66,40 @@ public final class org/jetbrains/kotlinx/dataframe/io/ReadJdbcKt { public static synthetic fun readAllSqlTables$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Ljava/sql/Connection;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/util/Map; public static synthetic fun readAllSqlTables$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Ljavax/sql/DataSource;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/util/Map; public static synthetic fun readAllSqlTables$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Lorg/jetbrains/kotlinx/dataframe/io/DbConnectionConfig;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/util/Map; - public static final fun readDataFrame (Ljava/sql/Connection;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;ZLkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun readDataFrame (Ljava/sql/Connection;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;Lorg/jetbrains/kotlinx/dataframe/io/SqlValidation;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static final fun readDataFrame (Ljava/sql/ResultSet;Ljava/sql/Connection;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static final fun readDataFrame (Ljava/sql/ResultSet;Lorg/jetbrains/kotlinx/dataframe/io/db/DbType;Ljava/lang/Integer;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun readDataFrame (Ljavax/sql/DataSource;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;ZLkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun readDataFrame (Lorg/jetbrains/kotlinx/dataframe/io/DbConnectionConfig;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;ZLkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static synthetic fun readDataFrame$default (Ljava/sql/Connection;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun readDataFrame (Ljavax/sql/DataSource;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;Lorg/jetbrains/kotlinx/dataframe/io/SqlValidation;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun readDataFrame (Lorg/jetbrains/kotlinx/dataframe/io/DbConnectionConfig;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;Lorg/jetbrains/kotlinx/dataframe/io/SqlValidation;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun readDataFrame$default (Ljava/sql/Connection;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;Lorg/jetbrains/kotlinx/dataframe/io/SqlValidation;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun readDataFrame$default (Ljava/sql/ResultSet;Ljava/sql/Connection;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun readDataFrame$default (Ljava/sql/ResultSet;Lorg/jetbrains/kotlinx/dataframe/io/db/DbType;Ljava/lang/Integer;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static synthetic fun readDataFrame$default (Ljavax/sql/DataSource;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static synthetic fun readDataFrame$default (Lorg/jetbrains/kotlinx/dataframe/io/DbConnectionConfig;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun readDataFrame$default (Ljavax/sql/DataSource;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;Lorg/jetbrains/kotlinx/dataframe/io/SqlValidation;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun readDataFrame$default (Lorg/jetbrains/kotlinx/dataframe/io/DbConnectionConfig;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;Lorg/jetbrains/kotlinx/dataframe/io/SqlValidation;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static final fun readResultSet (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Ljava/sql/ResultSet;Ljava/sql/Connection;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static final fun readResultSet (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Ljava/sql/ResultSet;Lorg/jetbrains/kotlinx/dataframe/io/db/DbType;Ljava/lang/Integer;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun readResultSet$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Ljava/sql/ResultSet;Ljava/sql/Connection;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun readResultSet$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Ljava/sql/ResultSet;Lorg/jetbrains/kotlinx/dataframe/io/db/DbType;Ljava/lang/Integer;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun readSqlQuery (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Ljava/sql/Connection;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;ZLkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun readSqlQuery (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Ljavax/sql/DataSource;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;ZLkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun readSqlQuery (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Lorg/jetbrains/kotlinx/dataframe/io/DbConnectionConfig;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;ZLkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static synthetic fun readSqlQuery$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Ljava/sql/Connection;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static synthetic fun readSqlQuery$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Ljavax/sql/DataSource;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static synthetic fun readSqlQuery$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Lorg/jetbrains/kotlinx/dataframe/io/DbConnectionConfig;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun readSqlTable (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Ljava/sql/Connection;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;ZLkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun readSqlTable (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Ljavax/sql/DataSource;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;ZLkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun readSqlTable (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Lorg/jetbrains/kotlinx/dataframe/io/DbConnectionConfig;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;ZLkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static synthetic fun readSqlTable$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Ljava/sql/Connection;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static synthetic fun readSqlTable$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Ljavax/sql/DataSource;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static synthetic fun readSqlTable$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Lorg/jetbrains/kotlinx/dataframe/io/DbConnectionConfig;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun readSqlQuery (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Ljava/sql/Connection;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;Lorg/jetbrains/kotlinx/dataframe/io/SqlValidation;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun readSqlQuery (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Ljavax/sql/DataSource;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;Lorg/jetbrains/kotlinx/dataframe/io/SqlValidation;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun readSqlQuery (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Lorg/jetbrains/kotlinx/dataframe/io/DbConnectionConfig;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;Lorg/jetbrains/kotlinx/dataframe/io/SqlValidation;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun readSqlQuery$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Ljava/sql/Connection;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;Lorg/jetbrains/kotlinx/dataframe/io/SqlValidation;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun readSqlQuery$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Ljavax/sql/DataSource;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;Lorg/jetbrains/kotlinx/dataframe/io/SqlValidation;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun readSqlQuery$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Lorg/jetbrains/kotlinx/dataframe/io/DbConnectionConfig;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;Lorg/jetbrains/kotlinx/dataframe/io/SqlValidation;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun readSqlTable (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Ljava/sql/Connection;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun readSqlTable (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Ljavax/sql/DataSource;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun readSqlTable (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Lorg/jetbrains/kotlinx/dataframe/io/DbConnectionConfig;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun readSqlTable$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Ljava/sql/Connection;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun readSqlTable$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Ljavax/sql/DataSource;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun readSqlTable$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame$Companion;Lorg/jetbrains/kotlinx/dataframe/io/DbConnectionConfig;Ljava/lang/String;Ljava/lang/Integer;ZLorg/jetbrains/kotlinx/dataframe/io/db/DbType;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; +} + +public final class org/jetbrains/kotlinx/dataframe/io/SqlValidation : java/lang/Enum { + public static final field None Lorg/jetbrains/kotlinx/dataframe/io/SqlValidation; + public static final field ReadOnly Lorg/jetbrains/kotlinx/dataframe/io/SqlValidation; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/io/SqlValidation; + public static fun values ()[Lorg/jetbrains/kotlinx/dataframe/io/SqlValidation; } public abstract class org/jetbrains/kotlinx/dataframe/io/db/AdvancedDbType : org/jetbrains/kotlinx/dataframe/io/db/DbType { From 176d8cf29bd2d54d9e18baad36e78932335c7c58 Mon Sep 17 00:00:00 2001 From: Jolan Rensen Date: Mon, 1 Jun 2026 12:05:33 +0200 Subject: [PATCH 4/5] changed validationUtil.kt back to LF --- .../kotlinx/dataframe/io/validationUtil.kt | Bin 11009 -> 10718 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/validationUtil.kt b/dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/validationUtil.kt index 2ee1ac08fe9bbd679043493000053119d35c15b3..d5b11f001473190d0f30b0db793142141fb8b79e 100644 GIT binary patch delta 1887 zcmb7ETTGi}7*5wCe+vbAgi`wTFFkT-*G&XQ2dw=WOx8kMP68W0r@g%Fc5%qvVJ*%0`Q7#3ci!g!@#j=*mI1lmY9{b0t3Gvo8#4S`3Srre-a+ZXJJe+ zsK72k*jA7Z0^yZp=;Z{P+v?y?@ims|Aj(4gyNU~ZfPUo#xUTHcV@Lc$BQ(35V~Tz7 zqjDHJR9+<~?1YfU2zeC&msN=OdRsLwK<%r-5LUO>@c^520cBAHg&?oCTX+$d#U`CY z87#)-&Se+iUG)G)6W66xhDBH4PqiQHngMXsG{Y6O4nEN7E%U6`kFxFURa?%bOu!9| zAHLCq4&qC(vZy_R!Z^l^3|kQ%*s0MRAc@{LYitFv4tKO#!9fG-TBYbKE8~q_JjgkWiq?GU z2zdFB1h-16jr(E_Bgjj7QRit4Md~{Ks{oEiGkmV|9bsV~%M&`s$&CLH0*7*xaZbuD zA-OWJwRW{MMz7bV;Mdx7{804PrNsHG3&5xN|4ZF`Eg!!unNR73sk^D40BwC6gz$f| zp5oni>S>TQ#QA-?VHmDAY(isW1~wZ*Lf9LPA=qmqw+$^|H?*n=e;-O?B4UOZyljZz zo_}R%69$pXwp7@{%D)Y6a2byhuwb+vw7!g1vMim;Ne;V4GuJ8DGwR`A=d#TY>H_ z*2NONlw%gfb1}2ZkElG@hc8Y3VdM9veE)MU&J+r=hVlm6QzA$;o*1A?4ZR zP`nx?Nlhi55D?r5k>{!8*(x42Lq(+^+vMgFFEHedvAN+u3;k0uCt~tX(@n1UoKu(V0un95@SIJJi z`;eRmy{i{)yDdPw82G|9?5PgR!H^V~(nf(rD>QyP#A^aQZKp&xH|(~Zfo_lIQC%tb zf{hQ8T|vG)UBY9sjGPg~Zsc-)d=-Rj-0+vX_y2@_$ulTCwPL!Z!UiKv^7oz|ep-=t z0iO3R35@*Y?FW}{0Q123dSS=+7>|6M;60!28%B delta 2285 zcmb7FUrd`-6ieoTAHG_0#C{4t+^9KbZ&iNu+da@c_m*cp_iF8rnC4;t}~M7I5u6%<~e%n zcN+=9v@EECf2zyxr}2R7w4A08jIPQiWi;NE&43KmyZ~~)ZB&_J7xD#`#t&IM}Aql?B@>KrZ@!k1u~%m|lT?-0~@o?~ISQBM3>-JA$$mCpgl z75PaWUkCu9VTQ}(*kUh@x8*}%R4P0mI~DC9#}r5mEGcHByt|5SFe#LQCL!G#Q$ShN zhe9-k!s2Dm zzEX)lu6Kg=kD9C-X$&AWl&=QX#83u&jxq{EGrq1-0=Q@~;}uGde^MzV>$JLF8iGZh z4Fq@u-cOk-u*{O6*P;y?Uss#(tXe4rgfw-K6(+@Pty(&GKamQR!-InTgu)$l$D#5G ziH+a_JU|^li`RD;<^V36E3zWs=Nh}fgyT?*RG3&4tVB!O)YTn#f*yz9*XeU&`|Q%= zQu_oN{9u~k<+X+xagPCtY_D)o9yQDX8XOeTpJx|vsL_Dajn6>X2aRNt?(_1O#+Zoi z*D^5smNqWxKWIrKJDS!&-fBvN{JSY6+XD zsFs5uBu>a9v|ilM2+3v*9YUKJ@Lhve>X>f~VX#5R3>?M~H;2HHuSyk%@CQGU@}zNC zB=18b;paPJ1f@st_lb`M8 zr{VT9larM)6W(7llN|TVUDBrfYM$ch4mS^iVY36VL9(5;r2 z#2`J^TaJSS7URBq+JS}%Zg$T~qHtz(kUAJ(pG0;!H@ zVr0}I-mQ*k?0hU4E30SYou$yy9R%K5z^L1X};olm)i5THw$E12>T1K$;VW+fP*?xbUa# z&w;+z?miOAkaN~1fMyqvcbO?cgJzJu4{@ux9C@$GHM;Pglhl0F3|fy7zv~JRD&Z3s zQ!1>&S}KR^d)GSNSiC_VZH! From a616f7409b8109258a58ab7a0a298730115ec4af Mon Sep 17 00:00:00 2001 From: zaleslaw Date: Mon, 15 Jun 2026 11:36:18 +0200 Subject: [PATCH 5/5] Improved KDoc formatting for SQL-related functions and `SqlValidation` enum. --- .../kotlinx/dataframe/io/readJdbc.kt | 148 +++++++++--------- .../kotlinx/dataframe/io/validationUtil.kt | Bin 10718 -> 10809 bytes 2 files changed, 74 insertions(+), 74 deletions(-) diff --git a/dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/readJdbc.kt b/dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/readJdbc.kt index d351eb09e9..6a65f9a8ca 100644 --- a/dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/readJdbc.kt +++ b/dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/readJdbc.kt @@ -43,13 +43,13 @@ private val logger = KotlinLogging.logger {} * @param [dbConfig] the configuration for the database, including URL, user, and password. * @param [tableName] the name of the table to read data from. * @param [limit] the maximum number of rows to retrieve from the table. - * `null` (default) means no limit - all available rows will be fetched - * or positive integer (e.g., `100`) - fetch at most that many rows + * `null` (default) means no limit - all available rows will be fetched + * or positive integer (e.g., `100`) - fetch at most that many rows * @param [inferNullability] indicates how the column nullability should be inferred. * @param [dbType] the type of database, could be a custom object, provided by user, optional, default is `null`, - * in that case the [dbType] will be recognized from the [dbConfig]. + * in that case the [dbType] will be recognized from the [dbConfig]. * @param [configureStatement] optional lambda to configure the [PreparedStatement] before execution. - * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. + * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. * @return the DataFrame containing the data from the SQL table. */ public fun DataFrame.Companion.readSqlTable( @@ -72,13 +72,13 @@ public fun DataFrame.Companion.readSqlTable( * @param [dataSource] the [DataSource] to get a database connection from. * @param [tableName] the name of the table to read data from. * @param [limit] the maximum number of rows to retrieve from the table. - * `null` (default) means no limit - all available rows will be fetched - * or positive integer (e.g., `100`) - fetch at most that many rows + * `null` (default) means no limit - all available rows will be fetched + * or positive integer (e.g., `100`) - fetch at most that many rows * @param [inferNullability] indicates how the column nullability should be inferred. * @param [dbType] the type of database, could be a custom object, provided by user, optional, default is `null`, - * in that case the [dbType] will be recognized from the [dataSource]. + * in that case the [dbType] will be recognized from the [dataSource]. * @param [configureStatement] optional lambda to configure the [PreparedStatement] before execution. - * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. + * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. * @return the DataFrame containing the data from the SQL table. * * @see [DataSource.getConnection] @@ -110,13 +110,13 @@ public fun DataFrame.Companion.readSqlTable( * @param [connection] the database connection to read tables from. * @param [tableName] the name of the table to read data from. * @param [limit] the maximum number of rows to retrieve from the table. - * `null` (default) means no limit - all available rows will be fetched - * or positive integer (e.g., `100`) - fetch at most that many rows + * `null` (default) means no limit - all available rows will be fetched + * or positive integer (e.g., `100`) - fetch at most that many rows * @param [inferNullability] indicates how the column nullability should be inferred. * @param [dbType] the type of database, could be a custom object, provided by user, optional, default is `null`, - * in that case the [dbType] will be recognized from the [connection]. + * in that case the [dbType] will be recognized from the [connection]. * @param [configureStatement] optional lambda to configure the [PreparedStatement] before execution. - * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. + * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. * @return the DataFrame containing the data from the SQL table. * * @see [DriverManager.getConnection] @@ -158,7 +158,7 @@ public fun DataFrame.Companion.readSqlTable( * @param [determinedDbType] The type of database being accessed, which determines specific configurations. * @param [configureStatement] A lambda function to configure the prepared statement before execution. * @param [limit] the maximum number of rows to retrieve from the table. - * `null` (default) means no limit - all available rows will be fetched. + * `null` (default) means no limit - all available rows will be fetched. * @param [inferNullability] A flag to determine whether to infer nullability for result set fields. * @return The data frame constructed from the database query results. * @throws [IllegalStateException] If an error occurs while reading from the database or processing the data. @@ -213,16 +213,16 @@ private fun executeQueryAndBuildDataFrame( * @param [dbConfig] the database configuration to connect to the database, including URL, user, and password. * @param [sqlQuery] the SQL query to execute. * @param [limit] the maximum number of rows to retrieve from the result of the SQL query execution. - * `null` (default) means no limit - all available rows will be fetched - * or positive integer (e.g., `100`) - fetch at most that many rows + * `null` (default) means no limit - all available rows will be fetched + * or positive integer (e.g., `100`) - fetch at most that many rows * @param [inferNullability] indicates how the column nullability should be inferred. * @param [dbType] the type of database, could be a custom object, provided by user, optional, default is `null`, - * in that case the [dbType] will be recognized from the [dbConfig]. + * in that case the [dbType] will be recognized from the [dbConfig]. * @param [validation] controls SQL query validation. [SqlValidation.ReadOnly] blocks DDL/DML statements and - * only allows read-oriented queries (SELECT, WITH, VALUES, TABLE, EXPLAIN). - * [SqlValidation.None] (default) passes the query to the database without validation. + * only allows read-oriented queries (SELECT, WITH, VALUES, TABLE, EXPLAIN). + * [SqlValidation.None] (default) passes the query to the database without validation. * @param [configureStatement] optional lambda to configure the [PreparedStatement] before execution. - * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. + * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. * @return the DataFrame containing the result of the SQL query. */ public fun DataFrame.Companion.readSqlQuery( @@ -246,16 +246,16 @@ public fun DataFrame.Companion.readSqlQuery( * @param [dataSource] the [DataSource] to obtain a database connection from. * @param [sqlQuery] the SQL query to execute. * @param [limit] the maximum number of rows to retrieve from the result of the SQL query execution. - * `null` (default) means no limit - all available rows will be fetched - * or positive integer (e.g., `100`) - fetch at most that many rows + * `null` (default) means no limit - all available rows will be fetched + * or positive integer (e.g., `100`) - fetch at most that many rows * @param [inferNullability] indicates how the column nullability should be inferred. * @param [dbType] the type of database, could be a custom object, provided by user, optional, default is `null`, - * in that case the [dbType] will be recognized from the [dataSource]. + * in that case the [dbType] will be recognized from the [dataSource]. * @param [validation] controls SQL query validation. [SqlValidation.ReadOnly] blocks DDL/DML statements and - * only allows read-oriented queries (SELECT, WITH, VALUES, TABLE, EXPLAIN). - * [SqlValidation.None] (default) passes the query to the database without validation. + * only allows read-oriented queries (SELECT, WITH, VALUES, TABLE, EXPLAIN). + * [SqlValidation.None] (default) passes the query to the database without validation. * @param [configureStatement] optional lambda to configure the [PreparedStatement] before execution. - * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. + * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. * @return the DataFrame containing the result of the SQL query. * * @see [DataSource.getConnection] @@ -281,16 +281,16 @@ public fun DataFrame.Companion.readSqlQuery( * @param [connection] the database connection to execute the SQL query. * @param [sqlQuery] the SQL query to execute. * @param [limit] the maximum number of rows to retrieve from the result of the SQL query execution. - * `null` (default) means no limit - all available rows will be fetched - * or positive integer (e.g., `100`) - fetch at most that many rows + * `null` (default) means no limit - all available rows will be fetched + * or positive integer (e.g., `100`) - fetch at most that many rows * @param [inferNullability] indicates how the column nullability should be inferred. * @param [dbType] the type of database, could be a custom object, provided by user, optional, default is `null`, - * in that case the [dbType] will be recognized from the [connection]. + * in that case the [dbType] will be recognized from the [connection]. * @param [validation] controls SQL query validation. [SqlValidation.ReadOnly] blocks DDL/DML statements and - * only allows read-oriented queries (SELECT, WITH, VALUES, TABLE, EXPLAIN). - * [SqlValidation.None] (default) passes the query to the database without validation. + * only allows read-oriented queries (SELECT, WITH, VALUES, TABLE, EXPLAIN). + * [SqlValidation.None] (default) passes the query to the database without validation. * @param [configureStatement] optional lambda to configure the [PreparedStatement] before execution. - * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. + * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. * @return the DataFrame containing the result of the SQL query. * * @see [DriverManager.getConnection] @@ -342,16 +342,16 @@ public fun DataFrame.Companion.readSqlQuery( * * @param [sqlQueryOrTableName] the SQL query to execute or the name of an SQL table. * @param [limit] the maximum number of rows to retrieve from the result of the SQL query execution. - * `null` (default) means no limit - all available rows will be fetched - * or positive integer (e.g., `100`) - fetch at most that many rows + * `null` (default) means no limit - all available rows will be fetched + * or positive integer (e.g., `100`) - fetch at most that many rows * @param [inferNullability] indicates how the column nullability should be inferred. * @param [dbType] the type of database, could be a custom object, provided by user, optional, default is `null`, - * in that case the [dbType] will be recognized from the [DbConnectionConfig]. + * in that case the [dbType] will be recognized from the [DbConnectionConfig]. * @param [validation] controls SQL query validation when a query (not a table name) is provided. - * [SqlValidation.ReadOnly] blocks DDL/DML; [SqlValidation.None] (default) skips validation. - * Table name validation is always strict regardless of this parameter. + * [SqlValidation.ReadOnly] blocks DDL/DML; [SqlValidation.None] (default) skips validation. + * Table name validation is always strict regardless of this parameter. * @param [configureStatement] optional lambda to configure the [PreparedStatement] before execution. - * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. + * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. * @return the DataFrame containing the result of the SQL query. */ public fun DbConnectionConfig.readDataFrame( @@ -394,16 +394,16 @@ public fun DbConnectionConfig.readDataFrame( * * @param [sqlQueryOrTableName] the SQL query to execute or the name of an SQL table. * @param [limit] the maximum number of rows to retrieve from the result of the SQL query execution. - * `null` (default) means no limit - all available rows will be fetched - * or positive integer (e.g., `100`) - fetch at most that many rows + * `null` (default) means no limit - all available rows will be fetched + * or positive integer (e.g., `100`) - fetch at most that many rows * @param [inferNullability] indicates how the column nullability should be inferred. * @param [dbType] the type of database, could be a custom object, provided by user, optional, default is `null`, - * in that case the [dbType] will be recognized from the [Connection]. + * in that case the [dbType] will be recognized from the [Connection]. * @param [validation] controls SQL query validation when a query (not a table name) is provided. - * [SqlValidation.ReadOnly] blocks DDL/DML; [SqlValidation.None] (default) skips validation. - * Table name validation is always strict regardless of this parameter. + * [SqlValidation.ReadOnly] blocks DDL/DML; [SqlValidation.None] (default) skips validation. + * Table name validation is always strict regardless of this parameter. * @param [configureStatement] optional lambda to configure the [PreparedStatement] before execution. - * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. + * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. * @return the DataFrame containing the result of the SQL query. */ public fun Connection.readDataFrame( @@ -465,16 +465,16 @@ public fun Connection.readDataFrame( * * @param [sqlQueryOrTableName] the SQL query to execute or the name of an SQL table. * @param [limit] the maximum number of rows to retrieve from the result of the SQL query execution. - * `null` (default) means no limit - all available rows will be fetched - * or positive integer (e.g., `100`) - fetch at most that many rows + * `null` (default) means no limit - all available rows will be fetched + * or positive integer (e.g., `100`) - fetch at most that many rows * @param [inferNullability] indicates how the column nullability should be inferred. * @param [dbType] the type of database, could be a custom object, provided by user, optional, default is `null`, - * in that case the [dbType] will be recognized from the [DataSource]. + * in that case the [dbType] will be recognized from the [DataSource]. * @param [validation] controls SQL query validation when a query (not a table name) is provided. - * [SqlValidation.ReadOnly] blocks DDL/DML; [SqlValidation.None] (default) skips validation. - * Table name validation is always strict regardless of this parameter. + * [SqlValidation.ReadOnly] blocks DDL/DML; [SqlValidation.None] (default) skips validation. + * Table name validation is always strict regardless of this parameter. * @param [configureStatement] optional lambda to configure the [PreparedStatement] before execution. - * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. + * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. * @return the DataFrame containing the result of the SQL query. * * @see [DataSource.getConnection] @@ -528,11 +528,11 @@ public fun DataSource.readDataFrame( * NOTE: Reading from the [ResultSet][java.sql.ResultSet] could potentially change its state. * * @param [resultSet] the [ResultSet][java.sql.ResultSet] containing the data to read. - * Its state may be altered after the read operation. + * Its state may be altered after the read operation. * @param [dbType] the type of database that the [ResultSet] belongs to. * @param [limit] the maximum number of rows to read from the [ResultSet][java.sql.ResultSet]. - * `null` (default) means no limit - all available rows will be fetched - * or positive integer (e.g., `100`) - fetch at most that many rows + * `null` (default) means no limit - all available rows will be fetched + * or positive integer (e.g., `100`) - fetch at most that many rows * @param [inferNullability] indicates how the column nullability should be inferred. * @return the DataFrame generated from the [ResultSet][java.sql.ResultSet] data. * @@ -562,8 +562,8 @@ public fun DataFrame.Companion.readResultSet( * * @param [dbType] the type of database that the [ResultSet] belongs to. * @param [limit] the maximum number of rows to read from the [ResultSet][java.sql.ResultSet]. - * `null` (default) means no limit - all available rows will be fetched - * or positive integer (e.g., `100`) - fetch at most that many rows + * `null` (default) means no limit - all available rows will be fetched + * or positive integer (e.g., `100`) - fetch at most that many rows * @param [inferNullability] indicates how the column nullability should be inferred. * @return the DataFrame generated from the [ResultSet][java.sql.ResultSet] data. * @@ -586,15 +586,15 @@ public fun ResultSet.readDataFrame(dbType: DbType, limit: Int? = null, inferNull * __NOTE:__ Reading from the [ResultSet][java.sql.ResultSet] could potentially change its state. * * @param [resultSet] the [ResultSet][java.sql.ResultSet] containing the data to read. - * Its state may be altered after the read operation. + * Its state may be altered after the read operation. * @param [connection] the connection to the database (it's required to extract the database type) * that the [ResultSet] belongs to. * @param [limit] the maximum number of rows to read from the [ResultSet][java.sql.ResultSet]. - * `null` (default) means no limit - all available rows will be fetched - * or positive integer (e.g., `100`) - fetch at most that many rows + * `null` (default) means no limit - all available rows will be fetched + * or positive integer (e.g., `100`) - fetch at most that many rows * @param [inferNullability] indicates how the column nullability should be inferred. * @param [dbType] the type of database, could be a custom object, provided by user, optional, default is `null`, - * in that case the [dbType] will be recognized from the [resultSet]. + * in that case the [dbType] will be recognized from the [resultSet]. * @return the DataFrame generated from the [ResultSet][java.sql.ResultSet] data. * * @see [java.sql.ResultSet] @@ -626,11 +626,11 @@ public fun DataFrame.Companion.readResultSet( * @param [connection] the connection to the database (it's required to extract the database type) * that the [ResultSet] belongs to. * @param [limit] the maximum number of rows to read from the [ResultSet][java.sql.ResultSet]. - * `null` (default) means no limit - all available rows will be fetched - * or positive integer (e.g., `100`) - fetch at most that many rows + * `null` (default) means no limit - all available rows will be fetched + * or positive integer (e.g., `100`) - fetch at most that many rows * @param [inferNullability] indicates how the column nullability should be inferred. * @param [dbType] the type of database, could be a custom object, provided by user, optional, default is `null`, - * in that case the [dbType] will be recognized from the [ResultSet]. + * in that case the [dbType] will be recognized from the [ResultSet]. * @return the DataFrame generated from the [ResultSet][java.sql.ResultSet] data. * * @see [java.sql.ResultSet] @@ -660,14 +660,14 @@ public fun ResultSet.readDataFrame( * * @param [dbConfig] the database configuration to connect to the database, including URL, user, and password. * @param [limit] the maximum number of rows to read from each table. - * `null` (default) means no limit - all available rows will be fetched - * or positive integer (e.g., `100`) - fetch at most that many rows + * `null` (default) means no limit - all available rows will be fetched + * or positive integer (e.g., `100`) - fetch at most that many rows * @param [catalogue] a name of the catalog from which tables will be retrieved. A null value retrieves tables from all catalogs. * @param [inferNullability] indicates how the column nullability should be inferred. * @param [dbType] the type of database, could be a custom object, provided by user, optional, default is `null`, - * in that case the [dbType] will be recognized from the [dbConfig]. + * in that case the [dbType] will be recognized from the [dbConfig]. * @param [configureStatement] optional lambda to configure the [PreparedStatement] before execution. - * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. + * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. * @return a map of [String] to [AnyFrame] objects representing the non-system tables from the database. */ public fun DataFrame.Companion.readAllSqlTables( @@ -711,13 +711,13 @@ public fun DataFrame.Companion.readAllSqlTables( * @param [dataSource] the [DataSource] to get a database connection from. * @param [catalogue] a name of the catalog from which tables will be retrieved. A null value retrieves tables from all catalogs. * @param [limit] the maximum number of rows to read from each table. - * `null` (default) means no limit - all available rows will be fetched - * or positive integer (e.g., `100`) - fetch at most that many rows + * `null` (default) means no limit - all available rows will be fetched + * or positive integer (e.g., `100`) - fetch at most that many rows * @param [inferNullability] indicates how the column nullability should be inferred. * @param [dbType] the type of database, could be a custom object, provided by user, optional, default is `null`, - * in that case the [dbType] will be recognized from the [dataSource]. + * in that case the [dbType] will be recognized from the [dataSource]. * @param [configureStatement] optional lambda to configure the [PreparedStatement] before execution. - * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. + * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. * @return a map of [String] to [AnyFrame] objects representing the non-system tables from the database. * * @see [DataSource.getConnection] @@ -742,14 +742,14 @@ public fun DataFrame.Companion.readAllSqlTables( * * @param [connection] the database connection to read tables from. * @param [limit] the maximum number of rows to read from each table. - * `null` (default) means no limit - all available rows will be fetched - * or positive integer (e.g., `100`) - fetch at most that many rows + * `null` (default) means no limit - all available rows will be fetched + * or positive integer (e.g., `100`) - fetch at most that many rows * @param [catalogue] a name of the catalog from which tables will be retrieved. A null value retrieves tables from all catalogs. * @param [inferNullability] indicates how the column nullability should be inferred. * @param [dbType] the type of database, could be a custom object, provided by user, optional, default is `null`, - * in that case the [dbType] will be recognized from the [connection]. + * in that case the [dbType] will be recognized from the [connection]. * @param [configureStatement] optional lambda to configure the [PreparedStatement] before execution. - * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. + * This allows for custom tuning of fetch size, query timeout, and other JDBC parameters. * @return a map of [String] to [AnyFrame] objects representing the non-system tables from the database. * * @see [DriverManager.getConnection] @@ -856,7 +856,7 @@ internal fun getTableColumnsMetadata(resultSet: ResultSet, dbType: DbType): List * @param [rs] the ResultSet object containing the data to be fetched and converted. * @param [dbType] the type of the database. * @param [limit] the maximum number of rows to retrieve from the table. - * `null` (default) means no limit - all available rows will be fetched. + * `null` (default) means no limit - all available rows will be fetched. * @param [inferNullability] indicates how the column nullability should be inferred. * @return A [DataFrame] containing the fetched and converted data. */ diff --git a/dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/validationUtil.kt b/dataframe-jdbc/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/validationUtil.kt index d5b11f001473190d0f30b0db793142141fb8b79e..29155c82c9b762a81233946b1ecf142f9e7e6bec 100644 GIT binary patch delta 163 zcmcZ?yfb7&9pmIm77Z?aEiEnu5YU>OD=js-m(i0M$eDbVF&0c4GDU#t|8oA^NvUc1 zMX6xblkYLbn1FTZgZV+Ji7EbhIh8tGU@pQ?h3MeIoUp{4%#_5E%=|pP$qvk}U;|s2 Xqrvn&<|r_2&f>@hF>v!L786wfw|XgP delta 75 zcmdlPaxZv89V083f|f$`G7C%8