Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import java.sql.Clob;
import java.sql.Date;
import java.sql.NClob;
import java.sql.RowId;
import java.sql.SQLXML;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
Expand Down Expand Up @@ -159,6 +161,8 @@ private static Map<String, JdbcType> declaredTypeRegistry() {
entry("TIMESTAMP", Types.TIMESTAMP, Timestamp.class, Timestamp.class, StorageClass.TEXT),
entry("CLOB", Types.CLOB, Clob.class, Clob.class, StorageClass.TEXT),
entry("NCLOB", Types.NCLOB, NClob.class, NClob.class, StorageClass.TEXT),
entry("SQLXML", Types.SQLXML, SQLXML.class, SQLXML.class, StorageClass.TEXT),
entry("ROWID", Types.ROWID, RowId.class, RowId.class, StorageClass.TEXT),
entry("BLOB", Types.BLOB, Blob.class, Blob.class, StorageClass.BLOB),
entry("DATALINK", Types.DATALINK, URL.class, URL.class, StorageClass.TEXT));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import java.sql.SQLFeatureNotSupportedException;

/** Read-only {@link Clob} over the materialized text of one result column. */
final class LibsqlClob implements Clob {
class LibsqlClob implements Clob {

private String text;
private boolean freed;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.github.magnusp.libsql.jdbc;

import java.sql.NClob;

/**
* Read-only {@link NClob} over the materialized text of one result column.
*
* <p>SQLite stores national and regular character data as the same UTF-8 text, so the national
* variant only adds the {@link NClob} interface to {@link LibsqlClob}.
*/
final class LibsqlNClob extends LibsqlClob implements NClob {

LibsqlNClob(String text) {
super(text);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
this.sql = sql;
this.returnsResultSet = returnsResultSet(sql);
this.parameterCount = SqlTokenizer.placeholderCount(sql);
this.parameterMetaData = new ParameterMetaDataView(this, parameterCount);

Check warning on line 60 in libsql-jdbc/src/main/java/com/github/magnusp/libsql/jdbc/LibsqlPreparedStatement.java

View workflow job for this annotation

GitHub Actions / Build & Test (Java 25)

possible 'this' escape before subclass is fully initialized

Check warning on line 60 in libsql-jdbc/src/main/java/com/github/magnusp/libsql/jdbc/LibsqlPreparedStatement.java

View workflow job for this annotation

GitHub Actions / Xerial Control (reference probe)

possible 'this' escape before subclass is fully initialized

Check warning on line 60 in libsql-jdbc/src/main/java/com/github/magnusp/libsql/jdbc/LibsqlPreparedStatement.java

View workflow job for this annotation

GitHub Actions / Build & Test (Java 26)

possible 'this' escape before subclass is fully initialized
}

private void setParam(int parameterIndex, Value value) throws SQLException {
Expand Down Expand Up @@ -359,7 +359,9 @@

@Override
public void setRowId(int parameterIndex, RowId x) throws SQLException {
throw new SQLFeatureNotSupportedException("RowId parameters are not supported");
// SQLite has no ROWID parameter type; BLOB binds the bytes unchanged, so getRowId reads
// back exactly the bytes the caller supplied.
setParam(parameterIndex, Value.of(x == null ? null : x.getBytes()));
}

@Override
Expand Down Expand Up @@ -394,7 +396,7 @@

@Override
public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {
throw new SQLFeatureNotSupportedException("SQLXML parameters are not supported");
setParam(parameterIndex, Value.of(xmlObject == null ? null : xmlObject.getString()));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import java.io.Reader;
import java.io.StringReader;
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.sql.Array;
import java.sql.Blob;
Expand Down Expand Up @@ -424,11 +426,21 @@ private static Object convertedObject(Value value, JdbcTypeMapping.JdbcType type
if (objectClass == Clob.class) {
return clobValue(value);
}
if (objectClass == NClob.class) {
return nclobValue(value);
}
if (objectClass == Blob.class) {
return blobValue(value);
}
// NCLOB and DATALINK resolve to their declared wrapper types, but the wrapper getters
// arrive in PR-3, so the value keeps its storage-class representation until then.
if (objectClass == RowId.class) {
return rowIdValue(value);
}
if (objectClass == SQLXML.class) {
return sqlxmlValue(value);
}
if (objectClass == URL.class) {
return urlValue(value);
}
return storedObject(value);
}

Expand Down Expand Up @@ -624,13 +636,19 @@ public boolean isLast() throws SQLException {
throw new SQLFeatureNotSupportedException("not supported by sqlite");
}

@Override public InputStream getAsciiStream(int columnIndex) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override
public InputStream getAsciiStream(int columnIndex) throws SQLException {
String text = getString(columnIndex);
return text == null
? null
: new ByteArrayInputStream(text.getBytes(java.nio.charset.StandardCharsets.US_ASCII));
}
@Override @Deprecated @SuppressWarnings("deprecation") public InputStream getUnicodeStream(int columnIndex) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public InputStream getBinaryStream(int columnIndex) throws SQLException {
byte[] bytes = getBytes(columnIndex);
return bytes == null ? null : new ByteArrayInputStream(bytes);
}
@Override public InputStream getAsciiStream(String columnLabel) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public InputStream getAsciiStream(String columnLabel) throws SQLException { return getAsciiStream(findColumn(columnLabel)); }
@Override @Deprecated @SuppressWarnings("deprecation") public InputStream getUnicodeStream(String columnLabel) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public InputStream getBinaryStream(String columnLabel) throws SQLException { return getBinaryStream(findColumn(columnLabel)); }
@Override public SQLWarning getWarnings() throws SQLException { return null; }
Expand Down Expand Up @@ -748,8 +766,25 @@ private static Clob clobValue(Value value) {
@Override public Time getTime(String columnLabel, Calendar cal) throws SQLException { return getTime(columnLabel); }
@Override public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { return getTimestamp(columnIndex); }
@Override public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException { return getTimestamp(columnLabel); }
@Override public URL getURL(int columnIndex) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public URL getURL(String columnLabel) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override
public URL getURL(int columnIndex) throws SQLException {
return urlValue(getCurrentValue(columnIndex));
}

private static URL urlValue(Value value) throws SQLException {
String text = stringValue(value);
if (text == null) {
return null;
}
try {
// URI.toURL replaces the deprecated URL(String) constructor and rejects the same text.
return URI.create(text).toURL();
} catch (IllegalArgumentException | MalformedURLException e) {
throw new SQLException("Bad value for type URL: " + text, e);
}
}

@Override public URL getURL(String columnLabel) throws SQLException { return getURL(findColumn(columnLabel)); }
@Override public void updateRef(int columnIndex, Ref x) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public void updateRef(String columnLabel, Ref x) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public void updateBlob(int columnIndex, Blob x) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
Expand All @@ -758,25 +793,46 @@ private static Clob clobValue(Value value) {
@Override public void updateClob(String columnLabel, Clob x) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public void updateArray(int columnIndex, Array x) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public void updateArray(String columnLabel, Array x) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public RowId getRowId(int columnIndex) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public RowId getRowId(String columnLabel) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public RowId getRowId(int columnIndex) throws SQLException {
return rowIdValue(getCurrentValue(columnIndex));
}
private static RowId rowIdValue(Value value) {
byte[] bytes = bytesValue(value);
return bytes == null ? null : new LibsqlRowId(bytes);
}
@Override public RowId getRowId(String columnLabel) throws SQLException { return getRowId(findColumn(columnLabel)); }
@Override public void updateRowId(int columnIndex, RowId x) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public void updateRowId(String columnLabel, RowId x) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public int getHoldability() throws SQLException { return CLOSE_CURSORS_AT_COMMIT; }
@Override public void updateNString(int columnIndex, String nString) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public void updateNString(String columnLabel, String nString) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public void updateNClob(int columnIndex, NClob nClob) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public void updateNClob(String columnLabel, NClob nClob) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public NClob getNClob(int columnIndex) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public NClob getNClob(String columnLabel) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public SQLXML getSQLXML(int columnIndex) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public SQLXML getSQLXML(String columnLabel) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public NClob getNClob(int columnIndex) throws SQLException {
return nclobValue(getCurrentValue(columnIndex));
}
private static NClob nclobValue(Value value) {
String text = stringValue(value);
return text == null ? null : new LibsqlNClob(text);
}
@Override public NClob getNClob(String columnLabel) throws SQLException { return getNClob(findColumn(columnLabel)); }
@Override public SQLXML getSQLXML(int columnIndex) throws SQLException {
return sqlxmlValue(getCurrentValue(columnIndex));
}
private static SQLXML sqlxmlValue(Value value) {
String text = stringValue(value);
return text == null ? null : new LibsqlSQLXML(text);
}
@Override public SQLXML getSQLXML(String columnLabel) throws SQLException { return getSQLXML(findColumn(columnLabel)); }
@Override public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public String getNString(int columnIndex) throws SQLException { return getString(columnIndex); }
@Override public String getNString(String columnLabel) throws SQLException { return getString(columnLabel); }
@Override public Reader getNCharacterStream(int columnIndex) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public Reader getNCharacterStream(String columnLabel) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public Reader getNCharacterStream(int columnIndex) throws SQLException {
String text = getNString(columnIndex);
return text == null ? null : new StringReader(text);
}
@Override public Reader getNCharacterStream(String columnLabel) throws SQLException { return getNCharacterStream(findColumn(columnLabel)); }
@Override public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
@Override public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException { throw new SQLFeatureNotSupportedException("not implemented by SQLite JDBC driver"); }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.github.magnusp.libsql.jdbc;

import java.sql.RowId;
import java.util.Arrays;

/** {@link RowId} over the materialized bytes of one result column. */
final class LibsqlRowId implements RowId {

private final byte[] bytes;

LibsqlRowId(byte[] bytes) {
this.bytes = bytes;
}

@Override
public byte[] getBytes() {
return bytes.clone();
}

@Override
public boolean equals(Object other) {
return other instanceof LibsqlRowId rowId && Arrays.equals(bytes, rowId.bytes);
}

@Override
public int hashCode() {
return Arrays.hashCode(bytes);
}

@Override
public String toString() {
return "LibsqlRowId" + Arrays.toString(bytes);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.github.magnusp.libsql.jdbc;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.SQLXML;

import javax.xml.transform.Result;
import javax.xml.transform.Source;

/** Read-only {@link SQLXML} over the materialized text of one result column. */
final class LibsqlSQLXML implements SQLXML {

private String text;
private boolean freed;

LibsqlSQLXML(String text) {
this.text = text;
}

private String data() throws SQLException {
if (freed) {
throw new SQLException("SQLXML has been freed");
}
return text;
}

@Override
public void free() throws SQLException {
freed = true;
text = null;
}

@Override
public String getString() throws SQLException {
return data();
}

@Override
public InputStream getBinaryStream() throws SQLException {
return new ByteArrayInputStream(data().getBytes(StandardCharsets.UTF_8));
}

@Override
public Reader getCharacterStream() throws SQLException {
return new StringReader(data());
}

@Override
public <T extends Source> T getSource(Class<T> sourceClass) throws SQLException {
throw new SQLFeatureNotSupportedException("SQLXML sources are not supported");
}

@Override
public OutputStream setBinaryStream() throws SQLException {
throw new SQLFeatureNotSupportedException("SQLXML is read-only");
}

@Override
public Writer setCharacterStream() throws SQLException {
throw new SQLFeatureNotSupportedException("SQLXML is read-only");
}

@Override
public void setString(String value) throws SQLException {
throw new SQLFeatureNotSupportedException("SQLXML is read-only");
}

@Override
public <T extends Result> T setResult(Class<T> resultClass) throws SQLException {
throw new SQLFeatureNotSupportedException("SQLXML is read-only");
}
}
Loading
Loading