SqlTest
abstract class SqlTest : Test
SqlTest is the base for the tests that run against a live database.
It is abstract, so fant skips it; the concrete subclasses at the bottom
of this file bind it to a Dialect.
Each test method gets a fresh instance, a fresh connection, and drops whatever tables it created. No test may depend on another's state.
Postgres array table
Batch tables
Connection for the current test method
A table that is never created
The main test table
Create a table from raw ddl, and register it to be dropped during teardown
Create the main test table
Insert a row built from a column-name:value map and return whatever Statement.execute returned
Insert into the main test table and return the auto-generated key
The single Int column selected by the given sql
Number of rows in the main test table
A full row of values for the main test table
The row in the main test table with the given key
The one row in the main test table whose v_str is the given key
The v_str values in the main test table, sorted
Postgres array columns map to Fantom Lists
Whether a batch insert yields keys depends on both the table and the driver, so this pins down all four corners of that
Binary round-trips through the setBinaryStream path in setParameters
Everything the driver rejects should surface as SqlErr, not as a raw SQLException or a null
An "@" inside quoted text is literal, not a parameter
Statement.execute returns one of three shapes depending on the sql
So must the postgres jsonb containment operator
A parameter missing from the map currently binds as null rather than raising, so a typo in a param name is silent
Exercise the fixture machinery end to end
Round-trip a set of values through every column of the main test table, so that a failure names the exact type and value that broke
A mysql session variable must be escaped inside a prepared statement
Values exercised by testTypeRoundTrip, keyed by logical type
Compare two cell values
Verify every cell in the row is null, apart from the named columns
Verify a row's cells against a column-name:value map
const Str : arrayTable
Postgres array table; created with raw ddl since it never runs elsewhere
const Str : batchAutoTable
const Str : batchTable
Batch tables; see Dialect.batchCols and Dialect.batchAutoCols
Void createRawTable(Str name, Str ddl)
Create a table from raw ddl, and register it to be dropped during teardown. For feature-gated tests, where a portable ColDef schema would be pointless because the test only ever runs on one database.
Void createVals()
Create the main test table
SqlConn? : db
Connection for the current test method
Obj insert(Str table, Str:Obj? vals)
Insert a row built from a column-name:value map and return whatever Statement.execute returned. Columns are emitted in sorted order so the generated SQL is deterministic.
Int insertVals(Str:Obj? vals)
Insert into the main test table and return the auto-generated key
Int[] ints(Str sql)
The single Int column selected by the given sql
const Str : missingTable
A table that is never created
Int rowCount()
Number of rows in the main test table
Str:Obj? sampleVals()
A full row of values for the main test table.
Note the float values are exactly representable in binary32, so that v_f32 round-trips through a 4 byte column without widening error, and the times carry no fractional seconds, which mysql datetime truncates. Probing the inexact cases belongs in a dedicated type test.
Row selectById(Int id)
The row in the main test table with the given key
Row selectOne(Str key)
The one row in the main test table whose v_str is the given key
virtual Void setup()
Str[] strs()
The v_str values in the main test table, sorted
virtual Void teardown()
Void testArrays()
Postgres array columns map to Fantom Lists; see SqlUtil.fanToSqlObj and SqlUtil.ToFanList.
Void testBatchExecutor()
Void testBatchKeys()
Whether a batch insert yields keys depends on both the table and the driver, so this pins down all four corners of that.
Void testBatchUpdate()
Void testBuf()
Binary round-trips through the setBinaryStream path in setParameters
Void testEmptyResult()
Void testErrors()
Everything the driver rejects should surface as SqlErr, not as a raw SQLException or a null
Void testEscapes()
An "@" inside quoted text is literal, not a parameter. TokenizerTest covers this at the unit level; here we prove the sql actually runs.
Void testExecute()
Statement.execute returns one of three shapes depending on the sql
Void testGenerateKeysOff()
Void testInsertAndSelect()
Void testJsonbOperator()
So must the postgres jsonb containment operator; see pod-doc "Escape Sequences". No table is needed, so the sql can be a raw dsl literal.
Void testLimit()
Void testMeta()
Void testMissingParam()
A parameter missing from the map currently binds as null rather than raising, so a typo in a param name is silent. This pins the current behavior; it is not necessarily the behavior we want.
Void testNulls()
Void testPrepared()
Void testQueryEach()
Void testQueryTimeout()
Void testQueryTimeoutFromPool()
Void testSmoke()
Exercise the fixture machinery end to end: connect, create, describe, insert, select, and verify both metadata and values.
Void testTransactions()
Void testTypeRoundTrip()
Round-trip a set of values through every column of the main test table, so that a failure names the exact type and value that broke. This is the conformance matrix: what each database can actually store and hand back unchanged.
Void testUserVars()
A mysql session variable must be escaped inside a prepared statement
Str:Obj?[] typeCases()
Values exercised by testTypeRoundTrip, keyed by logical type. Null is covered separately by testNulls.
Constraints these values respect:
- f32 values are exactly representable in binary32 and carry no more than 6 significant decimal digits. Exactness alone is not enough: mysql float round-trips through roughly 6 significant digits, so 2^24 comes back as 16777200 rather than 16777216
- dec values carry the scale of decimal(9,2). Decimal equality is scale sensitive, since FanDecimal.equals delegates to BigDecimal.equals, so 0d and 0.00d are not equal
- dt and time values are whole seconds, which mysql datetime and time truncate to by default
- char values are exactly 4 chars, because postgres bpchar pads to the declared width while mysql char strips trailing spaces
Bool valEq(Obj? a, Obj? b)
Compare two cell values. Buf does not define value equality, so binary cells are compared by content.
const Str : valsTable
The main test table; see Dialect.valsCols
Void verifyNullsExcept(Row row, Str[] except)
Verify every cell in the row is null, apart from the named columns
Void verifyRow(Row row, Str:Obj? expected)
Verify a row's cells against a column-name:value map. Only the named columns are checked.