Skip to content

Commit 1a3c139

Browse files
committed
#853 Fetch all known blob info items on open
Backport of #851
1 parent 082a7f7 commit 1a3c139

4 files changed

Lines changed: 232 additions & 86 deletions

File tree

src/main/org/firebirdsql/gds/ClumpletReader.java

Lines changed: 56 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.sql.SQLException;
2828
import java.util.Arrays;
2929

30+
import static org.firebirdsql.gds.ISCConstants.isc_spb_version;
3031
import static org.firebirdsql.gds.JaybirdErrorCodes.jb_clumpletReaderUsageError;
3132
import static org.firebirdsql.gds.JaybirdErrorCodes.jb_invalidClumpletStructure;
3233

@@ -49,18 +50,13 @@ public ClumpletReader(Kind kind, byte[] buffer) {
4950
}
5051

5152
public boolean isTagged() {
52-
switch (kind) {
53-
case Tpb:
54-
case Tagged:
55-
case WideTagged:
56-
case SpbAttach:
57-
return true;
58-
}
59-
60-
return false;
53+
return kind.isTagged();
6154
}
6255

6356
public int getBufferTag() throws SQLException {
57+
if (!isTagged()) {
58+
throw usageMistake("buffer is not tagged");
59+
}
6460
switch (kind) {
6561
case Tpb:
6662
case Tagged:
@@ -69,33 +65,16 @@ public int getBufferTag() throws SQLException {
6965
throw invalidStructure("empty buffer");
7066
}
7167
return buffer[0];
72-
case SpbStart:
73-
case UnTagged:
74-
case WideUnTagged:
75-
case SpbSendItems:
76-
case SpbReceiveItems:
77-
throw usageMistake("buffer is not tagged");
7868
case SpbAttach:
7969
if (buffer.length == 0) {
8070
throw invalidStructure("empty buffer");
81-
}
82-
switch (buffer[0]) {
83-
case ISCConstants.isc_spb_version1:
84-
// This is old SPB format, it's almost like DPB -
85-
// buffer's tag is the first byte.
86-
return buffer[0];
87-
case ISCConstants.isc_spb_version:
88-
// Buffer's tag is the second byte
71+
}else if (buffer[0] == isc_spb_version) {
8972
if (buffer.length == 1) {
90-
throw invalidStructure("buffer too short (1 byte)");
73+
throw invalidStructure("empty buffer");
9174
}
9275
return buffer[1];
93-
case ISCConstants.isc_spb_version3:
94-
// This is wide SPB attach format - buffer's tag is the first byte.
95-
return buffer[0];
96-
default:
97-
throw invalidStructure("spb in service attach should begin with isc_spb_version1 or isc_spb_version");
9876
}
77+
return buffer[0];
9978
default:
10079
throw new SQLException("Unexpected clumplet kind: " + kind);
10180
}
@@ -132,6 +111,7 @@ public ClumpletType getClumpletType(byte tag) throws SQLException {
132111
}
133112
return ClumpletType.StringSpb;
134113
case SpbReceiveItems:
114+
case InfoItems:
135115
return ClumpletType.SingleTpb;
136116
case SpbStart:
137117
switch (tag) {
@@ -293,6 +273,15 @@ public ClumpletType getClumpletType(byte tag) throws SQLException {
293273
break;
294274
}
295275
throw invalidStructure("wrong spb state");
276+
case InfoResponse:
277+
switch (tag) {
278+
case ISCConstants.isc_info_end:
279+
case ISCConstants.isc_info_truncated:
280+
case ISCConstants.isc_info_flag_end:
281+
return ClumpletType.SingleTpb;
282+
default:
283+
return ClumpletType.StringSpb;
284+
}
296285
}
297286
throw invalidStructure("unknown reason");
298287
}
@@ -383,32 +372,26 @@ public int getClumpletSize(boolean wTag, boolean wLength, boolean wData) throws
383372
public void moveNext() throws SQLException {
384373
if (isEof()) {
385374
return; // no need to raise useless exceptions
375+
} else if (kind == Kind.InfoResponse) {
376+
int clumpTag = getClumpTag();
377+
// terminating clumplet
378+
if (clumpTag == ISCConstants.isc_info_end || clumpTag == ISCConstants.isc_info_truncated) {
379+
position = getBufferLength();
380+
return;
381+
}
386382
}
387383
int cs = getClumpletSize(true, true, true);
388384
adjustSpbState();
389385
position += cs;
390386
}
391387

392-
public void rewind() throws SQLException {
393-
if (buffer == null || buffer.length == 0) {
388+
public void rewind() {
389+
if (buffer.length == 0 || !isTagged()) {
394390
position = 0;
395-
spbState = 0;
396-
return;
397-
}
398-
switch (kind) {
399-
case UnTagged:
400-
case WideUnTagged:
401-
case SpbStart:
402-
case SpbSendItems:
403-
case SpbReceiveItems:
404-
position = 0;
405-
break;
406-
default:
407-
if (kind == Kind.SpbAttach && getBufferLength() > 0 && buffer[0] != ISCConstants.isc_spb_version1) {
408-
position = 2;
409-
} else {
410-
position = 1;
411-
}
391+
} else if (kind == Kind.SpbAttach && getBufferLength() > 0 && buffer[0] == isc_spb_version) {
392+
position = 2;
393+
} else {
394+
position = 1;
412395
}
413396
spbState = 0;
414397
}
@@ -537,9 +520,7 @@ public boolean isEof() {
537520
}
538521

539522
private int getBufferLength() {
540-
if (buffer.length == 1 && kind != Kind.UnTagged && kind != Kind.SpbStart &&
541-
kind != Kind.WideUnTagged && kind != Kind.SpbSendItems &&
542-
kind != Kind.SpbReceiveItems) {
523+
if (buffer.length == 1 && isTagged()) {
543524
return 0;
544525
}
545526
return buffer.length;
@@ -554,16 +535,30 @@ private static SQLException usageMistake(String message) {
554535
}
555536

556537
public enum Kind {
557-
EndOfList,
558-
Tagged,
559-
UnTagged,
560-
SpbAttach,
561-
SpbStart,
562-
Tpb,
563-
WideTagged,
564-
WideUnTagged,
565-
SpbSendItems,
566-
SpbReceiveItems
538+
539+
Tagged(true),
540+
UnTagged(false),
541+
SpbAttach(true),
542+
SpbStart(false),
543+
Tpb(true),
544+
WideTagged(true),
545+
WideUnTagged(false),
546+
SpbSendItems(false),
547+
SpbReceiveItems(false),
548+
InfoResponse(false),
549+
InfoItems(false),
550+
;
551+
552+
private final boolean tagged;
553+
554+
Kind(boolean tagged) {
555+
this.tagged = tagged;
556+
}
557+
558+
public boolean isTagged() {
559+
return tagged;
560+
}
561+
567562
}
568563

569564
public enum ClumpletType {

src/main/org/firebirdsql/gds/ng/AbstractFbBlob.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.firebirdsql.jdbc.SQLStateConstants;
2828
import org.firebirdsql.logging.Logger;
2929
import org.firebirdsql.logging.LoggerFactory;
30+
import org.firebirdsql.util.ByteArrayHelper;
3031
import org.firebirdsql.util.IOUtils;
3132

3233
import java.sql.SQLException;
@@ -492,6 +493,20 @@ public <T> T getBlobInfo(final byte[] requestItems, final int bufferLength, fina
492493
}
493494
}
494495

496+
/**
497+
* The known blob info items for the connected server as a blob info request buffer.
498+
*
499+
* @return the known blob info items (possibly empty under implementation-specific circumstances)
500+
* @since 7
501+
*/
502+
protected byte[] getKnownBlobInfoItems() {
503+
FbDatabase db = getDatabase();
504+
if (db instanceof AbstractFbDatabase) {
505+
return ((AbstractFbDatabase<?>) db).getServerVersionInformation().getBlobInfoRequestItems();
506+
}
507+
return ByteArrayHelper.emptyByteArray();
508+
}
509+
495510
@Override
496511
public long length() throws SQLException {
497512
try (LockCloseable ignored = withLock()) {

src/main/org/firebirdsql/gds/ng/ServerVersionInformation.java

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,8 @@
2525
/**
2626
* Strategy for handling server version specific information needs that do not depend on the wire protocol (or client
2727
* library) version, but on the Firebird server version.
28-
* <p>
29-
* Currently only contains information items for statement info requests.
30-
* </p>
3128
*
32-
* @author <a href="mailto:mrotteveel@users.sourceforge.net">Mark Rotteveel</a>
29+
* @author Mark Rotteveel
3330
* @since 3.0
3431
*/
3532
enum ServerVersionInformation {
@@ -86,6 +83,14 @@ public byte[] getParameterDescriptionInfoRequestItems() {
8683
*/
8784
public abstract byte[] getParameterDescriptionInfoRequestItems();
8885

86+
/**
87+
* @return the known blob info request items
88+
* @since 7
89+
*/
90+
public byte[] getBlobInfoRequestItems() {
91+
return Constants.V_1_0_BLOB_INFO.clone();
92+
}
93+
8994
/**
9095
* Convenience method to check if the majorVersion.minorVersion of this instance is equal to or smaller than the
9196
* specified version.
@@ -138,8 +143,8 @@ public static ServerVersionInformation getForVersion(GDSServerVersion serverVers
138143
return getForVersion(serverVersion.getMajorVersion(), serverVersion.getMinorVersion());
139144
}
140145

141-
private static class Constants {
142-
public static final byte[] V1_0_STATEMENT_INFO = new byte[] {
146+
private static final class Constants {
147+
static final byte[] V1_0_STATEMENT_INFO = new byte[] {
143148
isc_info_sql_stmt_type,
144149
isc_info_sql_select,
145150
isc_info_sql_describe_vars,
@@ -165,7 +170,7 @@ private static class Constants {
165170
//isc_info_sql_owner,
166171
isc_info_sql_describe_end
167172
};
168-
public static final byte[] V_1_0_PARAMETER_INFO = new byte[] {
173+
static final byte[] V_1_0_PARAMETER_INFO = new byte[] {
169174
isc_info_sql_describe_vars,
170175
isc_info_sql_sqlda_seq,
171176
isc_info_sql_type, isc_info_sql_sub_type,
@@ -176,7 +181,15 @@ private static class Constants {
176181
isc_info_sql_owner,
177182
isc_info_sql_describe_end
178183
};
179-
public static final byte[] V_2_0_STATEMENT_INFO = new byte[] {
184+
static final byte[] V_1_0_BLOB_INFO = new byte[] {
185+
isc_info_blob_num_segments,
186+
isc_info_blob_max_segment,
187+
isc_info_blob_total_length,
188+
isc_info_blob_type,
189+
isc_info_end
190+
};
191+
192+
static final byte[] V_2_0_STATEMENT_INFO = new byte[] {
180193
isc_info_sql_stmt_type,
181194
isc_info_sql_select,
182195
isc_info_sql_describe_vars,
@@ -203,7 +216,7 @@ private static class Constants {
203216
//isc_info_sql_owner,
204217
isc_info_sql_describe_end
205218
};
206-
public static final byte[] V_2_0_PARAMETER_INFO = new byte[] {
219+
static final byte[] V_2_0_PARAMETER_INFO = new byte[] {
207220
isc_info_sql_describe_vars,
208221
isc_info_sql_sqlda_seq,
209222
isc_info_sql_type, isc_info_sql_sub_type,
@@ -215,5 +228,9 @@ private static class Constants {
215228
isc_info_sql_owner,
216229
isc_info_sql_describe_end
217230
};
231+
232+
private Constants() {
233+
// no instances
234+
}
218235
}
219236
}

0 commit comments

Comments
 (0)