Skip to content

fix: EXPOSED-1040 Support SELECT without FROM table clause - #2902

Open
Leonid Stashevsky (e5l) wants to merge 2 commits into
mainfrom
e5l/select-expression
Open

fix: EXPOSED-1040 Support SELECT without FROM table clause#2902
Leonid Stashevsky (e5l) wants to merge 2 commits into
mainfrom
e5l/select-expression

Conversation

@e5l

Copy link
Copy Markdown
Member

Description

Introduce select expression which allows to use select statement without column set.


Type of Change

Please mark the relevant options with an "X":

  • Bug fix
  • New feature
  • Documentation update

Updates/remove existing public API methods:

  • Is breaking change

Affected databases:

  • MariaDB
  • Mysql5
  • Mysql8
  • Oracle
  • Postgres
  • Redshift
  • SqlServer
  • H2
  • SQLite

Checklist

  • Unit tests are in place
  • The build is green (including the Detekt check)
  • All public methods affected by my PR has up to date API docs
  • Documentation for my change is up to date

Related Issues

EXPOSED-1040 Support SELECT without FROM table clause

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class support for “tableless” SELECT statements (i.e., SELECT 1 without an explicit FROM) across Exposed’s JDBC and R2DBC APIs, including convenience terminals for fetching a single projected value and documentation/tests to lock in the behavior.

Changes:

  • Introduces top-level tableless select(...) overloads (JDBC + R2DBC) backed by Table.Dual, plus selectValue(...) terminals.
  • Adds a generic literal(value) helper in exposed-core for wrapping common scalar Kotlin/Java values as SQL literals, plus tests.
  • Updates user documentation and changelog; refreshes SQL Server docker image tag used in dev/test infra.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
exposed-tests/src/test/kotlin/org/jetbrains/exposed/v1/tests/shared/types/LiteralOpTests.kt New tests for literal(value) type resolution, decimal precision/scale, and unsupported types.
exposed-tests/src/test/kotlin/org/jetbrains/exposed/v1/tests/shared/dml/SelectExpressionTest.kt New JDBC tests covering tableless selects, selectValue, set ops, derived table usage, and edge cases.
exposed-tests/src/test/kotlin/org/jetbrains/exposed/v1/tests/shared/dml/DualTableTest.kt Removes old Table.Dual-focused test, superseded by tableless select tests.
exposed-r2dbc/src/main/kotlin/org/jetbrains/exposed/v1/r2dbc/Queries.kt Adds tableless select(...) overloads and suspending selectValue(...) terminals for R2DBC.
exposed-r2dbc/api/exposed-r2dbc.api Public API surface update for the new R2DBC query helpers.
exposed-r2dbc-tests/src/test/kotlin/org/jetbrains/exposed/v1/r2dbc/sql/tests/shared/dml/SelectExpressionTest.kt New R2DBC tests validating tableless select and selectValue behavior.
exposed-r2dbc-tests/src/test/kotlin/org/jetbrains/exposed/v1/r2dbc/sql/tests/shared/dml/DualTableTest.kt Removes old R2DBC Table.Dual test, superseded by tableless select tests.
exposed-jdbc/src/main/kotlin/org/jetbrains/exposed/v1/jdbc/Queries.kt Adds tableless select(...) overloads and selectValue(...) terminals for JDBC.
exposed-jdbc/api/exposed-jdbc.api Public API surface update for the new JDBC query helpers.
exposed-core/src/main/kotlin/org/jetbrains/exposed/v1/core/LiteralOp.kt Adds literal(value) auto-resolver for common scalar types (+ UUID support).
exposed-core/src/main/kotlin/org/jetbrains/exposed/v1/core/BinaryLiteralColumnType.kt Internal column type to render ByteArray literals using blob/hex formatting rules.
exposed-core/api/exposed-core.api Public API surface update for the new literal(value) function.
documentation-website/Writerside/topics/DSL-Querying-data.topic Adds a “Tableless SELECT queries” documentation chapter with examples and caveats.
CHANGELOG.md Adds feature entry describing tableless select + selectValue + literal.
buildScripts/docker/docker-compose-sqlserver.yml Updates SQL Server container image tag.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread exposed-core/src/main/kotlin/org/jetbrains/exposed/v1/core/LiteralOp.kt Outdated

@bog-walk Chantal Loncle (bog-walk) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also check failing tests on some db?

Comment thread CHANGELOG.md Outdated
Comment on lines 29 to 30

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes sense for a test that relies solely on exposed-core to only have a single (JDBC) test suite.
Please still tag it using something like @Tag(NOT_APPLICABLE_TO_R2DBC) so we know why there is a test number discrepancy between JDBC & R2DBC (and why it doesn't need to be added).

Comment thread documentation-website/Writerside/topics/DSL-Querying-data.topic Outdated
Comment thread documentation-website/Writerside/topics/DSL-Querying-data.topic
Comment thread documentation-website/Writerside/topics/DSL-Querying-data.topic
Comment on lines 5 to 8

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issue with this class except I do wonder how differently the output is compared to what we already have. There is a current top-level .asLiteral() that returns a LiteralOp and it also has a special branch for ByteArray + BasicBinaryColumnType --> source code

Would literal(byteArrayOf(0x01, 0x7F)) provide the same result as column.asLiteral(byteArrayOf(0x01, 0x7F))?
I haven't checked, just wondering, but hopefully it does?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's interesting that we preferred the string literal, let me explore

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing asLiteral works not correct when the non-utf8 bytes are present in the array. Here is the simple test:

@Test
fun testBinaryDefaultPreservesNonUtf8Bytes() {
    val expected = byteArrayOf(0x89.toByte(), 0x50, 0x4E, 0x47)
    val table = object : Table("binary_default_test") {
        val payload = binary("payload").default(expected)
    }

    withTables(table) {
        table.insert {}

        val actual = table.selectAll().single()[table.payload]
        assertContentEquals(expected, actual)
    }
}

It follows the path default(bytes) -> asLiteral(bytes) -> dbDefaultToString(...). I will update the asLiteral to also follow hex serialization instead of utf-8

Comment thread exposed-jdbc/src/main/kotlin/org/jetbrains/exposed/v1/jdbc/Queries.kt Outdated
Comment thread exposed-jdbc/src/main/kotlin/org/jetbrains/exposed/v1/jdbc/Queries.kt Outdated
Comment thread exposed-jdbc/src/main/kotlin/org/jetbrains/exposed/v1/jdbc/Queries.kt Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants