├── .github └── workflows │ └── test.yml ├── .gitignore ├── .hgignore ├── .settings ├── org.eclipse.jdt.core.prefs ├── org.eclipse.ltk.core.refactoring.prefs └── org.eclipse.wst.validation.prefs ├── .travis.yml ├── CHANGELOG ├── LICENSE ├── LICENSE.zentus ├── Makefile ├── Makefile.common ├── NOTICE ├── README.md ├── README_BUILD.md ├── SQLiteJDBC.wiki ├── Usage.md ├── VERSION ├── amalgamation_version.sh ├── archive ├── nestedvm-2007-06-30.tgz ├── nestedvm-2009-08-09.tgz └── regex3.8a.tar.gz ├── demo ├── AppletDemo.jar ├── Sample.java └── applet-demo.html ├── docker ├── Dockerfile.alpine-linux_x86_64 ├── Dockerfile.linux_x86 ├── Dockerfile.linux_x86_64 ├── dockcross-android-arm ├── dockcross-android-arm64 ├── dockcross-android-x86 ├── dockcross-android-x86_64 ├── dockcross-arm64 ├── dockcross-armv5 ├── dockcross-armv6 ├── dockcross-armv7 ├── dockcross-armv7a ├── dockcross-ppc64 ├── dockcross-windows-arm64 ├── dockcross-windows-armv7 ├── dockcross-windows-x64 └── dockcross-windows-x86 ├── lib ├── inc_linux │ ├── jni.h │ └── jni_md.h ├── inc_mac │ ├── jni.h │ └── jni_md.h ├── inc_win │ ├── jni.h │ └── jni_md.h ├── jdbc-api-1.4.jar ├── jpassport-v0.5.0-alpha.jar ├── org │ └── sqlite │ │ ├── OSInfo.class │ │ └── util │ │ └── OSInfo.class └── sqlite-jdbc-panama-3.36.0.4-SNAPSHOT.jar ├── maven-eclipse.xml ├── pom.xml ├── scripts └── travis-deploy.sh ├── settings.xml └── src ├── main ├── ext │ └── extension-functions.c ├── java │ ├── module-info.java │ └── org │ │ └── sqlite │ │ ├── BusyHandler.java │ │ ├── Collation.java │ │ ├── ExtendedCommand.java │ │ ├── Function.java │ │ ├── JDBC.java │ │ ├── ProgressHandler.java │ │ ├── SQLiteCommitListener.java │ │ ├── SQLiteConfig.java │ │ ├── SQLiteConnection.java │ │ ├── SQLiteConnectionConfig.java │ │ ├── SQLiteDataSource.java │ │ ├── SQLiteErrorCode.java │ │ ├── SQLiteException.java │ │ ├── SQLiteJDBCLoader.java │ │ ├── SQLiteLimits.java │ │ ├── SQLiteOpenMode.java │ │ ├── SQLiteUpdateListener.java │ │ ├── core │ │ ├── Codes.java │ │ ├── CoreDatabaseMetaData.java │ │ ├── CorePreparedStatement.java │ │ ├── CoreResultSet.java │ │ ├── CoreStatement.java │ │ ├── DB.java │ │ ├── NativeDB.c │ │ ├── NativeDB.java │ │ ├── PanamaDBImpl.java │ │ └── panama │ │ │ ├── DBHandle.java │ │ │ ├── PanamaCallbacks.java │ │ │ ├── PanamaDB.java │ │ │ ├── PanamaDB_impl.java │ │ │ ├── PanamaFunction.java │ │ │ ├── PrepStmt.java │ │ │ └── ResultCode.java │ │ ├── date │ │ ├── DateFormatUtils.java │ │ ├── DateParser.java │ │ ├── DatePrinter.java │ │ ├── ExceptionUtils.java │ │ ├── FastDateFormat.java │ │ ├── FastDateParser.java │ │ ├── FastDatePrinter.java │ │ ├── FormatCache.java │ │ └── package-info.java │ │ ├── javax │ │ ├── SQLiteConnectionPoolDataSource.java │ │ └── SQLitePooledConnection.java │ │ ├── jdbc3 │ │ ├── JDBC3Connection.java │ │ ├── JDBC3DatabaseMetaData.java │ │ ├── JDBC3PreparedStatement.java │ │ ├── JDBC3ResultSet.java │ │ ├── JDBC3Savepoint.java │ │ └── JDBC3Statement.java │ │ ├── jdbc4 │ │ ├── JDBC4Connection.java │ │ ├── JDBC4DatabaseMetaData.java │ │ ├── JDBC4PooledConnection.java │ │ ├── JDBC4PreparedStatement.java │ │ ├── JDBC4ResultSet.java │ │ └── JDBC4Statement.java │ │ └── util │ │ ├── OSInfo.java │ │ ├── ProcessRunner.java │ │ ├── ResourceFinder.java │ │ └── StringUtils.java └── resources │ ├── META-INF │ └── native-image │ │ └── org.xerial │ │ └── sqlite-jdbc │ │ ├── jni-config.json │ │ ├── native-image.properties │ │ ├── reflect-config.json │ │ └── resource-config.json │ ├── java.sql.Driver │ ├── org │ └── sqlite │ │ └── native │ │ ├── FreeBSD │ │ ├── aarch64 │ │ │ └── libsqlitejdbc.so │ │ ├── x86 │ │ │ └── libsqlitejdbc.so │ │ └── x86_64 │ │ │ └── libsqlitejdbc.so │ │ ├── Linux-Musl │ │ └── x86_64 │ │ │ └── libsqlitejdbc.so │ │ ├── Linux │ │ ├── aarch64 │ │ │ └── libsqlitejdbc.so │ │ ├── arm │ │ │ └── libsqlitejdbc.so │ │ ├── armv6 │ │ │ └── libsqlitejdbc.so │ │ ├── armv7 │ │ │ └── libsqlitejdbc.so │ │ ├── ppc64 │ │ │ └── libsqlitejdbc.so │ │ ├── x86 │ │ │ └── libsqlitejdbc.so │ │ └── x86_64 │ │ │ └── libsqlite3.so │ │ ├── Mac │ │ ├── aarch64 │ │ │ └── libsqlitejdbc.jnilib │ │ └── x86_64 │ │ │ └── libsqlitejdbc.jnilib │ │ └── Windows │ │ ├── aarch64 │ │ └── sqlitejdbc.dll │ │ ├── armv7 │ │ └── sqlitejdbc.dll │ │ ├── x86 │ │ └── sqlite3.dll │ │ └── x86_64 │ │ └── sqlite3.dll │ └── sqlite-jdbc.properties └── test ├── java └── org │ └── sqlite │ ├── BackupTest.java │ ├── BusyHandlerTest.java │ ├── CollationTest.java │ ├── ConnectionTest.java │ ├── DBMetaDataTest.java │ ├── ErrorMessageTest.java │ ├── ExtendedCommandTest.java │ ├── ExtensionTest.java │ ├── FetchSizeTest.java │ ├── InsertQueryTest.java │ ├── JDBCTest.java │ ├── JSON1Test.java │ ├── ListenerTest.java │ ├── LoadDriver.java │ ├── MultipleClassLoaderTest.java │ ├── PrepStmtTest.java │ ├── ProgressHandlerTest.java │ ├── QueryTest.java │ ├── RSMetaDataTest.java │ ├── ReadUncommittedTest.java │ ├── ResultSetTest.java │ ├── SQLiteConfigTest.java │ ├── SQLiteConnectionPoolDataSourceTest.java │ ├── SQLiteDataSourceTest.java │ ├── SQLiteJDBCLoaderTest.java │ ├── SavepointTest.java │ ├── StatementTest.java │ ├── TransactionTest.java │ ├── TypeMapTest.java │ ├── UDFCustomErrorTest.java │ ├── UDFTest.java │ └── util │ └── OSInfoTest.java └── resources └── org └── sqlite ├── attach_test.db ├── sample.db └── testdb.jar /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - '**.java' 7 | - '**.xml' 8 | - '**.so' 9 | - '**.jnilib' 10 | - '**.dll' 11 | - '.github/workflows/*.yml' 12 | push: 13 | branches: 14 | - master 15 | paths: 16 | - '**.java' 17 | - '**.xml' 18 | - '**.so' 19 | - '**.jnilib' 20 | - '**.dll' 21 | - '.github/workflows/*.yml' 22 | 23 | jobs: 24 | lint: 25 | name: Check code formatting 26 | runs-on: ubuntu-latest 27 | steps: 28 | - uses: actions/checkout@v2 29 | - uses: actions/setup-java@v2 30 | with: 31 | distribution: 'adopt' 32 | java-version: 11 33 | java-package: jdk 34 | cache: 'maven' 35 | - name: spotless:check 36 | run: mvn spotless:check 37 | 38 | test: 39 | name: test ${{ matrix.os }} jdk${{ matrix.java }} 40 | strategy: 41 | matrix: 42 | os: [ ubuntu-latest, windows-latest, macos-latest ] 43 | java: [ 8, 11, 16 ] 44 | exclude: 45 | - os: windows-latest 46 | java: 11 47 | - os: windows-latest 48 | java: 8 49 | - os: macos-latest 50 | java: 11 51 | - os: macos-latest 52 | java: 8 53 | runs-on: ${{ matrix.os }} 54 | steps: 55 | - uses: actions/checkout@v2 56 | - uses: actions/setup-java@v2 57 | with: 58 | distribution: 'temurin' 59 | java-version: ${{ matrix.java }} 60 | java-package: jdk 61 | cache: 'maven' 62 | - name: Test 63 | run: mvn test 64 | 65 | test_graalvm: 66 | name: test ubuntu-latest jdk11 GraalVM native-image 67 | runs-on: ubuntu-latest 68 | steps: 69 | - uses: actions/checkout@v2 70 | - uses: DeLaGuardo/setup-graalvm@master 71 | with: 72 | # GraalVM version, no pattern syntax available atm 73 | graalvm: '21.0.0.2' 74 | # Java version, optional, defaults to 'java8'. Available options are 'java8' and 'java11'. 75 | java: 'java11' 76 | # Architecture flag, optional, defaults to 'amd64'. Available options are 'amd64' and 'aarch64'. Later is available only for linux runners. 77 | arch: 'amd64' 78 | - name: Install native-image component 79 | run: | 80 | gu install native-image 81 | - name: Test 82 | run: mvn -Pnative test 83 | 84 | test_multiarch: 85 | name: test ${{ matrix.arch }} ${{ matrix.distro }} jdk${{ matrix.java }} 86 | strategy: 87 | matrix: 88 | # armv6 cannot install the JDK properly via apt-get on Debian 89 | arch: [ armv7, aarch64 ] 90 | # no point adding Alpine, as we only have x86_64 binaries for it 91 | distro: [ ubuntu20.04 ] 92 | # cannot add Java 16, maven installed by apt-get is 3.6.x and does not support Java 16 93 | # use only java 11, so we don't run too many CI jobs 94 | java: [ 11 ] 95 | runs-on: ubuntu-latest 96 | steps: 97 | - uses: actions/checkout@v2 98 | - uses: uraimo/run-on-arch-action@v2.1.1 99 | name: Test 100 | with: 101 | arch: ${{ matrix.arch }} 102 | distro: ${{ matrix.distro }} 103 | 104 | # Not required, but speeds up builds 105 | githubToken: ${{ github.token }} 106 | 107 | # Install some dependencies in the container. This speeds up builds if 108 | # you are also using githubToken. Any dependencies installed here will 109 | # be part of the container image that gets cached, so subsequent 110 | # builds don't have to re-install them. The image layer is cached 111 | # publicly in your project's package repository, so it is vital that 112 | # no secrets are present in the container state or logs. 113 | install: | 114 | apt-get update -q -y 115 | apt-get install -q -y maven openjdk-${{ matrix.java }}-jdk 116 | 117 | # We use the Github Action user, 1001:121, so that maven can access 118 | # the /work directory and create target/classes 119 | dockerRunArgs: | 120 | --volume "${PWD}:/work" 121 | --user 1001:121 122 | 123 | run: | 124 | echo "Architecture: `uname -a`" 125 | mvn --version 126 | cd /work && mvn test 127 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | *~ 3 | sqlitejdbc/dl 4 | sqlitejdbc/build 5 | sqlitejdbc/nestedvm-* 6 | src/main/resources/org/ibex/nestedvm/*.o 7 | .idea 8 | *.iml 9 | atlassian-ide-plugin.xml 10 | .classpath 11 | .project 12 | .settings/ 13 | .DS_Store 14 | -------------------------------------------------------------------------------- /.hgignore: -------------------------------------------------------------------------------- 1 | target 2 | sqlitejdbc/build 3 | sqlitejdbc/dl 4 | sqlitejdbc/nestedvm-2009-08-09 5 | .classpath 6 | .project 7 | .idea 8 | 9 | syntax: glob 10 | src/main/resources/org/ibex/nestedvm/*.o 11 | *~ 12 | *.iml -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | #Thu Apr 28 10:35:24 JST 2011 2 | eclipse.preferences.version=1 3 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 4 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 5 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 6 | org.eclipse.jdt.core.compiler.compliance=1.8 7 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 8 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 9 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 10 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 11 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 12 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 13 | org.eclipse.jdt.core.compiler.source=1.8 14 | -------------------------------------------------------------------------------- /.settings/org.eclipse.ltk.core.refactoring.prefs: -------------------------------------------------------------------------------- 1 | #Mon Jan 19 11:25:47 GMT+09:00 2009 2 | eclipse.preferences.version=1 3 | org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false 4 | -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.validation.prefs: -------------------------------------------------------------------------------- 1 | #Mon Jan 19 11:25:47 GMT+09:00 2009 2 | DELEGATES_PREFERENCE=delegateValidatorList 3 | USER_BUILD_PREFERENCE=enabledBuildValidatorList 4 | USER_MANUAL_PREFERENCE=enabledManualValidatorList 5 | USER_PREFERENCE=overrideGlobalPreferencesfalse 6 | eclipse.preferences.version=1 7 | override=false 8 | suspend=false 9 | vf.version=3 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | os: linux 3 | dist: trusty 4 | 5 | services: 6 | - docker 7 | 8 | language: java 9 | 10 | jdk: 11 | # Unable to use openjdk6 https://github.com/travis-ci/travis-ci/issues/8199 12 | # - openjdk6 13 | # - openjdk7 14 | - oraclejdk8 15 | 16 | script: 17 | - ./scripts/travis-deploy.sh 18 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | Work in progress: 2 | 3 | * Issue #107 - DatabaseMetaData.getPrimaryKeys does not always return all primary keys for multi-line table definitions. 4 | * Issue #109 - SQLiteConfig ignores calls to setDateStringFormat/setDateClass/setDatePrecision. 5 | * Issue #116 - Move to Java 6 6 | * Created new branch refactor/JDBC4 7 | * Jar is packaged as sqlite-jdbc4* 8 | * Issue #65 - Calling Statement.setMaxRows(N) has the effect of returning N+1 rows 9 | * Issue #64 - ArrayIndexOutOfBoundsException when calling ResultSetMetaData.getScale() for VARCHAR column types 10 | * Issue #56 - Implement getBinaryStream() in RS.java 11 | * Issue #45 - Stmt.close() should not close metadata 12 | * Issue #49 - PreparedStatement.getUpdateCount should return -1 if the current result is a ResultSet or no more results exist 13 | * Issue #48 - PreparedStatement.getResultSet should return null if current result is an update 14 | * Issue #67 - Bad ResultSet returned from DatabaseMetaData.getColumns(), if a given table doesn't exist 15 | * Issue #73 - DatabaseMetaData.getTables() Memory Leak 16 | * Issue #68 - DatabaseMetaData.getTables() erroneously returns INDEX, TRIGGER, and other non-table objects 17 | * Issue #53 - getImportedKeys throws Null Exception for foreign key without explicit primary column name 18 | * Issue #18 - Add support for ConnectionPool 19 | * Implemented javax.sql.ConnectionPoolDataSource - javax.SQLiteConnectionPoolDataSource 20 | * Issue #27 - Allow user to specify busy-timeout when opening a database connection 21 | * Added support for sqlite3_busy_timeout 22 | 1. Added configuration property "busy_timeout" to SQLiteConfig. 23 | 2. Exposed setBusyTimeout and getBusyTimeout on SQLiteConnection. 24 | 3. Default busy_timeout of 3 seconds (3000ms) remains the same. 25 | * Issue #60 - ExtendedCommand (e.g backup) not supported on Stmt.execute(String) 26 | * Issue #23 - getDate() returns wrong values 27 | * Added support for specifying a date storage class. For more info 28 | * Issue #54 - Implement PreparedStatement.setBinaryStream() 29 | * Added support for InputStreams on PreparedStatement 30 | 1. setBinaryStream() 31 | 2. setAsciiStream() 32 | 3. setUnicodeStream() 33 | * Issue #60 - ExtendedCommand (e.g backup) not supported on Stmt.execute(String) 34 | * Issue #23 - getDate() returns wrong values 35 | * Added support for specifying a date storage class. For more info 36 | * Issue #54 - Implement PreparedStatement.setBinaryStream() 37 | * Added support for InputStreams on PreparedStatement 38 | 1. setBinaryStream() 39 | 2. setAsciiStream() 40 | 3. setUnicodeStream() 41 | 42 | Release 3.7.15-SNAPSHOT-2 43 | * Fixed clean target to remove previous driver builds 44 | * Issue #42 - Using shared in-memory with URI filename 45 | * Added support for URI filenames 46 | 1. examples 47 | * Issue #47 - MetaData.getExportedKeys() returns empty string for a named foreign key 48 | * Issue #46 - org.sqlite.MetaData.getExportedKeys constructs incorrect SQL 49 | * Issue #44 - getExportedKeys throws Null Exception for foreign key without explicit primary column name 50 | 1. Now returns keys for foreign key definitions like "create table referring (id, foreign key references referred)" 51 | * Implemented getPercision(int) and getScale(int) on ResultSetMetaData. 52 | * Issue #43 - ResultSetMetaData does not return the SQL Type if there are no results from the query. 53 | 1. ResultSetMetaData.getColumnTypeName() now gets type from either 'create table' statement or CAST(expr AS TYPE) otherwise sqlite3_value_type. 54 | 2. ResultSetMetaData.getColumnType() now parses the result from getColumnTypeName() to return a type. 55 | 3. Driver recognizes the types listed at under 'Affinity Name Examples'. 56 | * Issue #36 - Fixed case where a calling PreparedStatement.clearParameters() after a ResultSet is opened, caused subsequent calls to the ResultSet to return null. 57 | 1. PreparedStatement.clearParameters() now uses sqlite3_clear_bindings instead of sqlite3_reset. 58 | 2. PreparedStatement.clearParameters() does not reset current ResultSet. 59 | 3. PreparedStatement now checks if value(s) are bound to the statement parameters before executing; Throwing an exception if they are not. 60 | * Issue #40 - Fixed case where a call to Statement.getGeneratedKeys() could lead to "database is locked" error. 61 | 1. Calling Statement.Close() on a Statement on which getGeneratedKeys() was called, now releases all resources properly. 62 | * Issue #33 - Fixed Statement.cancel() to work when called from another thread 63 | 64 | Release 3.7.15-SNAPSHOT 65 | * Issue #10 - Dropped pure java support 66 | * Issue #22 - Fixed DatabaseMetaData.supportsGetGeneratedKeys to return true since it's already supported 67 | * Issue #17 - Enabled Statement.setEscapeProcessing(boolean) method so driver can be used in Ant tasks 68 | * Issue #20 - Fixed MetaData.getExportedKeys() to return all foreign keys. 69 | * Issue #14 - Fixed DatabaseMetaData.getColumns() resultSet to populate COLUMN_DEF with column default values. 70 | * Fixed Statement.close() so that calling it is a no-op on a closed connection. 71 | * Issue #13- Added support for Java Standard Edition Service Provider mechanism 72 | * Issue #12 - Fixed MetaData.getColumns() to return "YES" or "NO" for IS_NULLABLE column 73 | * Issue #16 - Fixed Statement.executeUpdate() to return 0 for DDL and more accurate changes for DML. (Added sqlite3_total_changes to native library) 74 | * Issue #15 - Modified Connection.setReadOnly(boolean) to throw an Exception if readOnly mode is modified after opening a connection 75 | * Changed driver to include architecture name in temporary filename in order to avoid conflicts when multiple JVMs with different architectures running at the same time 76 | * Issue #11 - Enhanced MetaData.getPrimaryKeys(): 77 | 1. Return named primary keys and correct key sequence. 78 | 2. Also result set is ordered by column name as per JDBC spec. 79 | * Issue #1 - Added support for WAL JournalMode. 80 | * Issue #4 - Enhanced SQLiteDataSource, SQLiteConfig and Conn to enable setting the transaction mode. 81 | * Issue #5 - Fixed NativeDB.c errors when compiling with Visual Studio 2010. 82 | * Issue #2 - Fixed issue where SQLiteDataSource: setEncoding not working. And also enabled using UTF-8, UTF-16, UTF-16le, and UTF-16be. 83 | -------------------------------------------------------------------------------- /LICENSE.zentus: -------------------------------------------------------------------------------- 1 | Copyright (c) 2006, David Crawshaw. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions 5 | are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 17 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 | SUCH DAMAGE. 24 | 25 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | This product includes the following softwares developed by David Crawshaw. 2 | See LICENSE.zentus file. 3 | 4 | And also, NestedVM (Apache License Version 2.0) is used inside sqlite- -------------------------------------------------------------------------------- /README_BUILD.md: -------------------------------------------------------------------------------- 1 | How to compile a new version of SQLiteJDBC 2 | =========================================== 3 | Prerequisites 4 | ------------- 5 | 1. JDK 1.5 6 | 2. Perl 7 | 3. Maven 8 | 4. make 9 | 5. gcc 10 | 6. curl 11 | 7. unzip 12 | 13 | Build 14 | ----- 15 | 1. Edit the `VERSION` file and set the SQLite version to use. 16 | 2. Edit the version number in `pom.xml` to match `VERSION`. 17 | 3. Then, run: 18 | 19 | $ make 20 | 21 | 22 | How to submit a patch 23 | ===================== 24 | GitHub Pull Request 25 | ---------------------- 26 | 1. Fork this project on GitHub 27 | 2. (make some change) 28 | 3. `git commit -m 'what changes are made to the source'` 29 | 4. `git push` 30 | 5. Create a pull request 31 | 32 | Patch file 33 | ---------- 34 | 1. Create a new issue on 35 | 2. Attach a patch file to issue 36 | 37 | 38 | How to build Win64 native library 39 | ================================= 40 | * Install cygwin with make, curl, unzip, and mingw64-x86_64-gcc-core 41 | * (You can install MinGW64 ) 42 | 43 | * After the installation, make sure your PATH environment variable 44 | points to `/usr/bin` before `/bin`. 45 | 46 | Here is the excerpt from 47 | 48 | The mingw-w64 toolchain has been officially added to Cygwin mirrors, 49 | you can find the basic C toolchain as mingw64-x86_64-gcc-core. The 50 | languages enabled are C, Ada, C++, Fortran, Object C and Objective 51 | C++. There is a known caveat where calling the compiler directly as 52 | "/bin/x86_64-w64-mingw32-gcc" will fail, use 53 | "/usr/bin/x86_64-w64-mingw32-gcc" instead and make sure that your PATH 54 | variable has "/usr/bin" before "/bin". 55 | 56 | * Instead, you can explicitly set the compiler: 57 | $ make native Windows-amd64_CC=/usr/bin/x86_64-w64-mingw32-gcc 58 | 59 | * Then, do 60 | $ make native 61 | 62 | How to build arm binary for Rapsberry Pi 63 | ============================== 64 | * Install docker 65 | * Run 66 | $ make linux-arm 67 | $ make linux-armhf 68 | 69 | How to build pure-java library 70 | ============================== 71 | ***The pure-java library is no longer supported as of version 3.7.15. 72 | *** 73 | 74 | * Use Mac OS X or Linux with gcc-3.x 75 | 76 | make purejava 77 | 78 | * The build will fail due to the broken regex libray, so copy the non-corrupted 79 | archive I downloaded: 80 | 81 | $ cp archive/regex3.8a.tar.gz target/build/nestedvm-2009-08-09/upstream/downlolad/ 82 | 83 | * then do 84 | 85 | 'make purejava' 86 | 87 | 88 | (for deployer only) How to build pure-java and native libraries 89 | =============================================================== 90 | make -fMakefile.package 91 | 92 | How to deploy to the maven repository 93 | ===================================== 94 | mvn deploy 95 | mvn deploy -Psourceforge 96 | (for uploading Sourceforge.jp repository, which are synchronized with the Maven 97 | central repository) 98 | -------------------------------------------------------------------------------- /SQLiteJDBC.wiki: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/SQLiteJDBC.wiki -------------------------------------------------------------------------------- /Usage.md: -------------------------------------------------------------------------------- 1 | ## How to Specify Database Files ## 2 | 3 | Here is an example to establishing a connection to a database file `C:\work\mydatabase.db` (in Windows) 4 | 5 | ```java 6 | Connection connection = DriverManager.getConnection("jdbc:sqlite:C:/work/mydatabase.db"); 7 | ``` 8 | 9 | Opening a UNIX (Linux, Mac OS X, etc.) file `/home/leo/work/mydatabase.db` 10 | ```java 11 | Connection connection = DriverManager.getConnection("jdbc:sqlite:/home/leo/work/mydatabase.db"); 12 | ``` 13 | 14 | ## How to Use Memory Databases ## 15 | 16 | SQLite supports on-memory database management, which does not create any database files. To use a memory database in your Java code, get the database connection as follows: 17 | 18 | 19 | ```java 20 | Connection connection = DriverManager.getConnection("jdbc:sqlite::memory:"); 21 | ``` 22 | 23 | And also, you can create memory database as follows: 24 | ```java 25 | Connection connection = DriverManager.getConnection("jdbc:sqlite:"); 26 | ``` 27 | 28 | ## How to use Online Backup and Restore Feature ## 29 | 30 | Take a backup of the whole database to `backup.db` file: 31 | 32 | 33 | ```java 34 | 35 | // Create a memory database 36 | Connection conn = DriverManager.getConnection("jdbc:sqlite:"); 37 | Statement stmt = conn.createStatement(); 38 | // Do some updates 39 | stmt.executeUpdate("create table sample(id, name)"); 40 | stmt.executeUpdate("insert into sample values(1, \"leo\")"); 41 | stmt.executeUpdate("insert into sample values(2, \"yui\")"); 42 | // Dump the database contents to a file 43 | stmt.executeUpdate("backup to backup.db"); 44 | 45 | ``` 46 | 47 | Restore the database from a backup file: 48 | 49 | ```java 50 | 51 | // Create a memory database 52 | Connection conn = DriverManager.getConnection("jdbc:sqlite:"); 53 | // Restore the database from a backup file 54 | Statement stat = conn.createStatement(); 55 | stat.executeUpdate("restore from backup.db"); 56 | 57 | ``` 58 | 59 | ## Creating BLOB data ## 60 | 61 | 1. Create a table with a column of blob type: `create table T (id integer, data blob)` 62 | 1. Create a prepared statement with `?` symbol: `insert into T values(1, ?)` 63 | 1. Prepare a blob data in byte array (e.g., `byte[] data = ...`) 64 | 1. `preparedStatement.setBytes(1, data)` 65 | 1. `preparedStatement.execute()...` 66 | 67 | ## Reading Database Files in classpaths or network (read-only) ## 68 | 69 | To load db files that can be found from the class loader (e.g., db 70 | files inside a jar file in the classpath), 71 | use `jdbc:sqlite::resource:` prefix. 72 | 73 | For example, here is an example to access an SQLite DB file, `sample.db` 74 | in a Java package `org.yourdomain`: 75 | 76 | 77 | ```java 78 | 79 | Connection conn = DriverManager.getConnection("jdbc:sqlite::resource:org/yourdomain/sample.db"); 80 | 81 | ``` 82 | 83 | In addition, external DB resources can be used as follows: 84 | 85 | 86 | ```java 87 | 88 | Connection conn = DriverManager.getConnection("jdbc:sqlite::resource:http://www.xerial.org/svn/project/XerialJ/trunk/sqlite-jdbc/src/test/java/org/sqlite/sample.db"); 89 | 90 | ``` 91 | 92 | To access db files inside some specific jar file (in local or remote), 93 | use the [JAR URL](http://java.sun.com/j2se/1.5.0/docs/api/java/net/JarURLConnection.html): 94 | 95 | 96 | ```java 97 | 98 | Connection conn = DriverManager.getConnection("jdbc:sqlite::resource:jar:http://www.xerial.org/svn/project/XerialJ/trunk/sqlite-jdbc/src/test/resources/testdb.jar!/sample.db"); 99 | 100 | ``` 101 | 102 | DB files will be extracted to a temporary folder specified in `System.getProperty("java.io.tmpdir")`. 103 | 104 | ## Configure Connections # 105 | 106 | 107 | ```java 108 | 109 | SQLiteConfig config = new SQLiteConfig(); 110 | // config.setReadOnly(true); 111 | config.setSharedCache(true); 112 | config.recursiveTriggers(true); 113 | // ... other configuration can be set via SQLiteConfig object 114 | Connection conn = DriverManager.getConnection("jdbc:sqlite:sample.db", config.toProperties()); 115 | ``` 116 | 117 | ## How to Use Encrypted Databases ## 118 | 119 | *__Important: xerial/sqlite-jdbc does not support encryption out of the box, you need a special .dll/.so__* 120 | 121 | SQLite support encryption of the database via special drivers and a key. To use an encrypted database you need a driver which supports encrypted database via `pragma key` or `pragma hexkey`, e.g. SQLite SSE or SQLCipher. You need to specify those drivers via directly referencing the .dll/.so through: 122 | 123 | ``` 124 | -Dorg.sqlite.lib.path=. 125 | -Dorg.sqlite.lib.name=sqlite_cryption_support.dll 126 | ``` 127 | 128 | Now the only need to specify the password is via: 129 | ```java 130 | Connection connection = DriverManager.getConnection("jdbc:sqlite:db.sqlite", "", "password"); 131 | ``` 132 | ### Binary Passphrase 133 | If you need to provide the password in binary form, you have to specify how the provided .dll/.so needs it. There are two different modes available: 134 | 135 | #### SSE: 136 | The binary password is provided via `pragma hexkey='AE...'` 137 | 138 | #### SQLCipher: 139 | The binary password is provided via `pragma key="x'AE...'"` 140 | 141 | You set the mode at the connectionstring level: 142 | ```java 143 | Connection connection = DriverManager.getConnection("jdbc:sqlite:db.sqlite?hexkey_mode=sse", "", "AE..."); 144 | ``` 145 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | version=3.36.0 2 | 3 | 4 | -------------------------------------------------------------------------------- /amalgamation_version.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Used to generate the version for the amalgamation download zip. 3 | # http://www.sqlite.org/download.html#encoding 4 | # The version is encoded so that filenames sort in order of increasing version number when viewed using "ls". 5 | # For version 3.X.Y the filename encoding is 3XXYY00. For branch version 3.X.Y.Z, the encoding is 3XXYYZZ. 6 | version="" 7 | i=0 8 | export IFS="." 9 | for num in $1; do 10 | if [ $i -gt 0 ]; then 11 | if [ $num -le 9 ]; then 12 | eval num=0$num 13 | fi 14 | fi 15 | eval version=$version$num 16 | let i+=1 17 | done 18 | unset IFS 19 | if [ $i -gt 3 ]; then 20 | echo "$version" 21 | else 22 | echo "$version"00 23 | fi 24 | -------------------------------------------------------------------------------- /archive/nestedvm-2007-06-30.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/archive/nestedvm-2007-06-30.tgz -------------------------------------------------------------------------------- /archive/nestedvm-2009-08-09.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/archive/nestedvm-2009-08-09.tgz -------------------------------------------------------------------------------- /archive/regex3.8a.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/archive/regex3.8a.tar.gz -------------------------------------------------------------------------------- /demo/AppletDemo.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/demo/AppletDemo.jar -------------------------------------------------------------------------------- /demo/Sample.java: -------------------------------------------------------------------------------- 1 | import java.sql.Connection; 2 | import java.sql.DriverManager; 3 | import java.sql.ResultSet; 4 | import java.sql.SQLException; 5 | import java.sql.Statement; 6 | 7 | public class Sample 8 | { 9 | public static void main(String[] args) 10 | { 11 | Connection connection = null; 12 | try 13 | { 14 | // create a database connection 15 | connection = DriverManager.getConnection("jdbc:sqlite:sample.db"); 16 | Statement statement = connection.createStatement(); 17 | statement.setQueryTimeout(30); // set timeout to 30 sec. 18 | 19 | statement.executeUpdate("drop table if exists person"); 20 | statement.executeUpdate("create table person (id integer, name string)"); 21 | statement.executeUpdate("insert into person values(1, 'leo')"); 22 | statement.executeUpdate("insert into person values(2, 'yui')"); 23 | ResultSet rs = statement.executeQuery("select * from person"); 24 | while(rs.next()) 25 | { 26 | // read the result set 27 | System.out.println("name = " + rs.getString("name")); 28 | System.out.println("id = " + rs.getInt("id")); 29 | } 30 | } 31 | catch(SQLException e) 32 | { 33 | // if the error message is "out of memory", 34 | // it probably means no database file is found 35 | System.err.println(e.getMessage()); 36 | } 37 | finally 38 | { 39 | try 40 | { 41 | if(connection != null) 42 | connection.close(); 43 | } 44 | catch(SQLException e) 45 | { 46 | // connection close failed. 47 | System.err.println(e); 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /demo/applet-demo.html: -------------------------------------------------------------------------------- 1 | 2 | Applet Demo 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /docker/Dockerfile.alpine-linux_x86_64: -------------------------------------------------------------------------------- 1 | FROM alpine:3.11 2 | MAINTAINER Taro L. Saito 3 | 4 | RUN apk --update add bash gcc make perl libc-dev 5 | 6 | WORKDIR /work 7 | -------------------------------------------------------------------------------- /docker/Dockerfile.linux_x86: -------------------------------------------------------------------------------- 1 | FROM centos:5 2 | MAINTAINER Taro L. Saito 3 | 4 | RUN yum -y install gcc glibc-devel.i386 make perl 5 | 6 | WORKDIR /work 7 | -------------------------------------------------------------------------------- /docker/Dockerfile.linux_x86_64: -------------------------------------------------------------------------------- 1 | FROM centos:5 2 | MAINTAINER Taro L. Saito 3 | 4 | RUN yum -y install gcc make perl 5 | 6 | WORKDIR /work 7 | -------------------------------------------------------------------------------- /docker/dockcross-windows-x64: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | DEFAULT_DOCKCROSS_IMAGE=dockcross/windows-x64:latest 4 | 5 | #------------------------------------------------------------------------------ 6 | # Helpers 7 | # 8 | err() { 9 | echo -e >&2 ERROR: $@\\n 10 | } 11 | 12 | die() { 13 | err $@ 14 | exit 1 15 | } 16 | 17 | has() { 18 | # eg. has command update 19 | local kind=$1 20 | local name=$2 21 | 22 | type -t $kind:$name | grep -q function 23 | } 24 | 25 | #------------------------------------------------------------------------------ 26 | # Command handlers 27 | # 28 | command:update-image() { 29 | docker pull $FINAL_IMAGE 30 | } 31 | 32 | help:update-image() { 33 | echo Pull the latest $FINAL_IMAGE . 34 | } 35 | 36 | command:update-script() { 37 | if cmp -s <( docker run --rm $FINAL_IMAGE ) $0; then 38 | echo $0 is up to date 39 | else 40 | echo -n Updating $0 '... ' 41 | docker run --rm $FINAL_IMAGE > $0 && echo ok 42 | fi 43 | } 44 | 45 | help:update-image() { 46 | echo Update $0 from $FINAL_IMAGE . 47 | } 48 | 49 | command:update() { 50 | command:update-image 51 | command:update-script 52 | } 53 | 54 | help:update() { 55 | echo Pull the latest $FINAL_IMAGE, and then update $0 from that. 56 | } 57 | 58 | command:help() { 59 | if [[ $# != 0 ]]; then 60 | if ! has command $1; then 61 | err \"$1\" is not an dockcross command 62 | command:help 63 | elif ! has help $1; then 64 | err No help found for \"$1\" 65 | else 66 | help:$1 67 | fi 68 | else 69 | cat >&2 < 88 | ENDHELP 89 | exit 1 90 | fi 91 | } 92 | 93 | #------------------------------------------------------------------------------ 94 | # Option processing 95 | # 96 | special_update_command='' 97 | while [[ $# != 0 ]]; do 98 | case $1 in 99 | 100 | --) 101 | shift 102 | break 103 | ;; 104 | 105 | --args|-a) 106 | ARG_ARGS="$2" 107 | shift 2 108 | ;; 109 | 110 | --config|-c) 111 | ARG_CONFIG="$2" 112 | shift 2 113 | ;; 114 | 115 | --image|-i) 116 | ARG_IMAGE="$2" 117 | shift 2 118 | ;; 119 | update|update-image|update-script) 120 | special_update_command=$1 121 | break 122 | ;; 123 | -*) 124 | err Unknown option \"$1\" 125 | command:help 126 | exit 127 | ;; 128 | 129 | *) 130 | break 131 | ;; 132 | 133 | esac 134 | done 135 | 136 | # The precedence for options is: 137 | # 1. command-line arguments 138 | # 2. environment variables 139 | # 3. defaults 140 | 141 | # Source the config file if it exists 142 | DEFAULT_DOCKCROSS_CONFIG=~/.dockcross 143 | FINAL_CONFIG=${ARG_CONFIG-${DOCKCROSS_CONFIG-$DEFAULT_DOCKCROSS_CONFIG}} 144 | 145 | [[ -f "$FINAL_CONFIG" ]] && source "$FINAL_CONFIG" 146 | 147 | # Set the docker image 148 | FINAL_IMAGE=${ARG_IMAGE-${DOCKCROSS_IMAGE-$DEFAULT_DOCKCROSS_IMAGE}} 149 | 150 | # Handle special update command 151 | if [ "$special_update_command" != "" ]; then 152 | case $special_update_command in 153 | 154 | update) 155 | command:update 156 | exit $? 157 | ;; 158 | 159 | update-image) 160 | command:update-image 161 | exit $? 162 | ;; 163 | 164 | update-script) 165 | command:update-script 166 | exit $? 167 | ;; 168 | 169 | esac 170 | fi 171 | 172 | # Set the docker run extra args (if any) 173 | FINAL_ARGS=${ARG_ARGS-${DOCKCROSS_ARGS}} 174 | 175 | # Bash on Ubuntu on Windows 176 | UBUNTU_ON_WINDOWS=$([ -e /proc/version ] && grep -l Microsoft /proc/version || echo "") 177 | # MSYS, Git Bash, etc. 178 | MSYS=$([ -e /proc/version ] && grep -l MINGW /proc/version || echo "") 179 | 180 | if [ -z "$UBUNTU_ON_WINDOWS" -a -z "$MSYS" ]; then 181 | USER_IDS=(-e BUILDER_UID="$( id -u )" -e BUILDER_GID="$( id -g )" -e BUILDER_USER="$( id -un )" -e BUILDER_GROUP="$( id -gn )") 182 | fi 183 | 184 | # Change the PWD when working in Docker on Windows 185 | if [ -n "$UBUNTU_ON_WINDOWS" ]; then 186 | WSL_ROOT="/mnt/" 187 | CFG_FILE=/etc/wsl.conf 188 | if [ -f "$CFG_FILE" ]; then 189 | CFG_CONTENT=$(cat $CFG_FILE | sed -r '/[^=]+=[^=]+/!d' | sed -r 's/\s+=\s/=/g') 190 | eval "$CFG_CONTENT" 191 | if [ -n "$root" ]; then 192 | WSL_ROOT=$root 193 | fi 194 | fi 195 | HOST_PWD=`pwd -P` 196 | HOST_PWD=${HOST_PWD/$WSL_ROOT//} 197 | elif [ -n "$MSYS" ]; then 198 | HOST_PWD=$PWD 199 | HOST_PWD=${HOST_PWD/\//} 200 | HOST_PWD=${HOST_PWD/\//:\/} 201 | else 202 | HOST_PWD=$PWD 203 | fi 204 | 205 | # Mount Additional Volumes 206 | if [ -z "$SSH_DIR" ]; then 207 | SSH_DIR="$HOME/.ssh" 208 | fi 209 | 210 | HOST_VOLUMES= 211 | if [ -e "$SSH_DIR" ]; then 212 | HOST_VOLUMES+="-v $SSH_DIR:/home/$(id -un)/.ssh" 213 | fi 214 | 215 | #------------------------------------------------------------------------------ 216 | # Now, finally, run the command in a container 217 | # 218 | tty -s && TTY_ARGS=-ti || TTY_ARGS= 219 | CONTAINER_NAME=dockcross_$RANDOM 220 | docker run $TTY_ARGS --name $CONTAINER_NAME \ 221 | -v "$HOST_PWD":/work \ 222 | $HOST_VOLUMES \ 223 | "${USER_IDS[@]}" \ 224 | $FINAL_ARGS \ 225 | $FINAL_IMAGE "$@" 226 | run_exit_code=$? 227 | 228 | # Attempt to delete container 229 | rm_output=$(docker rm -f $CONTAINER_NAME 2>&1) 230 | rm_exit_code=$? 231 | if [[ $rm_exit_code != 0 ]]; then 232 | if [[ "$CIRCLECI" == "true" ]] && [[ $rm_output == *"Driver btrfs failed to remove"* ]]; then 233 | : # Ignore error because of https://circleci.com/docs/docker-btrfs-error/ 234 | else 235 | echo "$rm_output" 236 | exit $rm_exit_code 237 | fi 238 | fi 239 | 240 | exit $run_exit_code 241 | 242 | ################################################################################ 243 | # 244 | # This image is not intended to be run manually. 245 | # 246 | # To create a dockcross helper script for the 247 | # dockcross/windows-x64:latest image, run: 248 | # 249 | # docker run --rm dockcross/windows-x64:latest > dockcross-windows-x64-latest 250 | # chmod +x dockcross-windows-x64-latest 251 | # 252 | # You may then wish to move the dockcross script to your PATH. 253 | # 254 | ################################################################################ 255 | -------------------------------------------------------------------------------- /docker/dockcross-windows-x86: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | DEFAULT_DOCKCROSS_IMAGE=dockcross/windows-x86:latest 4 | 5 | #------------------------------------------------------------------------------ 6 | # Helpers 7 | # 8 | err() { 9 | echo -e >&2 ERROR: $@\\n 10 | } 11 | 12 | die() { 13 | err $@ 14 | exit 1 15 | } 16 | 17 | has() { 18 | # eg. has command update 19 | local kind=$1 20 | local name=$2 21 | 22 | type -t $kind:$name | grep -q function 23 | } 24 | 25 | #------------------------------------------------------------------------------ 26 | # Command handlers 27 | # 28 | command:update-image() { 29 | docker pull $FINAL_IMAGE 30 | } 31 | 32 | help:update-image() { 33 | echo Pull the latest $FINAL_IMAGE . 34 | } 35 | 36 | command:update-script() { 37 | if cmp -s <( docker run --rm $FINAL_IMAGE ) $0; then 38 | echo $0 is up to date 39 | else 40 | echo -n Updating $0 '... ' 41 | docker run --rm $FINAL_IMAGE > $0 && echo ok 42 | fi 43 | } 44 | 45 | help:update-image() { 46 | echo Update $0 from $FINAL_IMAGE . 47 | } 48 | 49 | command:update() { 50 | command:update-image 51 | command:update-script 52 | } 53 | 54 | help:update() { 55 | echo Pull the latest $FINAL_IMAGE, and then update $0 from that. 56 | } 57 | 58 | command:help() { 59 | if [[ $# != 0 ]]; then 60 | if ! has command $1; then 61 | err \"$1\" is not an dockcross command 62 | command:help 63 | elif ! has help $1; then 64 | err No help found for \"$1\" 65 | else 66 | help:$1 67 | fi 68 | else 69 | cat >&2 < 88 | ENDHELP 89 | exit 1 90 | fi 91 | } 92 | 93 | #------------------------------------------------------------------------------ 94 | # Option processing 95 | # 96 | special_update_command='' 97 | while [[ $# != 0 ]]; do 98 | case $1 in 99 | 100 | --) 101 | shift 102 | break 103 | ;; 104 | 105 | --args|-a) 106 | ARG_ARGS="$2" 107 | shift 2 108 | ;; 109 | 110 | --config|-c) 111 | ARG_CONFIG="$2" 112 | shift 2 113 | ;; 114 | 115 | --image|-i) 116 | ARG_IMAGE="$2" 117 | shift 2 118 | ;; 119 | update|update-image|update-script) 120 | special_update_command=$1 121 | break 122 | ;; 123 | -*) 124 | err Unknown option \"$1\" 125 | command:help 126 | exit 127 | ;; 128 | 129 | *) 130 | break 131 | ;; 132 | 133 | esac 134 | done 135 | 136 | # The precedence for options is: 137 | # 1. command-line arguments 138 | # 2. environment variables 139 | # 3. defaults 140 | 141 | # Source the config file if it exists 142 | DEFAULT_DOCKCROSS_CONFIG=~/.dockcross 143 | FINAL_CONFIG=${ARG_CONFIG-${DOCKCROSS_CONFIG-$DEFAULT_DOCKCROSS_CONFIG}} 144 | 145 | [[ -f "$FINAL_CONFIG" ]] && source "$FINAL_CONFIG" 146 | 147 | # Set the docker image 148 | FINAL_IMAGE=${ARG_IMAGE-${DOCKCROSS_IMAGE-$DEFAULT_DOCKCROSS_IMAGE}} 149 | 150 | # Handle special update command 151 | if [ "$special_update_command" != "" ]; then 152 | case $special_update_command in 153 | 154 | update) 155 | command:update 156 | exit $? 157 | ;; 158 | 159 | update-image) 160 | command:update-image 161 | exit $? 162 | ;; 163 | 164 | update-script) 165 | command:update-script 166 | exit $? 167 | ;; 168 | 169 | esac 170 | fi 171 | 172 | # Set the docker run extra args (if any) 173 | FINAL_ARGS=${ARG_ARGS-${DOCKCROSS_ARGS}} 174 | 175 | # Bash on Ubuntu on Windows 176 | UBUNTU_ON_WINDOWS=$([ -e /proc/version ] && grep -l Microsoft /proc/version || echo "") 177 | # MSYS, Git Bash, etc. 178 | MSYS=$([ -e /proc/version ] && grep -l MINGW /proc/version || echo "") 179 | 180 | if [ -z "$UBUNTU_ON_WINDOWS" -a -z "$MSYS" ]; then 181 | USER_IDS=(-e BUILDER_UID="$( id -u )" -e BUILDER_GID="$( id -g )" -e BUILDER_USER="$( id -un )" -e BUILDER_GROUP="$( id -gn )") 182 | fi 183 | 184 | # Change the PWD when working in Docker on Windows 185 | if [ -n "$UBUNTU_ON_WINDOWS" ]; then 186 | WSL_ROOT="/mnt/" 187 | CFG_FILE=/etc/wsl.conf 188 | if [ -f "$CFG_FILE" ]; then 189 | CFG_CONTENT=$(cat $CFG_FILE | sed -r '/[^=]+=[^=]+/!d' | sed -r 's/\s+=\s/=/g') 190 | eval "$CFG_CONTENT" 191 | if [ -n "$root" ]; then 192 | WSL_ROOT=$root 193 | fi 194 | fi 195 | HOST_PWD=`pwd -P` 196 | HOST_PWD=${HOST_PWD/$WSL_ROOT//} 197 | elif [ -n "$MSYS" ]; then 198 | HOST_PWD=$PWD 199 | HOST_PWD=${HOST_PWD/\//} 200 | HOST_PWD=${HOST_PWD/\//:\/} 201 | else 202 | HOST_PWD=$PWD 203 | fi 204 | 205 | # Mount Additional Volumes 206 | if [ -z "$SSH_DIR" ]; then 207 | SSH_DIR="$HOME/.ssh" 208 | fi 209 | 210 | HOST_VOLUMES= 211 | if [ -e "$SSH_DIR" ]; then 212 | HOST_VOLUMES+="-v $SSH_DIR:/home/$(id -un)/.ssh" 213 | fi 214 | 215 | #------------------------------------------------------------------------------ 216 | # Now, finally, run the command in a container 217 | # 218 | tty -s && TTY_ARGS=-ti || TTY_ARGS= 219 | CONTAINER_NAME=dockcross_$RANDOM 220 | docker run $TTY_ARGS --name $CONTAINER_NAME \ 221 | -v "$HOST_PWD":/work \ 222 | $HOST_VOLUMES \ 223 | "${USER_IDS[@]}" \ 224 | $FINAL_ARGS \ 225 | $FINAL_IMAGE "$@" 226 | run_exit_code=$? 227 | 228 | # Attempt to delete container 229 | rm_output=$(docker rm -f $CONTAINER_NAME 2>&1) 230 | rm_exit_code=$? 231 | if [[ $rm_exit_code != 0 ]]; then 232 | if [[ "$CIRCLECI" == "true" ]] && [[ $rm_output == *"Driver btrfs failed to remove"* ]]; then 233 | : # Ignore error because of https://circleci.com/docs/docker-btrfs-error/ 234 | else 235 | echo "$rm_output" 236 | exit $rm_exit_code 237 | fi 238 | fi 239 | 240 | exit $run_exit_code 241 | 242 | ################################################################################ 243 | # 244 | # This image is not intended to be run manually. 245 | # 246 | # To create a dockcross helper script for the 247 | # dockcross/windows-x86:latest image, run: 248 | # 249 | # docker run --rm dockcross/windows-x86:latest > dockcross-windows-x86-latest 250 | # chmod +x dockcross-windows-x86-latest 251 | # 252 | # You may then wish to move the dockcross script to your PATH. 253 | # 254 | ################################################################################ 255 | -------------------------------------------------------------------------------- /lib/inc_linux/jni_md.h: -------------------------------------------------------------------------------- 1 | /* 2 | * %W% %E% 3 | * 4 | * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. 5 | * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 6 | */ 7 | 8 | #ifndef _JAVASOFT_JNI_MD_H_ 9 | #define _JAVASOFT_JNI_MD_H_ 10 | 11 | #define JNIEXPORT __attribute__((__visibility__("default"))) 12 | #define JNIIMPORT 13 | #define JNICALL 14 | 15 | typedef int jint; 16 | #ifdef _LP64 /* 64-bit Solaris */ 17 | typedef long jlong; 18 | #else 19 | typedef long long jlong; 20 | #endif 21 | 22 | typedef signed char jbyte; 23 | 24 | #endif /* !_JAVASOFT_JNI_MD_H_ */ 25 | -------------------------------------------------------------------------------- /lib/inc_mac/jni_md.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)jni_md.h 1.19 05/11/17 3 | * 4 | * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 5 | * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 6 | */ 7 | 8 | #ifndef _JAVASOFT_JNI_MD_H_ 9 | #define _JAVASOFT_JNI_MD_H_ 10 | 11 | #define JNIEXPORT __attribute__((visibility("default"))) 12 | #define JNIIMPORT 13 | #define JNICALL 14 | 15 | #if defined(__LP64__) && __LP64__ /* for -Wundef */ 16 | typedef int jint; 17 | #else 18 | typedef long jint; 19 | #endif 20 | typedef long long jlong; 21 | typedef signed char jbyte; 22 | 23 | #endif /* !_JAVASOFT_JNI_MD_H_ */ 24 | -------------------------------------------------------------------------------- /lib/inc_win/jni_md.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @(#)jni_md.h 1.14 03/12/19 3 | * 4 | * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 5 | * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 6 | */ 7 | 8 | #ifndef _JAVASOFT_JNI_MD_H_ 9 | #define _JAVASOFT_JNI_MD_H_ 10 | 11 | #define JNIEXPORT __declspec(dllexport) 12 | #define JNIIMPORT __declspec(dllimport) 13 | #define JNICALL __stdcall 14 | 15 | typedef long jint; 16 | typedef __int64 jlong; 17 | typedef signed char jbyte; 18 | 19 | #endif /* !_JAVASOFT_JNI_MD_H_ */ 20 | -------------------------------------------------------------------------------- /lib/jdbc-api-1.4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/lib/jdbc-api-1.4.jar -------------------------------------------------------------------------------- /lib/jpassport-v0.5.0-alpha.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/lib/jpassport-v0.5.0-alpha.jar -------------------------------------------------------------------------------- /lib/org/sqlite/OSInfo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/lib/org/sqlite/OSInfo.class -------------------------------------------------------------------------------- /lib/org/sqlite/util/OSInfo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/lib/org/sqlite/util/OSInfo.class -------------------------------------------------------------------------------- /lib/sqlite-jdbc-panama-3.36.0.4-SNAPSHOT.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/lib/sqlite-jdbc-panama-3.36.0.4-SNAPSHOT.jar -------------------------------------------------------------------------------- /maven-eclipse.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /scripts/travis-deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ev 3 | 4 | VERSION=$(mvn -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:1.2.1:exec) 5 | 6 | # Deploy a snapshot version only for master branch and jdk8 7 | if [[ "$TRAVIS_JDK_VERSION" == "oraclejdk8" ]]; then 8 | if [[ "$TRAVIS_PULL_REQUEST" == "false" ]] && [[ "$VERSION" == *SNAPSHOT ]]; then 9 | make && mvn -s settings.xml deploy -DskipTests; 10 | else 11 | make; 12 | fi; 13 | else 14 | make linux64 && mvn test; 15 | fi; 16 | -------------------------------------------------------------------------------- /settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | sonatype-nexus-staging 5 | ${env.SONATYPE_USERNAME} 6 | ${env.SONATYPE_PASSWORD} 7 | 8 | 9 | sonatype-nexus-snapshots 10 | ${env.SONATYPE_USERNAME} 11 | ${env.SONATYPE_PASSWORD} 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module sqlite.jdbc { 2 | requires java.sql; 3 | requires jpassport; 4 | requires jdk.incubator.foreign; 5 | 6 | exports org.sqlite.core.panama; 7 | exports org.sqlite; 8 | opens org.sqlite.util; 9 | 10 | provides java.sql.Driver with org.sqlite.JDBC; 11 | } -------------------------------------------------------------------------------- /src/main/java/org/sqlite/BusyHandler.java: -------------------------------------------------------------------------------- 1 | package org.sqlite; 2 | 3 | import java.sql.Connection; 4 | import java.sql.SQLException; 5 | 6 | /** https://www.sqlite.org/c3ref/busy_handler.html */ 7 | public abstract class BusyHandler { 8 | 9 | /** 10 | * commit the busy handler for the connection. 11 | * 12 | * @param conn the SQLite connection 13 | * @param busyHandler the busyHandler 14 | * @throws SQLException 15 | */ 16 | private static void commitHandler(Connection conn, BusyHandler busyHandler) 17 | throws SQLException { 18 | 19 | if (conn == null || !(conn instanceof SQLiteConnection)) { 20 | throw new SQLException("connection must be to an SQLite db"); 21 | } 22 | 23 | if (conn.isClosed()) { 24 | throw new SQLException("connection closed"); 25 | } 26 | 27 | SQLiteConnection sqliteConnection = (SQLiteConnection) conn; 28 | sqliteConnection.getDatabase().busy_handler(busyHandler); 29 | } 30 | 31 | /** 32 | * Sets a busy handler for the connection. 33 | * 34 | * @param conn the SQLite connection 35 | * @param busyHandler the busyHandler 36 | * @throws SQLException 37 | */ 38 | public static final void setHandler(Connection conn, BusyHandler busyHandler) 39 | throws SQLException { 40 | commitHandler(conn, busyHandler); 41 | } 42 | 43 | /** 44 | * Clears any busy handler registered with the connection. 45 | * 46 | * @param conn the SQLite connection 47 | * @throws SQLException 48 | */ 49 | public static final void clearHandler(Connection conn) throws SQLException { 50 | commitHandler(conn, null); 51 | } 52 | 53 | /** 54 | * https://www.sqlite.org/c3ref/busy_handler.html 55 | * 56 | * @param nbPrevInvok number of times that the busy handler has been invoked previously for the 57 | * same locking event 58 | * @throws SQLException 59 | * @return If the busy callback returns 0, then no additional attempts are made to access the 60 | * database and SQLITE_BUSY is returned to the application. If the callback returns 61 | * non-zero, then another attempt is made to access the database and the cycle repeats. 62 | */ 63 | public abstract int callback(int nbPrevInvok) throws SQLException; 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/Collation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Gauthier Roebroeck 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | package org.sqlite; 17 | 18 | import java.sql.Connection; 19 | import java.sql.SQLException; 20 | import org.sqlite.core.Codes; 21 | import org.sqlite.core.DB; 22 | 23 | /** 24 | * Provides an interface for creating SQLite user-defined collations. 25 | * 26 | *

A subclass of org.sqlite.Collation can be registered with Collation.create() 27 | * and called by the name it was given. All collations must implement xCompare(String, 28 | * String), which is called when SQLite compares two strings using the custom collation. Eg. 29 | * 30 | *

31 |  *      Class.forName("org.sqlite.JDBC");
32 |  *      Connection conn = DriverManager.getConnection("jdbc:sqlite:");
33 |  *
34 |  *      Collation.create(conn, "REVERSE", new Collation() {
35 |  *          protected int xCompare(String str1, String str2) {
36 |  *              return str1.compareTo(str2) * -1;
37 |  *          }
38 |  *      });
39 |  *
40 |  *      conn.createStatement().execute("select c1 from t order by c1 collate REVERSE;");
41 |  *  
42 | */ 43 | public abstract class Collation { 44 | private SQLiteConnection conn; 45 | private DB db; 46 | 47 | /** 48 | * Registers a given collation with the connection. 49 | * 50 | * @param conn The connection. 51 | * @param name The name of the collation. 52 | * @param f The collation to register. 53 | */ 54 | public static final void create(Connection conn, String name, Collation f) throws SQLException { 55 | if (conn == null || !(conn instanceof SQLiteConnection)) { 56 | throw new SQLException("connection must be to an SQLite db"); 57 | } 58 | if (conn.isClosed()) { 59 | throw new SQLException("connection closed"); 60 | } 61 | 62 | f.conn = (SQLiteConnection) conn; 63 | f.db = f.conn.getDatabase(); 64 | 65 | if (name == null || name.length() > 255) { 66 | throw new SQLException("invalid collation name: '" + name + "'"); 67 | } 68 | 69 | if (f.db.create_collation(name, f) != Codes.SQLITE_OK) { 70 | throw new SQLException("error creating collation"); 71 | } 72 | } 73 | 74 | /** 75 | * Removes a named collation from the given connection. 76 | * 77 | * @param conn The connection to remove the collation from. 78 | * @param name The name of the collation. 79 | * @throws SQLException 80 | */ 81 | public static final void destroy(Connection conn, String name) throws SQLException { 82 | if (conn == null || !(conn instanceof SQLiteConnection)) { 83 | throw new SQLException("connection must be to an SQLite db"); 84 | } 85 | ((SQLiteConnection) conn).getDatabase().destroy_collation(name); 86 | } 87 | 88 | /** 89 | * Called by SQLite as a custom collation to compare two strings. 90 | * 91 | * @param str1 the first string in the comparison 92 | * @param str2 the second string in the comparison 93 | * @return an integer that is negative, zero, or positive if the first string is less than, 94 | * equal to, or greater than the second, respectively 95 | */ 96 | public abstract int xCompare(String str1, String str2); 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/ExtendedCommand.java: -------------------------------------------------------------------------------- 1 | // -------------------------------------- 2 | // sqlite-jdbc Project 3 | // 4 | // ExtendedCommand.java 5 | // Since: Mar 12, 2010 6 | // 7 | // $URL$ 8 | // $Author$ 9 | // -------------------------------------- 10 | package org.sqlite; 11 | 12 | import java.sql.SQLException; 13 | import java.util.regex.Matcher; 14 | import java.util.regex.Pattern; 15 | import org.sqlite.core.DB; 16 | 17 | /** 18 | * parsing SQLite specific extension of SQL command 19 | * 20 | * @author leo 21 | */ 22 | public class ExtendedCommand { 23 | public static interface SQLExtension { 24 | public void execute(DB db) throws SQLException; 25 | } 26 | 27 | /** 28 | * Parses extended commands of "backup" or "restore" for SQLite database. 29 | * 30 | * @param sql One of the extended commands:
31 | * backup sourceDatabaseName to destinationFileName OR restore targetDatabaseName from 32 | * sourceFileName 33 | * @return BackupCommand object if the argument is a backup command; RestoreCommand object if 34 | * the argument is a restore command; 35 | * @throws SQLException 36 | */ 37 | public static SQLExtension parse(String sql) throws SQLException { 38 | if (sql == null) return null; 39 | if (sql.length() > 5 && sql.substring(0, 6).toLowerCase().equals("backup")) 40 | return BackupCommand.parse(sql); 41 | else if (sql.length() > 6 && sql.substring(0, 7).toLowerCase().equals("restore")) 42 | return RestoreCommand.parse(sql); 43 | 44 | return null; 45 | } 46 | 47 | /** 48 | * Remove the quotation mark from string. 49 | * 50 | * @param s String with quotation mark. 51 | * @return String with quotation mark removed. 52 | */ 53 | public static String removeQuotation(String s) { 54 | if (s == null) return s; 55 | 56 | if ((s.startsWith("\"") && s.endsWith("\"")) || (s.startsWith("'") && s.endsWith("'"))) 57 | return s.substring(1, s.length() - 1); 58 | else return s; 59 | } 60 | 61 | public static class BackupCommand implements SQLExtension { 62 | public final String srcDB; 63 | public final String destFile; 64 | 65 | /** 66 | * Constructs a BackupCommand instance that backup the database to a target file. 67 | * 68 | * @param srcDB Source database name. 69 | * @param destFile Target file name. 70 | */ 71 | public BackupCommand(String srcDB, String destFile) { 72 | this.srcDB = srcDB; 73 | this.destFile = destFile; 74 | } 75 | 76 | private static Pattern backupCmd = 77 | Pattern.compile( 78 | "backup(\\s+(\"[^\"]*\"|'[^\']*\'|\\S+))?\\s+to\\s+(\"[^\"]*\"|'[^\']*\'|\\S+)", 79 | Pattern.CASE_INSENSITIVE); 80 | 81 | /** 82 | * Parses SQLite database backup command and creates a BackupCommand object. 83 | * 84 | * @param sql SQLite database backup command. 85 | * @return BackupCommand object. 86 | * @throws SQLException 87 | */ 88 | public static BackupCommand parse(String sql) throws SQLException { 89 | if (sql != null) { 90 | Matcher m = backupCmd.matcher(sql); 91 | if (m.matches()) { 92 | String dbName = removeQuotation(m.group(2)); 93 | String dest = removeQuotation(m.group(3)); 94 | if (dbName == null || dbName.length() == 0) dbName = "main"; 95 | 96 | return new BackupCommand(dbName, dest); 97 | } 98 | } 99 | throw new SQLException("syntax error: " + sql); 100 | } 101 | 102 | public void execute(DB db) throws SQLException { 103 | db.backup(srcDB, destFile, null); 104 | } 105 | } 106 | 107 | public static class RestoreCommand implements SQLExtension { 108 | public final String targetDB; 109 | public final String srcFile; 110 | private static Pattern restoreCmd = 111 | Pattern.compile( 112 | "restore(\\s+(\"[^\"]*\"|'[^\']*\'|\\S+))?\\s+from\\s+(\"[^\"]*\"|'[^\']*\'|\\S+)", 113 | Pattern.CASE_INSENSITIVE); 114 | 115 | /** 116 | * Constructs a RestoreCommand instance that restores the database from a given source file. 117 | * 118 | * @param targetDB Target database name 119 | * @param srcFile Source file name 120 | */ 121 | public RestoreCommand(String targetDB, String srcFile) { 122 | this.targetDB = targetDB; 123 | this.srcFile = srcFile; 124 | } 125 | 126 | /** 127 | * Parses SQLite database restore command and creates a RestoreCommand object. 128 | * 129 | * @param sql SQLite restore backup command 130 | * @return RestoreCommand object. 131 | * @throws SQLException 132 | */ 133 | public static RestoreCommand parse(String sql) throws SQLException { 134 | if (sql != null) { 135 | Matcher m = restoreCmd.matcher(sql); 136 | if (m.matches()) { 137 | String dbName = removeQuotation(m.group(2)); 138 | String dest = removeQuotation(m.group(3)); 139 | if (dbName == null || dbName.length() == 0) dbName = "main"; 140 | return new RestoreCommand(dbName, dest); 141 | } 142 | } 143 | throw new SQLException("syntax error: " + sql); 144 | } 145 | 146 | /** @see org.sqlite.ExtendedCommand.SQLExtension#execute(org.sqlite.core.DB) */ 147 | public void execute(DB db) throws SQLException { 148 | db.restore(targetDB, srcFile, null); 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/JDBC.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007 David Crawshaw 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | package org.sqlite; 18 | 19 | import java.sql.*; 20 | import java.util.Properties; 21 | import java.util.logging.Logger; 22 | import org.sqlite.jdbc4.JDBC4Connection; 23 | 24 | public class JDBC implements Driver { 25 | public static final String PREFIX = "jdbc:sqlite:"; 26 | 27 | static { 28 | try { 29 | DriverManager.registerDriver(new JDBC()); 30 | } catch (SQLException e) { 31 | e.printStackTrace(); 32 | } 33 | } 34 | 35 | /** @see java.sql.Driver#getMajorVersion() */ 36 | public int getMajorVersion() { 37 | return SQLiteJDBCLoader.getMajorVersion(); 38 | } 39 | 40 | /** @see java.sql.Driver#getMinorVersion() */ 41 | public int getMinorVersion() { 42 | return SQLiteJDBCLoader.getMinorVersion(); 43 | } 44 | 45 | /** @see java.sql.Driver#jdbcCompliant() */ 46 | public boolean jdbcCompliant() { 47 | return false; 48 | } 49 | 50 | public Logger getParentLogger() throws SQLFeatureNotSupportedException { 51 | // TODO 52 | return null; 53 | } 54 | 55 | /** @see java.sql.Driver#acceptsURL(java.lang.String) */ 56 | public boolean acceptsURL(String url) { 57 | return isValidURL(url); 58 | } 59 | 60 | /** 61 | * Validates a URL 62 | * 63 | * @param url 64 | * @return true if the URL is valid, false otherwise 65 | */ 66 | public static boolean isValidURL(String url) { 67 | return url != null && url.toLowerCase().startsWith(PREFIX); 68 | } 69 | 70 | /** @see java.sql.Driver#getPropertyInfo(java.lang.String, java.util.Properties) */ 71 | public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException { 72 | return SQLiteConfig.getDriverPropertyInfo(); 73 | } 74 | 75 | /** @see java.sql.Driver#connect(java.lang.String, java.util.Properties) */ 76 | public Connection connect(String url, Properties info) throws SQLException { 77 | return createConnection(url, info); 78 | } 79 | 80 | /** 81 | * Gets the location to the database from a given URL. 82 | * 83 | * @param url The URL to extract the location from. 84 | * @return The location to the database. 85 | */ 86 | static String extractAddress(String url) { 87 | return url.substring(PREFIX.length()); 88 | } 89 | 90 | /** 91 | * Creates a new database connection to a given URL. 92 | * 93 | * @param url the URL 94 | * @param prop the properties 95 | * @return a Connection object that represents a connection to the URL 96 | * @throws SQLException 97 | * @see java.sql.Driver#connect(java.lang.String, java.util.Properties) 98 | */ 99 | public static SQLiteConnection createConnection(String url, Properties prop) 100 | throws SQLException { 101 | if (!isValidURL(url)) return null; 102 | 103 | url = url.trim(); 104 | return new JDBC4Connection(url, extractAddress(url), prop); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/ProgressHandler.java: -------------------------------------------------------------------------------- 1 | package org.sqlite; 2 | 3 | import java.sql.Connection; 4 | import java.sql.SQLException; 5 | 6 | /** https://sqlite.org/c3ref/progress_handler.html */ 7 | public abstract class ProgressHandler { 8 | /** 9 | * Sets a progress handler for the connection. 10 | * 11 | * @param conn the SQLite connection 12 | * @param vmCalls the approximate number of virtual machine instructions that are evaluated 13 | * between successive invocations of the progressHandler 14 | * @param progressHandler the progressHandler 15 | * @throws SQLException 16 | */ 17 | public static final void setHandler( 18 | Connection conn, int vmCalls, ProgressHandler progressHandler) throws SQLException { 19 | if (conn == null || !(conn instanceof SQLiteConnection)) { 20 | throw new SQLException("connection must be to an SQLite db"); 21 | } 22 | if (conn.isClosed()) { 23 | throw new SQLException("connection closed"); 24 | } 25 | SQLiteConnection sqliteConnection = (SQLiteConnection) conn; 26 | sqliteConnection.getDatabase().register_progress_handler(vmCalls, progressHandler); 27 | } 28 | 29 | /** 30 | * Clears any progress handler registered with the connection. 31 | * 32 | * @param conn the SQLite connection 33 | * @throws SQLException 34 | */ 35 | public static final void clearHandler(Connection conn) throws SQLException { 36 | SQLiteConnection sqliteConnection = (SQLiteConnection) conn; 37 | sqliteConnection.getDatabase().clear_progress_handler(); 38 | } 39 | 40 | public abstract int progress() throws SQLException; 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/SQLiteCommitListener.java: -------------------------------------------------------------------------------- 1 | package org.sqlite; 2 | 3 | /** https://www.sqlite.org/c3ref/commit_hook.html */ 4 | public interface SQLiteCommitListener { 5 | 6 | void onCommit(); 7 | 8 | void onRollback(); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/SQLiteConnectionConfig.java: -------------------------------------------------------------------------------- 1 | package org.sqlite; 2 | 3 | import static org.sqlite.SQLiteConfig.DEFAULT_DATE_STRING_FORMAT; 4 | 5 | import java.sql.Connection; 6 | import java.util.EnumMap; 7 | import java.util.Map; 8 | import java.util.Properties; 9 | import org.sqlite.date.FastDateFormat; 10 | 11 | /** Connection local configurations */ 12 | public class SQLiteConnectionConfig implements Cloneable { 13 | private SQLiteConfig.DateClass dateClass = SQLiteConfig.DateClass.INTEGER; 14 | private SQLiteConfig.DatePrecision datePrecision = 15 | SQLiteConfig.DatePrecision.MILLISECONDS; // Calendar.SECOND or Calendar.MILLISECOND 16 | private String dateStringFormat = DEFAULT_DATE_STRING_FORMAT; 17 | private FastDateFormat dateFormat = FastDateFormat.getInstance(dateStringFormat); 18 | 19 | private int transactionIsolation = Connection.TRANSACTION_SERIALIZABLE; 20 | private SQLiteConfig.TransactionMode transactionMode = SQLiteConfig.TransactionMode.DEFERRED; 21 | private boolean autoCommit = true; 22 | 23 | public static SQLiteConnectionConfig fromPragmaTable(Properties pragmaTable) { 24 | return new SQLiteConnectionConfig( 25 | SQLiteConfig.DateClass.getDateClass( 26 | pragmaTable.getProperty( 27 | SQLiteConfig.Pragma.DATE_CLASS.pragmaName, 28 | SQLiteConfig.DateClass.INTEGER.name())), 29 | SQLiteConfig.DatePrecision.getPrecision( 30 | pragmaTable.getProperty( 31 | SQLiteConfig.Pragma.DATE_PRECISION.pragmaName, 32 | SQLiteConfig.DatePrecision.MILLISECONDS.name())), 33 | pragmaTable.getProperty( 34 | SQLiteConfig.Pragma.DATE_STRING_FORMAT.pragmaName, 35 | DEFAULT_DATE_STRING_FORMAT), 36 | Connection.TRANSACTION_SERIALIZABLE, 37 | SQLiteConfig.TransactionMode.getMode( 38 | pragmaTable.getProperty( 39 | SQLiteConfig.Pragma.TRANSACTION_MODE.pragmaName, 40 | SQLiteConfig.TransactionMode.DEFERRED.name())), 41 | true); 42 | } 43 | 44 | public SQLiteConnectionConfig( 45 | SQLiteConfig.DateClass dateClass, 46 | SQLiteConfig.DatePrecision datePrecision, 47 | String dateStringFormat, 48 | int transactionIsolation, 49 | SQLiteConfig.TransactionMode transactionMode, 50 | boolean autoCommit) { 51 | setDateClass(dateClass); 52 | setDatePrecision(datePrecision); 53 | setDateStringFormat(dateStringFormat); 54 | setTransactionIsolation(transactionIsolation); 55 | setTransactionMode(transactionMode); 56 | setAutoCommit(autoCommit); 57 | } 58 | 59 | public SQLiteConnectionConfig copyConfig() { 60 | return new SQLiteConnectionConfig( 61 | dateClass, 62 | datePrecision, 63 | dateStringFormat, 64 | transactionIsolation, 65 | transactionMode, 66 | autoCommit); 67 | } 68 | 69 | public long getDateMultiplier() { 70 | return (datePrecision == SQLiteConfig.DatePrecision.MILLISECONDS) ? 1L : 1000L; 71 | } 72 | 73 | public SQLiteConfig.DateClass getDateClass() { 74 | return dateClass; 75 | } 76 | 77 | public void setDateClass(SQLiteConfig.DateClass dateClass) { 78 | this.dateClass = dateClass; 79 | } 80 | 81 | public SQLiteConfig.DatePrecision getDatePrecision() { 82 | return datePrecision; 83 | } 84 | 85 | public void setDatePrecision(SQLiteConfig.DatePrecision datePrecision) { 86 | this.datePrecision = datePrecision; 87 | } 88 | 89 | public String getDateStringFormat() { 90 | return dateStringFormat; 91 | } 92 | 93 | public void setDateStringFormat(String dateStringFormat) { 94 | this.dateStringFormat = dateStringFormat; 95 | this.dateFormat = FastDateFormat.getInstance(dateStringFormat); 96 | } 97 | 98 | public FastDateFormat getDateFormat() { 99 | return dateFormat; 100 | } 101 | 102 | public boolean isAutoCommit() { 103 | return autoCommit; 104 | } 105 | 106 | public void setAutoCommit(boolean autoCommit) { 107 | this.autoCommit = autoCommit; 108 | } 109 | 110 | public int getTransactionIsolation() { 111 | return transactionIsolation; 112 | } 113 | 114 | public void setTransactionIsolation(int transactionIsolation) { 115 | this.transactionIsolation = transactionIsolation; 116 | } 117 | 118 | public SQLiteConfig.TransactionMode getTransactionMode() { 119 | return transactionMode; 120 | } 121 | 122 | @SuppressWarnings("deprecation") 123 | public void setTransactionMode(SQLiteConfig.TransactionMode transactionMode) { 124 | if (transactionMode == SQLiteConfig.TransactionMode.DEFFERED) { 125 | transactionMode = SQLiteConfig.TransactionMode.DEFERRED; 126 | } 127 | this.transactionMode = transactionMode; 128 | } 129 | 130 | private static final Map beginCommandMap = 131 | new EnumMap(SQLiteConfig.TransactionMode.class); 132 | 133 | static { 134 | beginCommandMap.put(SQLiteConfig.TransactionMode.DEFERRED, "begin;"); 135 | beginCommandMap.put(SQLiteConfig.TransactionMode.IMMEDIATE, "begin immediate;"); 136 | beginCommandMap.put(SQLiteConfig.TransactionMode.EXCLUSIVE, "begin exclusive;"); 137 | } 138 | 139 | String transactionPrefix() { 140 | return beginCommandMap.get(transactionMode); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/SQLiteException.java: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------------- 2 | * Copyright 2016 Magnus Reftel 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *--------------------------------------------------------------------------*/ 16 | // -------------------------------------- 17 | // sqlite-jdbc Project 18 | // 19 | // SQLiteException.java 20 | // Since: Jun 28, 2016 21 | // 22 | // $URL$ 23 | // $Author$ 24 | // -------------------------------------- 25 | package org.sqlite; 26 | 27 | import java.sql.SQLException; 28 | 29 | public class SQLiteException extends SQLException { 30 | private SQLiteErrorCode resultCode; 31 | 32 | public SQLiteException(String message, SQLiteErrorCode resultCode) { 33 | super(message, null, resultCode.code & 0xff); 34 | this.resultCode = resultCode; 35 | } 36 | 37 | public SQLiteErrorCode getResultCode() { 38 | return resultCode; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/SQLiteLimits.java: -------------------------------------------------------------------------------- 1 | package org.sqlite; 2 | 3 | public enum SQLiteLimits { 4 | SQLITE_LIMIT_LENGTH(0), 5 | SQLITE_LIMIT_SQL_LENGTH(1), 6 | SQLITE_LIMIT_COLUMN(2), 7 | SQLITE_LIMIT_EXPR_DEPTH(3), 8 | SQLITE_LIMIT_COMPOUND_SELECT(4), 9 | SQLITE_LIMIT_VDBE_OP(5), 10 | SQLITE_LIMIT_FUNCTION_ARG(6), 11 | SQLITE_LIMIT_ATTACHED(7), 12 | SQLITE_LIMIT_LIKE_PATTERN_LENGTH(8), 13 | SQLITE_LIMIT_VARIABLE_NUMBER(9), 14 | SQLITE_LIMIT_TRIGGER_DEPTH(10), 15 | SQLITE_LIMIT_WORKER_THREADS(11), 16 | SQLITE_LIMIT_PAGE_COUNT(12); 17 | 18 | private final int id; 19 | 20 | private SQLiteLimits(int id) { 21 | this.id = id; 22 | } 23 | 24 | public int getId() { 25 | return id; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/SQLiteOpenMode.java: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------------- 2 | * Copyright 2009 Taro L. Saito 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *--------------------------------------------------------------------------*/ 16 | // -------------------------------------- 17 | // sqlite-jdbc Project 18 | // 19 | // SQLiteOpenMode.java 20 | // Since: Dec 8, 2009 21 | // 22 | // $URL$ 23 | // $Author$ 24 | // -------------------------------------- 25 | package org.sqlite; 26 | 27 | /** 28 | * Database file open modes of SQLite. 29 | * 30 | *

See also http://sqlite.org/c3ref/open.html 31 | * 32 | * @author leo 33 | */ 34 | public enum SQLiteOpenMode { 35 | READONLY(0x00000001), /* Ok for int SQLITE3_open_v2() */ 36 | READWRITE(0x00000002), /* Ok for int SQLITE3_open_v2() */ 37 | CREATE(0x00000004), /* Ok for int SQLITE3_open_v2() */ 38 | DELETEONCLOSE(0x00000008), /* VFS only */ 39 | EXCLUSIVE(0x00000010), /* VFS only */ 40 | OPEN_URI(0x00000040), /* Ok for sqlite3_open_v2() */ 41 | OPEN_MEMORY(0x00000080), /* Ok for sqlite3_open_v2() */ 42 | MAIN_DB(0x00000100), /* VFS only */ 43 | TEMP_DB(0x00000200), /* VFS only */ 44 | TRANSIENT_DB(0x00000400), /* VFS only */ 45 | MAIN_JOURNAL(0x00000800), /* VFS only */ 46 | TEMP_JOURNAL(0x00001000), /* VFS only */ 47 | SUBJOURNAL(0x00002000), /* VFS only */ 48 | MASTER_JOURNAL(0x00004000), /* VFS only */ 49 | NOMUTEX(0x00008000), /* Ok for int SQLITE3_open_v2() */ 50 | FULLMUTEX(0x00010000), /* Ok for int SQLITE3_open_v2() */ 51 | SHAREDCACHE(0x00020000), /* Ok for int SQLITE3_open_v2() */ 52 | PRIVATECACHE(0x00040000) /* Ok for sqlite3_open_v2() */; 53 | 54 | public final int flag; 55 | 56 | private SQLiteOpenMode(int flag) { 57 | this.flag = flag; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/SQLiteUpdateListener.java: -------------------------------------------------------------------------------- 1 | package org.sqlite; 2 | 3 | /** https://www.sqlite.org/c3ref/update_hook.html */ 4 | public interface SQLiteUpdateListener { 5 | 6 | public enum Type { 7 | INSERT, 8 | DELETE, 9 | UPDATE 10 | } 11 | 12 | void onUpdate(Type type, String database, String table, long rowId); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/core/Codes.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007 David Crawshaw 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | package org.sqlite.core; 17 | 18 | public interface Codes { 19 | /** Successful result */ 20 | public static final int SQLITE_OK = 0; 21 | 22 | /** SQL error or missing database */ 23 | public static final int SQLITE_ERROR = 1; 24 | 25 | /** An internal logic error in SQLite */ 26 | public static final int SQLITE_INTERNAL = 2; 27 | 28 | /** Access permission denied */ 29 | public static final int SQLITE_PERM = 3; 30 | 31 | /** Callback routine requested an abort */ 32 | public static final int SQLITE_ABORT = 4; 33 | 34 | /** The database file is locked */ 35 | public static final int SQLITE_BUSY = 5; 36 | 37 | /** A table in the database is locked */ 38 | public static final int SQLITE_LOCKED = 6; 39 | 40 | /** A malloc() failed */ 41 | public static final int SQLITE_NOMEM = 7; 42 | 43 | /** Attempt to write a readonly database */ 44 | public static final int SQLITE_READONLY = 8; 45 | 46 | /** Operation terminated by sqlite_interrupt() */ 47 | public static final int SQLITE_INTERRUPT = 9; 48 | 49 | /** Some kind of disk I/O error occurred */ 50 | public static final int SQLITE_IOERR = 10; 51 | 52 | /** The database disk image is malformed */ 53 | public static final int SQLITE_CORRUPT = 11; 54 | 55 | /** (Internal Only) Table or record not found */ 56 | public static final int SQLITE_NOTFOUND = 12; 57 | 58 | /** Insertion failed because database is full */ 59 | public static final int SQLITE_FULL = 13; 60 | 61 | /** Unable to open the database file */ 62 | public static final int SQLITE_CANTOPEN = 14; 63 | 64 | /** Database lock protocol error */ 65 | public static final int SQLITE_PROTOCOL = 15; 66 | 67 | /** (Internal Only) Database table is empty */ 68 | public static final int SQLITE_EMPTY = 16; 69 | 70 | /** The database schema changed */ 71 | public static final int SQLITE_SCHEMA = 17; 72 | 73 | /** Too much data for one row of a table */ 74 | public static final int SQLITE_TOOBIG = 18; 75 | 76 | /** Abort due to constraint violation */ 77 | public static final int SQLITE_CONSTRAINT = 19; 78 | 79 | /** Data type mismatch */ 80 | public static final int SQLITE_MISMATCH = 20; 81 | 82 | /** Library used incorrectly */ 83 | public static final int SQLITE_MISUSE = 21; 84 | 85 | /** Uses OS features not supported on host */ 86 | public static final int SQLITE_NOLFS = 22; 87 | 88 | /** Authorization denied */ 89 | public static final int SQLITE_AUTH = 23; 90 | 91 | /** sqlite_step() has another row ready */ 92 | public static final int SQLITE_ROW = 100; 93 | 94 | /** sqlite_step() has finished executing */ 95 | public static final int SQLITE_DONE = 101; 96 | 97 | // types returned by sqlite3_column_type() 98 | 99 | public static final int SQLITE_INTEGER = 1; 100 | public static final int SQLITE_FLOAT = 2; 101 | public static final int SQLITE_TEXT = 3; 102 | public static final int SQLITE_BLOB = 4; 103 | public static final int SQLITE_NULL = 5; 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/core/CorePreparedStatement.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007 David Crawshaw 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | package org.sqlite.core; 18 | 19 | import java.sql.Date; 20 | import java.sql.SQLException; 21 | import java.util.Calendar; 22 | import org.sqlite.SQLiteConnection; 23 | import org.sqlite.SQLiteConnectionConfig; 24 | import org.sqlite.date.FastDateFormat; 25 | import org.sqlite.jdbc4.JDBC4Statement; 26 | 27 | public abstract class CorePreparedStatement extends JDBC4Statement { 28 | protected int columnCount; 29 | protected int paramCount; 30 | protected int batchQueryCount; 31 | 32 | /** 33 | * Constructs a prepared statement on a provided connection. 34 | * 35 | * @param conn Connection on which to create the prepared statement. 36 | * @param sql The SQL script to prepare. 37 | * @throws SQLException 38 | */ 39 | protected CorePreparedStatement(SQLiteConnection conn, String sql) throws SQLException { 40 | super(conn); 41 | 42 | this.sql = sql; 43 | DB db = conn.getDatabase(); 44 | db.prepare(this); 45 | rs.colsMeta = db.column_names(pointer); 46 | columnCount = db.column_count(pointer); 47 | paramCount = db.bind_parameter_count(pointer); 48 | batchQueryCount = 0; 49 | batch = null; 50 | batchPos = 0; 51 | } 52 | 53 | /** @see org.sqlite.jdbc3.JDBC3Statement#executeBatch() */ 54 | @Override 55 | public int[] executeBatch() throws SQLException { 56 | if (batchQueryCount == 0) { 57 | return new int[] {}; 58 | } 59 | 60 | try { 61 | return conn.getDatabase() 62 | .executeBatch(pointer, batchQueryCount, batch, conn.getAutoCommit()); 63 | } finally { 64 | clearBatch(); 65 | } 66 | } 67 | 68 | /** @see org.sqlite.jdbc3.JDBC3Statement#clearBatch() () */ 69 | @Override 70 | public void clearBatch() throws SQLException { 71 | super.clearBatch(); 72 | batchQueryCount = 0; 73 | } 74 | 75 | /** @see org.sqlite.jdbc3.JDBC3Statement#getUpdateCount() */ 76 | @Override 77 | public int getUpdateCount() throws SQLException { 78 | if (pointer == 0 || resultsWaiting || rs.isOpen()) { 79 | return -1; 80 | } 81 | 82 | return conn.getDatabase().changes(); 83 | } 84 | 85 | // PARAMETER FUNCTIONS ////////////////////////////////////////// 86 | 87 | /** 88 | * Assigns the object value to the element at the specific position of array batch. 89 | * 90 | * @param pos 91 | * @param value 92 | * @throws SQLException 93 | */ 94 | protected void batch(int pos, Object value) throws SQLException { 95 | checkOpen(); 96 | if (batch == null) { 97 | batch = new Object[paramCount]; 98 | } 99 | batch[batchPos + pos - 1] = value; 100 | } 101 | 102 | /** Store the date in the user's preferred format (text, int, or real) */ 103 | protected void setDateByMilliseconds(int pos, Long value, Calendar calendar) 104 | throws SQLException { 105 | SQLiteConnectionConfig config = conn.getConnectionConfig(); 106 | switch (config.getDateClass()) { 107 | case TEXT: 108 | batch( 109 | pos, 110 | FastDateFormat.getInstance( 111 | config.getDateStringFormat(), calendar.getTimeZone()) 112 | .format(new Date(value))); 113 | break; 114 | 115 | case REAL: 116 | // long to Julian date 117 | batch(pos, new Double((value / 86400000.0) + 2440587.5)); 118 | break; 119 | 120 | default: // INTEGER: 121 | batch(pos, new Long(value / config.getDateMultiplier())); 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/core/CoreResultSet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007 David Crawshaw 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | package org.sqlite.core; 17 | 18 | import java.sql.SQLException; 19 | import java.sql.Statement; 20 | import java.util.HashMap; 21 | import java.util.Map; 22 | import org.sqlite.SQLiteConnectionConfig; 23 | 24 | /** Implements a JDBC ResultSet. */ 25 | public abstract class CoreResultSet implements Codes { 26 | protected final CoreStatement stmt; 27 | 28 | public boolean open = false; // true means have results and can iterate them 29 | public int maxRows; // max. number of rows as set by a Statement 30 | public String[] cols = null; // if null, the RS is closed() 31 | public String[] colsMeta = null; // same as cols, but used by Meta interface 32 | protected boolean[][] meta = null; 33 | 34 | protected int limitRows; // 0 means no limit, must check against maxRows 35 | protected int row = 0; // number of current row, starts at 1 (0 is for before loading data) 36 | protected int lastCol; // last column accessed, for wasNull(). -1 if none 37 | 38 | public boolean closeStmt; 39 | protected Map columnNameToIndex = null; 40 | 41 | /** 42 | * Default constructor for a given statement. 43 | * 44 | * @param stmt The statement. 45 | */ 46 | protected CoreResultSet(CoreStatement stmt) { 47 | this.stmt = stmt; 48 | } 49 | 50 | // INTERNAL FUNCTIONS /////////////////////////////////////////// 51 | 52 | protected DB getDatabase() { 53 | return stmt.getDatbase(); 54 | } 55 | 56 | protected SQLiteConnectionConfig getConnectionConfig() { 57 | return stmt.getConnectionConfig(); 58 | } 59 | 60 | /** 61 | * Checks the status of the result set. 62 | * 63 | * @return True if has results and can iterate them; false otherwise. 64 | */ 65 | public boolean isOpen() { 66 | return open; 67 | } 68 | 69 | /** @throws SQLException if ResultSet is not open. */ 70 | protected void checkOpen() throws SQLException { 71 | if (!open) { 72 | throw new SQLException("ResultSet closed"); 73 | } 74 | } 75 | 76 | /** 77 | * Takes col in [1,x] form, returns in [0,x-1] form 78 | * 79 | * @param col 80 | * @return 81 | * @throws SQLException 82 | */ 83 | public int checkCol(int col) throws SQLException { 84 | if (colsMeta == null) { 85 | throw new IllegalStateException("SQLite JDBC: inconsistent internal state"); 86 | } 87 | if (col < 1 || col > colsMeta.length) { 88 | throw new SQLException("column " + col + " out of bounds [1," + colsMeta.length + "]"); 89 | } 90 | return --col; 91 | } 92 | 93 | /** 94 | * Takes col in [1,x] form, marks it as last accessed and returns [0,x-1] 95 | * 96 | * @param col 97 | * @return 98 | * @throws SQLException 99 | */ 100 | protected int markCol(int col) throws SQLException { 101 | checkOpen(); 102 | checkCol(col); 103 | lastCol = col; 104 | return --col; 105 | } 106 | 107 | /** @throws SQLException */ 108 | public void checkMeta() throws SQLException { 109 | checkCol(1); 110 | if (meta == null) { 111 | meta = stmt.getDatbase().column_metadata(stmt.pointer); 112 | } 113 | } 114 | 115 | public void close() throws SQLException { 116 | cols = null; 117 | colsMeta = null; 118 | meta = null; 119 | limitRows = 0; 120 | row = 0; 121 | lastCol = -1; 122 | columnNameToIndex = null; 123 | 124 | if (!open) { 125 | return; 126 | } 127 | 128 | DB db = stmt.getDatbase(); 129 | synchronized (db) { 130 | if (stmt.pointer != 0) { 131 | db.reset(stmt.pointer); 132 | 133 | if (closeStmt) { 134 | closeStmt = false; // break recursive call 135 | ((Statement) stmt).close(); 136 | } 137 | } 138 | } 139 | 140 | open = false; 141 | } 142 | 143 | protected Integer findColumnIndexInCache(String col) { 144 | if (columnNameToIndex == null) { 145 | return null; 146 | } 147 | return columnNameToIndex.get(col); 148 | } 149 | 150 | protected int addColumnIndexInCache(String col, int index) { 151 | if (columnNameToIndex == null) { 152 | columnNameToIndex = new HashMap(cols.length); 153 | } 154 | columnNameToIndex.put(col, index); 155 | return index; 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/core/CoreStatement.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007 David Crawshaw 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | package org.sqlite.core; 17 | 18 | import java.sql.ResultSet; 19 | import java.sql.SQLException; 20 | import org.sqlite.SQLiteConnection; 21 | import org.sqlite.SQLiteConnectionConfig; 22 | import org.sqlite.jdbc4.JDBC4ResultSet; 23 | 24 | public abstract class CoreStatement implements Codes { 25 | public final SQLiteConnection conn; 26 | protected final CoreResultSet rs; 27 | 28 | public long pointer; 29 | protected String sql = null; 30 | 31 | protected int batchPos; 32 | protected Object[] batch = null; 33 | protected boolean resultsWaiting = false; 34 | 35 | protected CoreStatement(SQLiteConnection c) { 36 | conn = c; 37 | rs = new JDBC4ResultSet(this); 38 | } 39 | 40 | public DB getDatbase() { 41 | return conn.getDatabase(); 42 | } 43 | 44 | public SQLiteConnectionConfig getConnectionConfig() { 45 | return conn.getConnectionConfig(); 46 | } 47 | 48 | /** @throws SQLException If the database is not opened. */ 49 | protected final void checkOpen() throws SQLException { 50 | if (pointer == 0) throw new SQLException("statement is not executing"); 51 | } 52 | 53 | /** 54 | * @return True if the database is opened; false otherwise. 55 | * @throws SQLException 56 | */ 57 | boolean isOpen() throws SQLException { 58 | return (pointer != 0); 59 | } 60 | 61 | /** 62 | * Calls sqlite3_step() and sets up results. Expects a clean stmt. 63 | * 64 | * @return True if the ResultSet has at least one row; false otherwise. 65 | * @throws SQLException If the given SQL statement is null or no database is open. 66 | */ 67 | protected boolean exec() throws SQLException { 68 | if (sql == null) throw new SQLException("SQLiteJDBC internal error: sql==null"); 69 | if (rs.isOpen()) throw new SQLException("SQLite JDBC internal error: rs.isOpen() on exec."); 70 | 71 | boolean success = false; 72 | boolean rc = false; 73 | try { 74 | rc = conn.getDatabase().execute(this, null); 75 | success = true; 76 | } finally { 77 | resultsWaiting = rc; 78 | if (!success) conn.getDatabase().finalize(this); 79 | } 80 | 81 | return conn.getDatabase().column_count(pointer) != 0; 82 | } 83 | 84 | /** 85 | * Executes SQL statement and throws SQLExceptions if the given SQL statement is null or no 86 | * database is open. 87 | * 88 | * @param sql SQL statement. 89 | * @return True if the ResultSet has at least one row; false otherwise. 90 | * @throws SQLException If the given SQL statement is null or no database is open. 91 | */ 92 | protected boolean exec(String sql) throws SQLException { 93 | if (sql == null) throw new SQLException("SQLiteJDBC internal error: sql==null"); 94 | if (rs.isOpen()) throw new SQLException("SQLite JDBC internal error: rs.isOpen() on exec."); 95 | 96 | boolean rc = false; 97 | boolean success = false; 98 | try { 99 | rc = conn.getDatabase().execute(sql, conn.getAutoCommit()); 100 | success = true; 101 | } finally { 102 | resultsWaiting = rc; 103 | if (!success) conn.getDatabase().finalize(this); 104 | } 105 | 106 | return conn.getDatabase().column_count(pointer) != 0; 107 | } 108 | 109 | protected void internalClose() throws SQLException { 110 | if (pointer == 0) return; 111 | if (conn.isClosed()) throw DB.newSQLException(SQLITE_ERROR, "Connection is closed"); 112 | 113 | rs.close(); 114 | 115 | batch = null; 116 | batchPos = 0; 117 | int resp = conn.getDatabase().finalize(this); 118 | 119 | if (resp != SQLITE_OK && resp != SQLITE_MISUSE) conn.getDatabase().throwex(resp); 120 | } 121 | 122 | public abstract ResultSet executeQuery(String sql, boolean closeStmt) throws SQLException; 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/core/panama/DBHandle.java: -------------------------------------------------------------------------------- 1 | package org.sqlite.core.panama; 2 | 3 | 4 | import java.sql.SQLException; 5 | 6 | public record DBHandle(long handle) { 7 | static public DBHandle[] createOpenHandle() 8 | { 9 | return new DBHandle[] {new DBHandle(0)}; 10 | } 11 | 12 | public boolean isValid() 13 | { 14 | return handle != 0; 15 | } 16 | 17 | public void checkValid() throws SQLException 18 | { 19 | if (!isValid()) 20 | throw new SQLException("Database is closed"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/core/panama/PanamaCallbacks.java: -------------------------------------------------------------------------------- 1 | package org.sqlite.core.panama; 2 | 3 | import jdk.incubator.foreign.*; 4 | import org.sqlite.core.PanamaDBImpl; 5 | 6 | import java.lang.invoke.MethodHandles; 7 | import java.lang.invoke.MethodType; 8 | import java.lang.reflect.Method; 9 | import java.lang.reflect.Modifier; 10 | import java.util.Arrays; 11 | import java.util.List; 12 | import java.util.stream.Collectors; 13 | 14 | public class PanamaCallbacks { 15 | 16 | private final ResourceScope callbackScope = ResourceScope.newImplicitScope(); 17 | 18 | public MemoryAddress createCallback(Object ob, String methodName) 19 | { 20 | var methods = getDeclaredMethods(ob.getClass()); 21 | 22 | methods = methods.stream().filter(m -> m.getName().equals(methodName)).collect(Collectors.toList()); 23 | if (methods.size() == 0) 24 | throw new IllegalArgumentException("Could not find method " + methodName + " in class " + ob.getClass().getName()); 25 | else if (methods.size() > 1) 26 | throw new IllegalArgumentException("Multiple overloads of method " + methodName + " in class " + ob.getClass().getName()); 27 | 28 | Method callbackMethod = methods.get(0); 29 | 30 | Class retType = callbackMethod.getReturnType(); 31 | Class[] parameters = callbackMethod.getParameterTypes(); 32 | 33 | if (!retType.isPrimitive() && retType != MemoryAddress.class) 34 | throw new IllegalArgumentException("Callback method must return void, primitives, or MemoryAddress, not " + retType.getName()); 35 | 36 | 37 | for (Class parameter : parameters) { 38 | if (!parameter.isPrimitive() && parameter != MemoryAddress.class) 39 | throw new IllegalArgumentException("Callback parameters must be primitives or MemoryAddress, not " + parameter.getName()); 40 | } 41 | 42 | MemoryLayout[] memoryLayout = Arrays.stream(parameters).map(PanamaCallbacks::classToMemory).toArray(MemoryLayout[]::new); 43 | FunctionDescriptor fd; 44 | if (void.class.equals(retType)) 45 | fd = FunctionDescriptor.ofVoid(memoryLayout); 46 | else 47 | fd = FunctionDescriptor.of(classToMemory(retType), memoryLayout); 48 | 49 | try { 50 | var handle = MethodHandles.lookup().findVirtual(ob.getClass(), methodName, MethodType.methodType(retType, parameters)); 51 | var handleToCall = handle.bindTo(ob); 52 | 53 | return CLinker.getInstance().upcallStub(handleToCall, fd, callbackScope); 54 | } 55 | catch (NoSuchMethodException | IllegalAccessException ex) 56 | { 57 | throw new Error("Failed to create callback method", ex); 58 | } 59 | } 60 | 61 | static List getDeclaredMethods(Class interfaceClass) { 62 | Method[] methods = interfaceClass.getDeclaredMethods(); 63 | return Arrays.stream(methods).filter(method -> (method.getModifiers() & Modifier.STATIC) == 0).toList(); 64 | } 65 | 66 | private static MemoryLayout classToMemory(Class type) 67 | { 68 | if (double.class.equals(type)) 69 | return CLinker.C_DOUBLE; 70 | if (int.class.equals(type)) 71 | return CLinker.C_INT; 72 | if (float.class.equals(type)) 73 | return CLinker.C_FLOAT; 74 | if (short.class.equals(type)) 75 | return CLinker.C_SHORT; 76 | if (byte.class.equals(type)) 77 | return CLinker.C_CHAR; 78 | if (long.class.equals(type)) 79 | return CLinker.C_LONG_LONG; 80 | 81 | return CLinker.C_POINTER; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/core/panama/PanamaFunction.java: -------------------------------------------------------------------------------- 1 | package org.sqlite.core.panama; 2 | 3 | import jdk.incubator.foreign.MemoryAddress; 4 | import org.sqlite.Function; 5 | import org.sqlite.core.PanamaDBImpl; 6 | 7 | import java.sql.SQLException; 8 | 9 | 10 | public class PanamaFunction { 11 | 12 | private final Function function; 13 | private final PanamaDBImpl pDB; 14 | 15 | public PanamaFunction(PanamaDBImpl db, Function call) 16 | { 17 | function = call; 18 | pDB = db; 19 | } 20 | 21 | public void xFunc(long context, int args, MemoryAddress value) throws SQLException 22 | { 23 | synchronized (function) { 24 | function.setCallback(context, args, value.toRawLongValue()); 25 | try { 26 | function.xFunc(); 27 | } catch (SQLException ex) { 28 | pDB.setError(context, ex.getMessage()); 29 | } 30 | } 31 | function.setCallback(0, 0, 0); 32 | } 33 | 34 | public void xStep(long context, int args, MemoryAddress value) throws SQLException 35 | { 36 | function.setCallback(context, args, value.toRawLongValue()); 37 | try { 38 | ((Function.Aggregate)function).xStep(); 39 | } 40 | catch (SQLException ex) 41 | { 42 | pDB.setError(context, ex.getMessage()); 43 | } 44 | function.setCallback(0, 0, 0); 45 | } 46 | 47 | public void xInverse(long context, int args, MemoryAddress value) throws SQLException 48 | { 49 | function.setCallback(context, args, value.toRawLongValue()); 50 | try { 51 | ((Function.Window)function).xInverse(); 52 | } 53 | catch (SQLException ex) 54 | { 55 | pDB.setError(context, ex.getMessage()); 56 | } 57 | function.setCallback(0, 0, 0); 58 | } 59 | 60 | public void xFinal(long context) throws SQLException 61 | { 62 | function.setCallback(context,0, 0); 63 | try{ 64 | ((Function.Aggregate)function).xFinal(); 65 | } 66 | catch (SQLException ex) 67 | { 68 | pDB.setError(context, ex.getMessage()); 69 | } 70 | 71 | function.setCallback(0, 0, 0); 72 | } 73 | 74 | public void xValue(long context) throws SQLException 75 | { 76 | function.setCallback(context,0, 0); 77 | try { 78 | ((Function.Window)function).xValue(); 79 | } 80 | catch (SQLException ex) 81 | { 82 | pDB.setError(context, ex.getMessage()); 83 | } 84 | function.setCallback(0, 0, 0); 85 | } 86 | 87 | public MemoryAddress getxFuncCall() 88 | { 89 | return getCall("xFunc"); 90 | } 91 | 92 | public MemoryAddress getxStepCall() 93 | { 94 | if (!(function instanceof Function.Aggregate)) 95 | throw new IllegalArgumentException("Not an aggregate function!"); 96 | 97 | return getCall("xStep"); 98 | } 99 | 100 | public MemoryAddress getxInverseCall() 101 | { 102 | if (!(function instanceof Function.Window)) 103 | throw new IllegalArgumentException("Not an aggregate function!"); 104 | 105 | return getCall("xInverse"); 106 | } 107 | 108 | public MemoryAddress getxFinalCall() 109 | { 110 | if (!(function instanceof Function.Aggregate)) 111 | throw new IllegalArgumentException("Not an aggregate function!"); 112 | 113 | return getCall("xFinal"); 114 | } 115 | 116 | public MemoryAddress getxValueCall() 117 | { 118 | if (!(function instanceof Function.Aggregate)) 119 | throw new IllegalArgumentException("Not an aggregate function!"); 120 | return getCall("xValue"); 121 | } 122 | 123 | public MemoryAddress getCall(String name) 124 | { 125 | return pDB.getCallbackCreator().createCallback(this, name); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/core/panama/PrepStmt.java: -------------------------------------------------------------------------------- 1 | package org.sqlite.core.panama; 2 | 3 | public record PrepStmt(long handle) { 4 | static public PrepStmt[] createPrepareHandle() 5 | { 6 | return new PrepStmt[] {new PrepStmt(0)}; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/core/panama/ResultCode.java: -------------------------------------------------------------------------------- 1 | package org.sqlite.core.panama; 2 | 3 | import java.sql.SQLException; 4 | 5 | public enum ResultCode 6 | { 7 | SQLITE_OK(0, " Successful result"), /* Successful result */ 8 | /* beginning-of-error-codes */ 9 | SQLITE_ERROR (1, "Generic error"), /* Generic error */ 10 | SQLITE_INTERNAL (2, "Internal logic error in SQLite"), /* Internal logic error in SQLite */ 11 | SQLITE_PERM (3, "Access permission denied"), /* Access permission denied */ 12 | SQLITE_ABORT (4, "Callback routine requested an abort"), /* Callback routine requested an abort */ 13 | SQLITE_BUSY (5, "The database file is locked"), /* The database file is locked */ 14 | SQLITE_LOCKED (6, "A table in the database is locked"), /* A table in the database is locked */ 15 | SQLITE_NOMEM (7, "A malloc() failed"), /* A malloc() failed */ 16 | SQLITE_READONLY (8, "Attempt to write a readonly database"), /* Attempt to write a readonly database */ 17 | SQLITE_INTERRUPT (9, "Operation terminated by sqlite3_interrupt()"), /* Operation terminated by sqlite3_interrupt()*/ 18 | SQLITE_IOERR (10, "Some kind of disk I/O error occurred"), /* Some kind of disk I/O error occurred */ 19 | SQLITE_CORRUPT (11, "The database disk image is malformed"), /* The database disk image is malformed */ 20 | SQLITE_NOTFOUND (12, "Unknown opcode in sqlite3_file_control()"), /* Unknown opcode in sqlite3_file_control() */ 21 | SQLITE_FULL (13, "Insertion failed because database is full"), /* Insertion failed because database is full */ 22 | SQLITE_CANTOPEN (14, "Unable to open the database file"), /* Unable to open the database file */ 23 | SQLITE_PROTOCOL (15, "Database lock protocol error"), /* Database lock protocol error */ 24 | SQLITE_EMPTY (16, "Internal use only"), /* Internal use only */ 25 | SQLITE_SCHEMA (17, "The database schema changed"), /* The database schema changed */ 26 | SQLITE_TOOBIG (18, "String or BLOB exceeds size limit"), /* String or BLOB exceeds size limit */ 27 | SQLITE_CONSTRAINT (19, "Abort due to constraint violation"), /* Abort due to constraint violation */ 28 | SQLITE_MISMATCH (20, "Data type mismatch"), /* Data type mismatch */ 29 | SQLITE_MISUSE (21, "Library used incorrectly"), /* Library used incorrectly */ 30 | SQLITE_NOLFS (22, "Uses OS features not supported on host"), /* Uses OS features not supported on host */ 31 | SQLITE_AUTH (23, "Authorization denied"), /* Authorization denied */ 32 | SQLITE_FORMAT (24, "Not used"), /* Not used */ 33 | SQLITE_RANGE (25, "2nd parameter to sqlite3_bind out of range"), /* 2nd parameter to sqlite3_bind out of range */ 34 | SQLITE_NOTADB (26, "File opened that is not a database file"), /* File opened that is not a database file */ 35 | SQLITE_NOTICE (27, "Notifications from sqlite3_log()"), /* Notifications from sqlite3_log() */ 36 | SQLITE_WARNING (28, "Warnings from sqlite3_log()"), /* Warnings from sqlite3_log() */ 37 | SQLITE_ROW (100, "sqlite3_step() has another row ready"), /* sqlite3_step() has another row ready */ 38 | SQLITE_DONE (101, "sqlite3_step() has finished executing"); /* sqlite3_step() has finished executing */ 39 | 40 | int code; 41 | String description; 42 | 43 | ResultCode(int code, String description) 44 | { 45 | this.code = code; 46 | this.description = description; 47 | } 48 | 49 | public int code() 50 | { 51 | return code; 52 | } 53 | 54 | static final ResultCode[] codes = ResultCode.values(); 55 | 56 | public static void checkReturnCode(int returnCode) throws SQLException 57 | { 58 | if (returnCode == SQLITE_OK.code) 59 | return; 60 | 61 | for (ResultCode code : codes) 62 | { 63 | if (code.code == returnCode) 64 | throw new SQLException(code.description); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/date/DateParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.sqlite.date; 18 | 19 | import java.text.ParseException; 20 | import java.text.ParsePosition; 21 | import java.util.Date; 22 | import java.util.Locale; 23 | import java.util.TimeZone; 24 | 25 | /** 26 | * DateParser is the "missing" interface for the parsing methods of {@link java.text.DateFormat}. 27 | * 28 | * @since 3.2 29 | */ 30 | public interface DateParser { 31 | 32 | /** 33 | * Equivalent to DateFormat.parse(String). 34 | * 35 | *

See {@link java.text.DateFormat#parse(String)} for more information. 36 | * 37 | * @param source A String whose beginning should be parsed. 38 | * @return A Date parsed from the string 39 | * @throws ParseException if the beginning of the specified string cannot be parsed. 40 | */ 41 | Date parse(String source) throws ParseException; 42 | 43 | /** 44 | * Equivalent to DateFormat.parse(String, ParsePosition). 45 | * 46 | *

See {@link java.text.DateFormat#parse(String, ParsePosition)} for more information. 47 | * 48 | * @param source A String, part of which should be parsed. 49 | * @param pos A ParsePosition object with index and error index information as 50 | * described above. 51 | * @return A Date parsed from the string. In case of error, returns null. 52 | * @throws NullPointerException if text or pos is null. 53 | */ 54 | Date parse(String source, ParsePosition pos); 55 | 56 | // Accessors 57 | // ----------------------------------------------------------------------- 58 | /** 59 | * Get the pattern used by this parser. 60 | * 61 | * @return the pattern, {@link java.text.SimpleDateFormat} compatible 62 | */ 63 | String getPattern(); 64 | 65 | /** 66 | * Get the time zone used by this parser. 67 | * 68 | *

The default {@link TimeZone} used to create a {@link Date} when the {@link TimeZone} is 69 | * not specified by the format pattern. 70 | * 71 | * @return the time zone 72 | */ 73 | TimeZone getTimeZone(); 74 | 75 | /** 76 | * Get the locale used by this parser. 77 | * 78 | * @return the locale 79 | */ 80 | Locale getLocale(); 81 | 82 | /** 83 | * Parses text from a string to produce a Date. 84 | * 85 | * @param source A String whose beginning should be parsed. 86 | * @return a java.util.Date object 87 | * @throws ParseException if the beginning of the specified string cannot be parsed. 88 | * @see java.text.DateFormat#parseObject(String) 89 | */ 90 | Object parseObject(String source) throws ParseException; 91 | 92 | /** 93 | * Parse a date/time string according to the given parse position. 94 | * 95 | * @param source A String whose beginning should be parsed. 96 | * @param pos the parse position 97 | * @return a java.util.Date object 98 | * @see java.text.DateFormat#parseObject(String, ParsePosition) 99 | */ 100 | Object parseObject(String source, ParsePosition pos); 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/date/DatePrinter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.sqlite.date; 18 | 19 | import java.text.FieldPosition; 20 | import java.util.Calendar; 21 | import java.util.Date; 22 | import java.util.Locale; 23 | import java.util.TimeZone; 24 | 25 | /** 26 | * DatePrinter is the "missing" interface for the format methods of {@link java.text.DateFormat}. 27 | * 28 | * @since 3.2 29 | */ 30 | public interface DatePrinter { 31 | 32 | /** 33 | * Formats a millisecond {@code long} value. 34 | * 35 | * @param millis the millisecond value to format 36 | * @return the formatted string 37 | * @since 2.1 38 | */ 39 | String format(long millis); 40 | 41 | /** 42 | * Formats a {@code Date} object using a {@code GregorianCalendar}. 43 | * 44 | * @param date the date to format 45 | * @return the formatted string 46 | */ 47 | String format(Date date); 48 | 49 | /** 50 | * Formats a {@code Calendar} object. 51 | * 52 | * @param calendar the calendar to format 53 | * @return the formatted string 54 | */ 55 | String format(Calendar calendar); 56 | 57 | /** 58 | * Formats a milliseond {@code long} value into the supplied {@code StringBuffer}. 59 | * 60 | * @param millis the millisecond value to format 61 | * @param buf the buffer to format into 62 | * @return the specified string buffer 63 | */ 64 | StringBuffer format(long millis, StringBuffer buf); 65 | 66 | /** 67 | * Formats a {@code Date} object into the supplied {@code StringBuffer} using a {@code 68 | * GregorianCalendar}. 69 | * 70 | * @param date the date to format 71 | * @param buf the buffer to format into 72 | * @return the specified string buffer 73 | */ 74 | StringBuffer format(Date date, StringBuffer buf); 75 | 76 | /** 77 | * Formats a {@code Calendar} object into the supplied {@code StringBuffer}. 78 | * 79 | * @param calendar the calendar to format 80 | * @param buf the buffer to format into 81 | * @return the specified string buffer 82 | */ 83 | StringBuffer format(Calendar calendar, StringBuffer buf); 84 | 85 | // Accessors 86 | // ----------------------------------------------------------------------- 87 | /** 88 | * Gets the pattern used by this printer. 89 | * 90 | * @return the pattern, {@link java.text.SimpleDateFormat} compatible 91 | */ 92 | String getPattern(); 93 | 94 | /** 95 | * Gets the time zone used by this printer. 96 | * 97 | *

This zone is always used for {@code Date} printing. 98 | * 99 | * @return the time zone 100 | */ 101 | TimeZone getTimeZone(); 102 | 103 | /** 104 | * Gets the locale used by this printer. 105 | * 106 | * @return the locale 107 | */ 108 | Locale getLocale(); 109 | 110 | /** 111 | * Formats a {@code Date}, {@code Calendar} or {@code Long} (milliseconds) object. See {@link 112 | * java.text.DateFormat#format(Object, StringBuffer, FieldPosition)} 113 | * 114 | * @param obj the object to format 115 | * @param toAppendTo the buffer to append to 116 | * @param pos the position - ignored 117 | * @return the buffer passed in 118 | */ 119 | StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos); 120 | } 121 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/date/ExceptionUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.sqlite.date; 18 | 19 | /** 20 | * Provides utilities for manipulating and examining Throwable objects. 21 | * 22 | * @since 1.0 23 | */ 24 | public class ExceptionUtils { 25 | 26 | /** 27 | * Throw a checked exception without adding the exception to the throws clause of the calling 28 | * method. This method prevents throws clause pollution and reduces the clutter of "Caused by" 29 | * exceptions in the stacktrace. 30 | * 31 | *

The use of this technique may be controversial, but exceedingly useful to library 32 | * developers. 33 | * public int propagateExample { // note that there is no throws clause 34 | * try { 35 | * return invocation(); // throws IOException 36 | * } catch (Exception e) { 37 | * return ExceptionUtils.rethrow(e); // propagates a checked exception 38 | * } 39 | * } 40 | * 41 | * 42 | *

This is an alternative to the more conservative approach of wrapping the checked exception 43 | * in a RuntimeException: 44 | * public int wrapExample { // note that there is no throws clause 45 | * try { 46 | * return invocation(); // throws IOException 47 | * } catch (Error e) { 48 | * throw e; 49 | * } catch (RuntimeException e) { 50 | * throw e; // wraps a checked exception 51 | * } catch (Exception e) { 52 | * throw new UndeclaredThrowableException(e); // wraps a checked exception 53 | * } 54 | * } 55 | * 56 | * 57 | *

One downside to using this approach is that the java compiler will not allow invoking code 58 | * to specify a checked exception in a catch clause unless there is some code path within the 59 | * try block that has invoked a method declared with that checked exception. If the invoking 60 | * site wishes to catch the shaded checked exception, it must either invoke the shaded code 61 | * through a method re-declaring the desired checked exception, or catch Exception and use the 62 | * instanceof operator. Either of these techniques are required when interacting with non-java 63 | * jvm code such as Jyton, Scala, or Groovy, since these languages do not consider any 64 | * exceptions as checked. 65 | * 66 | * @since 3.5 67 | * @see {{@link #wrapAndThrow(Throwable)} 68 | * @param throwable The throwable to rethrow. 69 | * @return R Never actually returns, this generic type matches any type which the calling site 70 | * requires. "Returning" the results of this method, as done in the propagateExample above, 71 | * will satisfy the java compiler requirement that all code paths return a value. 72 | * @throws throwable 73 | */ 74 | public static R rethrow(Throwable throwable) { 75 | // claim that the typeErasure invocation throws a RuntimeException 76 | return ExceptionUtils.typeErasure(throwable); 77 | } 78 | 79 | /** 80 | * Claim a Throwable is another Exception type using type erasure. This hides a checked 81 | * exception from the java compiler, allowing a checked exception to be thrown without having 82 | * the exception in the method's throw clause. 83 | */ 84 | @SuppressWarnings("unchecked") 85 | private static R typeErasure(Throwable throwable) throws T { 86 | throw (T) throwable; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/date/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | /** 18 | * Provides classes and methods to work with dates and durations. These classes are immutable (and 19 | * therefore thread-safe) apart from org.apache.commons.lang3.time.StopWatch. 20 | * 21 | *

The time package contains some basic utilities for manipulating time (a delorean, police box 22 | * and grandfather clock?). These include a org.apache.commons.lang3.time.StopWatch for simple 23 | * performance measurements and an optimised {@link org.sqlite.date.FastDateFormat} class. 24 | * 25 | *

New in Lang 2.1 is the org.apache.commons.lang3.time.DurationFormatUtils class, which provides 26 | * various methods for formatting durations. 27 | * 28 | * @since 2.0 29 | */ 30 | package org.sqlite.date; 31 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/javax/SQLiteConnectionPoolDataSource.java: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------------- 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | *--------------------------------------------------------------------------*/ 14 | package org.sqlite.javax; 15 | 16 | import java.sql.SQLException; 17 | import javax.sql.PooledConnection; 18 | import org.sqlite.SQLiteConfig; 19 | import org.sqlite.SQLiteDataSource; 20 | 21 | public class SQLiteConnectionPoolDataSource extends SQLiteDataSource 22 | implements javax.sql.ConnectionPoolDataSource { 23 | 24 | /** Default constructor. */ 25 | public SQLiteConnectionPoolDataSource() { 26 | super(); 27 | } 28 | 29 | /** 30 | * Creates a data source based on the provided configuration. 31 | * 32 | * @param config The configuration for the data source. 33 | */ 34 | public SQLiteConnectionPoolDataSource(SQLiteConfig config) { 35 | super(config); 36 | } 37 | 38 | /** @see javax.sql.ConnectionPoolDataSource#getPooledConnection() */ 39 | public PooledConnection getPooledConnection() throws SQLException { 40 | return getPooledConnection(null, null); 41 | } 42 | 43 | /** 44 | * @see javax.sql.ConnectionPoolDataSource#getPooledConnection(java.lang.String, 45 | * java.lang.String) 46 | */ 47 | public PooledConnection getPooledConnection(String user, String password) throws SQLException { 48 | return new SQLitePooledConnection(getConnection(user, password)); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/jdbc3/JDBC3Savepoint.java: -------------------------------------------------------------------------------- 1 | package org.sqlite.jdbc3; 2 | 3 | import java.sql.SQLException; 4 | import java.sql.Savepoint; 5 | 6 | public class JDBC3Savepoint implements Savepoint { 7 | 8 | final int id; 9 | 10 | final String name; 11 | 12 | JDBC3Savepoint(int id) { 13 | this.id = id; 14 | this.name = null; 15 | } 16 | 17 | JDBC3Savepoint(int id, String name) { 18 | this.id = id; 19 | this.name = name; 20 | } 21 | 22 | public int getSavepointId() throws SQLException { 23 | return id; 24 | } 25 | 26 | public String getSavepointName() throws SQLException { 27 | return name == null ? String.format("SQLITE_SAVEPOINT_%s", id) : name; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/jdbc4/JDBC4Connection.java: -------------------------------------------------------------------------------- 1 | package org.sqlite.jdbc4; 2 | 3 | import java.sql.Array; 4 | import java.sql.Blob; 5 | import java.sql.Clob; 6 | import java.sql.NClob; 7 | import java.sql.PreparedStatement; 8 | import java.sql.SQLClientInfoException; 9 | import java.sql.SQLException; 10 | import java.sql.SQLFeatureNotSupportedException; 11 | import java.sql.SQLXML; 12 | import java.sql.Statement; 13 | import java.util.Properties; 14 | import org.sqlite.jdbc3.JDBC3Connection; 15 | 16 | public class JDBC4Connection extends JDBC3Connection { 17 | 18 | public JDBC4Connection(String url, String fileName, Properties prop) throws SQLException { 19 | super(url, fileName, prop); 20 | } 21 | 22 | public Statement createStatement(int rst, int rsc, int rsh) throws SQLException { 23 | checkOpen(); 24 | checkCursor(rst, rsc, rsh); 25 | 26 | return new JDBC4Statement(this); 27 | } 28 | 29 | public PreparedStatement prepareStatement(String sql, int rst, int rsc, int rsh) 30 | throws SQLException { 31 | checkOpen(); 32 | checkCursor(rst, rsc, rsh); 33 | 34 | return new JDBC4PreparedStatement(this, sql); 35 | } 36 | 37 | // JDBC 4 38 | /** @see java.sql.Connection#isClosed() */ 39 | public boolean isClosed() throws SQLException { 40 | return super.isClosed(); 41 | } 42 | 43 | public T unwrap(Class iface) throws ClassCastException { 44 | // caller should invoke isWrapperFor prior to unwrap 45 | return iface.cast(this); 46 | } 47 | 48 | public boolean isWrapperFor(Class iface) { 49 | return iface.isInstance(this); 50 | } 51 | 52 | public Clob createClob() throws SQLException { 53 | // TODO Support this 54 | throw new SQLFeatureNotSupportedException(); 55 | } 56 | 57 | public Blob createBlob() throws SQLException { 58 | // TODO Support this 59 | throw new SQLFeatureNotSupportedException(); 60 | } 61 | 62 | public NClob createNClob() throws SQLException { 63 | // TODO Support this 64 | throw new SQLFeatureNotSupportedException(); 65 | } 66 | 67 | public SQLXML createSQLXML() throws SQLException { 68 | // TODO Support this 69 | throw new SQLFeatureNotSupportedException(); 70 | } 71 | 72 | public boolean isValid(int timeout) throws SQLException { 73 | if (isClosed()) { 74 | return false; 75 | } 76 | Statement statement = createStatement(); 77 | try { 78 | return statement.execute("select 1"); 79 | } finally { 80 | statement.close(); 81 | } 82 | } 83 | 84 | public void setClientInfo(String name, String value) throws SQLClientInfoException { 85 | // TODO Auto-generated method stub 86 | 87 | } 88 | 89 | public void setClientInfo(Properties properties) throws SQLClientInfoException { 90 | // TODO Auto-generated method stub 91 | 92 | } 93 | 94 | public String getClientInfo(String name) throws SQLException { 95 | // TODO Auto-generated method stub 96 | return null; 97 | } 98 | 99 | public Properties getClientInfo() throws SQLException { 100 | // TODO Auto-generated method stub 101 | return null; 102 | } 103 | 104 | public Array createArrayOf(String typeName, Object[] elements) throws SQLException { 105 | // TODO Auto-generated method stub 106 | return null; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/jdbc4/JDBC4DatabaseMetaData.java: -------------------------------------------------------------------------------- 1 | package org.sqlite.jdbc4; 2 | 3 | import java.sql.ResultSet; 4 | import java.sql.RowIdLifetime; 5 | import java.sql.SQLException; 6 | import java.sql.SQLFeatureNotSupportedException; 7 | import org.sqlite.SQLiteConnection; 8 | import org.sqlite.jdbc3.JDBC3DatabaseMetaData; 9 | 10 | public class JDBC4DatabaseMetaData extends JDBC3DatabaseMetaData { 11 | public JDBC4DatabaseMetaData(SQLiteConnection conn) { 12 | super(conn); 13 | } 14 | 15 | // JDBC 4 16 | public T unwrap(Class iface) throws ClassCastException { 17 | return iface.cast(this); 18 | } 19 | 20 | public boolean isWrapperFor(Class iface) { 21 | return iface.isInstance(this); 22 | } 23 | 24 | public RowIdLifetime getRowIdLifetime() throws SQLException { 25 | throw new SQLFeatureNotSupportedException(); 26 | } 27 | 28 | public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException { 29 | throw new SQLFeatureNotSupportedException(); 30 | } 31 | 32 | public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException { 33 | throw new SQLFeatureNotSupportedException(); 34 | } 35 | 36 | public boolean autoCommitFailureClosesAllResultSets() throws SQLException { 37 | throw new SQLFeatureNotSupportedException(); 38 | } 39 | 40 | public ResultSet getClientInfoProperties() throws SQLException { 41 | throw new SQLFeatureNotSupportedException(); 42 | } 43 | 44 | public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) 45 | throws SQLException { 46 | throw new SQLFeatureNotSupportedException(); 47 | } 48 | 49 | public ResultSet getPseudoColumns( 50 | String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) 51 | throws SQLException { 52 | throw new SQLFeatureNotSupportedException(); 53 | } 54 | 55 | public boolean generatedKeyAlwaysReturned() throws SQLException { 56 | throw new SQLFeatureNotSupportedException(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/jdbc4/JDBC4PooledConnection.java: -------------------------------------------------------------------------------- 1 | package org.sqlite.jdbc4; 2 | 3 | import javax.sql.PooledConnection; 4 | import javax.sql.StatementEventListener; 5 | 6 | public abstract class JDBC4PooledConnection implements PooledConnection { 7 | 8 | public void addStatementEventListener(StatementEventListener listener) { 9 | // TODO impl 10 | } 11 | 12 | public void removeStatementEventListener(StatementEventListener listener) { 13 | // TODO impl 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/jdbc4/JDBC4PreparedStatement.java: -------------------------------------------------------------------------------- 1 | package org.sqlite.jdbc4; 2 | 3 | import java.io.InputStream; 4 | import java.io.Reader; 5 | import java.sql.NClob; 6 | import java.sql.ParameterMetaData; 7 | import java.sql.PreparedStatement; 8 | import java.sql.RowId; 9 | import java.sql.SQLException; 10 | import java.sql.SQLFeatureNotSupportedException; 11 | import java.sql.SQLXML; 12 | import java.util.Arrays; 13 | import org.sqlite.SQLiteConnection; 14 | import org.sqlite.jdbc3.JDBC3PreparedStatement; 15 | 16 | public class JDBC4PreparedStatement extends JDBC3PreparedStatement 17 | implements PreparedStatement, ParameterMetaData { 18 | 19 | @Override 20 | public String toString() { 21 | return sql + " \n parameters=" + Arrays.toString(batch); 22 | } 23 | 24 | public JDBC4PreparedStatement(SQLiteConnection conn, String sql) throws SQLException { 25 | super(conn, sql); 26 | } 27 | 28 | // JDBC 4 29 | public void setRowId(int parameterIndex, RowId x) throws SQLException { 30 | // TODO Support this 31 | throw new SQLFeatureNotSupportedException(); 32 | } 33 | 34 | public void setNString(int parameterIndex, String value) throws SQLException { 35 | // TODO Support this 36 | throw new SQLFeatureNotSupportedException(); 37 | } 38 | 39 | public void setNCharacterStream(int parameterIndex, Reader value, long length) 40 | throws SQLException { 41 | // TODO Support this 42 | throw new SQLFeatureNotSupportedException(); 43 | } 44 | 45 | public void setNClob(int parameterIndex, NClob value) throws SQLException { 46 | // TODO Support this 47 | throw new SQLFeatureNotSupportedException(); 48 | } 49 | 50 | public void setClob(int parameterIndex, Reader reader, long length) throws SQLException { 51 | // TODO Support this 52 | throw new SQLFeatureNotSupportedException(); 53 | } 54 | 55 | public void setBlob(int parameterIndex, InputStream inputStream, long length) 56 | throws SQLException { 57 | // TODO Support this 58 | throw new SQLFeatureNotSupportedException(); 59 | } 60 | 61 | public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException { 62 | // TODO Support this 63 | throw new SQLFeatureNotSupportedException(); 64 | } 65 | 66 | public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { 67 | // TODO Support this 68 | throw new SQLFeatureNotSupportedException(); 69 | } 70 | 71 | public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException { 72 | // TODO Support this 73 | throw new SQLFeatureNotSupportedException(); 74 | } 75 | 76 | public void setBinaryStream(int parameterIndex, InputStream x, long length) 77 | throws SQLException { 78 | // TODO Support this 79 | throw new SQLFeatureNotSupportedException(); 80 | } 81 | 82 | public void setCharacterStream(int parameterIndex, Reader reader, long length) 83 | throws SQLException { 84 | // TODO Support this 85 | throw new SQLFeatureNotSupportedException(); 86 | } 87 | 88 | public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException { 89 | // TODO Support this 90 | throw new SQLFeatureNotSupportedException(); 91 | } 92 | 93 | public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException { 94 | // TODO Support this 95 | throw new SQLFeatureNotSupportedException(); 96 | } 97 | 98 | public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException { 99 | // TODO Support this 100 | throw new SQLFeatureNotSupportedException(); 101 | } 102 | 103 | public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { 104 | // TODO Support this 105 | throw new SQLFeatureNotSupportedException(); 106 | } 107 | 108 | public void setClob(int parameterIndex, Reader reader) throws SQLException { 109 | // TODO Support this 110 | throw new SQLFeatureNotSupportedException(); 111 | } 112 | 113 | public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException { 114 | // TODO Support this 115 | throw new SQLFeatureNotSupportedException(); 116 | } 117 | 118 | public void setNClob(int parameterIndex, Reader reader) throws SQLException { 119 | // TODO Support this 120 | throw new SQLFeatureNotSupportedException(); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/jdbc4/JDBC4Statement.java: -------------------------------------------------------------------------------- 1 | package org.sqlite.jdbc4; 2 | 3 | import java.sql.SQLException; 4 | import java.sql.Statement; 5 | import org.sqlite.SQLiteConnection; 6 | import org.sqlite.jdbc3.JDBC3Statement; 7 | 8 | public class JDBC4Statement extends JDBC3Statement implements Statement { 9 | public JDBC4Statement(SQLiteConnection conn) { 10 | super(conn); 11 | } 12 | 13 | // JDBC 4 14 | public T unwrap(Class iface) throws ClassCastException { 15 | return iface.cast(this); 16 | } 17 | 18 | public boolean isWrapperFor(Class iface) { 19 | return iface.isInstance(this); 20 | } 21 | 22 | private boolean closed = false; 23 | 24 | @Override 25 | public void close() throws SQLException { 26 | super.close(); 27 | closed = true; // isClosed() should only return true when close() happened 28 | } 29 | 30 | public boolean isClosed() { 31 | return closed; 32 | } 33 | 34 | boolean closeOnCompletion; 35 | 36 | public void closeOnCompletion() throws SQLException { 37 | if (closed) throw new SQLException("statement is closed"); 38 | closeOnCompletion = true; 39 | } 40 | 41 | public boolean isCloseOnCompletion() throws SQLException { 42 | if (closed) throw new SQLException("statement is closed"); 43 | return closeOnCompletion; 44 | } 45 | 46 | public void setPoolable(boolean poolable) throws SQLException { 47 | // TODO Auto-generated method stub 48 | 49 | } 50 | 51 | public boolean isPoolable() throws SQLException { 52 | // TODO Auto-generated method stub 53 | return false; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/util/ProcessRunner.java: -------------------------------------------------------------------------------- 1 | package org.sqlite.util; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.util.concurrent.TimeUnit; 7 | 8 | public class ProcessRunner { 9 | String runAndWaitFor(String command) throws IOException, InterruptedException { 10 | Process p = Runtime.getRuntime().exec(command); 11 | p.waitFor(); 12 | 13 | return getProcessOutput(p); 14 | } 15 | 16 | String runAndWaitFor(String command, long timeout, TimeUnit unit) 17 | throws IOException, InterruptedException { 18 | Process p = Runtime.getRuntime().exec(command); 19 | p.waitFor(timeout, unit); 20 | 21 | return getProcessOutput(p); 22 | } 23 | 24 | static String getProcessOutput(Process process) throws IOException { 25 | try (InputStream in = process.getInputStream()) { 26 | int readLen; 27 | ByteArrayOutputStream b = new ByteArrayOutputStream(); 28 | byte[] buf = new byte[32]; 29 | while ((readLen = in.read(buf, 0, buf.length)) >= 0) { 30 | b.write(buf, 0, readLen); 31 | } 32 | return b.toString(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/util/ResourceFinder.java: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------------- 2 | * Copyright 2009 Taro L. Saito 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *--------------------------------------------------------------------------*/ 16 | // -------------------------------------- 17 | // sqlite-jdbc Project 18 | // 19 | // ResourceFinder.java 20 | // Since: Apr 28, 2009 21 | // 22 | // $URL$ 23 | // $Author$ 24 | // -------------------------------------- 25 | package org.sqlite.util; 26 | 27 | import java.net.URL; 28 | 29 | /** 30 | * Resource address finder for files inside the jar file 31 | * 32 | * @author leo 33 | */ 34 | public class ResourceFinder { 35 | /** 36 | * Gets the {@link URL} of the file resource 37 | * 38 | * @param referenceClass the base class for finding resources files. This method will search the 39 | * package containing the given referenceClass. 40 | * @param resourceFileName the resource file name relative to the package of the referenceClass 41 | * @return the URL of the file resource 42 | */ 43 | public static URL find(Class referenceClass, String resourceFileName) { 44 | return find(referenceClass.getClassLoader(), referenceClass.getPackage(), resourceFileName); 45 | } 46 | 47 | /** 48 | * Finds the {@link URL} of the resource 49 | * 50 | * @param basePackage the base package to find the resource 51 | * @param resourceFileName the resource file name relative to the package folder 52 | * @return the URL of the specified resource 53 | */ 54 | public static URL find(ClassLoader classLoader, Package basePackage, String resourceFileName) { 55 | return find(classLoader, basePackage.getName(), resourceFileName); 56 | } 57 | 58 | /** 59 | * Finds the {@link URL} of the resource 60 | * 61 | * @param packageName the base package name to find the resource 62 | * @param resourceFileName the resource file name relative to the package folder 63 | * @return the URL of the specified resource 64 | */ 65 | public static URL find(ClassLoader classLoader, String packageName, String resourceFileName) { 66 | String packagePath = packagePath(packageName); 67 | String resourcePath = packagePath + resourceFileName; 68 | if (!resourcePath.startsWith("/")) resourcePath = "/" + resourcePath; 69 | 70 | return classLoader.getResource(resourcePath); 71 | } 72 | 73 | @SuppressWarnings("unused") 74 | private static String packagePath(Class referenceClass) { 75 | return packagePath(referenceClass.getPackage()); 76 | } 77 | 78 | /** 79 | * @param basePackage Package object 80 | * @return Package path String in the unix-like format. 81 | */ 82 | private static String packagePath(Package basePackage) { 83 | return packagePath(basePackage.getName()); 84 | } 85 | 86 | /** 87 | * @param packageName Package name string 88 | * @return Package path String in the unix-like format. 89 | */ 90 | private static String packagePath(String packageName) { 91 | String packageAsPath = packageName.replaceAll("\\.", "/"); 92 | return packageAsPath.endsWith("/") ? packageAsPath : packageAsPath + "/"; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/org/sqlite/util/StringUtils.java: -------------------------------------------------------------------------------- 1 | package org.sqlite.util; 2 | 3 | import java.util.List; 4 | 5 | public class StringUtils { 6 | public static String join(List list, String separator) { 7 | StringBuilder sb = new StringBuilder(); 8 | boolean first = true; 9 | for (String item : list) { 10 | if (first) first = false; 11 | else sb.append(separator); 12 | 13 | sb.append(item); 14 | } 15 | return sb.toString(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/native-image/org.xerial/sqlite-jdbc/jni-config.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name":"org.sqlite.core.DB", 4 | "allDeclaredMethods":true, 5 | "allPublicMethods": true, 6 | "allDeclaredFields":true, 7 | "methods":[{"name":"","parameterTypes":["java.lang.String", "java.lang.String", "org.sqlite.SQLiteConfig"] }] 8 | }, 9 | { 10 | "name":"org.sqlite.core.NativeDB", 11 | "allDeclaredMethods":true, 12 | "allPublicMethods": true, 13 | "allDeclaredFields":true, 14 | "methods":[{"name":"","parameterTypes":["java.lang.String", "java.lang.String", "org.sqlite.SQLiteConfig"] }] 15 | }, 16 | { 17 | "name":"org.sqlite.BusyHandler", 18 | "allDeclaredMethods":true, 19 | "allPublicMethods": true, 20 | "methods":[{"name":"","parameterTypes":[] }] 21 | }, 22 | { 23 | "name":"org.sqlite.Function", 24 | "allDeclaredMethods":true, 25 | "allPublicMethods": true, 26 | "allDeclaredFields":true, 27 | "methods":[{"name":"","parameterTypes":[] }] 28 | }, 29 | { 30 | "name":"org.sqlite.Collation", 31 | "allDeclaredMethods":true, 32 | "allPublicMethods": true, 33 | "allDeclaredFields":true, 34 | "methods":[{"name":"","parameterTypes":[] }] 35 | }, 36 | { 37 | "name":"org.sqlite.ProgressHandler", 38 | "allDeclaredMethods":true, 39 | "allPublicMethods": true, 40 | "methods":[{"name":"","parameterTypes":[] }] 41 | }, 42 | { 43 | "name":"org.sqlite.Function$Aggregate", 44 | "allDeclaredMethods":true, 45 | "allPublicMethods": true, 46 | "methods":[{"name":"","parameterTypes":[] }] 47 | }, 48 | { 49 | "name":"org.sqlite.Function$Window", 50 | "allDeclaredMethods":true, 51 | "allPublicMethods": true, 52 | "methods":[{"name":"","parameterTypes":[] }] 53 | }, 54 | { 55 | "name":"org.sqlite.core.DB$ProgressObserver", 56 | "allDeclaredMethods":true, 57 | "allPublicMethods": true 58 | } 59 | ] 60 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/native-image/org.xerial/sqlite-jdbc/native-image.properties: -------------------------------------------------------------------------------- 1 | Args=-H:ResourceConfigurationResources=META-INF/native-image/org.xerial/sqlite-jdbc/resource-config.json 2 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/native-image/org.xerial/sqlite-jdbc/reflect-config.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name":"org.sqlite.core.DB", 4 | "allDeclaredMethods":true, 5 | "allPublicMethods": true, 6 | "allDeclaredFields":true, 7 | "methods":[{"name":"","parameterTypes":["java.lang.String", "java.lang.String", "org.sqlite.SQLiteConfig"] }] 8 | }, 9 | { 10 | "name":"org.sqlite.core.NativeDB", 11 | "allDeclaredMethods":true, 12 | "allPublicMethods": true, 13 | "allDeclaredFields":true, 14 | "methods":[{"name":"","parameterTypes":["java.lang.String", "java.lang.String", "org.sqlite.SQLiteConfig"] }] 15 | }, 16 | { 17 | "name":"org.sqlite.BusyHandler", 18 | "allDeclaredMethods":true, 19 | "allPublicMethods": true, 20 | "methods":[{"name":"","parameterTypes":[] }] 21 | }, 22 | { 23 | "name":"org.sqlite.Function", 24 | "allDeclaredMethods":true, 25 | "allPublicMethods": true, 26 | "allDeclaredFields":true, 27 | "methods":[{"name":"","parameterTypes":[] }] 28 | }, 29 | { 30 | "name":"org.sqlite.Collation", 31 | "allDeclaredMethods":true, 32 | "allPublicMethods": true, 33 | "allDeclaredFields":true, 34 | "methods":[{"name":"","parameterTypes":[] }] 35 | }, 36 | { 37 | "name":"org.sqlite.ProgressHandler", 38 | "allDeclaredMethods":true, 39 | "allPublicMethods": true, 40 | "methods":[{"name":"","parameterTypes":[] }] 41 | }, 42 | { 43 | "name":"org.sqlite.Function$Aggregate", 44 | "allDeclaredMethods":true, 45 | "allPublicMethods": true, 46 | "methods":[{"name":"","parameterTypes":[] }] 47 | }, 48 | { 49 | "name":"org.sqlite.Function$Window", 50 | "allDeclaredMethods":true, 51 | "allPublicMethods": true, 52 | "methods":[{"name":"","parameterTypes":[] }] 53 | }, 54 | { 55 | "name":"org.sqlite.core.DB$ProgressObserver", 56 | "allDeclaredMethods":true, 57 | "allPublicMethods": true 58 | } 59 | ] 60 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/native-image/org.xerial/sqlite-jdbc/resource-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "resources":{ 3 | "includes":[ 4 | {"pattern":"\\QMETA-INF/maven/org.xerial/sqlite-jdbc/VERSION\\E"}, 5 | {"pattern":"\\QMETA-INF/maven/org.xerial/sqlite-jdbc/pom.properties\\E"}, 6 | {"pattern":"\\QMETA-INF/services/java.sql.Driver\\E"}, 7 | {"pattern":"\\Qsqlite-jdbc.properties\\E"}, 8 | {"pattern":"org/sqlite/native/.*"}, 9 | {"pattern":"org/sqlite/.*"} 10 | ]}, 11 | "bundles":[] 12 | } 13 | -------------------------------------------------------------------------------- /src/main/resources/java.sql.Driver: -------------------------------------------------------------------------------- 1 | org.sqlite.JDBC -------------------------------------------------------------------------------- /src/main/resources/org/sqlite/native/FreeBSD/aarch64/libsqlitejdbc.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/src/main/resources/org/sqlite/native/FreeBSD/aarch64/libsqlitejdbc.so -------------------------------------------------------------------------------- /src/main/resources/org/sqlite/native/FreeBSD/x86/libsqlitejdbc.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/src/main/resources/org/sqlite/native/FreeBSD/x86/libsqlitejdbc.so -------------------------------------------------------------------------------- /src/main/resources/org/sqlite/native/FreeBSD/x86_64/libsqlitejdbc.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/src/main/resources/org/sqlite/native/FreeBSD/x86_64/libsqlitejdbc.so -------------------------------------------------------------------------------- /src/main/resources/org/sqlite/native/Linux-Musl/x86_64/libsqlitejdbc.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/src/main/resources/org/sqlite/native/Linux-Musl/x86_64/libsqlitejdbc.so -------------------------------------------------------------------------------- /src/main/resources/org/sqlite/native/Linux/aarch64/libsqlitejdbc.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/src/main/resources/org/sqlite/native/Linux/aarch64/libsqlitejdbc.so -------------------------------------------------------------------------------- /src/main/resources/org/sqlite/native/Linux/arm/libsqlitejdbc.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/src/main/resources/org/sqlite/native/Linux/arm/libsqlitejdbc.so -------------------------------------------------------------------------------- /src/main/resources/org/sqlite/native/Linux/armv6/libsqlitejdbc.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/src/main/resources/org/sqlite/native/Linux/armv6/libsqlitejdbc.so -------------------------------------------------------------------------------- /src/main/resources/org/sqlite/native/Linux/armv7/libsqlitejdbc.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/src/main/resources/org/sqlite/native/Linux/armv7/libsqlitejdbc.so -------------------------------------------------------------------------------- /src/main/resources/org/sqlite/native/Linux/ppc64/libsqlitejdbc.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/src/main/resources/org/sqlite/native/Linux/ppc64/libsqlitejdbc.so -------------------------------------------------------------------------------- /src/main/resources/org/sqlite/native/Linux/x86/libsqlitejdbc.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/src/main/resources/org/sqlite/native/Linux/x86/libsqlitejdbc.so -------------------------------------------------------------------------------- /src/main/resources/org/sqlite/native/Linux/x86_64/libsqlite3.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/src/main/resources/org/sqlite/native/Linux/x86_64/libsqlite3.so -------------------------------------------------------------------------------- /src/main/resources/org/sqlite/native/Mac/aarch64/libsqlitejdbc.jnilib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/src/main/resources/org/sqlite/native/Mac/aarch64/libsqlitejdbc.jnilib -------------------------------------------------------------------------------- /src/main/resources/org/sqlite/native/Mac/x86_64/libsqlitejdbc.jnilib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/src/main/resources/org/sqlite/native/Mac/x86_64/libsqlitejdbc.jnilib -------------------------------------------------------------------------------- /src/main/resources/org/sqlite/native/Windows/aarch64/sqlitejdbc.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/src/main/resources/org/sqlite/native/Windows/aarch64/sqlitejdbc.dll -------------------------------------------------------------------------------- /src/main/resources/org/sqlite/native/Windows/armv7/sqlitejdbc.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/src/main/resources/org/sqlite/native/Windows/armv7/sqlitejdbc.dll -------------------------------------------------------------------------------- /src/main/resources/org/sqlite/native/Windows/x86/sqlite3.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/src/main/resources/org/sqlite/native/Windows/x86/sqlite3.dll -------------------------------------------------------------------------------- /src/main/resources/org/sqlite/native/Windows/x86_64/sqlite3.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/src/main/resources/org/sqlite/native/Windows/x86_64/sqlite3.dll -------------------------------------------------------------------------------- /src/main/resources/sqlite-jdbc.properties: -------------------------------------------------------------------------------- 1 | name=${project.name} 2 | version=${project.version} 3 | -------------------------------------------------------------------------------- /src/test/java/org/sqlite/BackupTest.java: -------------------------------------------------------------------------------- 1 | // -------------------------------------- 2 | // sqlite-jdbc Project 3 | // 4 | // BackupTest.java 5 | // Since: Feb 18, 2009 6 | // 7 | // $URL$ 8 | // $Author$ 9 | // -------------------------------------- 10 | package org.sqlite; 11 | 12 | import static org.junit.jupiter.api.Assertions.assertEquals; 13 | 14 | import java.io.File; 15 | import java.io.IOException; 16 | import java.sql.Connection; 17 | import java.sql.DriverManager; 18 | import java.sql.ResultSet; 19 | import java.sql.SQLException; 20 | import java.sql.Statement; 21 | 22 | import org.junit.jupiter.api.BeforeEach; 23 | import org.junit.jupiter.api.Test; 24 | 25 | public class BackupTest { 26 | 27 | @BeforeEach 28 | public void loadDriver() throws ClassNotFoundException 29 | { 30 | LoadDriver.load(); 31 | } 32 | 33 | @Test 34 | public void backupAndRestore() throws SQLException, IOException, ClassNotFoundException { 35 | // create a memory database 36 | File tmpFile = File.createTempFile("backup-test", ".sqlite"); 37 | tmpFile.deleteOnExit(); 38 | 39 | // memory DB to file 40 | LoadDriver.load(); 41 | Connection conn = DriverManager.getConnection("jdbc:sqlite:"); 42 | Statement stmt = conn.createStatement(); 43 | stmt.executeUpdate("create table sample(id, name)"); 44 | stmt.executeUpdate("insert into sample values(1, \"leo\")"); 45 | stmt.executeUpdate("insert into sample values(2, \"yui\")"); 46 | 47 | stmt.executeUpdate("backup to " + tmpFile.getAbsolutePath()); 48 | stmt.close(); 49 | 50 | // open another memory database 51 | Connection conn2 = DriverManager.getConnection("jdbc:sqlite:"); 52 | Statement stmt2 = conn2.createStatement(); 53 | stmt2.execute("restore from " + tmpFile.getAbsolutePath()); 54 | ResultSet rs = stmt2.executeQuery("select * from sample"); 55 | int count = 0; 56 | while (rs.next()) { 57 | count++; 58 | } 59 | 60 | assertEquals(2, count); 61 | rs.close(); 62 | } 63 | 64 | @Test 65 | public void memoryToDisk() throws Exception { 66 | 67 | if (!SQLiteJDBCLoader.isNativeMode()) { 68 | return; // skip this test in pure-java mode 69 | } 70 | 71 | Connection conn = DriverManager.getConnection("jdbc:sqlite:"); 72 | Statement stmt = conn.createStatement(); 73 | stmt.executeUpdate("create table sample(id integer primary key autoincrement, name)"); 74 | for (int i = 0; i < 10000; i++) { 75 | stmt.executeUpdate("insert into sample(name) values(\"leo\")"); 76 | } 77 | 78 | File tmpFile = File.createTempFile("backup-test2", ".sqlite"); 79 | tmpFile.deleteOnExit(); 80 | // System.err.println("backup start"); 81 | stmt.executeUpdate("backup to " + tmpFile.getAbsolutePath()); 82 | stmt.close(); 83 | // System.err.println("backup done."); 84 | 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/test/java/org/sqlite/BusyHandlerTest.java: -------------------------------------------------------------------------------- 1 | package org.sqlite; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.fail; 5 | 6 | import java.sql.Connection; 7 | import java.sql.DriverManager; 8 | import java.sql.SQLException; 9 | import java.sql.Statement; 10 | import java.util.concurrent.CountDownLatch; 11 | import org.junit.jupiter.api.AfterEach; 12 | import org.junit.jupiter.api.BeforeEach; 13 | import org.junit.jupiter.api.Test; 14 | 15 | public class BusyHandlerTest { 16 | private Connection conn; 17 | private Statement stat; 18 | 19 | @BeforeEach 20 | public void connect() throws Exception { 21 | LoadDriver.load(); 22 | conn = DriverManager.getConnection("jdbc:sqlite:target/test.db"); 23 | stat = conn.createStatement(); 24 | } 25 | 26 | @AfterEach 27 | public void close() throws SQLException { 28 | stat.close(); 29 | conn.close(); 30 | } 31 | 32 | public class BusyWork extends Thread { 33 | private final Connection conn; 34 | private final Statement stat; 35 | private final CountDownLatch lockedLatch = new CountDownLatch(1); 36 | private final CountDownLatch completeLatch = new CountDownLatch(1); 37 | 38 | public BusyWork() throws Exception { 39 | conn = DriverManager.getConnection("jdbc:sqlite:target/test.db"); 40 | Function.create( 41 | conn, 42 | "wait_for_latch", 43 | new Function() { 44 | @Override 45 | public void xFunc() throws SQLException { 46 | lockedLatch.countDown(); 47 | try { 48 | completeLatch.await(); 49 | } catch (InterruptedException e) { 50 | throw new SQLException("Interrupted"); 51 | } 52 | result(100); 53 | } 54 | }); 55 | stat = conn.createStatement(); 56 | stat.setQueryTimeout(1); 57 | } 58 | 59 | @Override 60 | public void run() { 61 | try { 62 | // Generate some work for the sqlite vm 63 | stat.executeUpdate("drop table if exists foo;"); 64 | stat.executeUpdate("create table foo (id integer);"); 65 | stat.execute("insert into foo (id) values (wait_for_latch());"); 66 | } catch (SQLException ex) { 67 | System.out.println("HERE" + ex.toString()); 68 | } 69 | } 70 | } 71 | 72 | private void workWork() throws SQLException { 73 | // Generate some work for the sqlite vm 74 | int i = 0; 75 | while (i < 5) { 76 | stat.execute("insert into foo (id) values (" + i + ")"); 77 | i++; 78 | } 79 | } 80 | 81 | @Test 82 | public void basicBusyHandler() throws Exception { 83 | final int[] calls = {0}; 84 | BusyHandler.setHandler( 85 | conn, 86 | new BusyHandler() { 87 | @Override 88 | public int callback(int nbPrevInvok) throws SQLException { 89 | assertEquals(nbPrevInvok, calls[0]); 90 | calls[0]++; 91 | 92 | if (nbPrevInvok <= 1) { 93 | return 1; 94 | } else { 95 | return 0; 96 | } 97 | } 98 | }); 99 | 100 | BusyWork busyWork = new BusyWork(); 101 | busyWork.start(); 102 | 103 | // let busyWork block inside insert 104 | busyWork.lockedLatch.await(); 105 | 106 | try { 107 | workWork(); 108 | fail("Should throw SQLITE_BUSY exception"); 109 | } catch (SQLException ex) { 110 | assertEquals(SQLiteErrorCode.SQLITE_BUSY.code, ex.getErrorCode()); 111 | } 112 | 113 | busyWork.completeLatch.countDown(); 114 | busyWork.join(); 115 | assertEquals(3, calls[0]); 116 | } 117 | 118 | @Test 119 | public void testUnregister() throws Exception { 120 | final int[] calls = {0}; 121 | BusyHandler.setHandler( 122 | conn, 123 | new BusyHandler() { 124 | @Override 125 | public int callback(int nbPrevInvok) throws SQLException { 126 | assertEquals(nbPrevInvok, calls[0]); 127 | calls[0]++; 128 | 129 | if (nbPrevInvok <= 1) { 130 | return 1; 131 | } else { 132 | return 0; 133 | } 134 | } 135 | }); 136 | 137 | BusyWork busyWork = new BusyWork(); 138 | busyWork.start(); 139 | // let busyWork block inside insert 140 | busyWork.lockedLatch.await(); 141 | try { 142 | workWork(); 143 | fail("Should throw SQLITE_BUSY exception"); 144 | } catch (SQLException ex) { 145 | assertEquals(SQLiteErrorCode.SQLITE_BUSY.code, ex.getErrorCode()); 146 | } 147 | busyWork.completeLatch.countDown(); 148 | busyWork.join(); 149 | assertEquals(3, calls[0]); 150 | 151 | int totalCalls = calls[0]; 152 | BusyHandler.clearHandler(conn); 153 | busyWork = new BusyWork(); 154 | busyWork.start(); 155 | // let busyWork block inside insert 156 | busyWork.lockedLatch.await(); 157 | try { 158 | workWork(); 159 | fail("Should throw SQLITE_BUSY exception"); 160 | } catch (SQLException ex) { 161 | assertEquals(SQLiteErrorCode.SQLITE_BUSY.code, ex.getErrorCode()); 162 | } 163 | 164 | busyWork.completeLatch.countDown(); 165 | busyWork.join(); 166 | assertEquals(totalCalls, calls[0]); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/test/java/org/sqlite/ExtendedCommandTest.java: -------------------------------------------------------------------------------- 1 | // -------------------------------------- 2 | // sqlite-jdbc Project 3 | // 4 | // ExtendedCommandTest.java 5 | // Since: Mar 12, 2010 6 | // 7 | // $URL$ 8 | // $Author$ 9 | // -------------------------------------- 10 | package org.sqlite; 11 | 12 | import static org.junit.jupiter.api.Assertions.assertEquals; 13 | import static org.junit.jupiter.api.Assertions.assertTrue; 14 | 15 | import java.sql.SQLException; 16 | import org.junit.jupiter.api.Test; 17 | import org.sqlite.ExtendedCommand.BackupCommand; 18 | import org.sqlite.ExtendedCommand.RestoreCommand; 19 | import org.sqlite.ExtendedCommand.SQLExtension; 20 | 21 | public class ExtendedCommandTest { 22 | 23 | public static BackupCommand parseBackupCommand(String sql) throws SQLException { 24 | SQLExtension e = ExtendedCommand.parse(sql); 25 | assertTrue(e instanceof BackupCommand); 26 | return (BackupCommand) e; 27 | } 28 | 29 | public static RestoreCommand parseRestoreCommand(String sql) throws SQLException { 30 | SQLExtension e = ExtendedCommand.parse(sql); 31 | assertTrue(e instanceof RestoreCommand); 32 | return (RestoreCommand) e; 33 | } 34 | 35 | @Test 36 | public void parseBackupCmd() throws SQLException { 37 | BackupCommand b = parseBackupCommand("backup mydb to somewhere/backupfolder/mydb.sqlite"); 38 | assertEquals("mydb", b.srcDB); 39 | assertEquals("somewhere/backupfolder/mydb.sqlite", b.destFile); 40 | 41 | b = parseBackupCommand("backup main to \"tmp folder with space\""); 42 | assertEquals("main", b.srcDB); 43 | assertEquals("tmp folder with space", b.destFile); 44 | 45 | b = parseBackupCommand("backup main to 'tmp folder with space'"); 46 | assertEquals("main", b.srcDB); 47 | assertEquals("tmp folder with space", b.destFile); 48 | 49 | b = parseBackupCommand("backup to target/sample.db"); 50 | assertEquals("main", b.srcDB); 51 | assertEquals("target/sample.db", b.destFile); 52 | } 53 | 54 | @Test 55 | public void parseRestoreCmd() throws SQLException { 56 | RestoreCommand b = 57 | parseRestoreCommand("restore mydb from somewhere/backupfolder/mydb.sqlite"); 58 | assertEquals("mydb", b.targetDB); 59 | assertEquals("somewhere/backupfolder/mydb.sqlite", b.srcFile); 60 | 61 | b = parseRestoreCommand("restore main from \"tmp folder with space\""); 62 | assertEquals("main", b.targetDB); 63 | assertEquals("tmp folder with space", b.srcFile); 64 | 65 | b = parseRestoreCommand("restore main from 'tmp folder with space'"); 66 | assertEquals("main", b.targetDB); 67 | assertEquals("tmp folder with space", b.srcFile); 68 | 69 | b = parseRestoreCommand("restore from target/sample.db"); 70 | assertEquals("main", b.targetDB); 71 | assertEquals("target/sample.db", b.srcFile); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/test/java/org/sqlite/ExtensionTest.java: -------------------------------------------------------------------------------- 1 | package org.sqlite; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertTrue; 5 | import static org.junit.jupiter.api.Assumptions.*; 6 | 7 | import java.sql.Connection; 8 | import java.sql.DriverManager; 9 | import java.sql.ResultSet; 10 | import java.sql.Statement; 11 | import org.junit.jupiter.api.AfterEach; 12 | import org.junit.jupiter.api.BeforeEach; 13 | import org.junit.jupiter.api.Test; 14 | 15 | public class ExtensionTest { 16 | Connection conn; 17 | Statement stat; 18 | 19 | @BeforeEach 20 | public void setUp() throws Exception { 21 | LoadDriver.load(); 22 | conn = DriverManager.getConnection("jdbc:sqlite:"); 23 | stat = conn.createStatement(); 24 | } 25 | 26 | @AfterEach 27 | public void tearDown() throws Exception { 28 | if (stat != null) { 29 | stat.close(); 30 | } 31 | if (conn != null) { 32 | conn.close(); 33 | } 34 | } 35 | 36 | @Test 37 | public void extFTS3() throws Exception { 38 | stat.execute("create virtual table recipe using fts3(name, ingredients)"); 39 | stat.execute( 40 | "insert into recipe (name, ingredients) values('broccoli stew', 'broccoli peppers cheese tomatoes')"); 41 | stat.execute( 42 | "insert into recipe (name, ingredients) values('pumpkin stew', 'pumpkin onions garlic celery')"); 43 | 44 | ResultSet rs = 45 | stat.executeQuery( 46 | "select rowid, name, ingredients from recipe where ingredients match 'onions'"); 47 | assertTrue(rs.next()); 48 | assertEquals("pumpkin stew", rs.getString(2)); 49 | } 50 | 51 | @Test 52 | public void extFTS5() throws Exception { 53 | stat.execute("create virtual table recipe using fts5(name, ingredients)"); 54 | stat.execute( 55 | "insert into recipe (name, ingredients) values('broccoli stew', 'broccoli peppers cheese tomatoes')"); 56 | stat.execute( 57 | "insert into recipe (name, ingredients) values('pumpkin stew', 'pumpkin onions garlic celery')"); 58 | 59 | ResultSet rs = 60 | stat.executeQuery( 61 | "select rowid, name, ingredients from recipe where recipe match 'onions'"); 62 | assertTrue(rs.next()); 63 | assertEquals("pumpkin stew", rs.getString(2)); 64 | } 65 | 66 | @Test 67 | public void extFunctions() throws Exception { 68 | { 69 | ResultSet rs = stat.executeQuery("pragma compile_options"); 70 | boolean hasJdbcExtensions = false; 71 | while (rs.next()) { 72 | String compileOption = rs.getString(1); 73 | if (compileOption.equals("JDBC_EXTENSIONS")) { 74 | hasJdbcExtensions = true; 75 | break; 76 | } 77 | } 78 | rs.close(); 79 | // SQLite has to be compiled with JDBC Extensions for this test to 80 | // continue. 81 | assumeTrue(hasJdbcExtensions); 82 | } 83 | { 84 | ResultSet rs = stat.executeQuery("select cos(radians(45))"); 85 | assertTrue(rs.next()); 86 | assertEquals(0.707106781186548, rs.getDouble(1), 0.000000000000001); 87 | rs.close(); 88 | } 89 | 90 | { 91 | ResultSet rs = stat.executeQuery("select reverse(\"ACGT\")"); 92 | assertTrue(rs.next()); 93 | assertEquals("TGCA", rs.getString(1)); 94 | rs.close(); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/test/java/org/sqlite/FetchSizeTest.java: -------------------------------------------------------------------------------- 1 | package org.sqlite; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertFalse; 5 | import static org.junit.jupiter.api.Assertions.assertTrue; 6 | 7 | import java.sql.Connection; 8 | import java.sql.DriverManager; 9 | import java.sql.PreparedStatement; 10 | import java.sql.ResultSet; 11 | import java.sql.SQLException; 12 | import org.junit.jupiter.api.AfterEach; 13 | import org.junit.jupiter.api.BeforeEach; 14 | import org.junit.jupiter.api.Test; 15 | 16 | /** 17 | * Created by IntelliJ IDEA. User: david_donn Date: 19/01/2010 Time: 11:50:24 AM To change this 18 | * template use File | Settings | File Templates. 19 | */ 20 | public class FetchSizeTest { 21 | 22 | private Connection conn; 23 | 24 | @BeforeEach 25 | public void connect() throws Exception { 26 | LoadDriver.load(); 27 | conn = DriverManager.getConnection("jdbc:sqlite:"); 28 | } 29 | 30 | @AfterEach 31 | public void close() throws SQLException { 32 | conn.close(); 33 | } 34 | 35 | @Test 36 | public void testFetchSize() throws SQLException { 37 | assertEquals(conn.prepareStatement("create table s1 (c1)").executeUpdate(), 0); 38 | PreparedStatement insertPrep = conn.prepareStatement("insert into s1 values (?)"); 39 | insertPrep.setInt(1, 1); 40 | assertEquals(insertPrep.executeUpdate(), 1); 41 | insertPrep.setInt(1, 2); 42 | assertEquals(insertPrep.executeUpdate(), 1); 43 | insertPrep.setInt(1, 3); 44 | assertEquals(insertPrep.executeUpdate(), 1); 45 | insertPrep.setInt(1, 4); 46 | assertEquals(insertPrep.executeUpdate(), 1); 47 | insertPrep.setInt(1, 5); 48 | assertEquals(insertPrep.executeUpdate(), 1); 49 | insertPrep.close(); 50 | 51 | PreparedStatement selectPrep = conn.prepareStatement("select c1 from s1"); 52 | ResultSet rs = selectPrep.executeQuery(); 53 | rs.setFetchSize(2); 54 | assertTrue(rs.next()); 55 | assertTrue(rs.next()); 56 | assertTrue(rs.next()); 57 | assertTrue(rs.next()); 58 | assertTrue(rs.next()); 59 | assertFalse(rs.next()); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/test/java/org/sqlite/InsertQueryTest.java: -------------------------------------------------------------------------------- 1 | // -------------------------------------- 2 | // sqlite-jdbc Project 3 | // 4 | // InsertQueryTest.java 5 | // Since: Apr 7, 2009 6 | // 7 | // $URL$ 8 | // $Author$ 9 | // -------------------------------------- 10 | package org.sqlite; 11 | 12 | import java.io.File; 13 | import java.sql.Connection; 14 | import java.sql.DriverManager; 15 | import java.sql.PreparedStatement; 16 | import java.sql.ResultSet; 17 | import java.sql.SQLException; 18 | import java.sql.Statement; 19 | import org.junit.jupiter.api.AfterEach; 20 | import org.junit.jupiter.api.BeforeEach; 21 | import org.junit.jupiter.api.Disabled; 22 | import org.junit.jupiter.api.Test; 23 | 24 | public class InsertQueryTest { 25 | String dbName; 26 | 27 | @BeforeEach 28 | public void setUp() throws Exception { 29 | LoadDriver.load(); 30 | File tmpFile = File.createTempFile("tmp-sqlite", ".db"); 31 | tmpFile.deleteOnExit(); 32 | dbName = tmpFile.getAbsolutePath(); 33 | } 34 | 35 | @AfterEach 36 | public void tearDown() throws Exception {} 37 | 38 | interface ConnectionFactory { 39 | Connection getConnection() throws SQLException; 40 | 41 | void dispose() throws SQLException; 42 | } 43 | 44 | class IndependentConnectionFactory implements ConnectionFactory { 45 | public Connection getConnection() throws SQLException { 46 | return DriverManager.getConnection("jdbc:sqlite:" + dbName); 47 | } 48 | 49 | public void dispose() throws SQLException {} 50 | } 51 | 52 | class SharedConnectionFactory implements ConnectionFactory { 53 | private Connection conn = null; 54 | 55 | public Connection getConnection() throws SQLException { 56 | if (conn == null) { 57 | conn = DriverManager.getConnection("jdbc:sqlite:" + dbName); 58 | } 59 | return conn; 60 | } 61 | 62 | public void dispose() throws SQLException { 63 | if (conn != null) { 64 | conn.close(); 65 | } 66 | } 67 | } 68 | 69 | static class BD { 70 | String fullId; 71 | String type; 72 | 73 | public BD(String fullId, String type) { 74 | this.fullId = fullId; 75 | this.type = type; 76 | } 77 | 78 | public String getFullId() { 79 | return fullId; 80 | } 81 | 82 | public void setFullId(String fullId) { 83 | this.fullId = fullId; 84 | } 85 | 86 | public String getType() { 87 | return type; 88 | } 89 | 90 | public void setType(String type) { 91 | this.type = type; 92 | } 93 | 94 | public static byte[] serializeBD(BD item) { 95 | return new byte[0]; 96 | } 97 | } 98 | 99 | @Test 100 | public void insertLockTestUsingSharedConnection() throws Exception { 101 | insertAndQuery(new SharedConnectionFactory()); 102 | } 103 | 104 | @Test 105 | public void insertLockTestUsingIndependentConnection() throws Exception { 106 | insertAndQuery(new IndependentConnectionFactory()); 107 | } 108 | 109 | void insertAndQuery(ConnectionFactory factory) throws SQLException { 110 | try { 111 | Statement st = factory.getConnection().createStatement(); 112 | st.executeUpdate( 113 | "CREATE TABLE IF NOT EXISTS data (fid VARCHAR(255) PRIMARY KEY, type VARCHAR(64), data BLOB);"); 114 | st.executeUpdate( 115 | "CREATE TABLE IF NOT EXISTS ResourcesTags (bd_fid VARCHAR(255), name VARCHAR(64), version INTEGER);"); 116 | st.close(); 117 | 118 | factory.getConnection().setAutoCommit(false); 119 | 120 | // Object Serialization 121 | PreparedStatement statAddBD = 122 | factory.getConnection() 123 | .prepareStatement("INSERT OR REPLACE INTO data values (?, ?, ?)"); 124 | PreparedStatement statDelRT = 125 | factory.getConnection() 126 | .prepareStatement("DELETE FROM ResourcesTags WHERE bd_fid = ?"); 127 | PreparedStatement statAddRT = 128 | factory.getConnection() 129 | .prepareStatement("INSERT INTO ResourcesTags values (?, ?, ?)"); 130 | 131 | for (int i = 0; i < 10; i++) { 132 | BD item = new BD(Integer.toHexString(i), Integer.toString(i)); 133 | 134 | // SQLite database insertion 135 | statAddBD.setString(1, item.getFullId()); 136 | statAddBD.setString(2, item.getType()); 137 | statAddBD.setBytes(3, BD.serializeBD(item)); 138 | statAddBD.execute(); 139 | 140 | // Then, its resources tags 141 | statDelRT.setString(1, item.getFullId()); 142 | statDelRT.execute(); 143 | 144 | statAddRT.setString(1, item.getFullId()); 145 | 146 | for (int j = 0; j < 2; j++) { 147 | statAddRT.setString(2, "1"); 148 | statAddRT.setLong(3, 1L); 149 | statAddRT.execute(); 150 | } 151 | } 152 | 153 | factory.getConnection().setAutoCommit(true); 154 | 155 | statAddBD.close(); 156 | statDelRT.close(); 157 | statAddRT.close(); 158 | 159 | // 160 | PreparedStatement stat; 161 | Long result = 0L; 162 | String query = "SELECT COUNT(fid) FROM data"; 163 | 164 | stat = factory.getConnection().prepareStatement(query); 165 | ResultSet rs = stat.executeQuery(); 166 | 167 | rs.next(); 168 | result = rs.getLong(1); 169 | // System.out.println("count = " + result); 170 | 171 | rs.close(); 172 | stat.close(); 173 | } finally { 174 | factory.dispose(); 175 | } 176 | } 177 | 178 | @Disabled("Not sure this worked recently, the second query cannot find the table 'sample'") 179 | @Test 180 | public void reproduceDatabaseLocked() throws SQLException { 181 | Connection conn = DriverManager.getConnection("jdbc:sqlite:" + dbName); 182 | Connection conn2 = DriverManager.getConnection("jdbc:sqlite:" + dbName); 183 | Statement stat = conn.createStatement(); 184 | Statement stat2 = conn2.createStatement(); 185 | 186 | conn.setAutoCommit(false); 187 | 188 | stat.executeUpdate("drop table if exists sample"); 189 | stat.executeUpdate("create table sample(id, name)"); 190 | stat.executeUpdate("insert into sample values(1, 'leo')"); 191 | 192 | ResultSet rs = stat2.executeQuery("select count(*) from sample"); 193 | rs.next(); 194 | 195 | conn.commit(); // causes "database is locked" (SQLITE_BUSY) 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /src/test/java/org/sqlite/JDBCTest.java: -------------------------------------------------------------------------------- 1 | // -------------------------------------- 2 | // sqlite-jdbc Project 3 | // 4 | // JDBCTest.java 5 | // Since: Apr 8, 2009 6 | // 7 | // $URL$ 8 | // $Author$ 9 | // -------------------------------------- 10 | package org.sqlite; 11 | 12 | import static org.junit.jupiter.api.Assertions.assertNull; 13 | 14 | import java.sql.Connection; 15 | import java.sql.DriverManager; 16 | import java.sql.Statement; 17 | import java.util.Properties; 18 | 19 | import org.junit.jupiter.api.Disabled; 20 | import org.junit.jupiter.api.Test; 21 | 22 | public class JDBCTest { 23 | @Test 24 | public void enableLoadExtensionTest() throws Exception { 25 | Properties prop = new Properties(); 26 | prop.setProperty("enable_load_extension", "true"); 27 | 28 | try (Connection conn = DriverManager.getConnection("jdbc:sqlite:", prop)) { 29 | Statement stat = conn.createStatement(); 30 | 31 | // How to build shared lib in Windows 32 | // # mingw32-gcc -fPIC -c extension-function.c 33 | // # mingw32-gcc -shared -Wl -o extension-function.dll extension-function.o 34 | 35 | // stat.executeQuery("select load_extension('extension-function.dll')"); 36 | // 37 | // ResultSet rs = stat.executeQuery("select sqrt(4)"); 38 | // System.out.println(rs.getDouble(1)); 39 | 40 | } 41 | } 42 | 43 | @Disabled 44 | @Test 45 | public void majorVersion() throws Exception { 46 | int major = DriverManager.getDriver("jdbc:sqlite:").getMajorVersion(); 47 | int minor = DriverManager.getDriver("jdbc:sqlite:").getMinorVersion(); 48 | } 49 | 50 | @Test 51 | public void shouldReturnNullIfProtocolUnhandled() throws Exception { 52 | assertNull(JDBC.createConnection("jdbc:anotherpopulardatabaseprotocol:", null)); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/test/java/org/sqlite/LoadDriver.java: -------------------------------------------------------------------------------- 1 | package org.sqlite; 2 | 3 | public class LoadDriver { 4 | public static void load() throws ClassNotFoundException 5 | { 6 | // Class.forName("org.sqlite.JDBC"); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/test/java/org/sqlite/ProgressHandlerTest.java: -------------------------------------------------------------------------------- 1 | package org.sqlite; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertTrue; 5 | import static org.junit.jupiter.api.Assertions.fail; 6 | 7 | import java.sql.Connection; 8 | import java.sql.DriverManager; 9 | import java.sql.SQLException; 10 | import java.sql.Statement; 11 | import org.junit.jupiter.api.AfterEach; 12 | import org.junit.jupiter.api.BeforeEach; 13 | import org.junit.jupiter.api.Test; 14 | 15 | public class ProgressHandlerTest { 16 | private Connection conn; 17 | private Statement stat; 18 | 19 | @BeforeEach 20 | public void connect() throws Exception { 21 | LoadDriver.load(); 22 | conn = DriverManager.getConnection("jdbc:sqlite:"); 23 | stat = conn.createStatement(); 24 | } 25 | 26 | @AfterEach 27 | public void close() throws SQLException { 28 | stat.close(); 29 | conn.close(); 30 | } 31 | 32 | private void workWork() throws SQLException { 33 | // Generate some work for the sqlite vm 34 | stat.executeUpdate("drop table if exists foo;"); 35 | stat.executeUpdate("create table foo (id integer);"); 36 | stat.executeUpdate("insert into foo (id) values (1);"); 37 | for (int i = 0; i < 100; i++) { 38 | stat.executeQuery("select * from foo"); 39 | } 40 | } 41 | 42 | @Test 43 | public void basicProgressHandler() throws Exception { 44 | final int[] calls = {0}; 45 | ProgressHandler.setHandler( 46 | conn, 47 | 1, 48 | new ProgressHandler() { 49 | @Override 50 | public int progress() throws SQLException { 51 | calls[0]++; 52 | return 0; 53 | } 54 | }); 55 | workWork(); 56 | assertTrue(calls[0] > 0); 57 | } 58 | 59 | @Test 60 | public void testUnregister() throws Exception { 61 | final int[] calls = {0}; 62 | ProgressHandler.setHandler( 63 | conn, 64 | 1, 65 | new ProgressHandler() { 66 | @Override 67 | public int progress() throws SQLException { 68 | calls[0]++; 69 | return 0; 70 | } 71 | }); 72 | workWork(); 73 | assertTrue(calls[0] > 0); 74 | int totalCalls = calls[0]; 75 | ProgressHandler.clearHandler(conn); 76 | workWork(); 77 | assertEquals(totalCalls, calls[0]); 78 | } 79 | 80 | @Test 81 | public void testInterrupt() throws Exception { 82 | 83 | try { 84 | ProgressHandler.setHandler( 85 | conn, 86 | 1, 87 | new ProgressHandler() { 88 | @Override 89 | public int progress() throws SQLException { 90 | return 1; 91 | } 92 | }); 93 | workWork(); 94 | } catch (SQLException ex) { 95 | // Expected error 96 | return; 97 | } 98 | // Progress function throws, not reached 99 | fail(); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/test/java/org/sqlite/ReadUncommittedTest.java: -------------------------------------------------------------------------------- 1 | // -------------------------------------- 2 | // sqlite-jdbc Project 3 | // 4 | // ReadCommitedTest.java 5 | // Since: Jan 19, 2009 6 | // 7 | // $URL$ 8 | // $Author$ 9 | // -------------------------------------- 10 | package org.sqlite; 11 | 12 | import static org.junit.jupiter.api.Assertions.assertEquals; 13 | 14 | import java.sql.Connection; 15 | import java.sql.DriverManager; 16 | import java.sql.SQLException; 17 | import java.sql.Statement; 18 | import java.util.Properties; 19 | import org.junit.jupiter.api.AfterEach; 20 | import org.junit.jupiter.api.BeforeEach; 21 | import org.junit.jupiter.api.Test; 22 | 23 | public class ReadUncommittedTest { 24 | private Connection conn; 25 | private Statement stat; 26 | 27 | @BeforeEach 28 | public void connect() throws Exception { 29 | Properties prop = new Properties(); 30 | prop.setProperty("shared_cache", "true"); 31 | conn = DriverManager.getConnection("jdbc:sqlite:", prop); 32 | stat = conn.createStatement(); 33 | stat.executeUpdate("create table test (id integer primary key, fn, sn);"); 34 | stat.executeUpdate("create view testView as select * from test;"); 35 | } 36 | 37 | @AfterEach 38 | public void close() throws SQLException { 39 | stat.close(); 40 | conn.close(); 41 | } 42 | 43 | @Test 44 | public void setReadUncommitted() throws SQLException { 45 | conn.setTransactionIsolation(SQLiteConnection.TRANSACTION_READ_UNCOMMITTED); 46 | } 47 | 48 | @Test 49 | public void setSerializable() throws SQLException { 50 | conn.setTransactionIsolation(SQLiteConnection.TRANSACTION_SERIALIZABLE); 51 | } 52 | 53 | @Test 54 | public void setIsolationPromotedToSerializable() throws SQLException { 55 | conn.setTransactionIsolation(SQLiteConnection.TRANSACTION_REPEATABLE_READ); 56 | } 57 | 58 | @Test 59 | public void setReadUncommittedWithConfig() throws SQLException { 60 | // Override original setup 61 | Properties prop = new Properties(); 62 | prop.setProperty("shared_cache", "true"); 63 | conn = DriverManager.getConnection("jdbc:sqlite:", prop); 64 | stat = conn.createStatement(); 65 | assertEquals( 66 | stat.executeQuery("PRAGMA read_uncommitted;").getString(1), 67 | "0", 68 | "Fail to set pragma read_uncommitted"); 69 | 70 | prop.setProperty("read_uncommitted", "true"); 71 | conn = DriverManager.getConnection("jdbc:sqlite:", prop); 72 | stat = conn.createStatement(); 73 | assertEquals( 74 | "1", 75 | stat.executeQuery("PRAGMA read_uncommitted;").getString(1), 76 | "Fail to set pragma read_uncommitted"); 77 | 78 | prop.setProperty("read_uncommitted", "false"); 79 | conn = DriverManager.getConnection("jdbc:sqlite:", prop); 80 | stat = conn.createStatement(); 81 | assertEquals( 82 | "0", 83 | stat.executeQuery("PRAGMA read_uncommitted;").getString(1), 84 | "Fail to set pragma read_uncommitted"); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/test/java/org/sqlite/ResultSetTest.java: -------------------------------------------------------------------------------- 1 | package org.sqlite; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertFalse; 5 | import static org.junit.jupiter.api.Assertions.assertThrows; 6 | import static org.junit.jupiter.api.Assertions.assertTrue; 7 | 8 | import java.sql.Connection; 9 | import java.sql.DriverManager; 10 | import java.sql.PreparedStatement; 11 | import java.sql.ResultSet; 12 | import java.sql.SQLException; 13 | import java.sql.Statement; 14 | import org.junit.jupiter.api.AfterEach; 15 | import org.junit.jupiter.api.BeforeEach; 16 | import org.junit.jupiter.api.Test; 17 | 18 | public class ResultSetTest { 19 | 20 | private Connection conn; 21 | private Statement stat; 22 | 23 | @BeforeEach 24 | public void connect() throws Exception { 25 | LoadDriver.load(); 26 | conn = DriverManager.getConnection("jdbc:sqlite:"); 27 | stat = conn.createStatement(); 28 | stat.executeUpdate( 29 | "create table test (id int primary key, DESCRIPTION varchar(40), fOo varchar(3));"); 30 | stat.executeUpdate("insert into test values (1, 'description', 'bar')"); 31 | } 32 | 33 | @AfterEach 34 | public void close() throws SQLException { 35 | stat.close(); 36 | conn.close(); 37 | } 38 | 39 | @Test 40 | public void testTableColumnLowerNowFindLowerCaseColumn() throws SQLException { 41 | ResultSet resultSet = stat.executeQuery("select * from test"); 42 | assertTrue(resultSet.next()); 43 | assertEquals(1, resultSet.findColumn("id")); 44 | } 45 | 46 | @Test 47 | public void testTableColumnLowerNowFindUpperCaseColumn() throws SQLException { 48 | ResultSet resultSet = stat.executeQuery("select * from test"); 49 | assertTrue(resultSet.next()); 50 | assertEquals(1, resultSet.findColumn("ID")); 51 | } 52 | 53 | @Test 54 | public void testTableColumnLowerNowFindMixedCaseColumn() throws SQLException { 55 | ResultSet resultSet = stat.executeQuery("select * from test"); 56 | assertTrue(resultSet.next()); 57 | assertEquals(1, resultSet.findColumn("Id")); 58 | } 59 | 60 | @Test 61 | public void testTableColumnUpperNowFindLowerCaseColumn() throws SQLException { 62 | ResultSet resultSet = stat.executeQuery("select * from test"); 63 | assertTrue(resultSet.next()); 64 | assertEquals(2, resultSet.findColumn("description")); 65 | } 66 | 67 | @Test 68 | public void testTableColumnUpperNowFindUpperCaseColumn() throws SQLException { 69 | ResultSet resultSet = stat.executeQuery("select * from test"); 70 | assertTrue(resultSet.next()); 71 | assertEquals(2, resultSet.findColumn("DESCRIPTION")); 72 | } 73 | 74 | @Test 75 | public void testTableColumnUpperNowFindMixedCaseColumn() throws SQLException { 76 | ResultSet resultSet = stat.executeQuery("select * from test"); 77 | assertTrue(resultSet.next()); 78 | assertEquals(2, resultSet.findColumn("Description")); 79 | } 80 | 81 | @Test 82 | public void testTableColumnMixedNowFindLowerCaseColumn() throws SQLException { 83 | ResultSet resultSet = stat.executeQuery("select * from test"); 84 | assertTrue(resultSet.next()); 85 | assertEquals(3, resultSet.findColumn("foo")); 86 | } 87 | 88 | @Test 89 | public void testTableColumnMixedNowFindUpperCaseColumn() throws SQLException { 90 | ResultSet resultSet = stat.executeQuery("select * from test"); 91 | assertTrue(resultSet.next()); 92 | assertEquals(3, resultSet.findColumn("FOO")); 93 | } 94 | 95 | @Test 96 | public void testTableColumnMixedNowFindMixedCaseColumn() throws SQLException { 97 | ResultSet resultSet = stat.executeQuery("select * from test"); 98 | assertTrue(resultSet.next()); 99 | assertEquals(3, resultSet.findColumn("fOo")); 100 | } 101 | 102 | @Test 103 | public void testSelectWithTableNameAliasNowFindWithoutTableNameAlias() throws SQLException { 104 | ResultSet resultSet = stat.executeQuery("select t.id from test as t"); 105 | assertTrue(resultSet.next()); 106 | assertEquals(1, resultSet.findColumn("id")); 107 | } 108 | 109 | /** 110 | * Can't produce a case where column name contains table name 111 | * https://www.sqlite.org/c3ref/column_name.html : "If there is no AS clause then the name of 112 | * the column is unspecified" 113 | */ 114 | @Test 115 | public void testSelectWithTableNameAliasNowNotFindWithTableNameAlias() throws SQLException { 116 | ResultSet resultSet = stat.executeQuery("select t.id from test as t"); 117 | assertTrue(resultSet.next()); 118 | assertThrows(SQLException.class, () -> resultSet.findColumn("t.id")); 119 | } 120 | 121 | @Test 122 | public void testSelectWithTableNameNowFindWithoutTableName() throws SQLException { 123 | ResultSet resultSet = stat.executeQuery("select test.id from test"); 124 | assertTrue(resultSet.next()); 125 | assertEquals(1, resultSet.findColumn("id")); 126 | } 127 | 128 | @Test 129 | public void testSelectWithTableNameNowNotFindWithTableName() throws SQLException { 130 | ResultSet resultSet = stat.executeQuery("select test.id from test"); 131 | assertTrue(resultSet.next()); 132 | assertThrows(SQLException.class, () -> resultSet.findColumn("test.id")); 133 | } 134 | 135 | @Test 136 | public void testCloseStatement() throws SQLException { 137 | ResultSet resultSet = stat.executeQuery("select test.id from test"); 138 | 139 | stat.close(); 140 | 141 | assertTrue(stat.isClosed()); 142 | assertTrue(resultSet.isClosed()); 143 | 144 | resultSet.close(); 145 | 146 | assertTrue(resultSet.isClosed()); 147 | } 148 | 149 | @Test 150 | public void testReturnsNonAsciiCodepoints() throws SQLException { 151 | String nonAsciiString = "국정의 중요한 사항에 관한"; 152 | PreparedStatement pstat = conn.prepareStatement("select ?"); 153 | pstat.setString(1, nonAsciiString); 154 | 155 | ResultSet resultSet = pstat.executeQuery(); 156 | 157 | assertTrue(resultSet.next()); 158 | assertEquals(nonAsciiString, resultSet.getString(1)); 159 | assertFalse(resultSet.next()); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/test/java/org/sqlite/SQLiteConfigTest.java: -------------------------------------------------------------------------------- 1 | package org.sqlite; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import java.sql.SQLException; 6 | import java.util.Properties; 7 | import org.junit.jupiter.api.Test; 8 | 9 | public class SQLiteConfigTest { 10 | 11 | @Test 12 | public void toProperites() throws SQLException { 13 | SQLiteConfig config = new SQLiteConfig(); 14 | 15 | config.setReadOnly(true); 16 | config.setDateStringFormat("yyyy/mm/dd"); 17 | config.setDatePrecision("seconds"); 18 | config.setDateClass("real"); 19 | 20 | Properties properties = config.toProperties(); 21 | 22 | assertEquals( 23 | "yyyy/mm/dd", 24 | properties.getProperty(SQLiteConfig.Pragma.DATE_STRING_FORMAT.getPragmaName())); 25 | assertEquals( 26 | SQLiteConfig.DatePrecision.SECONDS.name(), 27 | properties.getProperty(SQLiteConfig.Pragma.DATE_PRECISION.getPragmaName())); 28 | assertEquals( 29 | SQLiteConfig.DateClass.REAL.name(), 30 | properties.getProperty(SQLiteConfig.Pragma.DATE_CLASS.getPragmaName())); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/org/sqlite/SQLiteConnectionPoolDataSourceTest.java: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------------- 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | * You may obtain a copy of the License at 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | *--------------------------------------------------------------------------*/ 14 | package org.sqlite; 15 | 16 | import static org.junit.jupiter.api.Assertions.assertEquals; 17 | import static org.junit.jupiter.api.Assertions.assertFalse; 18 | import static org.junit.jupiter.api.Assertions.assertTrue; 19 | import static org.junit.jupiter.api.Assertions.fail; 20 | 21 | import java.sql.Connection; 22 | import java.sql.SQLException; 23 | import java.sql.Statement; 24 | import javax.sql.ConnectionPoolDataSource; 25 | import javax.sql.PooledConnection; 26 | 27 | import org.junit.jupiter.api.BeforeEach; 28 | import org.junit.jupiter.api.Disabled; 29 | import org.junit.jupiter.api.Test; 30 | import org.sqlite.javax.SQLiteConnectionPoolDataSource; 31 | 32 | public class SQLiteConnectionPoolDataSourceTest { 33 | 34 | @BeforeEach 35 | public void loadDriver() throws ClassNotFoundException 36 | { 37 | LoadDriver.load(); 38 | } 39 | 40 | @Test 41 | public void connectionTest() throws SQLException { 42 | ConnectionPoolDataSource ds = new SQLiteConnectionPoolDataSource(); 43 | 44 | PooledConnection pooledConn = ds.getPooledConnection(); 45 | 46 | Connection handle = pooledConn.getConnection(); 47 | assertFalse(handle.isClosed()); 48 | assertTrue(handle.createStatement().execute("select 1")); 49 | 50 | Connection handle2 = pooledConn.getConnection(); 51 | assertTrue(handle.isClosed()); 52 | try { 53 | handle.createStatement().execute("select 1"); 54 | fail(); 55 | } catch (SQLException e) { 56 | assertEquals("Connection is closed", e.getMessage()); 57 | } 58 | 59 | assertTrue(handle2.createStatement().execute("select 1")); 60 | handle2.close(); 61 | 62 | handle = pooledConn.getConnection(); 63 | assertTrue(handle.createStatement().execute("select 1")); 64 | 65 | pooledConn.close(); 66 | assertTrue(handle.isClosed()); 67 | } 68 | 69 | @Disabled 70 | @Test 71 | public void proxyConnectionCloseTest() throws SQLException { 72 | ConnectionPoolDataSource ds = new SQLiteConnectionPoolDataSource(); 73 | PooledConnection pooledConn = ds.getPooledConnection(); 74 | System.out.println("pooledConn: " + pooledConn.getClass()); 75 | 76 | Connection handle = pooledConn.getConnection(); 77 | System.out.println("pooledConn.getConnection: " + handle.getClass()); 78 | 79 | Statement st = handle.createStatement(); 80 | System.out.println("statement: " + st.getClass()); 81 | Connection stConn = handle.createStatement().getConnection(); 82 | System.out.println("statement connection:" + stConn.getClass()); 83 | stConn.close(); // This closes the physical connection, not the proxy 84 | 85 | Connection handle2 = pooledConn.getConnection(); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/test/java/org/sqlite/SQLiteDataSourceTest.java: -------------------------------------------------------------------------------- 1 | // -------------------------------------- 2 | // sqlite-jdbc Project 3 | // 4 | // SQLiteDataSourceTest.java 5 | // Since: Mar 11, 2010 6 | // 7 | // $URL$ 8 | // $Author$ 9 | // -------------------------------------- 10 | package org.sqlite; 11 | 12 | import static org.junit.jupiter.api.Assertions.assertEquals; 13 | 14 | import java.nio.ByteOrder; 15 | import java.sql.Connection; 16 | import java.sql.ResultSet; 17 | import java.sql.Statement; 18 | import org.junit.jupiter.api.AfterEach; 19 | import org.junit.jupiter.api.BeforeEach; 20 | import org.junit.jupiter.api.Test; 21 | 22 | public class SQLiteDataSourceTest { 23 | 24 | @BeforeEach 25 | public void setUp() throws Exception {} 26 | 27 | @AfterEach 28 | public void tearDown() throws Exception {} 29 | 30 | @Test 31 | public void enumParam() throws Exception { 32 | 33 | SQLiteDataSource ds = new SQLiteDataSource(); 34 | Connection conn = ds.getConnection(); 35 | Statement stat = conn.createStatement(); 36 | try { 37 | 38 | stat.executeUpdate("create table A (id integer, name)"); 39 | stat.executeUpdate("insert into A values(1, 'leo')"); 40 | ResultSet rs = stat.executeQuery("select * from A"); 41 | int count = 0; 42 | while (rs.next()) { 43 | count++; 44 | int id = rs.getInt(1); 45 | String name = rs.getString(2); 46 | assertEquals(1, id); 47 | assertEquals("leo", name); 48 | } 49 | assertEquals(1, count); 50 | 51 | } finally { 52 | stat.close(); 53 | conn.close(); 54 | } 55 | } 56 | 57 | @Test 58 | public void encoding() throws Exception { 59 | 60 | String[] configArray = 61 | new String[] { 62 | "UTF8", "UTF-8", "UTF_8", 63 | "UTF16", "UTF-16", "UTF_16", 64 | "UTF_16LE", "UTF-16LE", "UTF16_LITTLE_ENDIAN", 65 | "UTF_16BE", "UTF-16BE", "UTF16_BIG_ENDIAN" 66 | }; 67 | 68 | String nativeOrder; 69 | if (ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN)) { 70 | nativeOrder = "le"; 71 | } else { 72 | nativeOrder = "be"; 73 | } 74 | String[] encodingArray = 75 | new String[] {"UTF-8", "UTF-16" + nativeOrder, "UTF-16le", "UTF-16be"}; 76 | 77 | for (int i = 0; i < configArray.length; i++) { 78 | SQLiteDataSource ds = new SQLiteDataSource(); 79 | ds.setEncoding(configArray[i]); 80 | 81 | Connection conn = ds.getConnection(); 82 | Statement stat = conn.createStatement(); 83 | try { 84 | 85 | ResultSet rs = stat.executeQuery("pragma encoding"); 86 | assertEquals(encodingArray[i / 3], rs.getString(1)); 87 | } finally { 88 | stat.close(); 89 | conn.close(); 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/test/java/org/sqlite/SQLiteJDBCLoaderTest.java: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------------- 2 | * Copyright 2007 Taro L. Saito 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *--------------------------------------------------------------------------*/ 16 | // -------------------------------------- 17 | // sqlite-jdbc Project 18 | // 19 | // SQLiteJDBCLoaderTest.java 20 | // Since: Oct 15, 2007 21 | // 22 | // $URL$ 23 | // $Author$ 24 | // -------------------------------------- 25 | package org.sqlite; 26 | 27 | import static org.junit.jupiter.api.Assertions.assertEquals; 28 | import static org.junit.jupiter.api.Assertions.assertTrue; 29 | import static org.junit.jupiter.api.Assertions.fail; 30 | 31 | import java.sql.Connection; 32 | import java.sql.DriverManager; 33 | import java.sql.ResultSet; 34 | import java.sql.SQLException; 35 | import java.sql.Statement; 36 | import java.util.concurrent.ExecutorService; 37 | import java.util.concurrent.Executors; 38 | import java.util.concurrent.TimeUnit; 39 | import java.util.concurrent.atomic.AtomicInteger; 40 | import org.junit.jupiter.api.AfterEach; 41 | import org.junit.jupiter.api.BeforeEach; 42 | import org.junit.jupiter.api.Test; 43 | 44 | public class SQLiteJDBCLoaderTest { 45 | 46 | private Connection connection = null; 47 | 48 | @BeforeEach 49 | public void setUp() throws Exception { 50 | LoadDriver.load(); 51 | connection = null; 52 | // create a database connection 53 | connection = DriverManager.getConnection("jdbc:sqlite::memory:"); 54 | } 55 | 56 | @AfterEach 57 | public void tearDown() throws Exception { 58 | if (connection != null) { 59 | connection.close(); 60 | } 61 | } 62 | 63 | @Test 64 | public void query() throws ClassNotFoundException { 65 | try { 66 | Statement statement = connection.createStatement(); 67 | statement.setQueryTimeout(30); // set timeout to 30 sec. 68 | 69 | statement.executeUpdate("create table person ( id integer, name string)"); 70 | statement.executeUpdate("insert into person values(1, 'leo')"); 71 | statement.executeUpdate("insert into person values(2, 'yui')"); 72 | 73 | ResultSet rs = statement.executeQuery("select * from person order by id"); 74 | while (rs.next()) { 75 | // read the result set 76 | rs.getInt(1); 77 | rs.getString(2); 78 | } 79 | } catch (SQLException e) { 80 | // if e.getMessage() is "out of memory", it probably means no 81 | // database file is found 82 | fail(e.getMessage()); 83 | } 84 | } 85 | 86 | @Test 87 | public void function() throws SQLException { 88 | Function.create( 89 | connection, 90 | "total", 91 | new Function() { 92 | @Override 93 | public void xFunc() throws SQLException { 94 | int sum = 0; 95 | for (int i = 0; i < args(); i++) { 96 | sum += value_int(i); 97 | } 98 | result(sum); 99 | } 100 | }); 101 | 102 | ResultSet rs = connection.createStatement().executeQuery("select total(1, 2, 3, 4, 5)"); 103 | assertTrue(rs.next()); 104 | assertEquals(rs.getInt(1), 1 + 2 + 3 + 4 + 5); 105 | } 106 | 107 | @Test 108 | public void version() { 109 | // System.out.println(SQLiteJDBCLoader.getVersion()); 110 | } 111 | 112 | @Test 113 | public void test() throws Throwable { 114 | final AtomicInteger completedThreads = new AtomicInteger(0); 115 | ExecutorService pool = Executors.newFixedThreadPool(32); 116 | for (int i = 0; i < 32; i++) { 117 | final String connStr = "jdbc:sqlite:target/sample-" + i + ".db"; 118 | final int sleepMillis = i; 119 | pool.execute( 120 | new Runnable() { 121 | public void run() { 122 | try { 123 | Thread.sleep(sleepMillis * 10); 124 | } catch (InterruptedException e) { 125 | } 126 | try { 127 | // Uncomment the synchronized block and everything works. 128 | // synchronized (TestSqlite.class) { 129 | Connection conn = DriverManager.getConnection(connStr); 130 | // } 131 | } catch (SQLException e) { 132 | e.printStackTrace(); 133 | fail(e.getLocalizedMessage()); 134 | } 135 | completedThreads.incrementAndGet(); 136 | } 137 | }); 138 | } 139 | pool.shutdown(); 140 | pool.awaitTermination(3, TimeUnit.SECONDS); 141 | assertEquals(32, completedThreads.get()); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/test/java/org/sqlite/TypeMapTest.java: -------------------------------------------------------------------------------- 1 | package org.sqlite; 2 | 3 | import java.sql.Connection; 4 | import java.sql.DriverManager; 5 | import java.sql.SQLException; 6 | import java.util.Map; 7 | 8 | import org.junit.jupiter.api.BeforeEach; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class TypeMapTest { 12 | 13 | @BeforeEach 14 | public void loadDriver() throws ClassNotFoundException 15 | { 16 | LoadDriver.load(); 17 | } 18 | 19 | 20 | public Connection getConnection() throws SQLException { 21 | return DriverManager.getConnection("jdbc:sqlite::memory:"); 22 | } 23 | 24 | @Test 25 | public void getTypeMap() throws Exception { 26 | Connection conn = getConnection(); 27 | 28 | Map> m = conn.getTypeMap(); 29 | 30 | conn.close(); 31 | } 32 | 33 | @Test 34 | public void setTypeMap() throws Exception { 35 | Connection conn = getConnection(); 36 | 37 | Map> m = conn.getTypeMap(); 38 | conn.setTypeMap(m); 39 | 40 | conn.close(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/java/org/sqlite/UDFCustomErrorTest.java: -------------------------------------------------------------------------------- 1 | package org.sqlite; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertThrows; 4 | 5 | import java.sql.Connection; 6 | import java.sql.DriverManager; 7 | import java.sql.SQLException; 8 | import java.sql.Statement; 9 | import org.junit.jupiter.api.AfterEach; 10 | import org.junit.jupiter.api.BeforeEach; 11 | import org.junit.jupiter.api.Test; 12 | 13 | /** Tests User Defined Functions. */ 14 | public class UDFCustomErrorTest { 15 | private Connection conn; 16 | private Statement stat; 17 | 18 | @BeforeEach 19 | public void connect() throws Exception { 20 | LoadDriver.load(); 21 | conn = DriverManager.getConnection("jdbc:sqlite:"); 22 | stat = conn.createStatement(); 23 | } 24 | 25 | @AfterEach 26 | public void close() throws SQLException { 27 | stat.close(); 28 | conn.close(); 29 | } 30 | 31 | @Test 32 | public void customErr() throws SQLException { 33 | Function.create( 34 | conn, 35 | "f9", 36 | new Function() { 37 | @Override 38 | public void xFunc() throws SQLException { 39 | throw new SQLException("myErr"); 40 | } 41 | }); 42 | assertThrows(SQLException.class, () -> stat.executeQuery("select f9();")); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/org/sqlite/util/OSInfoTest.java: -------------------------------------------------------------------------------- 1 | // -------------------------------------- 2 | // sqlite-jdbc Project 3 | // 4 | // OSInfoTest.java 5 | // Since: May 20, 2008 6 | // 7 | // $URL$ 8 | // $Author$ 9 | // -------------------------------------- 10 | package org.sqlite.util; 11 | 12 | import static org.junit.jupiter.api.Assertions.assertEquals; 13 | import static org.junit.jupiter.api.Assertions.assertFalse; 14 | import static org.junit.jupiter.api.Assertions.assertTrue; 15 | import static org.mockito.Mockito.mock; 16 | import static org.mockito.Mockito.when; 17 | 18 | import java.io.ByteArrayOutputStream; 19 | import java.io.IOException; 20 | import java.io.PrintStream; 21 | import java.util.logging.Logger; 22 | import org.junit.jupiter.api.Nested; 23 | import org.junit.jupiter.api.Test; 24 | import org.junitpioneer.jupiter.SetSystemProperty; 25 | 26 | public class OSInfoTest { 27 | private static final Logger logger = Logger.getLogger(OSInfoTest.class.getName()); 28 | 29 | @Test 30 | public void osName() { 31 | assertEquals("Windows", OSInfo.translateOSNameToFolderName("Windows XP")); 32 | assertEquals("Windows", OSInfo.translateOSNameToFolderName("Windows 2000")); 33 | assertEquals("Windows", OSInfo.translateOSNameToFolderName("Windows Vista")); 34 | assertEquals("Windows", OSInfo.translateOSNameToFolderName("Windows 98")); 35 | assertEquals("Windows", OSInfo.translateOSNameToFolderName("Windows 95")); 36 | 37 | assertEquals("Mac", OSInfo.translateOSNameToFolderName("Mac OS")); 38 | assertEquals("Mac", OSInfo.translateOSNameToFolderName("Mac OS X")); 39 | 40 | assertEquals("AIX", OSInfo.translateOSNameToFolderName("AIX")); 41 | 42 | assertEquals("Linux", OSInfo.translateOSNameToFolderName("Linux")); 43 | assertEquals("OS2", OSInfo.translateOSNameToFolderName("OS2")); 44 | 45 | assertEquals("HPUX", OSInfo.translateOSNameToFolderName("HP UX")); 46 | } 47 | 48 | @Test 49 | public void archName() { 50 | assertEquals("i386", OSInfo.translateArchNameToFolderName("i386")); 51 | assertEquals("x86", OSInfo.translateArchNameToFolderName("x86")); 52 | assertEquals("ppc", OSInfo.translateArchNameToFolderName("ppc")); 53 | assertEquals("amd64", OSInfo.translateArchNameToFolderName("amd64")); 54 | } 55 | 56 | @Test 57 | public void folderPath() { 58 | String[] component = OSInfo.getNativeLibFolderPathForCurrentOS().split("/"); 59 | assertEquals(2, component.length); 60 | assertEquals(OSInfo.getOSName(), component[0]); 61 | assertEquals(OSInfo.getArchName(), component[1]); 62 | } 63 | 64 | @Test 65 | public void testMainForOSName() throws Exception { 66 | 67 | // preserve the current System.out 68 | PrintStream out = System.out; 69 | try { 70 | // switch STDOUT 71 | ByteArrayOutputStream buf = new ByteArrayOutputStream(); 72 | PrintStream tmpOut = new PrintStream(buf); 73 | System.setOut(tmpOut); 74 | OSInfo.main(new String[] {"--os"}); 75 | assertEquals(OSInfo.getOSName(), buf.toString()); 76 | } finally { 77 | // reset STDOUT 78 | System.setOut(out); 79 | } 80 | } 81 | 82 | @Test 83 | public void testMainForArchName() throws Exception { 84 | 85 | // preserver the current System.out 86 | PrintStream out = System.out; 87 | try { 88 | // switch STDOUT 89 | ByteArrayOutputStream buf = new ByteArrayOutputStream(); 90 | PrintStream tmpOut = new PrintStream(buf); 91 | System.setOut(tmpOut); 92 | OSInfo.main(new String[] {"--arch"}); 93 | assertEquals(OSInfo.getArchName(), buf.toString()); 94 | } finally { 95 | // reset STDOUT 96 | System.setOut(out); 97 | } 98 | } 99 | 100 | @Test 101 | public void testGetHardwareName() throws Exception { 102 | String hardware = OSInfo.getHardwareName(); 103 | logger.info("Hardware name: " + hardware); 104 | } 105 | 106 | // it's unlikely we run tests on an Android device 107 | @Test 108 | void testIsNotAndroid() { 109 | assertFalse(OSInfo.isAndroid()); 110 | } 111 | 112 | @Nested 113 | @SetSystemProperty(key = "java.runtime.name", value = "Java for Android") 114 | @SetSystemProperty(key = "os.name", value = "Linux for Android") 115 | class Android { 116 | @Test 117 | public void testIsAndroid() { 118 | assertTrue(OSInfo.isAndroid()); 119 | } 120 | 121 | @Test 122 | @SetSystemProperty(key = "os.arch", value = "arm") 123 | public void testArmvNativePath() throws IOException, InterruptedException { 124 | try { 125 | ProcessRunner mockRunner = mock(ProcessRunner.class); 126 | OSInfo.processRunner = mockRunner; 127 | when(mockRunner.runAndWaitFor("uname -m")).thenReturn("armv7l"); 128 | 129 | assertEquals("Linux-Android/arm", OSInfo.getNativeLibFolderPathForCurrentOS()); 130 | } finally { 131 | OSInfo.processRunner = new ProcessRunner(); 132 | } 133 | } 134 | 135 | @Test 136 | @SetSystemProperty(key = "os.arch", value = "arm64") 137 | public void testArm64NativePath() throws IOException, InterruptedException { 138 | try { 139 | ProcessRunner mockRunner = mock(ProcessRunner.class); 140 | OSInfo.processRunner = mockRunner; 141 | when(mockRunner.runAndWaitFor("uname -m")).thenReturn("aarch64"); 142 | 143 | assertEquals("Linux-Android/aarch64", OSInfo.getNativeLibFolderPathForCurrentOS()); 144 | } finally { 145 | OSInfo.processRunner = new ProcessRunner(); 146 | } 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /src/test/resources/org/sqlite/attach_test.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/src/test/resources/org/sqlite/attach_test.db -------------------------------------------------------------------------------- /src/test/resources/org/sqlite/sample.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/src/test/resources/org/sqlite/sample.db -------------------------------------------------------------------------------- /src/test/resources/org/sqlite/testdb.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boulder-on/sqlite-jdbc/9de526874e3afbd5f9f6108b97e36d9170287a16/src/test/resources/org/sqlite/testdb.jar --------------------------------------------------------------------------------