|
| 1 | += jdp-2025-07: Statement Max Field Size |
| 2 | + |
| 3 | +// SPDX-FileCopyrightText: Copyright 2025 Mark Rotteveel |
| 4 | +// SPDX-License-Identifier: LicenseRef-PDL-1.0 |
| 5 | + |
| 6 | +== Status |
| 7 | + |
| 8 | +* Draft |
| 9 | +* Proposed for: Jaybird 7 |
| 10 | + |
| 11 | +== Type |
| 12 | + |
| 13 | +* Feature-Specification |
| 14 | + |
| 15 | +== Context |
| 16 | + |
| 17 | +JDBC defines the methods https://docs.oracle.com/en/java/javase/25/docs/api/java.sql/java/sql/Statement.html#setMaxFieldSize(int)[`setMaxFieldSize`^] and https://docs.oracle.com/en/java/javase/25/docs/api/java.sql/java/sql/Statement.html#getMaxFieldSize()[`getMaxFieldSize`^] on `java.sql.Statement`, with the following in its javadoc: |
| 18 | + |
| 19 | +[quote,,Java 25 API documentation] |
| 20 | +____ |
| 21 | +Sets the limit for the maximum number of bytes that can be returned for character and binary column values in a `ResultSet` object produced by this `Statement` object. |
| 22 | +This limit applies only to `BINARY`, `VARBINARY`, `LONGVARBINARY`, `CHAR`, `VARCHAR`, `NCHAR`, `NVARCHAR`, `LONGNVARCHAR` and `LONGVARCHAR` fields. |
| 23 | +If the limit is exceeded, the excess data is silently discarded. |
| 24 | +For maximum portability, use values greater than `256`. |
| 25 | +
|
| 26 | +Parameters: + |
| 27 | +`max` - the new column size limit in bytes; zero means there is no limit |
| 28 | +____ |
| 29 | + |
| 30 | +And in the specification: |
| 31 | + |
| 32 | +[quote,JDBC 4.3 Specification] |
| 33 | +____ |
| 34 | +[discrete] |
| 35 | +==== 8.3.1 Silent Truncation |
| 36 | +
|
| 37 | +The `Statement.setMaxFieldSize` method allows a maximum size (in bytes) to be set. |
| 38 | +This limit applies only to the `BINARY`, `VARBINARY`, `LONGVARBINARY`, `CHAR`, `VARCHAR`, `LONGVARCHAR`, `NCHAR`, `NVARCHAR`, and `LONGNVARCHAR` data types. |
| 39 | +If a limit has been set using `setMaxFieldSize` and there is an attempt to read data that exceeds the limit, any truncation that occurs as a result of exceeding the set limit will _not_ be reported. |
| 40 | +____ |
| 41 | + |
| 42 | +Firebird doesn't provide a way to restrict the maximum number of bytes returned that will not result in string truncation errors for longer values, or -- for shorter values -- would result in _"`wrong`"_ client-side length derivations of variable length encodings like UTF8 (which would result in excessive truncation). |
| 43 | + |
| 44 | +Jaybird considers `BLOB SUB_TYPE TEXT` to be `LONGVARCHAR` and `BLOB SUB_TYPE BINARY` to be `LONGVARBINARY` (though all blob subtypes can be treated that way). |
| 45 | + |
| 46 | +== Decision |
| 47 | + |
| 48 | +Jaybird 7 implements support for `setMaxFieldSize`/`getMaxFieldSize` using client-side truncation. |
| 49 | +This will be implemented for `CHAR`, `VARCHAR`, `BINARY`, and `VARBINARY`. |
| 50 | + |
| 51 | +To avoid problems with `RDB$DB_KEY` columns, implementation must ignore the limit for those columns, as indicated by `FieldDescriptor.isDbKey()`. |
| 52 | + |
| 53 | +Decision for handling `LONGVARCHAR`/`LONGVARBINARY` is pending further investigation. |
| 54 | +Currently, we're leaning towards _not_ honouring the maximum field size, or only for `ResultSet.getBytes`/`getString`. |
| 55 | + |
| 56 | +== Consequences |
| 57 | + |
| 58 | +Handling the truncation for `CHAR`, `VARCHAR`, `BINARY`, and `VARBINARY` will be delegated to the `FbStatement` implementation. |
| 59 | +The truncation will be done when receiving the data from the server (from the wire, or from fbclient). |
| 60 | + |
| 61 | +`FbStatement` will receive an `int` property `maxFieldSize` (getter/setter pair) with a default implementation that ignores the set value and returns 0. |
| 62 | +The actual implementation will override this, and use the set value when receiving data from the server. |
| 63 | + |
| 64 | +Caveats or possible pitfalls: |
| 65 | + |
| 66 | +* Given the truncation happens at a set number of bytes, values in a multibyte character set (UTF8) might end in the Unicode replacement character due to truncation before the end of the encoded codepoint. |
| 67 | +* The detection of `RDB$DB_KEY` column will also ignore "`normal`" `BINARY` columns called `DB_KEY`. |
| 68 | + |
| 69 | +[appendix] |
| 70 | +== License Notice |
| 71 | + |
| 72 | +The contents of this Documentation are subject to the Public Documentation License Version 1.0 (the “License”); |
| 73 | +you may only use this Documentation if you comply with the terms of this License. |
| 74 | +A copy of the License is available at https://firebirdsql.org/en/public-documentation-license/. |
| 75 | + |
| 76 | +The Original Documentation is "`jdp-2025-07: Statement Max Field Size`". |
| 77 | +The Initial Writer of the Original Documentation is Mark Rotteveel, Copyright © 2025. |
| 78 | +All Rights Reserved. |
| 79 | +(Initial Writer contact(s): mark (at) lawinegevaar (dot) nl). |
| 80 | + |
| 81 | +//// |
| 82 | +Contributor(s): ______________________________________. |
| 83 | +Portions created by ______ are Copyright © _________ [Insert year(s)]. |
| 84 | +All Rights Reserved. |
| 85 | +(Contributor contact(s): ________________ [Insert hyperlink/alias]). |
| 86 | +//// |
| 87 | + |
| 88 | +The exact file history is recorded in our Git repository; |
| 89 | +see https://github.com/FirebirdSQL/jaybird |
0 commit comments