|
19 | 19 | import com.google.cloud.ByteArray;
|
20 | 20 | import com.google.cloud.spanner.Statement;
|
21 | 21 | import com.google.cloud.spanner.Statement.Builder;
|
| 22 | +import com.google.cloud.spanner.Type; |
22 | 23 | import com.google.cloud.spanner.Value;
|
23 | 24 | import com.google.cloud.spanner.ValueBinder;
|
24 | 25 | import com.google.cloud.spanner.jdbc.JdbcSqlExceptionFactory.JdbcSqlExceptionImpl;
|
@@ -264,6 +265,7 @@ private boolean isTypeSupported(int sqlType) {
|
264 | 265 | case Types.NCLOB:
|
265 | 266 | case Types.NUMERIC:
|
266 | 267 | case Types.DECIMAL:
|
| 268 | + case JsonType.VENDOR_TYPE_NUMBER: |
267 | 269 | return true;
|
268 | 270 | }
|
269 | 271 | return false;
|
@@ -315,6 +317,11 @@ private boolean isValidTypeAndValue(Object value, int sqlType) {
|
315 | 317 | return value instanceof Clob || value instanceof Reader;
|
316 | 318 | case Types.NCLOB:
|
317 | 319 | return value instanceof NClob || value instanceof Reader;
|
| 320 | + case JsonType.VENDOR_TYPE_NUMBER: |
| 321 | + return value instanceof String |
| 322 | + || value instanceof InputStream |
| 323 | + || value instanceof Reader |
| 324 | + || (value instanceof Value && ((Value) value).getType().getCode() == Type.Code.JSON); |
318 | 325 | }
|
319 | 326 | return false;
|
320 | 327 | }
|
@@ -544,30 +551,34 @@ private Builder setParamWithKnownType(ValueBinder<Builder> binder, Object value,
|
544 | 551 | case Types.NCHAR:
|
545 | 552 | case Types.NVARCHAR:
|
546 | 553 | case Types.LONGNVARCHAR:
|
| 554 | + String stringValue; |
547 | 555 | if (value instanceof String) {
|
548 |
| - return binder.to((String) value); |
| 556 | + stringValue = (String) value; |
549 | 557 | } else if (value instanceof InputStream) {
|
550 |
| - InputStreamReader reader = |
551 |
| - new InputStreamReader((InputStream) value, StandardCharsets.US_ASCII); |
552 |
| - try { |
553 |
| - return binder.to(CharStreams.toString(reader)); |
554 |
| - } catch (IOException e) { |
555 |
| - throw JdbcSqlExceptionFactory.of( |
556 |
| - "could not set string from input stream", Code.INVALID_ARGUMENT, e); |
557 |
| - } |
| 558 | + stringValue = getStringFromInputStream((InputStream) value); |
558 | 559 | } else if (value instanceof Reader) {
|
559 |
| - try { |
560 |
| - return binder.to(CharStreams.toString((Reader) value)); |
561 |
| - } catch (IOException e) { |
562 |
| - throw JdbcSqlExceptionFactory.of( |
563 |
| - "could not set string from reader", Code.INVALID_ARGUMENT, e); |
564 |
| - } |
| 560 | + stringValue = getStringFromReader((Reader) value); |
565 | 561 | } else if (value instanceof URL) {
|
566 |
| - return binder.to(((URL) value).toString()); |
| 562 | + stringValue = ((URL) value).toString(); |
567 | 563 | } else if (value instanceof UUID) {
|
568 |
| - return binder.to(((UUID) value).toString()); |
| 564 | + stringValue = ((UUID) value).toString(); |
| 565 | + } else { |
| 566 | + throw JdbcSqlExceptionFactory.of(value + " is not a valid string", Code.INVALID_ARGUMENT); |
| 567 | + } |
| 568 | + return binder.to(stringValue); |
| 569 | + case JsonType.VENDOR_TYPE_NUMBER: |
| 570 | + String jsonValue; |
| 571 | + if (value instanceof String) { |
| 572 | + jsonValue = (String) value; |
| 573 | + } else if (value instanceof InputStream) { |
| 574 | + jsonValue = getStringFromInputStream((InputStream) value); |
| 575 | + } else if (value instanceof Reader) { |
| 576 | + jsonValue = getStringFromReader((Reader) value); |
| 577 | + } else { |
| 578 | + throw JdbcSqlExceptionFactory.of( |
| 579 | + value + " is not a valid JSON value", Code.INVALID_ARGUMENT); |
569 | 580 | }
|
570 |
| - throw JdbcSqlExceptionFactory.of(value + " is not a valid string", Code.INVALID_ARGUMENT); |
| 581 | + return binder.to(Value.json(jsonValue)); |
571 | 582 | case Types.DATE:
|
572 | 583 | if (value instanceof Date) {
|
573 | 584 | return binder.to(JdbcTypeConverter.toGoogleDate((Date) value));
|
@@ -652,6 +663,25 @@ private Builder setParamWithKnownType(ValueBinder<Builder> binder, Object value,
|
652 | 663 | return null;
|
653 | 664 | }
|
654 | 665 |
|
| 666 | + private String getStringFromInputStream(InputStream inputStream) throws SQLException { |
| 667 | + InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.US_ASCII); |
| 668 | + try { |
| 669 | + return CharStreams.toString(reader); |
| 670 | + } catch (IOException e) { |
| 671 | + throw JdbcSqlExceptionFactory.of( |
| 672 | + "could not set string from input stream", Code.INVALID_ARGUMENT, e); |
| 673 | + } |
| 674 | + } |
| 675 | + |
| 676 | + private String getStringFromReader(Reader reader) throws SQLException { |
| 677 | + try { |
| 678 | + return CharStreams.toString(reader); |
| 679 | + } catch (IOException e) { |
| 680 | + throw JdbcSqlExceptionFactory.of( |
| 681 | + "could not set string from reader", Code.INVALID_ARGUMENT, e); |
| 682 | + } |
| 683 | + } |
| 684 | + |
655 | 685 | /** Set the parameter value based purely on the type of the value. */
|
656 | 686 | private Builder setParamWithUnknownType(ValueBinder<Builder> binder, Object value)
|
657 | 687 | throws SQLException {
|
@@ -769,14 +799,16 @@ private Builder setArrayValue(ValueBinder<Builder> binder, int type, Object valu
|
769 | 799 | case Types.LONGNVARCHAR:
|
770 | 800 | case Types.CLOB:
|
771 | 801 | case Types.NCLOB:
|
772 |
| - return binder.toStringArray((Iterable<String>) null); |
| 802 | + return binder.toStringArray(null); |
| 803 | + case JsonType.VENDOR_TYPE_NUMBER: |
| 804 | + return binder.toJsonArray(null); |
773 | 805 | case Types.DATE:
|
774 |
| - return binder.toDateArray((Iterable<com.google.cloud.Date>) null); |
| 806 | + return binder.toDateArray(null); |
775 | 807 | case Types.TIME:
|
776 | 808 | case Types.TIME_WITH_TIMEZONE:
|
777 | 809 | case Types.TIMESTAMP:
|
778 | 810 | case Types.TIMESTAMP_WITH_TIMEZONE:
|
779 |
| - return binder.toTimestampArray((Iterable<com.google.cloud.Timestamp>) null); |
| 811 | + return binder.toTimestampArray(null); |
780 | 812 | case Types.BINARY:
|
781 | 813 | case Types.VARBINARY:
|
782 | 814 | case Types.LONGVARBINARY:
|
@@ -829,7 +861,11 @@ private Builder setArrayValue(ValueBinder<Builder> binder, int type, Object valu
|
829 | 861 | } else if (Timestamp[].class.isAssignableFrom(value.getClass())) {
|
830 | 862 | return binder.toTimestampArray(JdbcTypeConverter.toGoogleTimestamps((Timestamp[]) value));
|
831 | 863 | } else if (String[].class.isAssignableFrom(value.getClass())) {
|
832 |
| - return binder.toStringArray(Arrays.asList((String[]) value)); |
| 864 | + if (type == JsonType.VENDOR_TYPE_NUMBER) { |
| 865 | + return binder.toJsonArray(Arrays.asList((String[]) value)); |
| 866 | + } else { |
| 867 | + return binder.toStringArray(Arrays.asList((String[]) value)); |
| 868 | + } |
833 | 869 | } else if (byte[][].class.isAssignableFrom(value.getClass())) {
|
834 | 870 | return binder.toBytesArray(JdbcTypeConverter.toGoogleBytes((byte[][]) value));
|
835 | 871 | }
|
|
0 commit comments