[Git][java-team/xerial-sqlite-jdbc][upstream] New upstream version 3.50.3.0+dfsg
Ying-Chun Liu (@paulliu)
gitlab at salsa.debian.org
Wed Aug 13 14:49:32 BST 2025
Ying-Chun Liu pushed to branch upstream at Debian Java Maintainers / xerial-sqlite-jdbc
Commits:
fa4a925b by Ying-Chun Liu (PaulLiu) at 2025-08-13T14:27:16+01:00
New upstream version 3.50.3.0+dfsg
- - - - -
26 changed files:
- Makefile
- Makefile.common
- README.adoc
- VERSION
- pom.xml
- src/main/java/org/sqlite/ExtendedCommand.java
- src/main/java/org/sqlite/JDBC.java
- src/main/java/org/sqlite/SQLiteConnection.java
- src/main/java/org/sqlite/SQLiteJDBCLoader.java
- src/main/java/org/sqlite/core/NativeDB.java
- src/main/java/org/sqlite/jdbc3/JDBC3DatabaseMetaData.java
- src/main/java/org/sqlite/jdbc3/JDBC3PreparedStatement.java
- src/main/java/org/sqlite/jdbc3/JDBC3ResultSet.java
- src/main/java/org/sqlite/jdbc3/JDBC3Statement.java
- src/main/java/org/sqlite/jdbc4/JDBC4PreparedStatement.java
- src/main/java/org/sqlite/util/Logger.java
- src/main/java/org/sqlite/util/LoggerFactory.java
- src/main/java/org/sqlite/util/OSInfo.java
- src/main/java9/module-info.java
- src/test/java/org/sqlite/ConnectionTest.java
- src/test/java/org/sqlite/DBMetaDataTest.java
- src/test/java/org/sqlite/ExtendedCommandTest.java
- src/test/java/org/sqlite/PrepStmtTest.java
- src/test/java/org/sqlite/RSMetaDataTest.java
- src/test/java/org/sqlite/util/OSInfoTest.java
- + src/test/resources/META-INF/native-image/org.xerial/sqlite-jdbc/reachability-metadata.json
Changes:
=====================================
Makefile
=====================================
@@ -31,6 +31,7 @@ CCFLAGS:= -I$(SQLITE_OUT) -I$(SQLITE_INCLUDE) $(CCFLAGS)
$(SQLITE_ARCHIVE):
@mkdir -p $(@D)
+ curl -L --max-redirs 0 -f -o$@ https://www.sqlite.org/2025/$(SQLITE_AMAL_PREFIX).zip || \
curl -L --max-redirs 0 -f -o$@ https://www.sqlite.org/2024/$(SQLITE_AMAL_PREFIX).zip || \
curl -L --max-redirs 0 -f -o$@ https://www.sqlite.org/2023/$(SQLITE_AMAL_PREFIX).zip || \
curl -L --max-redirs 0 -f -o$@ https://www.sqlite.org/2022/$(SQLITE_AMAL_PREFIX).zip || \
=====================================
Makefile.common
=====================================
@@ -109,28 +109,28 @@ Linux-armv7_SQLITE_FLAGS :=
Linux-Android-arm_CC := $(CROSS_PREFIX)clang
Linux-Android-arm_STRIP := $(CROSS_ROOT)/bin/llvm-strip
Linux-Android-arm_CCFLAGS := -I$(JAVA_HOME)/include -Ilib/inc_linux -I$(CROSS_ROOT)/sysroot/usr/include -Os -fPIC -fvisibility=hidden -fPIE -pie -lm -lc -landroid -ldl -llog
-Linux-Android-arm_LINKFLAGS := $(Default_LINKFLAGS) -Wl,-soname,libsqlitejdbc.so
+Linux-Android-arm_LINKFLAGS := $(Default_LINKFLAGS) -Wl,-z,max-page-size=16384,-soname,libsqlitejdbc.so
Linux-Android-arm_LIBNAME := libsqlitejdbc.so
Linux-Android-arm_SQLITE_FLAGS :=
Linux-Android-aarch64_CC := $(CROSS_PREFIX)clang
Linux-Android-aarch64_STRIP := $(CROSS_ROOT)/bin/llvm-strip
Linux-Android-aarch64_CCFLAGS := -I$(JAVA_HOME)/include -Ilib/inc_linux -I$(CROSS_ROOT)/sysroot/usr/include -Os -fPIC -fvisibility=hidden -fPIE -pie -lm -lc -landroid -ldl -llog
-Linux-Android-aarch64_LINKFLAGS := $(Default_LINKFLAGS) -Wl,-soname,libsqlitejdbc.so
+Linux-Android-aarch64_LINKFLAGS := $(Default_LINKFLAGS) -Wl,-z,max-page-size=16384,-soname,libsqlitejdbc.so
Linux-Android-aarch64_LIBNAME := libsqlitejdbc.so
Linux-Android-aarch64_SQLITE_FLAGS :=
Linux-Android-x86_CC := $(CROSS_PREFIX)clang
Linux-Android-x86_STRIP := $(CROSS_ROOT)/bin/llvm-strip
Linux-Android-x86_CCFLAGS := -I$(JAVA_HOME)/include -Ilib/inc_linux -I$(CROSS_ROOT)/sysroot/usr/include -Os -fPIC -fvisibility=hidden -fPIE -pie -lm -lc -landroid -ldl -llog
-Linux-Android-x86_LINKFLAGS := $(Default_LINKFLAGS) -Wl,-soname,libsqlitejdbc.so
+Linux-Android-x86_LINKFLAGS := $(Default_LINKFLAGS) -Wl,-z,max-page-size=16384,-soname,libsqlitejdbc.so
Linux-Android-x86_LIBNAME := libsqlitejdbc.so
Linux-Android-x86_SQLITE_FLAGS :=
Linux-Android-x86_64_CC := $(CROSS_PREFIX)clang
Linux-Android-x86_64_STRIP := $(CROSS_ROOT)/bin/llvm-strip
Linux-Android-x86_64_CCFLAGS := -I$(JAVA_HOME)/include -Ilib/inc_linux -I$(CROSS_ROOT)/sysroot/usr/include -Os -fPIC -fvisibility=hidden -fPIE -pie -lm -lc -landroid -ldl -llog
-Linux-Android-x86_64_LINKFLAGS := $(Default_LINKFLAGS) -Wl,-soname,libsqlitejdbc.so
+Linux-Android-x86_64_LINKFLAGS := $(Default_LINKFLAGS) -Wl,-z,max-page-size=16384,-soname,libsqlitejdbc.so
Linux-Android-x86_64_LIBNAME := libsqlitejdbc.so
Linux-Android-x86_64_SQLITE_FLAGS :=
=====================================
README.adoc
=====================================
@@ -1,11 +1,11 @@
= SQLite JDBC Driver
-:project-version: 3.46.1.3
+:project-version: 3.50.3.0
image:https://img.shields.io/github/actions/workflow/status/xerial/sqlite-jdbc/ci.yml?branch=master[GitHub Workflow Status (branch),link=https://github.com/xerial/sqlite-jdbc/actions/workflows/ci.yml?query=branch%3Amaster]
image:https://badges.gitter.im/xerial/sqlite-jdbc.svg[Join the chat,link=https://gitter.im/xerial/sqlite-jdbc?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge]
-image:https://maven-badges.herokuapp.com/maven-central/org.xerial/sqlite-jdbc/badge.svg[Maven Central,link=https://maven-badges.herokuapp.com/maven-central/org.xerial/sqlite-jdbc/]
+image:https://img.shields.io/maven-central/v/org.xerial/sqlite-jdbc?label=maven%20central&color=dark-green[Maven Central,link=https://central.sonatype.com/artifact/org.xerial/sqlite-jdbc]
image:https://javadoc.io/badge2/org.xerial/sqlite-jdbc/javadoc.svg[javadoc,link=https://javadoc.io/doc/org.xerial/sqlite-jdbc]
-image:https://img.shields.io/nexus/s/org.xerial/sqlite-jdbc?color=blue&label=maven%20snapshot&server=https%3A%2F%2Foss.sonatype.org%2F[Sonatype Nexus (Snapshots),link=https://oss.sonatype.org/content/repositories/snapshots/org/xerial/sqlite-jdbc/]
+image:https://img.shields.io/maven-metadata/v?color=blue&label=maven%20snapshot&metadataUrl=https%3A%2F%2Fcentral.sonatype.com%2Frepository%2Fmaven-snapshots%2Forg%2Fxerial%2Fsqlite-jdbc%2Fmaven-metadata.xml[]
SQLite JDBC is a library for accessing and creating https://www.sqlite.org[SQLite] database files in Java.
@@ -115,7 +115,7 @@ the following operating systems:
|macOS | |✔ | | | |✔ | |
|Linux (libc) |✔ |✔ |✔ |✔ |✔ |✔ |✔ |✔
|Linux (musl) |✔ |✔ | | | |✔ | |
-|Android |✔ |✔ |✔ | | |✔ | |
+|Android (API Level 24+) |✔ |✔ |✔ | | |✔ | |
|FreeBSD |✔ |✔ | | | |✔ | |
|===
@@ -167,7 +167,7 @@ When packaging the resulting app, simply include the library in the distribution
== Download
-Download from https://search.maven.org/artifact/org.xerial/sqlite-jdbc[Maven Central] or from the https://github.com/xerial/sqlite-jdbc/releases[releases] page.
+Download from https://central.sonatype.com/artifact/org.xerial/sqlite-jdbc[Maven Central] or from the https://github.com/xerial/sqlite-jdbc/releases[releases] page.
[source,xml,subs="attributes+"]
----
=====================================
VERSION
=====================================
@@ -1 +1 @@
-version=3.46.1
+version=3.50.3
=====================================
pom.xml
=====================================
@@ -4,17 +4,17 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
- <version>3.46.1.3</version>
+ <version>3.50.3.0</version>
<name>SQLite JDBC</name>
<description>SQLite JDBC library</description>
<url>https://github.com/xerial/sqlite-jdbc</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <junit.version>5.11.0</junit.version>
- <surefire.version>3.5.0</surefire.version>
- <archunit.version>1.3.0</archunit.version>
- <graalvm.version>24.1.0</graalvm.version>
+ <junit.version>5.12.2</junit.version>
+ <surefire.version>3.5.3</surefire.version>
+ <archunit.version>1.4.1</archunit.version>
+ <graalvm.version>24.1.2</graalvm.version>
<java9.sourceDirectory>${project.basedir}/src/main/java9</java9.sourceDirectory>
</properties>
@@ -95,13 +95,13 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-help-plugin</artifactId>
- <version>3.5.0</version>
+ <version>3.5.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
- <version>3.13.0</version>
+ <version>3.14.0</version>
<configuration>
<release>8</release>
</configuration>
@@ -185,21 +185,21 @@
</plugin>
<plugin>
- <groupId>org.sonatype.plugins</groupId>
- <artifactId>nexus-staging-maven-plugin</artifactId>
- <version>1.7.0</version>
+ <groupId>org.sonatype.central</groupId>
+ <artifactId>central-publishing-maven-plugin</artifactId>
+ <version>0.8.0</version>
<extensions>true</extensions>
<configuration>
- <serverId>ossrh</serverId>
- <nexusUrl>https://oss.sonatype.org/</nexusUrl>
- <autoReleaseAfterClose>true</autoReleaseAfterClose>
+ <publishingServerId>central</publishingServerId>
+ <autoPublish>true</autoPublish>
+ <waitUntil>published</waitUntil>
</configuration>
</plugin>
<plugin>
<groupId>org.jreleaser</groupId>
<artifactId>jreleaser-maven-plugin</artifactId>
- <version>1.14.0</version>
+ <version>1.19.0</version>
<configuration>
<configFile>jreleaser.yml</configFile>
</configuration>
@@ -208,13 +208,13 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
- <version>2.17.1</version>
+ <version>2.18.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
- <version>3.5.0</version>
+ <version>3.6.0</version>
<executions>
<execution>
<id>enforce-maven</id>
@@ -264,13 +264,6 @@
<url>https://github.com/xerial/sqlite-jdbc</url>
</scm>
- <distributionManagement>
- <snapshotRepository>
- <id>ossrh</id>
- <url>https://oss.sonatype.org/content/repositories/snapshots</url>
- </snapshotRepository>
- </distributionManagement>
-
<profiles>
<profile>
<id>release</id>
@@ -285,7 +278,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
- <version>3.2.6</version>
+ <version>3.2.8</version>
<executions>
<execution>
<id>sign-artifacts</id>
@@ -299,7 +292,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
- <version>3.10.0</version>
+ <version>3.11.2</version>
<configuration>
<sourcepath>src/main/java</sourcepath>
<additionalOptions>-Xdoclint:none</additionalOptions>
@@ -338,7 +331,7 @@
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
- <version>0.10.3</version>
+ <version>0.10.6</version>
<extensions>true</extensions>
<executions>
<execution>
@@ -355,6 +348,15 @@
<buildArgs>
<!-- required to allow junit-pioneer to compile with strict image heap enabled -->
<arg>--initialize-at-build-time=org.junitpioneer.jupiter.issue.IssueExtensionExecutionListener</arg>
+ <!--
+ Issues with JUnit support should be largely resolved by https://github.com/graalvm/native-build-tools/issues/613
+ These are only necessary for GraalVM for JDK 22+ as this has the Strict Image Heap enabled by default,
+ and should be removed when aforementioned issue is released in a new buildtools release.
+ -->
+ <arg>--initialize-at-build-time=org.junit.jupiter.engine.descriptor.ExclusiveResourceCollector$DefaultExclusiveResourceCollector</arg>
+ <arg>--initialize-at-build-time=org.junit.jupiter.api.parallel.ResourceLock</arg>
+ <arg>--initialize-at-build-time=org.junit.jupiter.api.parallel.ResourceLockTarget</arg>
+ <arg>--initialize-at-build-time=org.junit.jupiter.api.parallel.ResourceAccessMode</arg>
</buildArgs>
</configuration>
</plugin>
@@ -431,13 +433,12 @@
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
- <version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
- <version>3.26.3</version>
+ <version>3.27.3</version>
<scope>test</scope>
<exclusions>
<exclusion>
@@ -453,13 +454,13 @@
<dependency>
<groupId>org.junit-pioneer</groupId>
<artifactId>junit-pioneer</artifactId>
- <version>2.2.0</version>
+ <version>2.3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
- <version>5.13.0</version>
+ <version>5.18.0</version>
<scope>test</scope>
</dependency>
<dependency>
@@ -476,4 +477,15 @@
<scope>test</scope>
</dependency>
</dependencies>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.junit</groupId>
+ <artifactId>junit-bom</artifactId>
+ <version>${junit.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
</project>
=====================================
src/main/java/org/sqlite/ExtendedCommand.java
=====================================
@@ -54,7 +54,7 @@ public class ExtendedCommand {
if (s == null) return s;
if ((s.startsWith("\"") && s.endsWith("\"")) || (s.startsWith("'") && s.endsWith("'")))
- return s.substring(1, s.length() - 1);
+ return (s.length() >= 2) ? s.substring(1, s.length() - 1) : s;
else return s;
}
=====================================
src/main/java/org/sqlite/JDBC.java
=====================================
@@ -30,7 +30,7 @@ public class JDBC implements Driver {
try {
DriverManager.registerDriver(new JDBC());
} catch (SQLException e) {
- logger.error("Could not register driver", e);
+ logger.error(() -> "Could not register driver", e);
}
}
=====================================
src/main/java/org/sqlite/SQLiteConnection.java
=====================================
@@ -251,26 +251,7 @@ public abstract class SQLiteConnection implements Connection {
throw new SQLException(String.format("failed to load %s: %s", resourceName, e));
}
} else {
- File file = new File(fileName).getAbsoluteFile();
- File parent = file.getParentFile();
- if (parent != null && !parent.exists()) {
- for (File up = parent; up != null && !up.exists(); ) {
- parent = up;
- up = up.getParentFile();
- }
- throw new SQLException(
- "path to '" + fileName + "': '" + parent + "' does not exist");
- }
-
- // check write access if file does not exist
- try {
- // The extra check to exists() is necessary as createNewFile()
- // does not follow the JavaDoc when used on read-only shares.
- if (!file.exists() && file.createNewFile()) file.delete();
- } catch (Exception e) {
- throw new SQLException("opening db: '" + fileName + "': " + e.getMessage());
- }
- fileName = file.getAbsolutePath();
+ fileName = new File(fileName).getAbsolutePath();
}
}
=====================================
src/main/java/org/sqlite/SQLiteJDBCLoader.java
=====================================
@@ -34,6 +34,7 @@ import java.nio.file.StandardCopyOption;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
+import java.text.MessageFormat;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
@@ -101,12 +102,12 @@ public class SQLiteJDBCLoader {
try {
Files.delete(nativeLib);
} catch (Exception e) {
- logger.error("Failed to delete old native lib", e);
+ logger.error(() -> "Failed to delete old native lib", e);
}
}
});
} catch (IOException e) {
- logger.error("Failed to open directory", e);
+ logger.error(() -> "Failed to open directory", e);
}
}
@@ -222,7 +223,7 @@ public class SQLiteJDBCLoader {
}
return loadNativeLibrary(targetFolder, extractedLibFileName);
} catch (IOException e) {
- logger.error("Unexpected IOException", e);
+ logger.error(() -> "Unexpected IOException", e);
return false;
}
}
@@ -246,7 +247,7 @@ public class SQLiteJDBCLoader {
connection.setUseCaches(false);
return connection.getInputStream();
} catch (IOException e) {
- logger.error("Could not connect", e);
+ logger.error(() -> "Could not connect", e);
return null;
}
}
@@ -268,9 +269,10 @@ public class SQLiteJDBCLoader {
} catch (UnsatisfiedLinkError e) {
logger.error(
- "Failed to load native library: {}. osinfo: {}",
- name,
- OSInfo.getNativeLibFolderPathForCurrentOS(),
+ () ->
+ MessageFormat.format(
+ "Failed to load native library: {0}. osinfo: {1}",
+ name, OSInfo.getNativeLibFolderPathForCurrentOS()),
e);
return false;
}
@@ -285,7 +287,7 @@ public class SQLiteJDBCLoader {
System.loadLibrary(LibraryLoaderUtil.NATIVE_LIB_BASE_NAME);
return true;
} catch (UnsatisfiedLinkError e) {
- logger.error("Failed to load native library through System.loadLibrary", e);
+ logger.error(() -> "Failed to load native library through System.loadLibrary", e);
return false;
}
}
@@ -417,8 +419,14 @@ public class SQLiteJDBCLoader {
} catch (IOException e) {
// inline creation of logger to avoid build-time initialization of the logging
// framework in native-image
+ URL finalVersionFile = versionFile;
LoggerFactory.getLogger(VersionHolder.class)
- .error("Could not read version from file: {}", versionFile, e);
+ .error(
+ () ->
+ MessageFormat.format(
+ "Could not read version from file: {0}",
+ finalVersionFile),
+ e);
}
VERSION = version;
}
=====================================
src/main/java/org/sqlite/core/NativeDB.java
=====================================
@@ -19,6 +19,7 @@ package org.sqlite.core;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
+import java.text.MessageFormat;
import org.sqlite.BusyHandler;
import org.sqlite.Collation;
import org.sqlite.Function;
@@ -90,10 +91,11 @@ public final class NativeDB extends DB {
/** @see org.sqlite.core.DB#_exec(java.lang.String) */
@Override
public synchronized int _exec(String sql) throws SQLException {
- if (logger.isTraceEnabled()) {
- logger.trace(
- "DriverManager [{}] [SQLite EXEC] {}", Thread.currentThread().getName(), sql);
- }
+ logger.trace(
+ () ->
+ MessageFormat.format(
+ "DriverManager [{0}] [SQLite EXEC] {1}",
+ Thread.currentThread().getName(), sql));
return _exec_utf8(stringToUtf8ByteArray(sql));
}
@@ -125,10 +127,11 @@ public final class NativeDB extends DB {
/** @see org.sqlite.core.DB#prepare(java.lang.String) */
@Override
protected synchronized SafeStmtPtr prepare(String sql) throws SQLException {
- if (logger.isTraceEnabled()) {
- logger.trace(
- "DriverManager [{}] [SQLite EXEC] {}", Thread.currentThread().getName(), sql);
- }
+ logger.trace(
+ () ->
+ MessageFormat.format(
+ "DriverManager [{0}] [SQLite EXEC] {1}",
+ Thread.currentThread().getName(), sql));
return new SafeStmtPtr(this, prepare_utf8(stringToUtf8ByteArray(sql)));
}
=====================================
src/main/java/org/sqlite/jdbc3/JDBC3DatabaseMetaData.java
=====================================
@@ -438,12 +438,12 @@ public abstract class JDBC3DatabaseMetaData extends CoreDatabaseMetaData {
/** @see java.sql.DatabaseMetaData#supportsAlterTableWithAddColumn() */
public boolean supportsAlterTableWithAddColumn() {
- return false;
+ return true;
}
/** @see java.sql.DatabaseMetaData#supportsAlterTableWithDropColumn() */
public boolean supportsAlterTableWithDropColumn() {
- return false;
+ return true;
}
/** @see java.sql.DatabaseMetaData#supportsANSI92EntryLevelSQL() */
@@ -964,14 +964,14 @@ public abstract class JDBC3DatabaseMetaData extends CoreDatabaseMetaData {
try {
rsColAutoinc.close();
} catch (Exception e) {
- LogHolder.logger.error("Could not close ResultSet", e);
+ LogHolder.logger.error(() -> "Could not close ResultSet", e);
}
}
if (statColAutoinc != null) {
try {
statColAutoinc.close();
} catch (Exception e) {
- LogHolder.logger.error("Could not close statement", e);
+ LogHolder.logger.error(() -> "Could not close statement", e);
}
}
}
@@ -1057,10 +1057,10 @@ public abstract class JDBC3DatabaseMetaData extends CoreDatabaseMetaData {
}
// try to parse the values
try {
- int iInteger = Integer.parseUnsignedInt(sInteger);
+ int iInteger = Integer.parseUnsignedInt(sInteger.trim());
// parse decimals?
if (sDecimal != null) {
- iDecimalDigits = Integer.parseUnsignedInt(sDecimal);
+ iDecimalDigits = Integer.parseUnsignedInt(sDecimal.trim());
// columns size equals sum of integer and decimal part
// of dimension
iColumnSize = iInteger + iDecimalDigits;
@@ -1125,7 +1125,7 @@ public abstract class JDBC3DatabaseMetaData extends CoreDatabaseMetaData {
try {
rs.close();
} catch (Exception e) {
- LogHolder.logger.error("Could not close ResultSet", e);
+ LogHolder.logger.error(() -> "Could not close ResultSet", e);
}
}
}
=====================================
src/main/java/org/sqlite/jdbc3/JDBC3PreparedStatement.java
=====================================
@@ -390,13 +390,14 @@ public abstract class JDBC3PreparedStatement extends CorePreparedStatement {
/** @see java.sql.PreparedStatement#setCharacterStream(int, java.io.Reader, int) */
public void setCharacterStream(int pos, Reader reader, int length) throws SQLException {
try {
- // copy chars from reader to StringBuffer
- StringBuffer sb = new StringBuffer();
+ // copy chars from reader to StringBuilder
+ StringBuilder sb = new StringBuilder();
char[] cbuf = new char[8192];
int cnt;
- while ((cnt = reader.read(cbuf)) > 0) {
+ while ((cnt = reader.read(cbuf, 0, Math.min(length, cbuf.length))) > 0) {
sb.append(cbuf, 0, cnt);
+ length -= cnt;
}
// set as string
=====================================
src/main/java/org/sqlite/jdbc3/JDBC3ResultSet.java
=====================================
@@ -573,7 +573,7 @@ public abstract class JDBC3ResultSet extends CoreResultSet {
/** @see java.sql.ResultSetMetaData#getCatalogName(int) */
public String getCatalogName(int col) throws SQLException {
- return safeGetColumnTableName(col);
+ return "";
}
/** @see java.sql.ResultSetMetaData#getColumnClassName(int) */
=====================================
src/main/java/org/sqlite/jdbc3/JDBC3Statement.java
=====================================
@@ -7,6 +7,7 @@ import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.SQLWarning;
import java.sql.Statement;
+import java.text.MessageFormat;
import java.util.Arrays;
import org.sqlite.ExtendedCommand;
import org.sqlite.ExtendedCommand.SQLExtension;
@@ -100,7 +101,10 @@ public abstract class JDBC3Statement extends CoreStatement {
private static final Logger logger = LoggerFactory.getLogger(BackupObserver.class);
public void progress(int remaining, int pageCount) {
- logger.info("remaining:{}, page count:{}", remaining, pageCount);
+ logger.info(
+ () ->
+ MessageFormat.format(
+ "remaining:{0}, page count:{1}", remaining, pageCount));
}
}
=====================================
src/main/java/org/sqlite/jdbc4/JDBC4PreparedStatement.java
=====================================
@@ -1,5 +1,8 @@
package org.sqlite.jdbc4;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.sql.NClob;
@@ -48,14 +51,21 @@ public class JDBC4PreparedStatement extends JDBC3PreparedStatement
}
public void setClob(int parameterIndex, Reader reader, long length) throws SQLException {
- // TODO Support this
- throw new SQLFeatureNotSupportedException();
+ requireLengthIsPositiveInt(length);
+ setCharacterStream(parameterIndex, reader, (int) length);
+ }
+
+ private void requireLengthIsPositiveInt(long length) throws SQLFeatureNotSupportedException {
+ if (length > Integer.MAX_VALUE || length < 0) {
+ throw new SQLFeatureNotSupportedException(
+ "Data must have a length between 0 and Integer.MAX_VALUE");
+ }
}
public void setBlob(int parameterIndex, InputStream inputStream, long length)
throws SQLException {
- // TODO Support this
- throw new SQLFeatureNotSupportedException();
+ requireLengthIsPositiveInt(length);
+ setBinaryStream(parameterIndex, inputStream, (int) length);
}
public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException {
@@ -69,35 +79,59 @@ public class JDBC4PreparedStatement extends JDBC3PreparedStatement
}
public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException {
- // TODO Support this
- throw new SQLFeatureNotSupportedException();
+ requireLengthIsPositiveInt(length);
+ setAsciiStream(parameterIndex, x, (int) length);
}
public void setBinaryStream(int parameterIndex, InputStream x, long length)
throws SQLException {
- // TODO Support this
- throw new SQLFeatureNotSupportedException();
+ requireLengthIsPositiveInt(length);
+ setBinaryStream(parameterIndex, x, (int) length);
}
public void setCharacterStream(int parameterIndex, Reader reader, long length)
throws SQLException {
- // TODO Support this
- throw new SQLFeatureNotSupportedException();
+ requireLengthIsPositiveInt(length);
+ setCharacterStream(parameterIndex, reader, (int) length);
}
public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException {
- // TODO Support this
- throw new SQLFeatureNotSupportedException();
+ byte[] bytes = readBytes(x);
+ setAsciiStream(parameterIndex, new ByteArrayInputStream(bytes), bytes.length);
+ }
+
+ /**
+ * Reads given number of bytes from an input stream.
+ *
+ * @param istream The input stream.
+ * @param length The number of bytes to read.
+ * @return byte array.
+ * @throws SQLException
+ */
+ private byte[] readBytes(InputStream istream) throws SQLException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ byte[] bytes = new byte[8192];
+
+ try {
+ int bytesRead;
+ while ((bytesRead = istream.read(bytes)) > 0) {
+ baos.write(bytes, 0, bytesRead);
+ }
+ return baos.toByteArray();
+ } catch (IOException cause) {
+ SQLException exception = new SQLException("Error reading stream");
+
+ exception.initCause(cause);
+ throw exception;
+ }
}
public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException {
- // TODO Support this
- throw new SQLFeatureNotSupportedException();
+ setBytes(parameterIndex, readBytes(x));
}
public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException {
- // TODO Support this
- throw new SQLFeatureNotSupportedException();
+ setCharacterStream(parameterIndex, reader, Integer.MAX_VALUE);
}
public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
@@ -106,13 +140,11 @@ public class JDBC4PreparedStatement extends JDBC3PreparedStatement
}
public void setClob(int parameterIndex, Reader reader) throws SQLException {
- // TODO Support this
- throw new SQLFeatureNotSupportedException();
+ setCharacterStream(parameterIndex, reader, Integer.MAX_VALUE);
}
public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException {
- // TODO Support this
- throw new SQLFeatureNotSupportedException();
+ setBytes(parameterIndex, readBytes(inputStream));
}
public void setNClob(int parameterIndex, Reader reader) throws SQLException {
=====================================
src/main/java/org/sqlite/util/Logger.java
=====================================
@@ -1,18 +1,14 @@
package org.sqlite.util;
+import java.util.function.Supplier;
+
/** A simple internal Logger interface. */
public interface Logger {
- boolean isTraceEnabled();
-
- void trace(String format, Object o1, Object o2);
-
- void info(String format, Object o1, Object o2);
-
- void warn(String msg);
+ void trace(Supplier<String> message);
- void error(String message, Throwable t);
+ void info(Supplier<String> message);
- void error(String format, Object o1, Throwable t);
+ void warn(Supplier<String> message);
- void error(String format, Object o1, Object o2, Throwable t);
+ void error(Supplier<String> message, Throwable t);
}
=====================================
src/main/java/org/sqlite/util/LoggerFactory.java
=====================================
@@ -1,6 +1,7 @@
package org.sqlite.util;
-import java.text.MessageFormat;
+import java.util.function.Supplier;
+import java.util.logging.Level;
/**
* A factory for {@link Logger} instances that uses SLF4J if present, falling back on a
@@ -42,45 +43,30 @@ public class LoggerFactory {
}
@Override
- public boolean isTraceEnabled() {
- return logger.isLoggable(java.util.logging.Level.FINEST);
- }
-
- @Override
- public void trace(String format, Object o1, Object o2) {
- if (logger.isLoggable(java.util.logging.Level.FINEST)) {
- logger.log(java.util.logging.Level.FINEST, MessageFormat.format(format, o1, o2));
+ public void trace(Supplier<String> message) {
+ if (logger.isLoggable(Level.FINEST)) {
+ logger.log(Level.FINEST, message.get());
}
}
@Override
- public void info(String format, Object o1, Object o2) {
- if (logger.isLoggable(java.util.logging.Level.INFO)) {
- logger.log(java.util.logging.Level.INFO, MessageFormat.format(format, o1, o2));
+ public void info(Supplier<String> message) {
+ if (logger.isLoggable(Level.INFO)) {
+ logger.log(Level.INFO, message.get());
}
}
@Override
- public void warn(String msg) {
- logger.log(java.util.logging.Level.WARNING, msg);
- }
-
- @Override
- public void error(String message, Throwable t) {
- logger.log(java.util.logging.Level.SEVERE, message, t);
- }
-
- @Override
- public void error(String format, Object o1, Throwable t) {
- if (logger.isLoggable(java.util.logging.Level.SEVERE)) {
- logger.log(java.util.logging.Level.SEVERE, MessageFormat.format(format, o1), t);
+ public void warn(Supplier<String> message) {
+ if (logger.isLoggable(Level.WARNING)) {
+ logger.log(Level.WARNING, message.get());
}
}
@Override
- public void error(String format, Object o1, Object o2, Throwable t) {
- if (logger.isLoggable(java.util.logging.Level.SEVERE)) {
- logger.log(java.util.logging.Level.SEVERE, MessageFormat.format(format, o1, o2), t);
+ public void error(Supplier<String> message, Throwable t) {
+ if (logger.isLoggable(Level.SEVERE)) {
+ logger.log(Level.SEVERE, message.get(), t);
}
}
}
@@ -93,38 +79,31 @@ public class LoggerFactory {
}
@Override
- public boolean isTraceEnabled() {
- return logger.isTraceEnabled();
- }
-
- @Override
- public void trace(String format, Object o1, Object o2) {
- logger.trace(format, o1, o2);
- }
-
- @Override
- public void info(String format, Object o1, Object o2) {
- logger.info(format, o1, o2);
- }
-
- @Override
- public void warn(String msg) {
- logger.warn(msg);
+ public void trace(Supplier<String> message) {
+ if (logger.isTraceEnabled()) {
+ logger.trace(message.get());
+ }
}
@Override
- public void error(String message, Throwable t) {
- logger.error(message, t);
+ public void info(Supplier<String> message) {
+ if (logger.isInfoEnabled()) {
+ logger.info(message.get());
+ }
}
@Override
- public void error(String format, Object o1, Throwable t) {
- logger.error(format, o1, t);
+ public void warn(Supplier<String> message) {
+ if (logger.isWarnEnabled()) {
+ logger.warn(message.get());
+ }
}
@Override
- public void error(String format, Object o1, Object o2, Throwable t) {
- logger.error(format, o1, o2, t);
+ public void error(Supplier<String> message, Throwable t) {
+ if (logger.isErrorEnabled()) {
+ logger.error(message.get(), t);
+ }
}
}
}
=====================================
src/main/java/org/sqlite/util/OSInfo.java
=====================================
@@ -24,6 +24,7 @@
// --------------------------------------
package org.sqlite.util;
+import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -114,7 +115,21 @@ public class OSInfo {
}
public static boolean isAndroid() {
- return isAndroidRuntime() || isAndroidTermux();
+ return isAndroidRuntime() || isAndroidTermux() || isRunningAndroid();
+ }
+
+ private static boolean isRunningAndroid() {
+ // This file is guaranteed to be present on every android version since 1.6 (Donut, API 4),
+ // see https://developer.android.com/ndk/guides/stable_apis#graphics
+ // We don't use libc/libm/libdl because that has changed what directory its pointing to and
+ // OEMs implement the symlink that allows backwards compatibility
+ // for apps that use the old path differently, which may cause this check to fail because
+ // of common undocumented behaviour. See
+ // https://developer.android.com/about/versions/10/behavior-changes-all#bionic
+ File androidGLES = new File("/system/lib/libGLESv1_CM.so");
+ File android64GLES = new File("/system/lib64/libGLESv1_CM.so");
+
+ return android64GLES.exists() || androidGLES.exists();
}
public static boolean isAndroidRuntime() {
@@ -161,7 +176,7 @@ public class OSInfo {
try {
return processRunner.runAndWaitFor("uname -m");
} catch (Throwable e) {
- LogHolder.logger.error("Error while running uname -m", e);
+ LogHolder.logger.error(() -> "Error while running uname -m", e);
return "unknown";
}
}
@@ -203,7 +218,7 @@ public class OSInfo {
}
// Java 1.8 introduces a system property to determine armel or armhf
- // http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8005545
+ // https://bugs.openjdk.org/browse/JDK-8005545
String abi = System.getProperty("sun.arch.abi");
if (abi != null && abi.startsWith("gnueabihf")) {
return "armv7";
@@ -229,7 +244,8 @@ public class OSInfo {
}
} else {
LogHolder.logger.warn(
- "readelf not found. Cannot check if running on an armhf system, armel architecture will be presumed");
+ () ->
+ "readelf not found. Cannot check if running on an armhf system, armel architecture will be presumed");
}
} catch (IOException | InterruptedException e) {
// ignored: fall back to "arm" arch (soft-float ABI)
=====================================
src/main/java9/module-info.java
=====================================
@@ -1,6 +1,6 @@
module org.xerial.sqlitejdbc {
- requires org.slf4j;
+ requires static org.slf4j;
requires transitive java.sql;
requires transitive java.sql.rowset;
requires static org.graalvm.nativeimage;
=====================================
src/test/java/org/sqlite/ConnectionTest.java
=====================================
@@ -6,6 +6,10 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.nio.file.AccessDeniedException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.sql.*;
import java.util.ArrayList;
import java.util.Properties;
@@ -14,6 +18,8 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledOnOs;
+import org.junit.jupiter.api.condition.OS;
import org.junit.jupiter.api.io.TempDir;
import org.sqlite.SQLiteConfig.JournalMode;
import org.sqlite.SQLiteConfig.Pragma;
@@ -409,4 +415,49 @@ public class ConnectionTest {
stat.close();
conn.close();
}
+
+ @Test
+ public void openNonExistingFileNoCreate() {
+ Path nonExisting = Paths.get("non_existing.db").toAbsolutePath();
+ assertThat(Files.exists(nonExisting)).isFalse();
+ SQLiteConfig cfg = new SQLiteConfig();
+ cfg.resetOpenMode(SQLiteOpenMode.CREATE);
+ assertThatExceptionOfType(SQLiteException.class)
+ .isThrownBy(
+ () -> {
+ @SuppressWarnings({"resource", "unused"})
+ Connection _c = cfg.createConnection("jdbc:sqlite:" + nonExisting);
+ })
+ .satisfies(
+ e ->
+ assertThat(e.getResultCode())
+ .isEqualTo(SQLiteErrorCode.SQLITE_CANTOPEN));
+ assertThat(Files.exists(nonExisting)).isFalse();
+ }
+
+ @DisabledOnOs(OS.WINDOWS) // File.setReadOnly doesn't seem to work here
+ @Test
+ public void openNonExistingFileInReadOnlyDirectory(@TempDir Path tmpDir) {
+ assertThat(tmpDir.toFile().setReadOnly()).isTrue();
+ assertThat(Files.exists(tmpDir)).isTrue();
+ Path nonExisting = tmpDir.resolve("non_existing.db").toAbsolutePath();
+ assertThatThrownBy(() -> Files.createFile(nonExisting))
+ .isInstanceOf(AccessDeniedException.class);
+ assertThat(Files.exists(nonExisting)).isFalse();
+ SQLiteConfig cfg = new SQLiteConfig();
+ assertThatExceptionOfType(SQLiteException.class)
+ .isThrownBy(
+ () -> {
+ @SuppressWarnings({"resource", "unused"})
+ Connection _c = cfg.createConnection("jdbc:sqlite:" + nonExisting);
+ })
+ .satisfies(
+ e ->
+ // It would be nice, if the native error code were more specific on
+ // why the file can't be
+ // opened, but this is what we get:
+ assertThat(e.getResultCode())
+ .isEqualTo(SQLiteErrorCode.SQLITE_CANTOPEN));
+ assertThat(Files.exists(nonExisting)).isFalse();
+ }
}
=====================================
src/test/java/org/sqlite/DBMetaDataTest.java
=====================================
@@ -477,6 +477,24 @@ public class DBMetaDataTest {
assertThat(rs.getString("COLUMN_NAME")).isEqualTo("sql");
}
+ @Test
+ public void getColumnsPrecisionScale() throws SQLException {
+ stat.executeUpdate("create table gh_1215 (n numeric ( 10 , 5 ), d decimal ( 10 ))");
+
+ ResultSet rs = meta.getColumns(null, null, "gh_1215", "%");
+ assertThat(rs.next()).isTrue();
+ assertThat(rs.getString("COLUMN_NAME")).isEqualTo("n");
+ assertThat(rs.getString("TYPE_NAME")).isEqualTo("NUMERIC");
+ assertThat(rs.getString("COLUMN_SIZE")).isEqualTo("15");
+ assertThat(rs.getString("DECIMAL_DIGITS")).isEqualTo("5");
+ assertThat(rs.next()).isTrue();
+ assertThat(rs.getString("COLUMN_NAME")).isEqualTo("d");
+ assertThat(rs.getString("TYPE_NAME")).isEqualTo("DECIMAL");
+ assertThat(rs.getString("COLUMN_SIZE")).isEqualTo("10");
+ assertThat(rs.getString("DECIMAL_DIGITS")).isEqualTo("0");
+ assertThat(rs.next()).isFalse();
+ }
+
@Test
public void getColumnsIncludingGenerated() throws SQLException {
stat.executeUpdate("create table gh_724 (i integer,j integer generated always as (i))");
=====================================
src/test/java/org/sqlite/ExtendedCommandTest.java
=====================================
@@ -12,7 +12,11 @@ package org.sqlite;
import static org.assertj.core.api.Assertions.assertThat;
import java.sql.SQLException;
+import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import org.sqlite.ExtendedCommand.BackupCommand;
import org.sqlite.ExtendedCommand.RestoreCommand;
import org.sqlite.ExtendedCommand.SQLExtension;
@@ -69,4 +73,22 @@ public class ExtendedCommandTest {
assertThat(b.targetDB).isEqualTo("main");
assertThat(b.srcFile).isEqualTo("target/sample.db");
}
+
+ @ParameterizedTest
+ @MethodSource
+ public void removeQuotation(String input, String expected) throws SQLException {
+ assertThat(ExtendedCommand.removeQuotation(input)).isEqualTo(expected);
+ }
+
+ private static Stream<Arguments> removeQuotation() {
+ return Stream.of(
+ Arguments.of(null, null), // Null String
+ Arguments.of("'", "'"), // String with one single quotation only
+ Arguments.of("\"", "\""), // String with one double quotation only
+ Arguments.of("'Test\"", "'Test\""), // String with two mismatch quotations
+ Arguments.of("'Test'", "Test"), // String with two matching single quotations
+ Arguments.of("\"Test\"", "Test"), // String with two matching double quotations
+ Arguments.of("'Te's\"t'", "Te's\"t") // String with more than two quotations
+ );
+ }
}
=====================================
src/test/java/org/sqlite/PrepStmtTest.java
=====================================
@@ -7,6 +7,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.data.Offset.offset;
import java.io.ByteArrayInputStream;
+import java.io.StringReader;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
@@ -177,6 +178,32 @@ public class PrepStmtTest {
rs.close();
}
+ @Test
+ public void clobRS() throws SQLException {
+ String name = "Gandhi";
+ PreparedStatement prep = conn.prepareStatement("select ?;");
+ prep.setClob(1, new StringReader(name));
+ ResultSet rs = prep.executeQuery();
+ assertThat(prep.getUpdateCount()).isEqualTo(-1);
+ assertThat(rs.next()).isTrue();
+ assertThat(rs.getString(1)).isEqualTo(name);
+ assertThat(rs.next()).isFalse();
+ rs.close();
+ }
+
+ @Test
+ public void blobRS() throws SQLException {
+ String name = "Gandhi";
+ PreparedStatement prep = conn.prepareStatement("select ?;");
+ prep.setBlob(1, new ByteArrayInputStream(name.getBytes()));
+ ResultSet rs = prep.executeQuery();
+ assertThat(prep.getUpdateCount()).isEqualTo(-1);
+ assertThat(rs.next()).isTrue();
+ assertThat(rs.getBytes(1)).isEqualTo(name.getBytes());
+ assertThat(rs.next()).isFalse();
+ rs.close();
+ }
+
@Test
public void finalizePrep() throws SQLException {
conn.prepareStatement("select null;");
=====================================
src/test/java/org/sqlite/RSMetaDataTest.java
=====================================
@@ -43,7 +43,12 @@ public class RSMetaDataTest {
@Test
public void catalogName() throws SQLException {
- assertThat(meta.getCatalogName(1)).isEqualTo("People");
+ assertThat(meta.getCatalogName(1)).isEqualTo("");
+ }
+
+ @Test
+ public void schemaName() throws SQLException {
+ assertThat(meta.getSchemaName(1)).isEqualTo("");
}
@Test
@@ -196,8 +201,8 @@ public class RSMetaDataTest {
}
@Test
- public void badCatalogIndex() {
- assertThatExceptionOfType(SQLException.class).isThrownBy(() -> meta.getCatalogName(4));
+ public void badTableIndex() {
+ assertThatExceptionOfType(SQLException.class).isThrownBy(() -> meta.getTableName(5));
}
@Test
=====================================
src/test/java/org/sqlite/util/OSInfoTest.java
=====================================
@@ -133,8 +133,8 @@ public class OSInfoTest {
}
@Nested
- @SetSystemProperty(key = "java.runtime.name", value = "Java for Android")
- @SetSystemProperty(key = "os.name", value = "Linux for Android")
+ @SetSystemProperty(key = "java.runtime.name", value = "Android Runtime")
+ @SetSystemProperty(key = "os.name", value = "Linux")
class AndroidRuntime {
@Test
=====================================
src/test/resources/META-INF/native-image/org.xerial/sqlite-jdbc/reachability-metadata.json
=====================================
@@ -0,0 +1,35 @@
+{
+ "comment": "New reachability metadata format introduced in GraalVM for JDK 23, this merges the other *-config.json files into one: https://www.graalvm.org/latest/reference-manual/native-image/metadata/",
+ "resources": [
+ {
+ "glob": "org/sqlite/*.jar"
+ },
+ {
+ "glob": "org/sqlite/*.db"
+ },
+ {
+ "module": "java.sql.rowset",
+ "glob": "javax/sql/rowset/rowset.properties"
+ }
+ ],
+ "bundles": [
+ {
+ "name": "com.sun.rowset.RowSetResourceBundle"
+ }
+ ],
+ "reflection": [
+ {
+ "type": "com.sun.rowset.providers.RIOptimisticProvider",
+ "methods": [
+ {
+ "name": "<init>",
+ "parameterTypes": []
+ }
+ ]
+ },
+ {
+ "type": "java.sql.Types",
+ "allPublicFields": true
+ }
+ ]
+}
View it on GitLab: https://salsa.debian.org/java-team/xerial-sqlite-jdbc/-/commit/fa4a925be5e204c198990da1e769b457a3cc95a8
--
View it on GitLab: https://salsa.debian.org/java-team/xerial-sqlite-jdbc/-/commit/fa4a925be5e204c198990da1e769b457a3cc95a8
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20250813/692478ab/attachment.htm>
More information about the pkg-java-commits
mailing list