You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 4a359b0
Browse filesBrowse the repository at this point in the historyBrowse files
fix(jdbc): read declared columns through implemented getters
Table B-6 was enforced as a rejection list, so getBytes on a declared BLOB
threw SQLFeatureNotSupportedException. Treat the table as the required
support matrix and let the stored value decide the conversion, matching
sqlite-jdbc. Only the five N/A declared types remain rejected.
The getter mask, Getter enum, and getterMask field were used only by the
rejection, so remove them.
Copy file name to clipboardExpand all lines: AGENTS.md
+2-1Lines changed: 2 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -138,8 +138,9 @@ Use the absolute path shown. A relative `DOCKER_CONFIG` is resolved against the
138
138
139
139
JDBC 4.3 Appendix B is the oracle for type mapping. The source is [`vendor/JDBC4-TYPE-MAPPING.md`](vendor/JDBC4-TYPE-MAPPING.md).
140
140
141
-
- When Appendix B and sqlite-jdbc disagree, Appendix B wins. A conformance test that encodes the xerial behavior is quarantined in `libsql-conformance`, not copied.
141
+
- When Appendix B defines a conversion or mapping and sqlite-jdbc disagrees, Appendix B wins. A conformance test that encodes the xerial behavior is quarantined in `libsql-conformance`, not copied.
142
142
- Keep sqlite-jdbc parity only where Appendix B is silent. Parity never overrides a defined Appendix B conversion.
143
+
- Table B-6 is a required-support matrix, not a rejection list. A representable declared column is not rejected because of its declared type; the stored value decides the conversion, matching sqlite-jdbc. Reject a declared type only for the five N/A types. Unimplemented getters still throw for any column.
143
144
-`ARRAY`, `STRUCT`, `REF`, `JAVA_OBJECT`, and `DISTINCT` are N/A. The driver throws `SQLFeatureNotSupportedException` and does not emulate them.
144
145
- An expression column has no declared type. Its storage-class fallback is a documented exception in [`docs/jdbc-appendix-b-compliance.md`](docs/jdbc-appendix-b-compliance.md), not a supported Appendix B row.
Copy file name to clipboardExpand all lines: docs/jdbc-appendix-b-compliance.md
+38-27Lines changed: 38 additions & 27 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -202,37 +202,48 @@ Table B-5 is observed through `setObject(int, Object, int)`. A listed pair must
202
202
203
203
## Table B-6, ResultSet getter conversions
204
204
205
-
Table B-6 is observed through each getter against its recommended declared type.
205
+
Table B-6 is the matrix of conversions the driver must support, observed through each getter against its recommended declared type. The driver does not reject a conversion because the table omits it. A representable declared column is not rejected because of its declared type, and the stored value decides whether the conversion succeeds, matching sqlite-jdbc. The five N/A types are still rejected before the getter runs.
206
206
207
207
| Appendix B row | Status | Reason | Test |
208
208
|---|---|---|---|
209
-
|`getByte`| supported | Reads a numeric, boolean or text value as a byte. |`Jdbc4AppendixBReadTest#b6GetterHonoursSupportedJdbcTypes`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
210
-
|`getShort`| supported | Reads a numeric, boolean or text value as a short. |`Jdbc4AppendixBReadTest#b6GetterHonoursSupportedJdbcTypes`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
211
-
|`getInt`| supported | Reads a numeric, boolean or text value as an int. |`Jdbc4AppendixBReadTest#b6GetterHonoursSupportedJdbcTypes`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
212
-
|`getLong`| supported | Reads a numeric, boolean or text value as a long. |`Jdbc4AppendixBReadTest#b6GetterHonoursSupportedJdbcTypes`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
213
-
|`getFloat`| supported | Reads a numeric, boolean or text value as a float. |`Jdbc4AppendixBReadTest#b6GetterHonoursSupportedJdbcTypes`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
214
-
|`getDouble`| supported | Reads a numeric, boolean or text value as a double. |`Jdbc4AppendixBReadTest#b6GetterHonoursSupportedJdbcTypes`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
215
-
|`getBigDecimal`| supported | Reads a numeric, boolean or text value as BigDecimal. |`Jdbc4AppendixBReadTest#b6GetterHonoursSupportedJdbcTypes`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
216
-
|`getBoolean`| emulated | Reads integer 0 or 1, and the text true or false, as Boolean. |`Jdbc4AppendixBReadTest#b6GetterHonoursSupportedJdbcTypes`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
217
-
|`getString`| supported | Reads text and the listed scalar types as String. |`Jdbc4AppendixBReadTest#b6GetterHonoursSupportedJdbcTypes`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
218
-
|`getNString`| supported | Reads text and the listed scalar types as String. |`Jdbc4AppendixBReadTest#b6GetterHonoursSupportedJdbcTypes`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
219
-
|`getBytes`| supported | Reads binary values and the listed types as byte[]. |`Jdbc4AppendixBReadTest#b6GetterHonoursSupportedJdbcTypes`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
220
-
|`getDate`| emulated | Parses the supported text forms into java.sql.Date. |`Jdbc4AppendixBReadTest#b6GetterHonoursSupportedJdbcTypes`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
221
-
|`getTime`| emulated | Parses the supported text forms into java.sql.Time. |`Jdbc4AppendixBReadTest#b6GetterHonoursSupportedJdbcTypes`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
222
-
|`getTimestamp`| emulated | Parses the supported text forms into java.sql.Timestamp. |`Jdbc4AppendixBReadTest#b6GetterHonoursSupportedJdbcTypes`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
223
-
|`getAsciiStream`| emulated | Returns the text bytes as a US-ASCII stream. |`Jdbc4AppendixBReadTest#b6GetterHonoursSupportedJdbcTypes`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
224
-
|`getBinaryStream`| supported | Returns the blob bytes as a stream. |`Jdbc4AppendixBReadTest#b6GetterHonoursSupportedJdbcTypes`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
225
-
|`getCharacterStream`| emulated | Returns a reader over the stored text or bytes. |`Jdbc4AppendixBReadTest#b6GetterHonoursSupportedJdbcTypes`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
226
-
|`getNCharacterStream`| emulated | Returns a reader over the stored text or bytes. |`Jdbc4AppendixBReadTest#b6GetterHonoursSupportedJdbcTypes`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
227
-
|`getClob`| emulated | Wraps stored text in java.sql.Clob. |`Jdbc4AppendixBReadTest#b6GetterHonoursSupportedJdbcTypes`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
228
-
|`getNClob`| emulated | Wraps stored text in java.sql.NClob. |`Jdbc4AppendixBReadTest#b6GetterHonoursSupportedJdbcTypes`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
229
-
|`getBlob`| supported | Wraps stored bytes in java.sql.Blob. |`Jdbc4AppendixBReadTest#b6GetterHonoursSupportedJdbcTypes`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
209
+
|`getByte`| supported | Reads a numeric, boolean or text value as a byte. |`Jdbc4AppendixBReadTest#b6RequiredConversionsAndPermissiveReads`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
210
+
|`getShort`| supported | Reads a numeric, boolean or text value as a short. |`Jdbc4AppendixBReadTest#b6RequiredConversionsAndPermissiveReads`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
211
+
|`getInt`| supported | Reads a numeric, boolean or text value as an int. |`Jdbc4AppendixBReadTest#b6RequiredConversionsAndPermissiveReads`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
212
+
|`getLong`| supported | Reads a numeric, boolean or text value as a long. |`Jdbc4AppendixBReadTest#b6RequiredConversionsAndPermissiveReads`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
213
+
|`getFloat`| supported | Reads a numeric, boolean or text value as a float. |`Jdbc4AppendixBReadTest#b6RequiredConversionsAndPermissiveReads`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
214
+
|`getDouble`| supported | Reads a numeric, boolean or text value as a double. |`Jdbc4AppendixBReadTest#b6RequiredConversionsAndPermissiveReads`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
215
+
|`getBigDecimal`| supported | Reads a numeric, boolean or text value as BigDecimal. |`Jdbc4AppendixBReadTest#b6RequiredConversionsAndPermissiveReads`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
216
+
|`getBoolean`| emulated | Reads integer 0 or 1, and the text true or false, as Boolean. |`Jdbc4AppendixBReadTest#b6RequiredConversionsAndPermissiveReads`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
217
+
|`getString`| supported | Reads any stored value as String; blobs decode as UTF-8. |`Jdbc4AppendixBReadTest#b6RequiredConversionsAndPermissiveReads`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
218
+
|`getNString`| supported | Reads any stored value as String; blobs decode as UTF-8. |`Jdbc4AppendixBReadTest#b6RequiredConversionsAndPermissiveReads`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
219
+
|`getBytes`| supported | Reads any stored value as byte[]; text encodes as UTF-8. |`Jdbc4AppendixBReadTest#b6RequiredConversionsAndPermissiveReads`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
220
+
|`getDate`| emulated | Parses the supported text forms into java.sql.Date. |`Jdbc4AppendixBReadTest#b6RequiredConversionsAndPermissiveReads`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
221
+
|`getTime`| emulated | Parses the supported text forms into java.sql.Time. |`Jdbc4AppendixBReadTest#b6RequiredConversionsAndPermissiveReads`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
222
+
|`getTimestamp`| emulated | Parses the supported text forms into java.sql.Timestamp. |`Jdbc4AppendixBReadTest#b6RequiredConversionsAndPermissiveReads`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
223
+
|`getAsciiStream`| emulated | Returns any stored value as a US-ASCII stream. |`Jdbc4AppendixBReadTest#b6RequiredConversionsAndPermissiveReads`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
224
+
|`getBinaryStream`| supported | Returns any stored value as a byte stream. |`Jdbc4AppendixBReadTest#b6RequiredConversionsAndPermissiveReads`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
225
+
|`getCharacterStream`| emulated | Returns a reader over the stored text or bytes. |`Jdbc4AppendixBReadTest#b6RequiredConversionsAndPermissiveReads`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
226
+
|`getNCharacterStream`| emulated | Returns a reader over the stored text or bytes. |`Jdbc4AppendixBReadTest#b6RequiredConversionsAndPermissiveReads`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
227
+
|`getClob`| emulated | Wraps any stored value in java.sql.Clob. |`Jdbc4AppendixBReadTest#b6RequiredConversionsAndPermissiveReads`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
228
+
|`getNClob`| emulated | Wraps any stored value in java.sql.NClob. |`Jdbc4AppendixBReadTest#b6RequiredConversionsAndPermissiveReads`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
229
+
|`getBlob`| supported | Wraps any stored value in java.sql.Blob. |`Jdbc4AppendixBReadTest#b6RequiredConversionsAndPermissiveReads`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
230
230
|`getArray`| N/A | SQLite has no interoperable representation. The driver throws SQLFeatureNotSupportedException. |`Jdbc4AppendixBProfileTest#everyUnsupportedDeclaredTypeThrowsFeatureNotSupported`|
231
231
|`getRef`| N/A | SQLite has no interoperable representation. The driver throws SQLFeatureNotSupportedException. |`Jdbc4AppendixBProfileTest#everyUnsupportedDeclaredTypeThrowsFeatureNotSupported`|
232
-
|`getURL`| emulated | Parses stored text into java.net.URL. |`Jdbc4AppendixBReadTest#b6GetterHonoursSupportedJdbcTypes`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
233
-
|`getObject`| supported | Returns the Table B-3 object type for each supported declared type. |`Jdbc4AppendixBReadTest#b6GetterHonoursSupportedJdbcTypes`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
234
-
|`getRowId`| emulated | Wraps stored text or bytes in java.sql.RowId. |`Jdbc4AppendixBReadTest#b6GetterHonoursSupportedJdbcTypes`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
235
-
|`getSQLXML`| emulated | Wraps stored text in java.sql.SQLXML. |`Jdbc4AppendixBReadTest#b6GetterHonoursSupportedJdbcTypes`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
232
+
|`getURL`| emulated | Parses stored text into java.net.URL. |`Jdbc4AppendixBReadTest#b6RequiredConversionsAndPermissiveReads`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
233
+
|`getObject`| supported | Returns the Table B-3 object type for each supported declared type. |`Jdbc4AppendixBReadTest#b6RequiredConversionsAndPermissiveReads`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
234
+
|`getRowId`| emulated | Wraps any stored value in java.sql.RowId. |`Jdbc4AppendixBReadTest#b6RequiredConversionsAndPermissiveReads`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
235
+
|`getSQLXML`| emulated | Wraps any stored value in java.sql.SQLXML. |`Jdbc4AppendixBReadTest#b6RequiredConversionsAndPermissiveReads`, `Jdbc4AppendixBTypeMappingIT#b6GetterReadsRecommendedTypeFromRealDdl`|
236
+
237
+
### Read conversions beyond Table B-6
238
+
239
+
Table B-6 defines the conversions a driver must support; it does not require the driver to reject
240
+
the rest. The driver therefore does not reject a representable declared column because of its
241
+
declared type, and the stored value decides the conversion. A declared `BLOB` reads through
242
+
`getBytes`, `getString` and `getBinaryStream`, as it does in sqlite-jdbc. A conversion the stored
243
+
value cannot satisfy throws `SQLException`. Only the five N/A declared types are rejected because of
244
+
the declared type; unimplemented getters (`getArray`, `getRef`, `getUnicodeStream`) still throw
245
+
`SQLFeatureNotSupportedException` for any column. Regression coverage is
@@ -242,4 +253,4 @@ The fallback is covered by `Jdbc4AppendixBProfileTest#expressionFallbackStaysPer
242
253
243
254
## Conformance quarantines
244
255
245
-
The xerial conformance suite keeps its selected tests except for four methods whose expectations Appendix B replaces. The list and the reason for each one are in [`../libsql-conformance/README.md`](../libsql-conformance/README.md). They still run in the `xerial-control` profile.
256
+
The xerial conformance suite keeps its selected tests except for three methods whose expectations Appendix B replaces. The list and the reason for each one are in [`../libsql-conformance/README.md`](../libsql-conformance/README.md). They still run in the `xerial-control` profile.
| Test | Why the xerial expectation is quarantined |
63
63
|---|---|
64
-
|`org.sqlite.StatementTest#bytesTest`| xerial allows `getBytes` on a declared `BLOB`. Table B-6 lists `getBytes` only for `BINARY`, `VARBINARY`, and `LONGVARBINARY`. |
65
64
|`org.sqlite.RSMetaDataTest#columnTypes`| xerial reports a declared `NCHAR` as `Types.CHAR`. Appendix B defines `NCHAR` as its own JDBC type, so the driver reports `Types.NCHAR`. |
66
65
|`org.sqlite.RSMetaDataTest#testGetColumnClassName`| xerial reports a declared `BLOB` as `java.lang.Object`. Table B-3 maps `BLOB` to `java.sql.Blob`. |
67
66
|`org.sqlite.PrepStmtTest#getObject`| xerial returns an `Integer` for `getObject` on a declared `BIT`. Table B-3 maps `BIT` to `Boolean`. |
68
67
69
68
The exclusion is method-level, so each method also loses checks that do not
70
69
conflict with Appendix B:
71
70
72
-
-`StatementTest#bytesTest` also loses its BLOB `setBytes`/`getBytes` round trip.
73
71
-`RSMetaDataTest#columnTypes` also checks other column types that do not conflict, including the INTEGER family, text, numeric, boolean, date and timestamp types, plus DECIMAL precision and scale.
74
72
-`RSMetaDataTest#testGetColumnClassName` also checks the INTEGER, VARCHAR, and DOUBLE class names.
75
73
-`PrepStmtTest#getObject` also checks other `getObject` rows (INTEGER, FLOAT, untyped, VARCHAR and BLOB columns) and the typed getters above them.
0 commit comments