diff --git a/.travis.yml b/.travis.yml index de8ec181f..657792ba5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ language: java services: - docker - mysql -jdk: openjdk11 +jdk: openjdk17 addons: hosts: - mariadb.example.com @@ -48,8 +48,6 @@ jobs: - env: srv=build - env: srv=xpand TEST_DB_OTHER="&initSql=SET NAMES UTF8" - env: srv=mariadb-es local=1 - - env: srv=skysql - - env: srv=skysql-ha include: - stage: Minimal env: srv=mariadb v=10.6 packet=8 @@ -75,10 +73,6 @@ jobs: name: "Maxscale" - env: srv=xpand TEST_DB_OTHER="&initSql=SET NAMES UTF8" name: "Xpand" - - env: srv=skysql - name: "SkySQL" - - env: srv=skysql-ha - name: "SkySQL with replication" - stage: Community env: srv=mariadb v=10.6 @@ -99,11 +93,11 @@ jobs: name: "CS 10.11" - env: srv=mariadb v=11.0 local=1 name: "CS 11.0" - - env: srv=mariadb v=11.1-rc local=1 + - env: srv=mariadb v=11.1 local=1 name: "CS 11.1" - env: srv=mariadb v=10.6 packet=40 - jdk: openjdk17 - name: "CS 10.6 - openjdk 17" + jdk: openjdk11 + name: "CS 10.6 - openjdk 11" - env: srv=mariadb v=10.6 packet=8 name: "CS 10.6 - packet 8M" - env: srv=mariadb v=10.6 local=1 BENCH=1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 4938f7618..2c58c8c3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,45 +1,72 @@ # Change Log +## [3.3.0](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.3.0) (Nov 2023) + +[Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.2.0...3.3.0) + +##### Notable Changes + +* CONJ-1115 Make connector become more virtual-thread friendly +* CONJ-1108 Database metadata listing TEMPORARY tables/sequences +* CONJ-1113 update ed25519 to recent version +* CONJ-1116 Avoid unnecessary synchronization on calendar when no calendar parameter + +##### Bugs Fixed + +* CONJ-1102 BatchUpdateException.getUpdateCounts() returns SUCCESS_NO_INFO but expects EXECUTE_FAILED + ## [3.2.0](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.2.0) (Aug 2023) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.1.4...3.2.0) ##### Notable Changes -* CONJ-920 Java batched statements with optimistic locking failing. the option `useBulkStmts` is now disable by default, a new option `useBulkStmtsForInserts` is enable by default, permetting using bulk for INSERT commands only. This permits optimistic behavior working by default. -* CONJ-1084 When using maxscale 23.08.0+, and a maxscale node fails, connector will now priorize reconnection to the maxscale node having less connection, to ensure repartition after failover -* CONJ-1088 Implement `databaseTerm` option for mysql compatibility + +* CONJ-920 Java batched statements with optimistic locking failing. the option `useBulkStmts` is now disable by default, + a new option `useBulkStmtsForInserts` is enabled by default, permitting using bulk for INSERT commands only. This + permits optimistic behavior working by default. +* CONJ-1084 When using maxscale 23.08.0+, and a maxscale node fails, connector will now priorize reconnection to the + maxscale node having less connection, to ensure repartition after failover +* CONJ-1088 Implement `databaseTerm` option for mysql compatibility * CONJ-1096 adding option `useLocalSessionState` to permit avoiding queries when application only use JDBC methods. ##### Bugs Fixed + * CONJ-1075 LOAD DATA INFILE is broken on windows -* CONJ-1079 getGeneratedKeys after batch will not return all generated id's if first batch command return no generated id. -* CONJ-1080 maridb Java connector sslMode=verify-ca complaining unable to find trust certificate. +* CONJ-1079 getGeneratedKeys after batch will not return all generated id's if first batch command return no generated + id. +* CONJ-1080 mariadb Java connector sslMode=verify-ca complaining unable to find trust certificate. * CONJ-1082 Multiple session system variables parsing fails -* CONJ-1083 Using /*client prepare*/ prefix to force client side prepared statement -* CONJ-1091 can't make a connection when the Read Replica DB is in a hang state when SocketTimeout=0 set +* CONJ-1083 Using /*client prepare*/ prefix to force client side prepared statement +* CONJ-1091 can't make a connection when the Read Replica DB is in a hang state when SocketTimeout=0 set * CONJ-1092 ensure respecting server collation -* CONJ-1094 Missing mariadb/mysql collation - +* CONJ-1094 Missing mariadb/mysql collation ## [3.0.11](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.11) (Aug 2023) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.10...3.0.11) -* CONJ-1089 correcting 3.0.10 incompatibility with in java 8 +* CONJ-1089 correcting 3.0.10 incompatibility with in java 8 ## [2.7.10](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.7.10) (Aug 2023) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.7.9...2.7.10) -* CONJ-1091 Ensure setting connectTimeout as timeout for socket timeout until connection is done. This permit to set a connectTimeout, while socketTimeout can still be set to 0 +* CONJ-1091 Ensure setting connectTimeout as timeout for socket timeout until connection is done. This permit to set a + connectTimeout, while socketTimeout can still be set to 0 ## [3.1.4](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.1.4) (Apr 2023) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.1.3...3.1.4) * CONJ-1065 wrong Resultset.wasNull() for zero-date timestamps -* CONJ-1070 getBlob on TEXT columns throw Exception -* CONJ-1071 Error response during Bulk execution might result in connection wrong state -* CONJ-1067 When some numeric data types are set to UNSIGNED, ResultSetMetaData.getColumnTypeName() does not return UNSIGNED +* CONJ-1070 getBlob on TEXT columns throw Exception +* CONJ-1071 Error response during Bulk execution might result in connection wrong state +* CONJ-1067 When some numeric data types are set to UNSIGNED, ResultSetMetaData.getColumnTypeName() does not return + UNSIGNED ## [3.1.3](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.1.3) (Mar 2023) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.1.2...3.1.3) * CONJ-1054 Threadsafety issue when using CredentialPlugin in v3.x @@ -50,65 +77,74 @@ * report 2.7.9 bug fixes CONJ-1062 and CONJ-1063 ## [2.7.9](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.7.9) (Mar 2023) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.7.8...2.7.9) * CONJ-1062 correcting TlsSocketPlugin to use Driver classloader * CONJ-1063 DatabaseMetaData.getTypeInfo() returns wrong value for UNSIGNED_ATTRIBUTE ## [3.1.2](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.1.2) (Jan 2023) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.1.1...3.1.2) * CONJ-1040 possible ConcurrentModificationException when connecting * CONJ-1041 possible ArrayIndexOutOfBoundsException ## [2.7.8](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.7.8) (Jan 2023) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.7.7...2.7.8) * CONJ-1039 setQueryTimeout not honored by CallableStatement for procedures depending on security context * CONJ-1041 possible ArrayIndexOutOfBoundsException * CONJ-1023 set missing SSL capability in handshake after SSL exchanges - ## [3.1.1](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.1.1) (Jan 2023) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.1.0...3.1.1) - 3.0.10 bug fix: - - CONJ-1023 Connector/J doesn't set SSL cap bit in Handshake Response Packet - - CONJ-1026 timezone=auto option failure on non-fixed-offset zone machine - - CONJ-1032 Compatibility for deprecated arguments is case sensitive now -- CONJ-1036 org.mariadb.jdbc.client.socket.impl.PacketWriter.writeAscii() broken in 3.1.0 - + - CONJ-1023 Connector/J doesn't set SSL cap bit in Handshake Response Packet + - CONJ-1026 timezone=auto option failure on non-fixed-offset zone machine + - CONJ-1032 Compatibility for deprecated arguments is case sensitive now +- CONJ-1036 org.mariadb.jdbc.client.socket.impl.PacketWriter.writeAscii() broken in 3.1.0 ## [3.0.10](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.10) (Jan 2023) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.9...3.0.10) -* CONJ-1023 Connector/J doesn't set SSL cap bit in Handshake Response Packet -* CONJ-1026 timezone=auto option failure on non-fixed-offset zone machine -* CONJ-1032 Compatibility for deprecated arguments is case sensitive now +* CONJ-1023 Connector/J doesn't set SSL cap bit in Handshake Response Packet +* CONJ-1026 timezone=auto option failure on non-fixed-offset zone machine +* CONJ-1032 Compatibility for deprecated arguments is case sensitive now ## [3.1.0](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.1.0) (Nov 2022) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.9...3.1.0) ##### Notable Changes + * CONJ-899 Support UUID Object * CONJ-916 when a failover occurs, log replayed transaction * CONJ-917 deprecated options use must be logged * CONJ-992 load balance distribution -* CONJ-1008 default value for socket option useReadAheadInput -* CONJ-1009 improve performance reading big result-set -* CONJ-1014 avoid creating array when receiving server packet -* CONJ-1015 pipelining sending multiple packet to socket +* CONJ-1008 default value for socket option useReadAheadInput +* CONJ-1009 improve performance reading big result-set +* CONJ-1014 avoid creating array when receiving server packet +* CONJ-1015 pipelining sending multiple packet to socket ##### Bugs Fixed -* CONJ-1020 java 11 option setting ignored + +* CONJ-1020 java 11 option setting ignored ## [3.0.9](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.9) (Nov 2022) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.8...3.0.9) + * 2.7.7 merge -* CONJ-1012 stored procedure register output parameter as null if set before registerOutParameter command +* CONJ-1012 stored procedure register output parameter as null if set before registerOutParameter command * CONJ-1017 Calendar possible race condition, cause wrong timestamp setting ## [2.7.7](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.7.7) (Nov 2022) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.7.6...2.7.7) * CONJ-1021 GSSAPI authentication might result in connection reset @@ -118,13 +154,16 @@ * CONJ-1007 Socket file descriptors are leaked after connecting with unix socket if DB is not up running ## [3.0.8](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.8) (Sept 2022) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.7...3.0.8) ##### Notable Changes + * small performance improvement - * [CONJ-1010] improve client side prepared parameter parameter substitution - + * [CONJ-1010] improve client side prepared parameter parameter substitution + ##### Bugs Fixed + * [CONJ-997] regression in 3.x when using option galeraAllowedState resulting in an IndexOutOfBoundsException * [CONJ-1002] 2nd failover reconnection ignores default database/schema setting when not set by connection string * [CONJ-1003] replication configuration always use 1st replica on 3.0 @@ -134,19 +173,20 @@ * [CONJ-1010] improve client side prepare statement parameter substitution * [CONJ-999] setting createDatabaseIfNotExist option use on read-only server will refuse connection on 3.0 - ## [3.0.7](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.7) (Jul 2022) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.6...3.0.7) -* [CONJ-993] SQLDataException reading DATA_TYPE on DatabaseMetaData.getTypeInfo() after 3.0.4 -* [CONJ-986] Permit specific Statement.setLocalInfileInputStream for compatibility -* [CONJ-987] Version 3.0.0 returns String for VARBINARY instead of byte[] as 2.7.6 did +* [CONJ-993] SQLDataException reading DATA_TYPE on DatabaseMetaData.getTypeInfo() after 3.0.4 +* [CONJ-986] Permit specific Statement.setLocalInfileInputStream for compatibility +* [CONJ-987] Version 3.0.0 returns String for VARBINARY instead of byte[] as 2.7.6 did * [CONJ-989] Binary column read as String -* [CONJ-990] Setting timezone=UTC result in SQLSyntaxErrorException -* [CONJ-991] Regression: binary(16) is returned as String by getObject() +* [CONJ-990] Setting timezone=UTC result in SQLSyntaxErrorException +* [CONJ-991] Regression: binary(16) is returned as String by getObject() * [CONJ-994] Version 3.x rejects previously accepted boolean string parameter for BOOLEAN field ## [3.0.6](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.6) (Jun 2022) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.5...3.0.6) * [CONJ-953] PreparedStatement.getGeneratedKeys() returns rows when no keys are generated in insert @@ -158,30 +198,32 @@ * [CONJ-985] ResultSet.getObject() returns ByteSet instead of Byte[] for BIT ## [3.0.5](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.5) (may 2022) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.4...3.0.5) -* [CONJ-956] ArrayIndexOutOfBoundsException when alias length > 250 -* [CONJ-947] value after milliseconds precision lost when timestamp is encoded +* [CONJ-956] ArrayIndexOutOfBoundsException when alias length > 250 +* [CONJ-947] value after milliseconds precision lost when timestamp is encoded * [CONJ-949] keep clientCertificateKeyStoreUrl and clientCertificateKeyStoreUrl aliases * [CONJ-950] metadata TEXT/TINYTEXT/MEDIUMTEXT/LONGTEXT wrong column type and length * [CONJ-954] java.time.OffsetDateTime not supported -* [CONJ-958] compatibility with 2.7: now loop through hosts when multiple host without failover mode -* [CONJ-959] java.time.Instant not supported -* [CONJ-961] LOAD DATA LOCAL INFILE was disable by default -* [CONJ-962] resultset for negative TIME value return erronous LocalDateTime values +* [CONJ-958] compatibility with 2.7: now loop through hosts when multiple host without failover mode +* [CONJ-959] java.time.Instant not supported +* [CONJ-961] LOAD DATA LOCAL INFILE was disable by default +* [CONJ-962] resultset for negative TIME value return erronous LocalDateTime values * [CONJ-965] better error message when not loading serverSslCert file -* [CONJ-967] clearParameters() breaks validity when using output parameters in stored procedures +* [CONJ-967] clearParameters() breaks validity when using output parameters in stored procedures * [CONJ-969] org.mariadb.jdbc.ClientPreparedStatement is missing a toString implementation, useful for logging - ## [3.0.4](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.4) (Mar 2022) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.3...3.0.4) * [CONJ-915] javadoc addition * [CONJ-921] DatabaseMetadata#getTables with null value for tableNamePattern throws Syntax error * [CONJ-922] DECIMAL overflow for long/int/short not throwing exception * [CONJ-924] NULL column type might result in java.lang.IllegalArgumentException: Unexpected datatype NULL -* [CONJ-926] Client restrict authentication to 'mysql_native_password,client_ed25519,auth_gssapi_client' if restrictedAuth parameter is not set +* [CONJ-926] Client restrict authentication to 'mysql_native_password,client_ed25519,auth_gssapi_client' if + restrictedAuth parameter is not set * [CONJ-924] NULL column test correction * [CONJ-923] correctly return 64 bits generated id / updated rows * [CONJ-933] load-balancing failover doesn't timeout @@ -194,17 +236,19 @@ * [CONJ-940] Permit updating rows when not having primary info on metadata (Xpand) * [CONJ-939] add Xpand testing - ## [3.0.3](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.3) (Jan 2022) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.2-rc...3.0.3) -* [CONJ-908] correct Connection.prepareStatement(String sql, int[] columnIndexes/String[] columnNames) to return generated keys +* [CONJ-908] correct Connection.prepareStatement(String sql, int[] columnIndexes/String[] columnNames) to return + generated keys * [CONJ-909] adding createDatabaseIfNotExist option for 2.x compatibility * [CONJ-910] permit jdbc:mysql scheme when connection string contains "permitMysqlScheme" for compatibility * [CONJ-913] Avoid executing additional command on connection for faster connection creation * [CONJ-912] remove security manager code (JEP 411) * [CONJ-911] enable keep-alive by default -* failover improvement. some specific commands not in transaction are considered to be replayed in case of failover, like PING, PREPARE, ROLLBACK, ... +* failover improvement. some specific commands not in transaction are considered to be replayed in case of failover, + like PING, PREPARE, ROLLBACK, ... * CONJ-705 parameter metadata get parameter count even when query cannot be prepared * prepareStatement.addBatch must initialize with previous set * Connection.prepareStatement(String sql, int[] columnIndexes/String[] columnNames) must return generated keys @@ -218,57 +262,63 @@ * [CONJ-901] ArrayIndexOutOfBoundsException on StandardReadableByteBuf.readByte error ## [3.0.2-rc](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.2-rc) (31 Aug 2021) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.1-beta...3.0.2-rc) * CONJ-879 Java 9 module full support - * Aws IAM credential now use sdk v2 authentication that support java 9 modularity + * Aws IAM credential now use sdk v2 authentication that support java 9 modularity * CONJ-896 Ensure pool connections validation when a socket fail * CONJ-897 Ensure having connection's thread id in Exception / debug logs -minor: -* Ensure travis testing for PR/fork +minor: + +* Ensure travis testing for PR/fork ## [3.0.1-beta](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.1-beta) (29 Jul 2021) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/3.0.0-alpha...3.0.1-beta) * CONJ-879 Provide JPMS module descriptor * CONJ-880 metadata query performance correction * CONJ-884 MariaDbPoolDataSource leaks connections when the mariadb server restarts * CONJ-885 org.mariadb.jdbc.internal.util.pool.Pool swallows SQLException during addConnection -* CONJ-891 getImportedKeys with null catalog restrict result to current database +* CONJ-891 getImportedKeys with null catalog restrict result to current database * CONJ-894 Adding useMysqlMetadata for 2.7 compatibility - ## [2.7.4](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.7.4) (29 Jul 2021) -[Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.7.3...2.7.4) -* CONJ-890 getImportedKeys/getTables regression returning an empty resultset for null/empty catalog -* CONJ-863 Ensure socket state when SocketTimeout occurs -* CONJ-873 IndexOutOfBoundsException when executing prepared queries using automatic key generation in parallel -* CONJ-884 MariaDbPoolDataSource leaks connections when the mariadb server restarts -* CONJ-893 DatabaseMetaData.getColumns regression causing TINYINT(x) with x > 1 to return BIT type in place of TINYINT -* CONJ-889 CallableStatement using function throw wrong error on getter +[Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.7.3...2.7.4) +* CONJ-890 getImportedKeys/getTables regression returning an empty resultset for null/empty catalog +* CONJ-863 Ensure socket state when SocketTimeout occurs +* CONJ-873 IndexOutOfBoundsException when executing prepared queries using automatic key generation in parallel +* CONJ-884 MariaDbPoolDataSource leaks connections when the mariadb server restarts +* CONJ-893 DatabaseMetaData.getColumns regression causing TINYINT(x) with x > 1 to return BIT type in place of TINYINT +* CONJ-889 CallableStatement using function throw wrong error on getter ## [3.0.0](https://github.com/mariadb-corporation/mariadb-connector-j/tree/3.0.0) (3 May 2021) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.7.2...3.0.0) -This version is a total rewrite of java driver. +This version is a total rewrite of java driver. * complete rewrite, code clarification, reduced size (15%), more than 90% coverage tested. * Encoding/decoding implementation are now registred by Codec, permitting codec registry implementation - * example support of Geometry Object + * example support of Geometry Object * Permit authentication plugin restriction by option `restrictedAuth` * performance improvement: - * Prepare and execution are now using pipelining when using option `useServerPrepStmts` - * performance enhancement with MariaDB 10.6 server when using option `useServerPrepStmts`, skipping metadata (see https://jira.mariadb.org/browse/MDEV-19237) + * Prepare and execution are now using pipelining when using option `useServerPrepStmts` + * performance enhancement with MariaDB 10.6 server when using option `useServerPrepStmts`, skipping metadata ( + see https://jira.mariadb.org/browse/MDEV-19237) +correction: -correction: -* CONJ-864 includeThreadDumpInDeadlockExceptions always includes the thread dump, even when it is not a deadlock exception +* CONJ-864 includeThreadDumpInDeadlockExceptions always includes the thread dump, even when it is not a deadlock + exception * CONJ-858 Properties parameter that differ from string not taken in account ### Easy logging + If using slf4J, just enabled package "org.mariadb.jdbc" log. level ERROR will log connection error @@ -276,19 +326,21 @@ level WARNING will log query errors level DEBUG will log queries level TRACE will log all exchanges with server. -If not using slf4J, console will be used. -If really wanting to use JDK logger, System property "mariadb.logging.fallback" set to JDK will indicate to use common logging. - +If not using slf4J, console will be used. +If really wanting to use JDK logger, System property "mariadb.logging.fallback" set to JDK will indicate to use common +logging. ### Failover -Failover implementation now permit redoing transaction : -when creating a transaction, all command will be cached, and can be replayed in case of failover. + +Failover implementation now permit redoing transaction : +when creating a transaction, all command will be cached, and can be replayed in case of failover. This functionality can be enabled using option `transactionReplay`. -This is not enabled by default, because this required that application to avoid using non-idempotent commands. +This is not enabled by default, because this required that application to avoid using non-idempotent commands. example: + ```sql START TRANSACTION; select next_val(hibernate_sequence); @@ -301,37 +353,40 @@ COMMIT; ### Allow setup of TCP_KEEPIDLE, TCP_KEEPCOUNT, TCP_KEEPINTERVAL Equivalent options are `tcpKeepIdle`, `tcpKeepCount`, `tcpKeepInterval` -Since available only with java 11, setting this option with java < 11 will have no effect. +Since available only with java 11, setting this option with java < 11 will have no effect. ## [2.7.3](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.7.3) (12 May 2021) -[Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.7.2...2.7.3) -* CONJ-619 Multiple batch update fails after LOAD DATA LOCAL INFILE -* CONJ-854 LOAD XML INFILE breaks when using LOCAL -* CONJ-855 throwing more specific exception for updatable result-set that can not be updated by ResultSet -* CONJ-857 Remove use of mysql.proc table, relying on information_schema.parameters -* CONJ-864 includeThreadDumpInDeadlockExceptions always includes the thread dump, even when it is not a deadlock exception -* CONJ-866 long binary parsing improvement -* CONJ-871 OSGi: Missing Import-Package in Connector/J bundle (javax.sql.rowset.serial) -* CONJ-878 option serverSslCert file location -* CONJ-880 metadata query performance correction -* CONJ-858 Properties.put with object that differ from String supported even if use is not recommended -* CONJ-861 executeBatch must not clear last parameter value. -* CONJ-883 using unix socket, hostname is not mandatory anymore +[Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.7.2...2.7.3) +* CONJ-619 Multiple batch update fails after LOAD DATA LOCAL INFILE +* CONJ-854 LOAD XML INFILE breaks when using LOCAL +* CONJ-855 throwing more specific exception for updatable result-set that can not be updated by ResultSet +* CONJ-857 Remove use of mysql.proc table, relying on information_schema.parameters +* CONJ-864 includeThreadDumpInDeadlockExceptions always includes the thread dump, even when it is not a deadlock + exception +* CONJ-866 long binary parsing improvement +* CONJ-871 OSGi: Missing Import-Package in Connector/J bundle (javax.sql.rowset.serial) +* CONJ-878 option serverSslCert file location +* CONJ-880 metadata query performance correction +* CONJ-858 Properties.put with object that differ from String supported even if use is not recommended +* CONJ-861 executeBatch must not clear last parameter value. +* CONJ-883 using unix socket, hostname is not mandatory anymore ## [2.7.2](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.7.2) (29 Jan. 2021) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.7.1...2.7.2) * CONJ-847 NPE at UpdatableResultSet#close -* CONJ-849 driver now doesn't close connection caused java.io.NotSerializableException as a result of incorrect data bind to a prepared statement parameter +* CONJ-849 driver now doesn't close connection caused java.io.NotSerializableException as a result of incorrect data + bind to a prepared statement parameter * CONJ-850 MariaDbResultSetMetaData#getPrecision(int) now returns correct length for character data * CONJ-851 metadata getBestRowIdentifier incompatibility with MySQL 8 correction * CONJ-853 Support Aurora cluster custom endpoints * CONJ-852 ON DUPLICATE KEY detection failed when using new line - ## [2.7.1](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.7.1) (23 Nov. 2020) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.7.0...2.7.1) * CONJ-834 use of BULK batch is conditioned by capability, not checking server version @@ -340,39 +395,42 @@ Since available only with java 11, setting this option with java < 11 will have * CONJ-841 ResultSetMetaData::getColumnTypeName() returns incorrect type name for LONGTEXT * CONJ-842 Byte array parameters are now send as long data * CONJ-837 prepared statement cache leak on ResultSet CONCUR_UPDATABLE concurrency -* CONJ-843 ParameterMetaData::getParameterType for CallableStatement parameter return expected "BINARY" value for BINARY type +* CONJ-843 ParameterMetaData::getParameterType for CallableStatement parameter return expected "BINARY" value for BINARY + type minor: + * CONJ-845 test suite now test SkySQL with replication setting * CONJ-838 have a 'replica' alias for 'slave' connection option - ## [2.7.0](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.7.0) (24 Sep. 2020) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.6.2...2.7.0) -* CONJ-805 maxFieldSize string truncation occurs on bytes' length, not character length -* CONJ-807 Correcting possible Get Access Denied error if using multiple classloader -* CONJ-810 normalization of resultset getDate/getTime of timestamp field. -* CONJ-812 DatabaseMetadata.getBestRowIdentifier and getMaxProcedureNameLength correction -* CONJ-813 setConfiguration not being called on classes that extend ConfigurableSocketFactory -* CONJ-816 Table with primary key with DEFAULT function can be inserted for 10.5 servers -* CONJ-817 Switched position of REMARKS and PROCEDURE_TYPE in the getProcedures result -* CONJ-820 MySQLPreparedStatement.setObject can now handle java.lang.Character type -* CONJ-828 new option `ensureSocketState` to ensure protocol state -* CONJ-829 Option to cache callablestatement is now disabled by default -* CONJ-830 connector now throw a better error if SSL is mandatory and server doesn't support SSL -* CONJ-814 Small possible improvement of getCrossReference, getExportedKeys and getImportedKey -* CONJ-825 XAResource.isSameRM implementation +* CONJ-805 maxFieldSize string truncation occurs on bytes' length, not character length +* CONJ-807 Correcting possible Get Access Denied error if using multiple classloader +* CONJ-810 normalization of resultset getDate/getTime of timestamp field. +* CONJ-812 DatabaseMetadata.getBestRowIdentifier and getMaxProcedureNameLength correction +* CONJ-813 setConfiguration not being called on classes that extend ConfigurableSocketFactory +* CONJ-816 Table with primary key with DEFAULT function can be inserted for 10.5 servers +* CONJ-817 Switched position of REMARKS and PROCEDURE_TYPE in the getProcedures result +* CONJ-820 MySQLPreparedStatement.setObject can now handle java.lang.Character type +* CONJ-828 new option `ensureSocketState` to ensure protocol state +* CONJ-829 Option to cache callablestatement is now disabled by default +* CONJ-830 connector now throw a better error if SSL is mandatory and server doesn't support SSL +* CONJ-814 Small possible improvement of getCrossReference, getExportedKeys and getImportedKey +* CONJ-825 XAResource.isSameRM implementation ## [2.6.2](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.6.2) (23 Jul. 2020) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.6.1...2.6.2) * CONJ-804 - Automatic charset correction * CONJ-809 - SelectResultSet's (ResultSet)MetaData always indicates all columns to be readonly * CONJ-802 - Version parsing depending on Classloader might result in connection Exception - ## [2.6.1](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.6.1) (23 Jun. 2020) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.6.0...2.6.1) * CONJ-781 - DatabaseMetaData.supportsMultipleResultSets() now return correctly true. @@ -381,7 +439,8 @@ minor: * CONJ-775 - avoid a NPE for malformed "jdbc:mariadb:///" connection string. * CONJ-776 - Temporal Data Tables are not listed in metadata * CONJ-785 - corrected escape sequence for multiple backslash escape -* CONJ-786 - Connection.setReadOnly(true ) with option `assureReadOnly` now force read only connection even for mono server* +* CONJ-786 - Connection.setReadOnly(true ) with option `assureReadOnly` now force read only connection even for mono + server* * CONJ-795 - permit resultset.getRow() for TYPE_FORWARD_ONLY when streaming * CONJ-797 - Connector set UTF8mb4 equivalent in case of server configured with UTF8mb3 collation * CONJ-800 - implement Statement setEscapeProcessing to avoid escape @@ -394,9 +453,11 @@ minor: * CONJ-782 - SkySQL testing ## [2.6.0](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.6.0) (19 Mar. 2020) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.5.4...2.6.0) -* CONJ-768 - Check Galera allowed state when connecting when option `galeraAllowedState` is set, and not only on validation +* CONJ-768 - Check Galera allowed state when connecting when option `galeraAllowedState` is set, and not only on + validation * CONJ-759 - on failover, catalog changed might not be set when automatically recreating a connection. * CONJ-761 - remove unnecessary dependencies for fedora tar creation * CONJ-763 - Custom SocketFactory now can change options @@ -408,12 +469,14 @@ minor: * CONJ-772 - JDBC Conversion Function support parsing correction ## [2.5.4](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.5.4) (27 Jan. 2020) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.5.3...2.5.4) * CONJ-756 - Logging correction when using enablePacketDebug option * CONJ-755 - permits avoiding setting session_track_schema with new option `trackSchema` ## [2.5.3](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.5.3) (07 Jan. 2020) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.5.2...2.5.3) * CONJ-752 - Manifest file wrong entry - thanks to Christoph Läubrich @@ -421,14 +484,15 @@ minor: * CONJ-747 - JDBC Conversion Function fast-path skipped, always using longer implementation ## [2.5.2](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.5.2) (22 Nov. 2019) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.5.1...2.5.2) * CONJ-745 - use pool reset only for corrected COM_RESET_CONNECTION * CONJ-743 - byte signed value wrong serialization for text protocol * CONJ-742 - ensure plugin using Driver classloader - ## [2.5.1](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.5.1) (15 Oct. 2019) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.5.0...2.5.1) * CONJ-736 - OSGI compliance @@ -436,28 +500,33 @@ minor: * CONJ-738 - PAM authentication multiple exchanges permitting multiple step in connection string * CONJ-735 - Multi insert regression correction returning multi generated keys - ## [2.5.0](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.5.0) (02 Oct. 2019) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.4.4...2.5.0) -* CONJ-663 - Client authentication plugins are now defined as services. The driver has 2 new plugins `caching_sha2_password` and `sha256_password plugin` for MySQL compatibility +* CONJ-663 - Client authentication plugins are now defined as services. The driver has 2 new + plugins `caching_sha2_password` and `sha256_password plugin` for MySQL compatibility * CONJ-733 - Credential service: AWS IAM authentication * CONJ-727 - Support configuration of custom SSLSocketFactory -* CONJ-561 - JDBC 4.3 partial implementation java.sql.Statement methods isSimpleIdentifier, enquoteIdentifier, enquoteLiteral and enquoteNCharLiteral +* CONJ-561 - JDBC 4.3 partial implementation java.sql.Statement methods isSimpleIdentifier, enquoteIdentifier, + enquoteLiteral and enquoteNCharLiteral * CONJ-692 - ConnectionPoolDataSource interface addition to MariaDbPoolDataSource * CONJ-563 - closing possible option batch thread on driver registration. * CONJ-732 - Driver getPropertyInfo returns no options' information when url is empty * CONJ-734 - DatabaseMetaData.getSchemaTerm now return "schema", not empty string ## [2.4.4](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.4.4) (14 Sep. 2019) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.4.3...2.4.4) * CONJ-724 - Do not ignore the Calendar parameter in ResultSet#getTime(int, Calendar) * CONJ-725 - Connection Failure when using PAM authenticated user on 10.4 MariaDB server -* CONJ-729 - master-slave regression: commit on read-only server Executed only when there is an active transaction on master connection +* CONJ-729 - master-slave regression: commit on read-only server Executed only when there is an active transaction on + master connection * CONJ-726 - removing possible NPE after failover on aurora cluster ## [2.4.3](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.4.3) (02 Jul. 2019) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.4.2...2.4.3) * CONJ-717 - conversion function support for other data type than default MariaDB conversion type @@ -466,39 +535,50 @@ minor: * CONJ-716 - Correcting possible NPE on non thread safe NumberFormat (logging) ## [2.4.2](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.4.2) (17 Jun. 2019) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.4.1...2.4.2) Security + * CONJ-679 - parse Query when receiving LOAD LOCAL INFILE Bugs + * CONJ-703 - ClassNotFoundException when trying to connect using two-authentication in an OSGI environment. * CONJ-711 - Xid format id is unsigned integer, currently sending as signed value. * CONJ-700 - autoReconnect=true on Basic Failover doesn't reconnect -* CONJ-707 - failover might throw an unexpected exception with using "failover"/"sequential" configuration on socket error -* CONJ-709 - includeThreadDumpInDeadlockExceptions is thrown only if option includeInnodbStatusInDeadlockExceptions is set +* CONJ-707 - failover might throw an unexpected exception with using "failover"/"sequential" configuration on socket + error +* CONJ-709 - includeThreadDumpInDeadlockExceptions is thrown only if option includeInnodbStatusInDeadlockExceptions is + set * CONJ-710 - Throw complete stackTrace when having an exception on XA Commands * CONJ-714 - Error on connection on galera server when in detached mode. * CONJ-701 - typo in error message in SelectResultSet.java ## [2.4.1](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.4.1) (15 Mar. 2019) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.4.0...2.4.1) Evolutions + * misc - enabled running of 'SHOW ENGINE INNODB STATUS' for error code 1213 (@mtykhenko) * misc - reduce mutex using select @@innodb_read_only for aurora (@matsuzayaws) Bugs + * misc - updating checkstyle version dependency * misc - permit using SSL on localsocket * CONJ-687 - addition of option "useMysqlMetadata" to permit MySQL meta compatibility * misc - java PID using java 9 ProcessHandle if existing, relying on JNA if present -* CONJ-682 - internal pool correction: when receiving an RST during connection validation, the pool will end up throwing connection timeout exception in place of reusing another connection. +* CONJ-682 - internal pool correction: when receiving an RST during connection validation, the pool will end up throwing + connection timeout exception in place of reusing another connection. ## [2.4.0](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.4.0) (28 Jan. 2019) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.3.0...2.4.0) Evolutions + * CONJ-675 - permit multiple alternative authentication methods for the same user (future MariaDB 10.4 feature) * CONJ-678 - permit indication of truststore/keystore type (JKS/PKCS12), then not relying on java default type * CONJ-378 - GSSAPI: client can provide SPN @@ -509,14 +589,15 @@ Evolutions New options -|Option|Description| -|---|---| -|useReadAheadInput|use a buffered inputSteam that read socket available data.
Default: true| -|keyStoreType|indicate key store type (JKS/PKCS12). default is null, then using java default type.| -|trustStoreType|indicate trust store type (JKS/PKCS12). default is null, then using java default type| -|servicePrincipalName|when using GSSAPI authentication, SPN (Service Principal Name) use the server SPN information. When set, connector will use this value, ignoring server information| +| Option | Description | +|----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| useReadAheadInput | use a buffered inputSteam that read socket available data.
Default: true | +| keyStoreType | indicate key store type (JKS/PKCS12). default is null, then using java default type. | +| trustStoreType | indicate trust store type (JKS/PKCS12). default is null, then using java default type | +| servicePrincipalName | when using GSSAPI authentication, SPN (Service Principal Name) use the server SPN information. When set, connector will use this value, ignoring server information | Bugs + * CONJ-646 - possible NullPointerException when connection lost to database using aurora configuration with one node * CONJ-672 - batch using multi-send can hang when using query timeout * CONJ-544 - disable SSL session resumption when using SSL @@ -530,12 +611,13 @@ Bugs * CONJ-674 - make dumpQueriesOnException = false by default as per documentation minor: + * CONJ-644 - small optimization when validating galera connection * CONJ-625 - add coverage test * CONJ-654 - DatabaseMetaData.getDriverName() returns connector/J with a lowercase c - ## [2.3.0](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.3.0) (06 Sep. 2018) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.2.6...2.3.0) #### [CONJ-398] Improve deadlock debugging capabilities @@ -543,82 +625,99 @@ minor: MariaDB has now 2 new options to permit identifying deadlock : New options -|Option|Description| -|---|---| -|includeInnodbStatusInDeadlockExceptions|add "SHOW ENGINE INNODB STATUS" result to exception trace when having a deadlock exception.
//Default: false| -|includeThreadDumpInDeadlockExceptions|add thread dump to exception trace when having a deadlock exception.
Default: false| +| Option | Description | +|-----------------------------------------|--------------------------------------------------------------------------------------------------------------------------| +| includeInnodbStatusInDeadlockExceptions | add "SHOW ENGINE INNODB STATUS" result to exception trace when having a deadlock exception.
//Default: false | +| includeThreadDumpInDeadlockExceptions | add thread dump to exception trace when having a deadlock exception.
Default: false | #### [CONJ-639] the option "enabledSslProtocolSuites" now include TLSv1.2 by default -previous default value was "TLSv1, TLSv1.1", disabling TLSv1.2 by default, due to a corrected issue (MDEV-12190) with servers using YaSSL - not openSSL. Server error was . -Now, the default value is "TLSv1, TLSv1.1, TLSv1.2". So TLSv1.2 can be use directly. -Connecting MySQL community server use YaSSL without correction, and connection might result in SSLException: "Unsupported record version Unknown-0.0". +previous default value was "TLSv1, TLSv1.1", disabling TLSv1.2 by default, due to a corrected issue (MDEV-12190) with +servers using YaSSL - not openSSL. Server error was . +Now, the default value is "TLSv1, TLSv1.1, TLSv1.2". So TLSv1.2 can be use directly. +Connecting MySQL community server use YaSSL without correction, and connection might result in SSLException: " +Unsupported record version Unknown-0.0". #### [CONJ-642] disable the option "useBulkStmts" by default + Using useBulkStmts permit faster batch, but cause one major issue : Batch return -1 = SUCCESS_NO_INFO Different option use this information for optimistic update, and cannot confirm if update succeed or not. This option still makes sense, since for big batch is way faster, but will not be activated by default. - ##= Minor change: + * CONJ-628 - optimization to read metadata faster -* CONJ-637 - java.sql.Driver class implement DriverPropertyInfo[] getPropertyInfo, permitting listing options on querying tools +* CONJ-637 - java.sql.Driver class implement DriverPropertyInfo[] getPropertyInfo, permitting listing options on + querying tools * CONJ-639 - enabledSslProtocolSuites does not include TLSv1.2 by default * CONJ-641 - update maven test dependencies for java 10 compatibility -* CONJ-643 - PreparedStatement::getParameterMetaData always returns VARSTRING as type resulting in downstream libraries interpreting values wrongly +* CONJ-643 - PreparedStatement::getParameterMetaData always returns VARSTRING as type resulting in downstream libraries + interpreting values wrongly ##= Bug correction: -* CONJ-616 - correction on possible NPE on getConnection when using failover configuration and master is down, not throwing a proper exception -* CONJ-636 - Error in batch might throw a NPE and not the proper Exception +* CONJ-616 - correction on possible NPE on getConnection when using failover configuration and master is down, not + throwing a proper exception +* CONJ-636 - Error in batch might throw a NPE and not the proper Exception ## [2.2.6](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.2.6) (19 Jul. 2018) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.2.5...2.2.6) minor change: + * CONJ-623 - Increase connection logging when Primary node connection fails * CONJ-384 - Permit knowing affected rows number, not only real changed rows New options |=useAffectedRows|default correspond to the JDBC standard, reporting real affected rows. if -enable, will report "affected" rows. example : if enabled, an update command that doesn't change a row value will still be "affected", then report.
Default: false. Since 2.2.6 +enable, will report "affected" rows. example : if enabled, an update command that doesn't change a row value will still +be "affected", then report.
Default: false. Since 2.2.6 Bug correction: + * CONJ-624 - MariaDbPoolDataSource possible NPE on configuration getter * CONJ-623 - Increase connection logging when Primary node connection fails * CONJ-622 - The option "connectTimeout" must take in account DriverManager.getLoginTimeout() when set * CONJ-621 - wrong escaping when having curly bracket in table/field name * CONJ-618 - Client preparestatement parsing error on escaped ' / " in query - ## [2.2.5](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.2.5) (28 May. 2018) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.2.4...2.2.5) minor change: + * CONJ-602 - Add server hostname to connection packet for proxy * CONJ-604 - handle support for mysql 8.0 tx_isolation replacement by transaction_isolation Bug correction: + * CONJ-613 - Connection using "replication" Parameters fail when no slave is available * CONJ-595 - Create option to configure DONOR/DESYNCED Galera nodes to be unavailable for load-balancing * CONJ-605 - Newlines where breaking calling stored procedures -* CONJ-609 - Using getDate with function DATE_ADD() with parameter using string format where return wrong result using binary protocol +* CONJ-609 - Using getDate with function DATE_ADD() with parameter using string format where return wrong result using + binary protocol * CONJ-610 - Option "allowMasterDownConnection" improvement on connection validation and Exceptions on master down ## [2.2.4](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.2.4) (04 May. 2018) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.2.3...2.2.4) Minor changes: + * CONJ-580 - Some options are missing in documentation like default 'autocommit' value * CONJ-597 - Internal exchanges send utf8mb4 with server even if default server collation is not utf8/utf8mb4 * CONJ-600 - Upgrading non-mandatory Waffle dependency to 1.9.0 (windows GSSAPI authentication) * CONJ-575 - test addition to ensure YaSSL downgrade TLSv1.2 protocol to TLSv1.1 ## [2.2.3](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.2.3) (08 Mar. 2018) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.2.2...2.2.3) Bug correction: + * CONJ-583 - possible hang indefinitely using master/slave configuration and failover occur * CONJ-586 - erroneous transaction state when first command result as error * CONJ-587 - using allowMasterDownConnection option can lead to NPE when using setReadOnly() @@ -626,9 +725,11 @@ Bug correction: * CONJ-534 - Connection.isValid() must be routed to Master and Slave connections to avoid any server timeout ## [2.2.2](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.2.2) (20 Feb. 2018) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.2.1...2.2.2) Bug correction: + * CONJ-564 - Never ever throw an instance of java.lang.Error * CONJ-579 - Keywords missing from DatabaseMetaData.getSQLKeywords() * CONJ-567 - UrlParser.initialUrl gets overwritten @@ -639,81 +740,90 @@ Bug correction: * CONJ-570 - Add tests for 10.3.3 INVISIBLE column ## [2.2.1](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.2.1) (22 Dec. 2017) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.2.0...2.2.1) * CONJ-501 - provide support for authentication plugin ed25519 Bug correction: -* CONJ-529 - failover : the driver will pause for 250ms if no servers are available before attempting to reconnect another time + +* CONJ-529 - failover : the driver will pause for 250ms if no servers are available before attempting to reconnect + another time * CONJ-548 - don't use COM_STMT_BULK_EXECUTE for INSERT ... SELECT statements -* CONJ-549 - correction on connection reset when using MariaDbPoolDataSource with options useServerPrepStmts and useResetConnection enabled +* CONJ-549 - correction on connection reset when using MariaDbPoolDataSource with options useServerPrepStmts and + useResetConnection enabled * CONJ-555 - failover caused by client timeout must not reuse connection * CONJ-558 - removing extra ".0" to resultset.getString() value for FLOAT/DOUBLE fields * CONJ-550 - fetching state correction when reusing statement without having read all results * CONJ-553 - RejectedExecutionException was thrown when having large amount of concurrent batches - - ## [2.2.0](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.2.0) (08 Nov. 2017) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.1.2...2.2.0) Evolutions: + #### CONJ-522 - Pool datasource implementation MariaDB has now 2 different Datasource implementation : + * MariaDbDataSource : Basic implementation. A new connection each time method getConnection() is called. -* MariaDbPoolDataSource : Connection pooling implementation. MariaDB Driver will keep a pool of connection and borrow Connections when asked for it. +* MariaDbPoolDataSource : Connection pooling implementation. MariaDB Driver will keep a pool of connection and borrow + Connections when asked for it. New options -|Option|Description| -|---|---| -|pool|Use pool. This option is useful only if not using a DataSource object, but only connection object.
Default: false. since 2.2.0| -|poolName|Pool name that will permit to identify thread.
default: auto-generated as MariaDb-pool- since 2.2.0| -|maxPoolSize| The maximum number of physical connections that the pool should contain.
Default: 8. since 2.2.0| -|minPoolSize| When connection are removed since not used since more than "maxIdleTime", connections are closed and removed from pool. "minPoolSize" indicate the number of physical connections the pool should keep available at all times. Should be less or equal to maxPoolSize.
Default: maxPoolSize value. Since 2.2.0| -|poolValidMinDelay| When asking a connection to pool, Pool will validate connection state. "poolValidMinDelay" permit to disable this validation if connection has been borrowed recently avoiding useless verification in case of frequent reuse of connection. 0 meaning validation is done each time connection is asked.
Default: 1000 (in milliseconds). Since 2.2.0| -|maxIdleTime|The maximum amount of time in seconds that a connection can stay in pool when not used. This value must always be below @wait_timeout value - 45s
Default: 600 in seconds (=10 minutes), minimum value is 60 seconds. Since 2.2.0| -|staticGlobal|Indicate the following global variable (@@max_allowed_packet,@@wait_timeout,@@autocommit,@@auto_increment_increment,@@time_zone,@@system_time_zone,@@tx_isolation) values won't changed, permitting to pool to create new connection faster.
Default: false. Since 2.2.0| -|useResetConnection|When a connection is closed() (give back to pool), pool reset connection state. Setting this option, session variables change will be reset, and user variables will be destroyed when server permit it (MariaDB >= 10.2.4, MySQL >= 5.7.3), permitting to save memory on server if application make extensive use of variables
Default: false. Since 2.2.0| +| Option | Description | +|--------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| pool | Use pool. This option is useful only if not using a DataSource object, but only connection object.
Default: false. since 2.2.0 | +| poolName | Pool name that will permit to identify thread.
default: auto-generated as MariaDb-pool- since 2.2.0 | +| maxPoolSize | The maximum number of physical connections that the pool should contain.
Default: 8. since 2.2.0 | +| minPoolSize | When connection are removed since not used since more than "maxIdleTime", connections are closed and removed from pool. "minPoolSize" indicate the number of physical connections the pool should keep available at all times. Should be less or equal to maxPoolSize.
Default: maxPoolSize value. Since 2.2.0 | +| poolValidMinDelay | When asking a connection to pool, Pool will validate connection state. "poolValidMinDelay" permit to disable this validation if connection has been borrowed recently avoiding useless verification in case of frequent reuse of connection. 0 meaning validation is done each time connection is asked.
Default: 1000 (in milliseconds). Since 2.2.0 | +| maxIdleTime | The maximum amount of time in seconds that a connection can stay in pool when not used. This value must always be below @wait_timeout value - 45s
Default: 600 in seconds (=10 minutes), minimum value is 60 seconds. Since 2.2.0 | +| staticGlobal | Indicate the following global variable (@@max_allowed_packet,@@wait_timeout,@@autocommit,@@auto_increment_increment,@@time_zone,@@system_time_zone,@@tx_isolation) values won't changed, permitting to pool to create new connection faster.
Default: false. Since 2.2.0 | +| useResetConnection | When a connection is closed() (give back to pool), pool reset connection state. Setting this option, session variables change will be reset, and user variables will be destroyed when server permit it (MariaDB >= 10.2.4, MySQL >= 5.7.3), permitting to save memory on server if application make extensive use of variables
Default: false. Since 2.2.0 | Other evolutions: + * CONJ-530 - Permit Connection.abort() forcing killing the connection, even if connection is stuck in another thread * CONJ-531 - permit cancelling streaming result-set using Statement.cancel. * CONJ-495 - Improve reading result-set data * CONJ-510 - allow execution of read-only statements on slaves when master is down - Bug : + * CONJ-532 - correction Statement.getMoreResults() for multi-queries -* CONJ-533 - PrepareStatement.setTime() may insert incorrect time according to current timezone, time and option "useLegacyDatetimeCode" +* CONJ-533 - PrepareStatement.setTime() may insert incorrect time according to current timezone, time and option " + useLegacyDatetimeCode" * CONJ-535 - correction on numerical getter for big BIT data type fields * CONJ-541 - Fix behavior of ResultSet#relative when crossing result set boundaries - Misc: + * CONJ-469 - Improve Blob/Clob implementation (avoiding array copy from result-set row) * CONJ-539 - better message when server close connection * misc - resultset.findColumn method use column name if alias not found * misc - default option "connectTimeout" value to 30 seconds (was 0 = no timeout) * misc - ensure that enablePacketDebug option works when timer tick is big - - ## [2.1.2](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.1.2) (24 Sep. 2017) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.1.1...2.1.2) Bug : + * CONJ-525 - Batch result-set return array correction when DELETE statement when bulk option is used * CONJ-526 - better error message getting metadata information when SQL syntax is wrong * CONJ-527 - Resultset.last() return wrong value if resultset has only one result * CONJ-528 - Error executing LOAD DATA LOCAL INFILE when file is larger than max_allowed_packet - ## [2.1.1](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.1.1) (05 Sep. 2017) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.1.0...2.1.1) Bug : + * CONJ-519 - Updatable result-set possible NPE when same field is repeated. * CONJ-514 - ResultSet method wasNull() always return true after a call on a "null-date" field binary protocol handling * CONJ-516 - Permit using updatable result-set when fetching @@ -721,19 +831,23 @@ Bug : * CONJ-515 - Improve MariaDB driver stability in case JNA errors misc : + * correct typo in error message when setting wrong parameter * add trace to HostnameVerifier implementation * handling connection error when no database is provided - ## [2.1.0](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.1.0) (29 Jul. 2017) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.0.3...2.1.0) ##= CONJ-422 : verification of SSL Certificate Name Mismatch -When using ssl, driver check hostname against the server's identity as presented in the server's Certificate (checking alternative names or certificate CN) to prevent man-in-the-middle attack. +When using ssl, driver check hostname against the server's identity as presented in the server's Certificate (checking +alternative names or certificate CN) to prevent man-in-the-middle attack. A new option "disableSslHostnameVerification" permit to deactivate this validation. -|=disableSslHostnameVerification| When using ssl, driver check hostname against the server's identity as presented in the server's Certificate (checking alternative names or certificate CN) to prevent man-in-the-middle attack. This option permit to deactivate this validation.
//Default: false. Since 2.1.0// +|=disableSslHostnameVerification| When using ssl, driver check hostname against the server's identity as presented in +the server's Certificate (checking alternative names or certificate CN) to prevent man-in-the-middle attack. This option +permit to deactivate this validation.
//Default: false. Since 2.1.0// ##= CONJ-400 - Galera validation When configuration with multi-master, Connection.isValid() will not only validate connection, but primary state. @@ -758,40 +872,45 @@ rs.updateRow(); } }}} - ##= CONJ-389 - faster batch insert -Use dedicated [COM_STMT_BULK_EXECUTE |https://mariadb.com/kb/en/mariadb/com_stmt_bulk_execute/] protocol for batch insert when possible. +Use dedicated [COM_STMT_BULK_EXECUTE |https://mariadb.com/kb/en/mariadb/com_stmt_bulk_execute/] protocol for batch +insert when possible. (batch without Statement.RETURN_GENERATED_KEYS and streams) to have faster batch. (significant only if server MariaDB ≥ 10.2.7) A new option "useBulkStmts" permit to deactivate this functionality. -|=useBulkStmts| Use dedicated COM_STMT_BULK_EXECUTE protocol for batch insert when possible. (batch without Statement.RETURN_GENERATED_KEYS and streams) to have faster batch. (significant only if server MariaDB ≥ 10.2.7)
//Default: true. Since 2.1.0// - +|=useBulkStmts| Use dedicated COM_STMT_BULK_EXECUTE protocol for batch insert when possible. (batch without +Statement.RETURN_GENERATED_KEYS and streams) to have faster batch. (significant only if server MariaDB ≥ +10.2.7)
//Default: true. Since 2.1.0// other evolution + * CONJ-508 - Connection.getCatalog() optimisation for 10.2+ server using new session_track_schema capabilities * CONJ-492 - Failover handle automatic reconnection on KILL command Bug + * CONJ-502 - isolation leak when using multiple pools on same VM on failover * CONJ-503 - regression on aurora Connection.isReadOnly() * CONJ-505 - correcting issue that ended throwing "Unknown prepared statement handler given to mysqld_stmt_execute" * CONJ-496 - return rounded numeric when querying on a decimal field in place of throwing an exception for compatibility - ## [2.0.3](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.0.3) (27 Jun. 2017) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.0.2...2.0.3) Bug + * CONJ-473 - when useServerPrepStmts is not set, the PREPARE statement must not be cached. * CONJ-494 - Handle PrepareStatement.getParameterMetaData() if query cannot be PREPAREd * CONJ-497 - escape string correction for big query - ## [2.0.2](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.0.2) (05 Jun. 2017) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.0.1...2.0.2) Bug + * CONJ-490 - DataSource connectTimeout is in second, but was set on socket timeout that is in milliseconds * CONJ-481 - Buffer overrun reading ResultSet when using option "useServerPrepStmts" * CONJ-470 - Error when executing SQL contains "values" and rewriteBatchedStatements=true @@ -804,11 +923,13 @@ Bug * CONJ-489 - javax.transaction.xa.XAException message error truncated ( near '0x ) Task + * CONJ-478 - Change CI tests to use maxscale 2.1 version * CONJ-482 - Connection.setNetworkTimeout don't throw exception if no executor * CONJ-488 - Use java.net.URL to read keyStore and trustStore again ## [2.0.1](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.0.1) (10 May. 2017) + [Full Changelog](https://github.com/mariadb-corporation/mariadb-connector-j/compare/2.0.0-RC...2.0.1) * CONJ-467 - changing database metadata to 4.2 @@ -819,11 +940,12 @@ Task * CONJ-465 - new option "enablePacketDebug" New Options : -|=enablePacketDebug|Driver will save the last 16 MySQL packet exchanges (limited to first 1000 bytes).
Hexadecimal value of this packet will be added to stacktrace when an IOException occur.
This options has no performance incidence (< 1 microseconds per query) but driver will then take 16kb more memory.//Default: true. Since 1.6.0//| +|=enablePacketDebug|Driver will save the last 16 MySQL packet exchanges (limited to first 1000 bytes).
Hexadecimal +value of this packet will be added to stacktrace when an IOException occur.
This options has no performance +incidence (< 1 microseconds per query) but driver will then take 16kb more memory.//Default: true. Since 1.6.0//| * CONJ-468 - autoIncrementIncrement value loaded during connection, avoiding a query for first statement for rewrite - ## [2.0.0-RC](https://github.com/mariadb-corporation/mariadb-connector-j/tree/2.0.0-RC) (20 Apr. 2017) Release candidate version. @@ -835,30 +957,36 @@ Implement some protocol changes that permit to save some bytes.(part of https:// ##= CONJ-341 : handle SERVER_SESSION_STATE_CHANGE status flag With server with version MariaDB 10.2, MySQL 5.7, ensure driver state : -- driver does now always get current database, even database is changed by query. -- when using rewriteBatchedStatements does return correct autoincrement ids even when session variable @auto_increment_increment has change during session. +- driver does now always get current database, even database is changed by query. +- when using rewriteBatchedStatements does return correct autoincrement ids even when session variable + @auto_increment_increment has change during session. ##= CONJ-393 : improve setQueryTimeout to use SET STATEMENT max_statement_time -Previous implementation of query timeout handling (using Statement.setQueryTimeout) will create an additional thread with a scheduler. -When timeout is reached, a temporary connection will be created to permit executing "KILL QUERY ", then closing the temporary connection. +Previous implementation of query timeout handling (using Statement.setQueryTimeout) will create an additional thread +with a scheduler. +When timeout is reached, a temporary connection will be created to permit executing "KILL +QUERY ", then closing the temporary connection. When query ended before timeout, the scheduled task will be canceled. If server is > 10.1.2, query timeout will be handle server side using "SET MAX_STATEMENT_TIME FOR" command. ##= [CONJ-315] -Closing a Statement that was fetching a result-set (using Statement.setFetchSize) and all rows where not read at the time of closing, a kill query command +Closing a Statement that was fetching a result-set (using Statement.setFetchSize) and all rows where not read at the +time of closing, a kill query command will be executed on close, to avoid having to parse all remaining results. ##= [CONJ-442] Memory optimization : streaming query. -Very big command now doesn't use any intermediate buffer. Commands are sent directly to socket avoiding using memory, This permit to send very large object (1G) without using any additional memory. +Very big command now doesn't use any intermediate buffer. Commands are sent directly to socket avoiding using memory, +This permit to send very large object (1G) without using any additional memory. ##= [CONJ-366] Faster connection : bundle first commands in authentication packet -Driver execute different command on connection. Those queries are now send using pipeline (all queries are sent, then only all results are reads). +Driver execute different command on connection. Those queries are now send using pipeline (all queries are sent, then +only all results are reads). New Options : |=usePipelineAuth|Fast connection creation.//Default: true. Since 2.0.0//| @@ -867,6 +995,7 @@ New Options : Parsing row result optimisation to avoid creating byte array to the maximum for faster results and less memory use. ##= Remaining JDBC 4.2 missing implementation : + - CONJ-414 - support for large update count [CONJ-414] - CONJ-409 - PrepareStatement.setObject(...) support for with java 8 temporal object. - CONJ-411 - support for Statement maxFieldSize @@ -887,8 +1016,8 @@ Parsing row result optimisation to avoid creating byte array to the maximum for * CONJ-411 - Implement Statement maxFieldSize * CONJ-449 - Permit CallableStatement streaming - ## 1.5.9 + * CONJ-212 : Implement password encoding charset option * CONJ-423 : Permit to have MySQL driver and MariaDB driver in same classpath * CONJ-431 : multi-values queries return only one generated key @@ -898,9 +1027,11 @@ Parsing row result optimisation to avoid creating byte array to the maximum for * CONJ-446 : ResultSet first() throw an exception for scroll type if TYPE_FORWARD_ONLY when streaming * CONJ-440 : handle very big COM_STMT_SEND_LONG_DATA packet (1Gb) * CONJ-429 : ResultSet.getDouble/getFloat may throw a NumberFormatException -* CONJ-438 : using option rewriteBatchedStatements, permit rewrite when query has column/table that contain 'select' keyword. +* CONJ-438 : using option rewriteBatchedStatements, permit rewrite when query has column/table that contain 'select' + keyword. ## 1.5.8 + * CONJ-424 : getGeneratedKeys() on table without generated key failed on second execution * CONJ-412 : Metadata take in account tinyInt1isBit in method columnTypeClause * CONJ-418 : ResultSet.last() isLast() afterLast() and isAfterLast() correction when streaming @@ -911,12 +1042,13 @@ Parsing row result optimisation to avoid creating byte array to the maximum for * CONJ-420 : High CPU usage against Aurora after 2 hours inactivity ## 1.5.7 + * CONJ-407 : handling failover when packet > max_allowed_packet reset the connection state. * CONJ-403 : possible NPE on ResultSet.close() correction * CONJ-405 : Calendar instance not cleared before being used in ResultSet.getTimestamp - ## 1.5.6 + * CONJ-399 : resultSet getLong() for BIGINT column fails if value is Long.MIN_VALUE in Text protocol * CONJ-395 : Aurora does not randomise selection of read replicas * CONJ-392 : Aurora cluster endpoint detection timezone issue @@ -927,6 +1059,7 @@ Parsing row result optimisation to avoid creating byte array to the maximum for * CONJ-396 : handling multiple resultSet correctly (was failing if more than 2) ## 1.5.5 + * CONJ-386 : Disabling useBatchMultiSend option for Aurora, since can hang connection. * CONJ-385 : Store procedure with resultSet get wrong getUpdateCount() value (0 in place of -1) * CONJ-383 : permit OldAuthSwitchRequest protocol (compatibility with 5.5 server using plugin) @@ -940,12 +1073,15 @@ Parsing row result optimisation to avoid creating byte array to the maximum for * CONJ-362 : fix a possible race condition MariaDbPooledConnection ## 1.5.4 + * CONJ-363 : Connection.getClientInfo implementation correction to follow JDBC rules * CONJ-361 : PrepareStatement setString() with empty string correction. -* CONJ-360 : replacing ManagementFactory.getRuntimeMXBean() that cause possible slow connection depending on JVM / environment +* CONJ-360 : replacing ManagementFactory.getRuntimeMXBean() that cause possible slow connection depending on JVM / + environment * CONJ-359 : Metadata getColumns(...) resultSet doesnt have "IS_GENERATEDCOLUMN" info ## 1.5.3 + * CONJ-358 : Permit using private key with password that differ from keyStore password * CONJ-356 : secure connection : use KeyStore private key and associate public keys certificates only * CONJ-342 : Empty clientCertificateKeyStoreUrl option correction @@ -956,32 +1092,43 @@ Parsing row result optimisation to avoid creating byte array to the maximum for * CONJ-350 : make prepare fallback to client prepare if query cannot be prepared ## 1.5.2 + Release version + * CONJ-331 : clearWarnings() now throw exception on closed connection * CONJ-299 : PreparedStatement.setObject(Type.BIT, "1") registered as true. * CONJ-293 : permit named pipe connection without host * CONJ-333 : ResultSet.getString() of PreparedStatement return NULL When TIME column value=00:00:00 RC corrections + * CONJ-335 : Pool connection may fail to connect with good user * CONJ-332 : option enabledSslCipherSuites rely on java supportedCipherSuites (replacing enabledCipherSuites) * UTF-8 conversion correction ## 1.5.1 + Release candidate version + ### Evolution + #### Aurora host auto-discovery + (CONJ-325) Aurora now auto discover nodes from cluster endpoint. ##### Aurora endpoints -Every aurora instance has a specific endpoint, i.e. a URL that identify the host. Those endpoints look like `xxx.yyy.zzz.rds.amazonaws.com`. +Every aurora instance has a specific endpoint, i.e. a URL that identify the host. Those endpoints look +like `xxx.yyy.zzz.rds.amazonaws.com`. -There is another endpoint named "cluster endpoint" (format `xxx.cluster-yyy.zzz.rds.amazonaws.com`) which is assigned to the current master instance and will change when a new master is promoted. +There is another endpoint named "cluster endpoint" (format `xxx.cluster-yyy.zzz.rds.amazonaws.com`) which is assigned to +the current master instance and will change when a new master is promoted. -In previous version, cluster endpoint use was discouraged, since when a failover occur, this cluster endpoint can point for a limited time to a host that isn't the current master anymore. Old recommandation was to list all specific end-points, like :
+In previous version, cluster endpoint use was discouraged, since when a failover occur, this cluster endpoint can point +for a limited time to a host that isn't the current master anymore. Old recommandation was to list all specific +end-points, like :
{{{ jdbc:mariadb:aurora://a.yyy.zzz.rds.amazonaws.com.com,b.yyy.zzz.rds.amazonaws.com.com/db }}} @@ -990,35 +1137,47 @@ This kind of url string will still work, but now, recommended url string has to jdbc:mariadb:aurora://xxx.cluster-yyy.zzz.rds.amazonaws.com/db }}} -Driver will automatically discover master and slaves of this cluster from current cluster end-point during connection time. This permit to add new replicas to the cluster instance will be discovered without changing driver configuration. +Driver will automatically discover master and slaves of this cluster from current cluster end-point during connection +time. This permit to add new replicas to the cluster instance will be discovered without changing driver configuration. -This discovery append at connection time, so if you are using pool framework, check if this framework as a property that controls the maximum lifetime of a connection in the pool, and set a value to avoid infinite lifetime. When this lifetime is reached, pool will discard the current connection, and create a new one (if needed). New connections will use the new replicas. +This discovery append at connection time, so if you are using pool framework, check if this framework as a property that +controls the maximum lifetime of a connection in the pool, and set a value to avoid infinite lifetime. When this +lifetime is reached, pool will discard the current connection, and create a new one (if needed). New connections will +use the new replicas. (If connections are never discarded, new replicas will begin be used only when a failover occur) - ### Bugfix + * CONJ-329 and CONJ-330 : rewriteBatchedStatements execute single query exceptions correction. -

+

## 1.5.0 + Release candidate version + ### Use native SSPI windows implementation + CONJ-295.
Java kerberos implementation is not well implemented with windows : -* need a Windows registry entry (HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\Kerberos\Parameters\AllowTGTSessionKey) so windows shared current ticket to java. + +* need a Windows registry entry ( + HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\Kerberos\Parameters\AllowTGTSessionKey) so windows shared + current ticket to java. * java kinit must be executed to create a Ticket. * restriction when client with local admin rights * ... [see openJDK issue](https://bugs.openjdk.java.net/browse/JDK-6722928) for more information -Kerberos GSSAPI implementation on Windows in now based on [Waffle](https://github.com/dblock/waffle) that support windows SSPI based on [JNA](https://github.com/java-native-access/jna).
+Kerberos GSSAPI implementation on Windows in now based on [Waffle](https://github.com/dblock/waffle) that support +windows SSPI based on [JNA](https://github.com/java-native-access/jna).
if waffle-jna (and dependencies) is on classpath, native implementation will automatically be used. This removes all those problems ### Support for TLSv1.1 and TLSv1.2 + CONJ-249/CONJ-301
Driver before version 1.5 support only TLSv1.
@@ -1026,24 +1185,34 @@ Default supported protocol are now TLSv1 and TLSv1.1, other protocols can be act MariaDB and MySQL community server permit TLSv1 and TLSv1.1.
MariaDB server from version 10.0.15 is using the openSSL library permitting TLSv1.2 (>= 5.5.41 for the 5.5 branch). -//YaSSL doesn't support TLSv1.2, so if MariaDB server is build from sources with YaSSL, only TLSv1 and TLSv1.1 will be available, even for version > 10.0.15// +//YaSSL doesn't support TLSv1.2, so if MariaDB server is build from sources with YaSSL, only TLSv1 and TLSv1.1 will be +available, even for version > 10.0.15// TLSv1.2 can be enabled by setting option {{{enabledSslProtocolSuites}}} to values {{{"TLSv1, TLSv1.1, TLSv1.2"}}}. A new option {{{enabledSslCipherSuites}}} permit setting specific cipher. New Options : -|=enabledSslProtocolSuites|Force TLS/SSL protocol to a specific set of TLS versions (comma separated list).
Example : "TLSv1, TLSv1.1, TLSv1.2"
//Default: TLSv1, TLSv1.1. Since 1.5.0//| -|=enabledSslCipherSuites|Force TLS/SSL cipher (comma separated list).
Example : "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"
//Default: use JRE ciphers. Since 1.5.0//| +|=enabledSslProtocolSuites|Force TLS/SSL protocol to a specific set of TLS versions (comma separated list).
+Example : "TLSv1, TLSv1.1, TLSv1.2"
//Default: TLSv1, TLSv1.1. Since 1.5.0//| +|=enabledSslCipherSuites|Force TLS/SSL cipher (comma separated list).
Example : " +TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"
//Default: use JRE ciphers. Since +1.5.0//| ### Performance improvement + [CONJ-291]
Different performance improvement have been done : -* Using PreparedStatement on client side use a simple query parser to identify query parameters. This parsing was taking up to 7% of query time, reduced to 3%. + +* Using PreparedStatement on client side use a simple query parser to identify query parameters. This parsing was taking + up to 7% of query time, reduced to 3%. * Better UTF-8 decoding avoiding memory consumption and gain 1-2% query time for big String. -* client parsing optimization : rewriteBatchedStatements (insert into ab (i) values (1) and insert into ab (i) values (2) rewritten as insert into ab (i) values (1), (2)) - is now 19% faster (Depending on queries 40-50% of CPU time was spend testing that buffer size is big enough to contain query). +* client parsing optimization : rewriteBatchedStatements (insert into ab (i) values (1) and insert into ab (i) values ( + 2) rewritten as insert into ab (i) values (1), (2)) + is now 19% faster (Depending on queries 40-50% of CPU time was spend testing that buffer size is big enough to + contain + query). * there was some memory wastage when query return big resultset (> 10kb), slowing query. * ... @@ -1052,13 +1221,17 @@ Send X well established MySQL protocol without reading results, and read those X Basically that permit to avoid a lot of 'ping-pong' between driver and server. New Options : -|=useBatchMultiSend|PreparedStatement.executeBatch() will send many QUERY before reading result packets.//Default: true. Since 1.5.0//| -|=useBatchMultiSendNumber|When using useBatchMultiSend, indicate maximum query that can be sent at a time.
//Default: 100. Since 1.5.0//| +|=useBatchMultiSend|PreparedStatement.executeBatch() will send many QUERY before reading result packets.//Default: true. +Since 1.5.0//| +|=useBatchMultiSendNumber|When using useBatchMultiSend, indicate maximum query that can be sent at a time.
+//Default: 100. Since 1.5.0//| ### Prepare + execute in one call + CONJ-296 When using MySQL/MariaDB prepared statement, there will be 3 exchanges with server : + * PREPARE - Prepares statement for execution. * EXECUTE - Executes a prepared statement preparing by a PREPARE statement. * DEALLOCATE PREPARE - Releases a prepared statement. @@ -1067,7 +1240,8 @@ See [Server prepare documentation](https://mariadb.com/kb/en/mariadb/prepare-sta information. PREPARE and DEALLOCATE PREPARE are 2 additional client-server round-trip. -Since MariaDB 10.2, a new functionality named COM-MULTI to permitting to send different task to server in one round-trip. +Since MariaDB 10.2, a new functionality named COM-MULTI to permitting to send different task to server in one +round-trip. Driver is using this functionality to PREPARE and EXECUTE in one client-server round-trip. ### Client logging @@ -1077,24 +1251,33 @@ This implementation need the standard SLF4J dependency. New Options : |=log|Enable log information. require Slf4j version > 1.4 dependency.
//Default: false. Since 1.5.0//| -|=maxQuerySizeToLog|Only the first characters corresponding to this options size will be displayed in logs
//Default: 1024. Since 1.5.0//| -|=slowQueryThresholdNanos|Will log query with execution time superior to this value (if defined )
//Default: 1024. Since 1.5.0//| +|=maxQuerySizeToLog|Only the first characters corresponding to this options size will be displayed in logs
+//Default: 1024. Since 1.5.0//| +|=slowQueryThresholdNanos|Will log query with execution time superior to this value (if defined )
//Default: 1024. +Since 1.5.0//| |=profileSql|log query execution time.
//Default: false. Since 1.5.0//| - ### "LOAD DATA INFILE" Interceptors + CONJ-305 -LOAD DATA INFILE The fastest way to load many datas is using query [LOAD DATA INFILE](https://mariadb.com/kb/en/mariadb/load-data-infile/). +LOAD DATA INFILE The fastest way to load many datas is using +query [LOAD DATA INFILE](https://mariadb.com/kb/en/mariadb/load-data-infile/).
Problem is using "LOAD DATA LOCAL INFILE" (ie : loading a file from client), may be a security problem : -* A "man in the middle" proxy server can change the actual file asked from server so client will send a Local file to this proxy. -* If someone has can execute query from client, he can have access to any file on client (according to the rights of the user running the client process). -See [load-data-infile documentation](./documentation/use-mariadb-connector-j-driver.creole#load-data-infile) for more information. +* A "man in the middle" proxy server can change the actual file asked from server so client will send a Local file to + this proxy. +* If someone has can execute query from client, he can have access to any file on client (according to the rights of the + user running the client process). + +See [load-data-infile documentation](./documentation/use-mariadb-connector-j-driver.creole#load-data-infile) for more +information. Interceptors can now filter LOAD DATA LOCAL INFILE query's file location to validate path / file name. Those interceptors: + * Must implement interface {{{org.mariadb.jdbc.LocalInfileInterceptor}}}. -* Use [[http://docs.oracle.com/javase/7/docs/api/java/util/ServiceLoader.html|ServiceLoader]] implementation, so interceptors classes must be listed in file META-INF/services/org.mariadb.jdbc.LocalInfileInterceptor. +* Use [[http://docs.oracle.com/javase/7/docs/api/java/util/ServiceLoader.html|ServiceLoader]] implementation, so + interceptors classes must be listed in file META-INF/services/org.mariadb.jdbc.LocalInfileInterceptor. Example: {{{ @@ -1109,9 +1292,12 @@ return filePath.equals("/var/tmp/exchanges"); } } }}} -file META-INF/services/org.mariadb.jdbc.LocalInfileInterceptor must exist with content {{{org.project.LocalInfileInterceptorImpl}}}. +file META-INF/services/org.mariadb.jdbc.LocalInfileInterceptor must exist with content +{{{org.project.LocalInfileInterceptorImpl}}}. -You can get rid of defining the META-INF/services file using [[https://github.com/google/auto/tree/master/service|google auto-service]] framework, permitting to use annotation {{{@AutoService(LocalInfileInterceptor.class)}}} that will register the implementation as a service automatically. +You can get rid of defining the META-INF/services file +using [[https://github.com/google/auto/tree/master/service|google auto-service]] framework, permitting to use annotation +{{{@AutoService(LocalInfileInterceptor.class)}}} that will register the implementation as a service automatically. Using the previous example: {{{ @@ -1127,29 +1313,33 @@ return filePath.equals("/var/tmp/exchanges"); } }}} - - ### Minor evolution + * CONJ-260 : Add jdbc nString, nCharacterStream, nClob implementation ### Bugfix + * CONJ-316 : Wrong Exception thrown for ScrollType TYPE_SCROLL_INSENSITIVE * CONJ-298 : Error on Callable function exception when no parameter and space before parenthesis * CONJ-314 : Permit using Call with Statement / Prepare Statement -


+


+ ## 1.4.6 + * CONJ-293] Permit named pipe connection without host * CONJ-309] Possible NPE on aurora when failover occur during connection initialisation * CONJ-312] NPE while loading a null from TIMESTAMP field using binary protocol * misc] batch with one parameter correction (using rewriteBatchedStatements option) ## 1.4.5 + * CONJ-297] Useless memory consumption when using Statement.setQueryTimeout * CONJ-294] PrepareStatement on master reconnection after a failover * CONJ-288] using SHOW VARIABLES to replace SELECT on connection to permit connection on a galera non primary node * CONJ-290] Timestamps format error when using prepareStatement with options useFractionalSeconds and useServerPrepStmts ## 1.4.4 + * CONJ-289] PrepareStatement on master reconnection after a failover * CONJ-288] using SHOW VARIABLES to replace SELECT on connection to permit connection on a galera non primary node @@ -1165,73 +1355,91 @@ return filePath.equals("/var/tmp/exchanges"); * CONJ-275] Streaming result without result throw "Current position is before the first row" - ## 1.4.1 - * CONJ-274] correction to permit connection to MySQL 5.1 server * CONJ-273] correction when using prepareStatement without parameters and option rewriteBatchedStatements to true * CONJ-270] permit 65535 parameters to server preparedStatement * CONJ-268] update license header -* misc] when option rewriteBatchedStatements is set to true, correction of packet separation when query size > max_allow_packet +* misc] when option rewriteBatchedStatements is set to true, correction of packet separation when query size > + max_allow_packet * misc] performance improvement for select result. ## 1.4.0 ### Complete implementation of fetch size. + CONJ-26 JDBC allows to specify the number of rows fetched for a query, and this number is referred to as the fetch size Before version 1.4.0, query were loading all results or row by row using Statement.setFetchSize(Integer.MIN_VALUE). Now it's possible to set fetch size according to your need. -Loading all results for large result sets is using a lot of memory. This functionality permit to save memory without having performance decrease. +Loading all results for large result sets is using a lot of memory. This functionality permit to save memory without +having performance decrease. ### Memory footprint improvement + CONJ-125 Buffers have been optimized to reduced memory footprint ### CallableStatement performance improvement. + CONJ-209 -Calling function / procedure performance is now optimized according to query. Depending on queries, difference can be up to 300%. +Calling function / procedure performance is now optimized according to query. Depending on queries, difference can be up +to 300%. ### Authentication evolution -CONJ-251 Permit now new authentication possibility : [[https://mariadb.com/kb/en/mariadb/pam-authentication-plugin/|PAM authentication]], and GSSAPI/SSPI authentication. + +CONJ-251 Permit now new authentication +possibility : [[https://mariadb.com/kb/en/mariadb/pam-authentication-plugin/|PAM authentication]], and GSSAPI/SSPI +authentication. GSSAPI/SSPI authentication authentication plugin for MariaDB permit a passwordless login. -On Unix systems, GSSAPI is usually synonymous with Kerberos authentication. Windows has slightly different but very similar API called SSPI, that along with Kerberos, also supports NTLM authentication. -See more detail in [[https://github.com/mariadb-corporation/mariadb-connector-j/blob/master/documentation/plugin/GSSAPI|GSSAPI/SSPI configuration]] +On Unix systems, GSSAPI is usually synonymous with Kerberos authentication. Windows has slightly different but very +similar API called SSPI, that along with Kerberos, also supports NTLM authentication. +See more detail +in [[https://github.com/mariadb-corporation/mariadb-connector-j/blob/master/documentation/plugin/GSSAPI|GSSAPI/SSPI configuration]] ### Connection attributes + CONJ-217 -Driver information informations are now send to [[https://mariadb.com/kb/en/mariadb/performance-schema-session_connect_attrs-table/|connection attributes tables]] (performance_schema must be activated). +Driver information informations are now send +to [[https://mariadb.com/kb/en/mariadb/performance-schema-session_connect_attrs-table/|connection attributes tables]] ( +performance_schema must be activated). A new option "connectionAttributes" permit to add client specifics data. -For example when connecting with the following connection string {{{"jdbc:mariadb://localhost:3306/testj?user=root&connectionAttributes=myOption:1,mySecondOption:'jj'"}}}, -if performance_schema is activated, information about this connection will be available during the time this connection is active : +For example when connecting with the following connection string {{{"jdbc:mariadb://localhost: +3306/testj?user=root&connectionAttributes=myOption:1,mySecondOption:'jj'"}}}, +if performance_schema is activated, information about this connection will be available during the time this connection +is active : {{{ select * from performance_schema.session_connect_attrs where processList_id = 5 +----------------+-----------------+---------------------+------------------+ -| PROCESSLIST_ID | ATTR_NAME | ATTR_VALUE | ORDINAL_POSITION | +| PROCESSLIST_ID | ATTR_NAME | ATTR_VALUE | ORDINAL_POSITION | +----------------+-----------------+---------------------+------------------+ -|5 |_client_name |MariaDB connector/J |0 | -|5 |_client_version |1.4.0-SNAPSHOT |1 | -|5 |_os |Windows 8.1 |2 | -|5 |_pid |14124@portable-diego |3 | -|5 |_thread |5 |4 | -|5 |_java_vendor |Oracle Corporation |5 | -|5 |_java_version |1.7.0_79 |6 | -|5 |myOption |1 |7 | -|5 |mySecondOption |'jj' |8 | +|5 |_client_name |MariaDB connector/J |0 | +|5 |_client_version |1.4.0-SNAPSHOT |1 | +|5 |_os |Windows 8.1 |2 | +|5 |_pid |14124@portable-diego |3 | +|5 |_thread |5 |4 | +|5 |_java_vendor |Oracle Corporation |5 | +|5 |_java_version |1.7.0_79 |6 | +|5 |myOption |1 |7 | +|5 |mySecondOption |'jj' |8 | +----------------+-----------------+---------------------+------------------+ }}} - ## Minor evolution + * CONJ-210 : adding a "jdbcCompliantTruncation" option to force truncation warning as SQLException. -* CONJ-211 : when in master/slave configuration, option "assureReadOnly" will ensure that slaves are in read-only mode ( forcing transaction by a query "SET SESSION TRANSACTION READ ONLY"). -* CONJ-213 : new option "continueBatchOnError". Permit to continue batch when an exception occur : When executing a batch and an error occur, must the batch stop immediatly (default) or finish remaining batch before throwing exception. +* CONJ-211 : when in master/slave configuration, option "assureReadOnly" will ensure that slaves are in read-only mode ( + forcing transaction by a query "SET SESSION TRANSACTION READ ONLY"). +* CONJ-213 : new option "continueBatchOnError". Permit to continue batch when an exception occur : When executing a + batch and an error occur, must the batch stop immediatly (default) or finish remaining batch before throwing + exception. ## Bugfix + * CONJ-236 : Using a parametrized query with a smallint -1 does return the unsigned value * CONJ-250 : Tomcat doesn't stop when using Aurora failover configuration * CONJ-260 : Add jdbc nString, nCharacterStream, nClob implementation diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 952fe34a2..8dc2bff4a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,70 +1,80 @@ # Contributing -Each pull request should address a single issue, and contain both the fix and a description of how the pull request and tests that validate that the PR fixes the issue in question. +Each pull request should address a single issue, and contain both the fix and a description of how the pull request and +tests that validate that the PR fixes the issue in question. -For significant feature additions, we like to have an open issue in [MariaDB JIRA](https://mariadb.atlassian.net/secure/RapidBoard.jspa?projectKey=CONJ). It is expected that discussion will have taken place in the attached issue. +For significant feature additions, we like to have an open issue +in [MariaDB JIRA](https://mariadb.atlassian.net/secure/RapidBoard.jspa?projectKey=CONJ). It is expected that discussion +will have taken place in the attached issue. # Install Prerequisites -These are the set of tools which are required in order to complete any build. Follow the links to download and install them on your own before continuing. +These are the set of tools which are required in order to complete any build. Follow the links to download and install +them on your own before continuing. * At least one GPG Key see https://help.github.com/en/articles/generating-a-new-gpg-key -* [Oracle JDK 8](http://www.oracle.com/technetwork/java/javase/downloads/index.html) ( with [JCE policies](http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html) if using TLS/SSL) +* [Oracle JDK 8](http://www.oracle.com/technetwork/java/javase/downloads/index.html) ( + with [JCE policies](http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html) if using + TLS/SSL) * IDE (eclipse / netbean / intelliJ) with maven and GIT plugins # Fork source -Before downloading source, fork the project to your own repository, and use your repository as source. +Before downloading source, fork the project to your own repository, and use your repository as source. ## Branch signification * master : correspond to the last released version * develop : Develop new features for upcoming releases (compatible with java 8) -* develop-jre6 : maintenance branch compatible with java 6 / 7 +* develop-jre6 : maintenance branch compatible with java 6 / 7 # Run local test Before any submission : -Run the test locally : by default, you need to have a MySQL/MariaDB server on localhost:3306 with a database named "testj" and a user root without password. -so you can run - +Run the test locally : by default, you need to have a MySQL/MariaDB server on localhost:3306 with a database named " +testj" and a user root without password. +so you can run + ```script - mvn test + mvn test ``` - -You can change this parameter by adding -DdbUrl parameter. like : - + +You can change this parameter by adding -DdbUrl parameter. like : + ```script - mvn test -DdbUrl=jdbc:mariadb://127.0.0.1:3306/testj?user=root&password=***** + mvn test -DdbUrl=jdbc:mariadb://127.0.0.1:3306/testj?user=root&password=***** ``` - + You can launch a specific test by adding -Dtest ```script - mvn test -Dtest=org.mariadb.jdbc.JdbcParserTest + mvn test -Dtest=org.mariadb.jdbc.JdbcParserTest ``` - + When all test are passing, you can package project. -Additional tests , like javadoc formatting, code style validation will be done : - +Additional tests , like javadoc formatting, code style validation will be done : + ```script - mvn package -Dmaven.test.skip=true + mvn package -Dmaven.test.skip=true ``` - + If operation succeed, a new mariadb-java-client jar will be on the target folder. - + # Run travis test - -You can activate travis to validate your repository. -The advantage of travis compare to running test locally is that it will launch tests for a combination of those parameters : + +You can activate travis to validate your repository. +The advantage of travis compare to running test locally is that it will launch tests for a combination of those +parameters : jdk: + * oraclejdk8 -and if your work is on develop-jre6 branch + and if your work is on develop-jre6 branch * openjdk6 * openjdk7 server : + * MariaDB 5.5 * MariaDB 10.0 * MariaDB 10.1 @@ -73,17 +83,20 @@ server : * MySQL 5.7 max_allowed_packet : (this permit to check multipacket send) + * 8M * 20M * 40M -For that, you have to go on [travis website](https://travis-ci.org), connect with your github account, and activate your mariadb-connector-j repository. -After this step, every push to your repository will launch a travis test. +For that, you have to go on [travis website](https://travis-ci.org), connect with your github account, and activate your +mariadb-connector-j repository. +After this step, every push to your repository will launch a travis test. ## Submitting a request -When your repository has the correction/change done, you can submit a pull request by clicking the "Pull request" button on github. -Please detail the operation done in your request. +When your repository has the correction/change done, you can submit a pull request by clicking the "Pull request" button +on github. +Please detail the operation done in your request. ## License diff --git a/README.md b/README.md index bfc94ef93..90f2572be 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,18 @@ -

- - - +

+ + mariadb logo +

# MariaDB java connector -MariaDB java connector is a JDBC 4.2 compatible driver, used to connect applications developed in Java to MariaDB and MySQL databases. MariaDB Connector/J is LGPL licensed. +MariaDB java connector is a JDBC 4.2 compatible driver, used to connect applications developed in Java to MariaDB and +MySQL databases. MariaDB Connector/J is LGPL licensed. Tracker link https://jira.mariadb.org/projects/CONJ/issues/ ## Status + [![Linux Build](https://travis-ci.com/mariadb-corporation/mariadb-connector-j.svg?branch=master)](https://app.travis-ci.com/github/mariadb-corporation/mariadb-connector-j) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.mariadb.jdbc/mariadb-java-client/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.mariadb.jdbc/mariadb-java-client) [![License (LGPL version 2.1)](https://img.shields.io/badge/license-GNU%20LGPL%20version%202.1-green.svg?style=flat-square)](http://opensource.org/licenses/LGPL-2.1) @@ -21,43 +23,45 @@ Tracker link https://ji For java 8+ : The driver (jar) can be downloaded from [mariadb connector download](https://mariadb.com/downloads/#connectors) -or maven : +or maven : + ```script org.mariadb.jdbc mariadb-java-client - 3.2.0 + 3.3.0 ``` - Development snapshot are available on sonatype nexus repository + ```script - - sonatype-nexus-snapshots - Sonatype Nexus Snapshots - https://oss.sonatype.org/content/repositories/snapshots - + + sonatype-nexus-snapshots + Sonatype Nexus Snapshots + https://oss.sonatype.org/content/repositories/snapshots + - - org.mariadb.jdbc - mariadb-java-client - 3.2.1-SNAPSHOT - + + org.mariadb.jdbc + mariadb-java-client + 3.4.0-SNAPSHOT + ``` ## Documentation -For a Getting started guide, API docs, recipes, etc. see the +For a Getting started guide, API docs, recipes, etc. see the + * [About MariaDB connector/J](https://mariadb.com/kb/en/about-mariadb-connector-j/) * [Install driver](https://mariadb.com/kb/en/installing-mariadb-connectorj/) * [Changelog](/CHANGELOG.md) * [Failover and high-availability](https://mariadb.com/kb/en/failover-and-high-availability-with-mariadb-connector-j/) - [codecov-image]:https://codecov.io/gh/mariadb-corporation/mariadb-connector-j/branch/master/graph/badge.svg + [codecov-url]:https://codecov.io/gh/mariadb-corporation/mariadb-connector-j diff --git a/bnd.bnd b/bnd.bnd index f189fdab7..c984e13de 100644 --- a/bnd.bnd +++ b/bnd.bnd @@ -1,4 +1,4 @@ -Export-Package: org.mariadb.jdbc;org.mariadb.jdbc.client;org.mariadb.jdbc.client.util;org.mariadb.jdbc.client.socket;org.mariadb.jdbc.message;org.mariadb.jdbc.type;org.mariadb.jdbc.export;org.mariadb.jdbc.plugin;org.mariadb.jdbc.plugin.codec;org.mariadb.jdbc.plugin.authentication.standard;org.mariadb.jdbc.plugin.authentication.addon;org.mariadb.jdbc.plugin.credential.aws;org.mariadb.jdbc.plugin.credential.env;org.mariadb.jdbc.plugin.credential.system;org.mariadb.jdbc.plugin.tls.main +Export-Package: org.mariadb.jdbc;org.mariadb.jdbc.client;org.mariadb.jdbc.client.util;org.mariadb.jdbc.util.constants;org.mariadb.jdbc.client.socket;org.mariadb.jdbc.message;org.mariadb.jdbc.type;org.mariadb.jdbc.export;org.mariadb.jdbc.plugin;org.mariadb.jdbc.plugin.codec;org.mariadb.jdbc.plugin.authentication.standard;org.mariadb.jdbc.plugin.authentication.addon;org.mariadb.jdbc.plugin.credential.aws;org.mariadb.jdbc.plugin.credential.env;org.mariadb.jdbc.plugin.credential.system;org.mariadb.jdbc.plugin.tls.main Import-Package: \ javax.naming,\ diff --git a/licenseheader.txt b/licenseheader.txt new file mode 100644 index 000000000..6c585c76f --- /dev/null +++ b/licenseheader.txt @@ -0,0 +1,3 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +// Copyright (c) 2012-2014 Monty Program Ab +// Copyright (c) 2015-2023 MariaDB Corporation Ab diff --git a/pom.xml b/pom.xml index 116cc8b6a..88cd801bd 100644 --- a/pom.xml +++ b/pom.xml @@ -7,13 +7,13 @@ mariadb-java-client jar mariadb-java-client - 3.2.0 + 3.3.0 JDBC driver for MariaDB and MySQL https://mariadb.com/kb/en/mariadb/about-mariadb-connector-j/ UTF-8 - 1.34 + 1.37 5.8.2 1.5.0 3.22.0 @@ -21,10 +21,11 @@ 5.0.0 UTF-8 1.4.4 - 0.8.8 - 3.2.0 - 8.0.31 + 0.8.10 + 3.3.0 + 8.1.0 6.3.1 + 2.40.0 @@ -79,7 +80,7 @@ software.amazon.awssdk bom - 2.18.10 + 2.21.1 pom import @@ -231,24 +232,53 @@ - - com.coveo - fmt-maven-plugin - 2.13 - - - - format - - - + com.diffplug.spotless + spotless-maven-plugin + ${spotless.version} + + + + + + + + + *.md + .gitignore + + + + + + true + 2 + + + + + + src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/**/*.java + + src/main/java/org/mariadb/jdbc/client/socket/impl/UnixDomainSocket.java + + + 1.18.1 + + true + true + com.google.googlejavaformat:google-java-format + + + ${project.basedir}/licenseheader.txt + + + - org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M7 + 3.1.2 @@ -390,11 +420,15 @@ - mysql - mysql-connector-java + com.mysql + mysql-connector-j ${mysql-connector-java.version} - + + com.zaxxer + HikariCP + 5.0.1 + diff --git a/src/benchmark/README.md b/src/benchmark/README.md index 1a5158f14..ca7eedd74 100644 --- a/src/benchmark/README.md +++ b/src/benchmark/README.md @@ -1,12 +1,13 @@ -

+

- + mariadb logo

# Benchmark -How to run : +How to run : + ```script mvn clean package -P bench -DskipTests @@ -18,6 +19,7 @@ java -Duser.country=US -Duser.language=en -jar target/benchmarks.jar "Select_100 ``` Configuration by system properties : + * TEST_HOST: Hostname. default "localhost" * TEST_PORT: port. default 3306 * TEST_USERNAME: user name. default "root" @@ -25,7 +27,8 @@ Configuration by system properties : * TEST_DATABASE: database. default "testj" * TEST_OTHER: permit adding connection string options. default "" -example: +example: + ```script mvn clean package -P bench -Dmaven.test.skip java -DTEST_PORT=3307 -Duser.country=US -Duser.language=en -jar target/benchmarks.jar "Select_100_cols" diff --git a/src/benchmark/java/org/mariadb/jdbc/Common.java b/src/benchmark/java/org/mariadb/jdbc/Common.java index 9d68aee58..2fc9a654c 100644 --- a/src/benchmark/java/org/mariadb/jdbc/Common.java +++ b/src/benchmark/java/org/mariadb/jdbc/Common.java @@ -1,17 +1,15 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; -import org.openjdk.jmh.annotations.*; - import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.*; @State(Scope.Benchmark) @Warmup(iterations = 10, timeUnit = TimeUnit.SECONDS, time = 1) diff --git a/src/benchmark/java/org/mariadb/jdbc/Do_1.java b/src/benchmark/java/org/mariadb/jdbc/Do_1.java index 7b23d008e..96eec41ce 100644 --- a/src/benchmark/java/org/mariadb/jdbc/Do_1.java +++ b/src/benchmark/java/org/mariadb/jdbc/Do_1.java @@ -1,21 +1,17 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; -import org.openjdk.jmh.annotations.Benchmark; - -import java.sql.ResultSet; import java.sql.Statement; +import org.openjdk.jmh.annotations.Benchmark; public class Do_1 extends Common { - @Benchmark - public int run(MyState state) throws Throwable { - try (Statement st = state.connectionText.createStatement()) { - return st.executeUpdate("DO 1"); - } + @Benchmark + public int run(MyState state) throws Throwable { + try (Statement st = state.connectionText.createStatement()) { + return st.executeUpdate("DO 1"); } - + } } diff --git a/src/benchmark/java/org/mariadb/jdbc/Do_1000_params.java b/src/benchmark/java/org/mariadb/jdbc/Do_1000_params.java index 0c6e157b6..147aeb144 100644 --- a/src/benchmark/java/org/mariadb/jdbc/Do_1000_params.java +++ b/src/benchmark/java/org/mariadb/jdbc/Do_1000_params.java @@ -1,14 +1,11 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; -import org.openjdk.jmh.annotations.Benchmark; - import java.sql.Connection; import java.sql.PreparedStatement; -import java.sql.ResultSet; +import org.openjdk.jmh.annotations.Benchmark; public class Do_1000_params extends Common { diff --git a/src/benchmark/java/org/mariadb/jdbc/Insert_batch.java b/src/benchmark/java/org/mariadb/jdbc/Insert_batch.java index 7b9ebbcba..dc438e222 100644 --- a/src/benchmark/java/org/mariadb/jdbc/Insert_batch.java +++ b/src/benchmark/java/org/mariadb/jdbc/Insert_batch.java @@ -1,18 +1,14 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; -import org.openjdk.jmh.annotations.Benchmark; - import java.sql.Connection; import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.Statement; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.openjdk.jmh.annotations.Benchmark; public class Insert_batch extends Common { diff --git a/src/benchmark/java/org/mariadb/jdbc/Select_1.java b/src/benchmark/java/org/mariadb/jdbc/Select_1.java index 4a5a63815..d5be55470 100644 --- a/src/benchmark/java/org/mariadb/jdbc/Select_1.java +++ b/src/benchmark/java/org/mariadb/jdbc/Select_1.java @@ -1,13 +1,11 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; -import org.openjdk.jmh.annotations.Benchmark; - import java.sql.ResultSet; import java.sql.Statement; +import org.openjdk.jmh.annotations.Benchmark; public class Select_1 extends Common { diff --git a/src/benchmark/java/org/mariadb/jdbc/Select_1000_Rows.java b/src/benchmark/java/org/mariadb/jdbc/Select_1000_Rows.java index a1848381c..9aecb14f5 100644 --- a/src/benchmark/java/org/mariadb/jdbc/Select_1000_Rows.java +++ b/src/benchmark/java/org/mariadb/jdbc/Select_1000_Rows.java @@ -1,14 +1,12 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; -import org.openjdk.jmh.annotations.Benchmark; - import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; +import org.openjdk.jmh.annotations.Benchmark; public class Select_1000_Rows extends Common { private static final String sql = diff --git a/src/benchmark/java/org/mariadb/jdbc/Select_100_cols.java b/src/benchmark/java/org/mariadb/jdbc/Select_100_cols.java index a4f5a03a8..4e256fdfb 100644 --- a/src/benchmark/java/org/mariadb/jdbc/Select_100_cols.java +++ b/src/benchmark/java/org/mariadb/jdbc/Select_100_cols.java @@ -1,16 +1,11 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; - import java.sql.*; import java.sql.Connection; -import java.sql.Statement; +import org.openjdk.jmh.annotations.Benchmark; public class Select_100_cols extends Common { diff --git a/src/benchmark/resources/logback-test.xml b/src/benchmark/resources/logback-test.xml index 3dbbecb7a..4a424742f 100644 --- a/src/benchmark/resources/logback-test.xml +++ b/src/benchmark/resources/logback-test.xml @@ -1,17 +1,17 @@ - - - %d{yyyy-MM-dd} | %d{HH:mm:ss.SSS} | %-20.20thread | %5p | %logger{25} | %m%n - - - + + + %d{yyyy-MM-dd} | %d{HH:mm:ss.SSS} | %-20.20thread | %5p | %logger{25} | %m%n + + + - + - - - + + + \ No newline at end of file diff --git a/src/main/java/org/mariadb/jdbc/BaseCallableStatement.java b/src/main/java/org/mariadb/jdbc/BaseCallableStatement.java index 2a9516ae1..6e945eb07 100644 --- a/src/main/java/org/mariadb/jdbc/BaseCallableStatement.java +++ b/src/main/java/org/mariadb/jdbc/BaseCallableStatement.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; import java.io.InputStream; @@ -28,12 +27,12 @@ public abstract class BaseCallableStatement extends ServerPreparedStatement /** Procedure name */ protected final String procedureName; - /** parameter metadata */ - protected CallableParameterMetaData parameterMetaData = null; - /** Declared output parameters */ protected final Set outputParameters = new HashSet<>(); + /** parameter metadata */ + protected CallableParameterMetaData parameterMetaData = null; + /** output parameter result */ private Result outputResult = null; diff --git a/src/main/java/org/mariadb/jdbc/BasePreparedStatement.java b/src/main/java/org/mariadb/jdbc/BasePreparedStatement.java index 0d0ec46ea..9915f43ee 100644 --- a/src/main/java/org/mariadb/jdbc/BasePreparedStatement.java +++ b/src/main/java/org/mariadb/jdbc/BasePreparedStatement.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; import java.io.InputStream; @@ -26,7 +25,10 @@ /** Common methods for prepare statement, for client and server prepare statement. */ public abstract class BasePreparedStatement extends Statement implements PreparedStatement { private static final Pattern INSERT_STATEMENT_PATTERN = - Pattern.compile("^(\\s*\\/\\*([^*]|\\*[^/])*\\*\\/)*\\s*(INSERT)", Pattern.CASE_INSENSITIVE); + Pattern.compile("^(\\s*/\\*([^*]|\\*[^/])*\\*/)*\\s*(INSERT)", Pattern.CASE_INSENSITIVE); + + /** prepare statement sql command */ + protected final String sql; /** parameters */ protected Parameters parameters; @@ -34,9 +36,6 @@ public abstract class BasePreparedStatement extends Statement implements Prepare /** batching parameters */ protected List batchParameters; - /** prepare statement sql command */ - protected final String sql; - /** PREPARE command result */ protected Prepare prepareResult = null; @@ -98,7 +97,7 @@ public String toString() { protected void checkIfInsertCommand() { if (isCommandInsert == null) - isCommandInsert = (sql == null) ? false : INSERT_STATEMENT_PATTERN.matcher(sql).find(); + isCommandInsert = sql != null && INSERT_STATEMENT_PATTERN.matcher(sql).find(); } /** @@ -215,7 +214,8 @@ public int executeUpdate(String sql) throws SQLException { public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { throw exceptionFactory() .create( - "executeUpdate(String sql, int autoGeneratedKeys) cannot be called on preparedStatement"); + "executeUpdate(String sql, int autoGeneratedKeys) cannot be called on" + + " preparedStatement"); } @Override @@ -229,7 +229,8 @@ public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { public int executeUpdate(String sql, String[] columnNames) throws SQLException { throw exceptionFactory() .create( - "executeUpdate(String sql, String[] columnNames) cannot be called on preparedStatement"); + "executeUpdate(String sql, String[] columnNames) cannot be called on" + + " preparedStatement"); } @Override @@ -242,21 +243,24 @@ public long executeLargeUpdate(String sql) throws SQLException { public long executeLargeUpdate(String sql, int autoGeneratedKeys) throws SQLException { throw exceptionFactory() .create( - "executeLargeUpdate(String sql, int autoGeneratedKeys) cannot be called on preparedStatement"); + "executeLargeUpdate(String sql, int autoGeneratedKeys) cannot be called on" + + " preparedStatement"); } @Override public long executeLargeUpdate(String sql, int[] columnIndexes) throws SQLException { throw exceptionFactory() .create( - "executeLargeUpdate(String sql, int[] columnIndexes) cannot be called on preparedStatement"); + "executeLargeUpdate(String sql, int[] columnIndexes) cannot be called on" + + " preparedStatement"); } @Override public long executeLargeUpdate(String sql, String[] columnNames) throws SQLException { throw exceptionFactory() .create( - "executeLargeUpdate(String sql, String[] columnNames) cannot be called on preparedStatement"); + "executeLargeUpdate(String sql, String[] columnNames) cannot be called on" + + " preparedStatement"); } // *************************************************************************************************** @@ -1145,13 +1149,13 @@ private void setInternalObject( return; case Types.DOUBLE: case Types.FLOAT: - setDouble(parameterIndex, Double.valueOf(str)); + setDouble(parameterIndex, Double.parseDouble(str)); return; case Types.REAL: - setFloat(parameterIndex, Float.valueOf(str)); + setFloat(parameterIndex, Float.parseFloat(str)); return; case Types.BIGINT: - setLong(parameterIndex, Long.valueOf(str)); + setLong(parameterIndex, Long.parseLong(str)); return; case Types.DECIMAL: case Types.NUMERIC: @@ -1175,7 +1179,7 @@ private void setInternalObject( } return; case Types.TIME: - setTime(parameterIndex, Time.valueOf((String) obj)); + setTime(parameterIndex, Time.valueOf(str)); return; default: throw exceptionFactory() diff --git a/src/main/java/org/mariadb/jdbc/CallableParameterMetaData.java b/src/main/java/org/mariadb/jdbc/CallableParameterMetaData.java index c46e41b44..e64635adb 100644 --- a/src/main/java/org/mariadb/jdbc/CallableParameterMetaData.java +++ b/src/main/java/org/mariadb/jdbc/CallableParameterMetaData.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; import java.math.BigDecimal; diff --git a/src/main/java/org/mariadb/jdbc/ClientPreparedStatement.java b/src/main/java/org/mariadb/jdbc/ClientPreparedStatement.java index cdbd0b713..f103e4d7d 100644 --- a/src/main/java/org/mariadb/jdbc/ClientPreparedStatement.java +++ b/src/main/java/org/mariadb/jdbc/ClientPreparedStatement.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; import static org.mariadb.jdbc.util.constants.Capabilities.*; diff --git a/src/main/java/org/mariadb/jdbc/Configuration.java b/src/main/java/org/mariadb/jdbc/Configuration.java index a43153168..9570076ca 100644 --- a/src/main/java/org/mariadb/jdbc/Configuration.java +++ b/src/main/java/org/mariadb/jdbc/Configuration.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; import java.io.IOException; @@ -760,6 +759,266 @@ private static HaMode parseHaMode(String url, int separator) { } } + /** + * Permit to have string information on how string is parsed. example : + * Configuration.toConf("jdbc:mariadb://localhost/test") will return a String containing: + * Configuration: + * * resulting Url : jdbc:mariadb://localhost/test + * Unknown options : None + * + * Non default options : + * * database : test + * + * default options : + * * user : null + * ... + * + * + * @param url url string + * @return string describing the configuration parsed from url + * @throws SQLException if parsing fails + */ + public static String toConf(String url) throws SQLException { + Configuration conf = Configuration.parseInternal(url, new Properties()); + StringBuilder sb = new StringBuilder(); + StringBuilder sbUnknownOpts = new StringBuilder(); + + if (conf.nonMappedOptions.isEmpty()) { + sbUnknownOpts.append("None"); + } else { + for (Map.Entry entry : conf.nonMappedOptions.entrySet()) { + sbUnknownOpts.append("\n * ").append(entry.getKey()).append(" : ").append(entry.getValue()); + } + } + sb.append("Configuration:") + .append("\n * resulting Url : ") + .append(conf.initialUrl) + .append("\nUnknown options : ") + .append(sbUnknownOpts) + .append("\n") + .append("\nNon default options : "); + + Configuration defaultConf = Configuration.parse("jdbc:mariadb://localhost/"); + StringBuilder sbDefaultOpts = new StringBuilder(); + StringBuilder sbDifferentOpts = new StringBuilder(); + try { + List propertyToSkip = Arrays.asList("initialUrl", "logger", "codecs", "$jacocoData"); + Field[] fields = Configuration.class.getDeclaredFields(); + Arrays.sort(fields, Comparator.comparing(Field::getName)); + + for (Field field : fields) { + if (!propertyToSkip.contains(field.getName())) { + Object fieldValue = field.get(conf); + if (fieldValue == null) { + (Objects.equals(fieldValue, field.get(defaultConf)) ? sbDefaultOpts : sbDifferentOpts) + .append("\n * ") + .append(field.getName()) + .append(" : ") + .append(fieldValue); + } else { + if (field.getName().equals("haMode")) { + (Objects.equals(fieldValue, field.get(defaultConf)) ? sbDefaultOpts : sbDifferentOpts) + .append("\n * ") + .append(field.getName()) + .append(" : ") + .append(fieldValue); + continue; + } + switch (fieldValue.getClass().getSimpleName()) { + case "String": + case "Boolean": + case "HaMode": + case "TransactionIsolation": + case "Integer": + case "SslMode": + case "CatalogTerm": + (Objects.equals(fieldValue, field.get(defaultConf)) + ? sbDefaultOpts + : sbDifferentOpts) + .append("\n * ") + .append(field.getName()) + .append(" : ") + .append(fieldValue); + break; + case "ArrayList": + (Objects.equals(fieldValue.toString(), field.get(defaultConf).toString()) + ? sbDefaultOpts + : sbDifferentOpts) + .append("\n * ") + .append(field.getName()) + .append(" : ") + .append(fieldValue); + break; + case "Properties": + break; + default: + throw new IllegalArgumentException( + "field type not expected for fields " + field.getName()); + } + } + } + } + + String diff = sbDifferentOpts.toString(); + if (diff.isEmpty()) { + sb.append("None\n"); + } else { + sb.append(diff); + } + + sb.append("\n\ndefault options :"); + String same = sbDefaultOpts.toString(); + if (same.isEmpty()) { + sb.append("None\n"); + } else { + sb.append(same); + } + + } catch (IllegalArgumentException | IllegalAccessException e) { + throw new IllegalArgumentException("Wrong parsing", e); + } + return sb.toString(); + } + + /** + * Generate initialURL property + * + * @param conf current configuration + * @return initialUrl value. + */ + protected static String buildUrl(Configuration conf) { + Configuration defaultConf = new Configuration(); + StringBuilder sb = new StringBuilder(); + sb.append("jdbc:mariadb:"); + if (conf.haMode != HaMode.NONE) { + sb.append(conf.haMode.toString().toLowerCase(Locale.ROOT)).append(":"); + } + sb.append("//"); + for (int i = 0; i < conf.addresses.size(); i++) { + HostAddress hostAddress = conf.addresses.get(i); + if (i > 0) { + sb.append(","); + } + if ((conf.haMode == HaMode.NONE && hostAddress.primary) + || (conf.haMode == HaMode.REPLICATION + && ((i == 0 && hostAddress.primary) || (i != 0 && !hostAddress.primary)))) { + sb.append(hostAddress.host); + if (hostAddress.port != 3306) sb.append(":").append(hostAddress.port); + } else { + sb.append("address=(host=") + .append(hostAddress.host) + .append(")") + .append("(port=") + .append(hostAddress.port) + .append(")"); + sb.append("(type=").append(hostAddress.primary ? "primary" : "replica").append(")"); + } + } + + sb.append("/"); + if (conf.database != null) { + sb.append(conf.database); + } + + try { + // Option object is already initialized to default values. + // loop on properties, + // - check DefaultOption to check that property value correspond to type (and range) + // - set values + boolean first = true; + + Field[] fields = Configuration.class.getDeclaredFields(); + for (Field field : fields) { + if ("database".equals(field.getName()) + || "haMode".equals(field.getName()) + || "$jacocoData".equals(field.getName()) + || "addresses".equals(field.getName())) { + continue; + } + Object obj = field.get(conf); + + if (obj != null && (!(obj instanceof Properties) || ((Properties) obj).size() > 0)) { + + if ("password".equals(field.getName())) { + sb.append(first ? '?' : '&'); + first = false; + sb.append(field.getName()).append('='); + sb.append("***"); + continue; + } + + if (field.getType().equals(String.class)) { + sb.append(first ? '?' : '&'); + first = false; + sb.append(field.getName()).append('='); + sb.append((String) obj); + } else if (field.getType().equals(boolean.class)) { + boolean defaultValue = field.getBoolean(defaultConf); + if (!obj.equals(defaultValue)) { + sb.append(first ? '?' : '&'); + first = false; + sb.append(field.getName()).append('='); + sb.append(obj); + } + } else if (field.getType().equals(int.class)) { + try { + int defaultValue = field.getInt(defaultConf); + if (!obj.equals(defaultValue)) { + sb.append(first ? '?' : '&'); + sb.append(field.getName()).append('=').append(obj); + first = false; + } + } catch (IllegalAccessException n) { + // eat + } + } else if (field.getType().equals(Properties.class)) { + sb.append(first ? '?' : '&'); + first = false; + boolean firstProp = true; + Properties properties = (Properties) obj; + for (Object key : properties.keySet()) { + if (firstProp) { + firstProp = false; + } else { + sb.append('&'); + } + sb.append(key).append('='); + sb.append(properties.get(key)); + } + } else if (field.getType().equals(CredentialPlugin.class)) { + Object defaultValue = field.get(defaultConf); + if (!obj.equals(defaultValue)) { + sb.append(first ? '?' : '&'); + first = false; + sb.append(field.getName()).append('='); + sb.append(((CredentialPlugin) obj).type()); + } + } else { + Object defaultValue = field.get(defaultConf); + if (!obj.equals(defaultValue)) { + sb.append(first ? '?' : '&'); + first = false; + sb.append(field.getName()).append('='); + sb.append(obj); + } + } + } + } + + } catch (IllegalAccessException n) { + n.printStackTrace(); + } catch (SecurityException s) { + // only for jws, so never thrown + throw new IllegalArgumentException("Security too restrictive : " + s.getMessage()); + } + conf.loadCodecs(); + return sb.toString(); + } + + private static String nullOrEmpty(String val) { + return (val == null || val.isEmpty()) ? null : val; + } + /** * Clone configuration with another user/password * @@ -1472,387 +1731,130 @@ public boolean registerJmxPool() { * Pool mininum validation delay. * * @return pool validation delay - */ - public int poolValidMinDelay() { - return poolValidMinDelay; - } - - /** - * Must connection returned to pool be RESET - * - * @return use RESET on connection - */ - public boolean useResetConnection() { - return useResetConnection; - } - - /** - * Server RSA public key file for caching_sha2_password authentication - * - * @return server key file - */ - public String serverRsaPublicKeyFile() { - return serverRsaPublicKeyFile; - } - - /** - * permit mysql authentication to retrieve server certificate - * - * @return is driver allowed to retrieve server certificate from server - */ - public boolean allowPublicKeyRetrieval() { - return allowPublicKeyRetrieval; - } - - /** - * Read all data from socket in advance - * - * @return use read ahead buffer implementation - */ - public boolean useReadAheadInput() { - return useReadAheadInput; - } - - /** - * Cache prepared statement result. - * - * @return cache prepare results - */ - public boolean cachePrepStmts() { - return cachePrepStmts; - } - - /** - * implements transaction replay failover - * - * @return true if transaction must be replayed on failover. - */ - public boolean transactionReplay() { - return transactionReplay; - } - - /** - * transaction replay maximum number of saved command. - * - * @return transaction replay buffer size. - */ - public int transactionReplaySize() { - return transactionReplaySize; - } - - /** - * geometry default decoding implementation - * - * @return geometry default type - */ - public String geometryDefaultType() { - return geometryDefaultType; - } - - /** - * Restrict authentication plugin to comma separated plugin list - * - * @return authorized authentication list - */ - public String restrictedAuth() { - return restrictedAuth; - } - - /** - * Execute initial command when connection is established - * - * @return initial SQL command - */ - public String initSql() { - return initSql; - } - - /** - * datatype Encoder/decoder list - * - * @return codec list - */ - public Codec[] codecs() { - return codecs; - } - - /** - * ToString implementation. - * - * @return String value - */ - public String toString() { - return initialUrl; - } - - /** - * Permit to have string information on how string is parsed. example : - * Configuration.toConf("jdbc:mariadb://localhost/test") will return a String containing: - * Configuration: - * * resulting Url : jdbc:mariadb://localhost/test - * Unknown options : None - * - * Non default options : - * * database : test - * - * default options : - * * user : null - * ... - * - * - * @param url url string - * @return string describing the configuration parsed from url - * @throws SQLException if parsing fails - */ - public static String toConf(String url) throws SQLException { - Configuration conf = Configuration.parseInternal(url, new Properties()); - StringBuilder sb = new StringBuilder(); - StringBuilder sbUnknownOpts = new StringBuilder(); - - if (conf.nonMappedOptions.isEmpty()) { - sbUnknownOpts.append("None"); - } else { - for (Map.Entry entry : conf.nonMappedOptions.entrySet()) { - sbUnknownOpts.append("\n * ").append(entry.getKey()).append(" : ").append(entry.getValue()); - } - } - sb.append("Configuration:") - .append("\n * resulting Url : ") - .append(conf.initialUrl) - .append("\nUnknown options : ") - .append(sbUnknownOpts) - .append("\n") - .append("\nNon default options : "); - - Configuration defaultConf = Configuration.parse("jdbc:mariadb://localhost/"); - StringBuilder sbDefaultOpts = new StringBuilder(); - StringBuilder sbDifferentOpts = new StringBuilder(); - try { - List propertyToSkip = - Arrays.asList(new String[] {"initialUrl", "logger", "codecs", "$jacocoData"}); - Field[] fields = Configuration.class.getDeclaredFields(); - Arrays.sort(fields, Comparator.comparing(Field::getName)); - - for (Field field : fields) { - if (!propertyToSkip.contains(field.getName())) { - Object fieldValue = field.get(conf); - if (fieldValue == null) { - (Objects.equals(fieldValue, field.get(defaultConf)) ? sbDefaultOpts : sbDifferentOpts) - .append("\n * ") - .append(field.getName()) - .append(" : ") - .append(fieldValue); - } else { - if (field.getName().equals("haMode")) { - (Objects.equals(fieldValue, field.get(defaultConf)) ? sbDefaultOpts : sbDifferentOpts) - .append("\n * ") - .append(field.getName()) - .append(" : ") - .append(fieldValue); - continue; - } - switch (fieldValue.getClass().getSimpleName()) { - case "String": - case "Boolean": - case "HaMode": - case "TransactionIsolation": - case "Integer": - case "SslMode": - case "CatalogTerm": - (Objects.equals(fieldValue, field.get(defaultConf)) - ? sbDefaultOpts - : sbDifferentOpts) - .append("\n * ") - .append(field.getName()) - .append(" : ") - .append(fieldValue); - break; - case "ArrayList": - (Objects.equals(fieldValue.toString(), field.get(defaultConf).toString()) - ? sbDefaultOpts - : sbDifferentOpts) - .append("\n * ") - .append(field.getName()) - .append(" : ") - .append(fieldValue); - break; - case "Properties": - break; - default: - throw new IllegalArgumentException( - "field type not expected for fields " + field.getName()); - } - } - } - } + */ + public int poolValidMinDelay() { + return poolValidMinDelay; + } - String diff = sbDifferentOpts.toString(); - if (diff.isEmpty()) { - sb.append("None\n"); - } else { - sb.append(diff); - } + /** + * Must connection returned to pool be RESET + * + * @return use RESET on connection + */ + public boolean useResetConnection() { + return useResetConnection; + } - sb.append("\n\ndefault options :"); - String same = sbDefaultOpts.toString(); - if (same.isEmpty()) { - sb.append("None\n"); - } else { - sb.append(same); - } + /** + * Server RSA public key file for caching_sha2_password authentication + * + * @return server key file + */ + public String serverRsaPublicKeyFile() { + return serverRsaPublicKeyFile; + } - } catch (IllegalArgumentException | IllegalAccessException e) { - throw new IllegalArgumentException("Wrong parsing", e); - } - return sb.toString(); + /** + * permit mysql authentication to retrieve server certificate + * + * @return is driver allowed to retrieve server certificate from server + */ + public boolean allowPublicKeyRetrieval() { + return allowPublicKeyRetrieval; } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + /** + * Read all data from socket in advance + * + * @return use read ahead buffer implementation + */ + public boolean useReadAheadInput() { + return useReadAheadInput; + } - Configuration that = (Configuration) o; + /** + * Cache prepared statement result. + * + * @return cache prepare results + */ + public boolean cachePrepStmts() { + return cachePrepStmts; + } - if (password == null) { - return initialUrl.equals(that.initialUrl) && that.password == null; - } - return initialUrl.equals(that.initialUrl) && password.equals(that.password); + /** + * implements transaction replay failover + * + * @return true if transaction must be replayed on failover. + */ + public boolean transactionReplay() { + return transactionReplay; } /** - * Generate initialURL property + * transaction replay maximum number of saved command. * - * @param conf current configuration - * @return initialUrl value. + * @return transaction replay buffer size. */ - protected static String buildUrl(Configuration conf) { - Configuration defaultConf = new Configuration(); - StringBuilder sb = new StringBuilder(); - sb.append("jdbc:mariadb:"); - if (conf.haMode != HaMode.NONE) { - sb.append(conf.haMode.toString().toLowerCase(Locale.ROOT)).append(":"); - } - sb.append("//"); - for (int i = 0; i < conf.addresses.size(); i++) { - HostAddress hostAddress = conf.addresses.get(i); - if (i > 0) { - sb.append(","); - } - if ((conf.haMode == HaMode.NONE && hostAddress.primary) - || (conf.haMode == HaMode.REPLICATION - && ((i == 0 && hostAddress.primary) || (i != 0 && !hostAddress.primary)))) { - sb.append(hostAddress.host); - if (hostAddress.port != 3306) sb.append(":").append(hostAddress.port); - } else { - sb.append("address=(host=") - .append(hostAddress.host) - .append(")") - .append("(port=") - .append(hostAddress.port) - .append(")"); - sb.append("(type=").append(hostAddress.primary ? "primary" : "replica").append(")"); - } - } + public int transactionReplaySize() { + return transactionReplaySize; + } - sb.append("/"); - if (conf.database != null) { - sb.append(conf.database); - } + /** + * geometry default decoding implementation + * + * @return geometry default type + */ + public String geometryDefaultType() { + return geometryDefaultType; + } - try { - // Option object is already initialized to default values. - // loop on properties, - // - check DefaultOption to check that property value correspond to type (and range) - // - set values - boolean first = true; + /** + * Restrict authentication plugin to comma separated plugin list + * + * @return authorized authentication list + */ + public String restrictedAuth() { + return restrictedAuth; + } - Field[] fields = Configuration.class.getDeclaredFields(); - for (Field field : fields) { - if ("database".equals(field.getName()) - || "haMode".equals(field.getName()) - || "$jacocoData".equals(field.getName()) - || "addresses".equals(field.getName())) { - continue; - } - Object obj = field.get(conf); + /** + * Execute initial command when connection is established + * + * @return initial SQL command + */ + public String initSql() { + return initSql; + } - if (obj != null && (!(obj instanceof Properties) || ((Properties) obj).size() > 0)) { + /** + * datatype Encoder/decoder list + * + * @return codec list + */ + public Codec[] codecs() { + return codecs; + } - if ("password".equals(field.getName())) { - sb.append(first ? '?' : '&'); - first = false; - sb.append(field.getName()).append('='); - sb.append("***"); - continue; - } + /** + * ToString implementation. + * + * @return String value + */ + public String toString() { + return initialUrl; + } - if (field.getType().equals(String.class)) { - sb.append(first ? '?' : '&'); - first = false; - sb.append(field.getName()).append('='); - sb.append((String) obj); - } else if (field.getType().equals(boolean.class)) { - boolean defaultValue = field.getBoolean(defaultConf); - if (!obj.equals(defaultValue)) { - sb.append(first ? '?' : '&'); - first = false; - sb.append(field.getName()).append('='); - sb.append(obj); - } - } else if (field.getType().equals(int.class)) { - try { - int defaultValue = field.getInt(defaultConf); - if (!obj.equals(defaultValue)) { - sb.append(first ? '?' : '&'); - sb.append(field.getName()).append('=').append(obj); - first = false; - } - } catch (IllegalAccessException n) { - // eat - } - } else if (field.getType().equals(Properties.class)) { - sb.append(first ? '?' : '&'); - first = false; - boolean firstProp = true; - Properties properties = (Properties) obj; - for (Object key : properties.keySet()) { - if (firstProp) { - firstProp = false; - } else { - sb.append('&'); - } - sb.append(key).append('='); - sb.append(properties.get(key)); - } - } else if (field.getType().equals(CredentialPlugin.class)) { - Object defaultValue = field.get(defaultConf); - if (!obj.equals(defaultValue)) { - sb.append(first ? '?' : '&'); - first = false; - sb.append(field.getName()).append('='); - sb.append(((CredentialPlugin) obj).type()); - } - } else { - Object defaultValue = field.get(defaultConf); - if (!obj.equals(defaultValue)) { - sb.append(first ? '?' : '&'); - first = false; - sb.append(field.getName()).append('='); - sb.append(obj); - } - } - } - } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; - } catch (IllegalAccessException n) { - n.printStackTrace(); - } catch (SecurityException s) { - // only for jws, so never thrown - throw new IllegalArgumentException("Security too restrictive : " + s.getMessage()); + Configuration that = (Configuration) o; + + if (password == null) { + return initialUrl.equals(that.initialUrl) && that.password == null; } - conf.loadCodecs(); - return sb.toString(); + return initialUrl.equals(that.initialUrl) && password.equals(that.password); } @SuppressWarnings("rawtypes") @@ -2971,8 +2973,4 @@ public Configuration build() throws SQLException { return conf; } } - - private static String nullOrEmpty(String val) { - return (val == null || val.isEmpty()) ? null : val; - } } diff --git a/src/main/java/org/mariadb/jdbc/Connection.java b/src/main/java/org/mariadb/jdbc/Connection.java index 4e9db8b1b..9bb43a272 100644 --- a/src/main/java/org/mariadb/jdbc/Connection.java +++ b/src/main/java/org/mariadb/jdbc/Connection.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; import java.sql.*; @@ -39,17 +38,17 @@ public class Connection implements java.sql.Connection { private final ReentrantLock lock; private final Configuration conf; - private ExceptionFactory exceptionFactory; private final Client client; private final Properties clientInfo = new Properties(); - private int lowercaseTableNames = -1; private final AtomicInteger savepointId = new AtomicInteger(); - private boolean readOnly; private final boolean canUseServerTimeout; private final boolean canCachePrepStmts; private final boolean canUseServerMaxRows; private final int defaultFetchSize; private final boolean forceTransactionEnd; + private ExceptionFactory exceptionFactory; + private int lowercaseTableNames = -1; + private boolean readOnly; private MariaDbPoolConnection poolConnection; /** @@ -59,6 +58,7 @@ public class Connection implements java.sql.Connection { * @param lock thread safe locker * @param client client object */ + @SuppressWarnings({"this-escape"}) public Connection(Configuration conf, ReentrantLock lock, Client client) { this.conf = conf; this.forceTransactionEnd = @@ -94,8 +94,15 @@ public void setPoolConnection(MariaDbPoolConnection poolConnection) { * @throws SQLException never thrown */ public void cancelCurrentQuery() throws SQLException { - try (Client cli = - new StandardClient(conf, client.getHostAddress(), new ReentrantLock(), true)) { + // prefer relying on IP compare to DNS if not using Unix socket/PIPE + String currentIp = client.getSocketIp(); + HostAddress hostAddress = + currentIp == null + ? client.getHostAddress() + : HostAddress.from( + currentIp, client.getHostAddress().port, client.getHostAddress().primary); + + try (Client cli = new StandardClient(conf, hostAddress, new ReentrantLock(), true)) { cli.execute(new QueryPacket("KILL QUERY " + client.getContext().getThreadId()), false); } } @@ -323,11 +330,12 @@ private String getDatabase() throws SQLException { return client.getContext().getDatabase(); } - Statement stmt = createStatement(); - ResultSet rs = stmt.executeQuery("select database()"); - rs.next(); - client.getContext().setDatabase(rs.getString(1)); - return client.getContext().getDatabase(); + try (Statement stmt = createStatement()) { + ResultSet rs = stmt.executeQuery("select database()"); + rs.next(); + client.getContext().setDatabase(rs.getString(1)); + return client.getContext().getDatabase(); + } } private void setDatabase(String database) throws SQLException { @@ -365,29 +373,31 @@ public int getTransactionIsolation() throws SQLException { } } - ResultSet rs = createStatement().executeQuery(sql); - if (rs.next()) { - final String response = rs.getString(1); - switch (response) { - case "REPEATABLE-READ": - return java.sql.Connection.TRANSACTION_REPEATABLE_READ; + try (Statement stmt = createStatement()) { + ResultSet rs = stmt.executeQuery(sql); + if (rs.next()) { + final String response = rs.getString(1); + switch (response) { + case "REPEATABLE-READ": + return java.sql.Connection.TRANSACTION_REPEATABLE_READ; - case "READ-UNCOMMITTED": - return java.sql.Connection.TRANSACTION_READ_UNCOMMITTED; + case "READ-UNCOMMITTED": + return java.sql.Connection.TRANSACTION_READ_UNCOMMITTED; - case "READ-COMMITTED": - return java.sql.Connection.TRANSACTION_READ_COMMITTED; + case "READ-COMMITTED": + return java.sql.Connection.TRANSACTION_READ_COMMITTED; - case "SERIALIZABLE": - return java.sql.Connection.TRANSACTION_SERIALIZABLE; + case "SERIALIZABLE": + return java.sql.Connection.TRANSACTION_SERIALIZABLE; - default: - throw exceptionFactory.create( - String.format( - "Could not get transaction isolation level: Invalid value \"%s\"", response)); + default: + throw exceptionFactory.create( + String.format( + "Could not get transaction isolation level: Invalid value \"%s\"", response)); + } } + throw exceptionFactory.create("Failed to retrieve transaction isolation"); } - throw exceptionFactory.create("Failed to retrieve transaction isolation"); } @Override @@ -493,7 +503,8 @@ public CallableStatement prepareCall(String sql, int resultSetType, int resultSe Matcher matcher = CALLABLE_STATEMENT_PATTERN.matcher(sql); if (!matcher.matches()) { throw new SQLSyntaxErrorException( - "invalid callable syntax. must be like {[?=]call [(?,?, ...)]}\n but was : " + "invalid callable syntax. must be like {[?=]call [(?,?, ...)]}\n" + + " but was : " + sql); } @@ -796,55 +807,6 @@ public Client getClient() { return client; } - /** Internal Savepoint implementation */ - class MariaDbSavepoint implements java.sql.Savepoint { - - private final String name; - private final Integer id; - - public MariaDbSavepoint(final String name) { - this.name = name; - this.id = null; - } - - public MariaDbSavepoint(final int savepointId) { - this.id = savepointId; - this.name = null; - } - - /** - * Retrieves the generated ID for the savepoint that this Savepoint object - * represents. - * - * @return the numeric ID of this savepoint - */ - public int getSavepointId() throws SQLException { - if (name != null) { - throw exceptionFactory.create("Cannot retrieve savepoint id of a named savepoint"); - } - return id; - } - - /** - * Retrieves the name of the savepoint that this Savepoint object represents. - * - * @return the name of this savepoint - */ - public String getSavepointName() throws SQLException { - if (id != null) { - throw exceptionFactory.create("Cannot retrieve savepoint name of an unnamed savepoint"); - } - return name; - } - - public String rawValue() { - if (id != null) { - return "_jid_" + id; - } - return name; - } - } - /** * Reset connection set has it was after creating a "fresh" new connection. * defaultTransactionIsolation must have been initialized. @@ -884,7 +846,7 @@ && getContext().getVersion().getMinorVersion() == 2 setNetworkTimeout(null, conf.socketTimeout()); } if ((stateFlag & ConnectionState.STATE_AUTOCOMMIT) != 0) { - setAutoCommit(conf.autocommit() == null ? true : conf.autocommit()); + setAutoCommit(conf.autocommit() == null || conf.autocommit()); } if ((stateFlag & ConnectionState.STATE_DATABASE) != 0) { setCatalog(conf.database()); @@ -946,4 +908,53 @@ protected ExceptionFactory getExceptionFactory() { public String __test_host() { return this.client.getHostAddress().toString(); } + + /** Internal Savepoint implementation */ + class MariaDbSavepoint implements java.sql.Savepoint { + + private final String name; + private final Integer id; + + public MariaDbSavepoint(final String name) { + this.name = name; + this.id = null; + } + + public MariaDbSavepoint(final int savepointId) { + this.id = savepointId; + this.name = null; + } + + /** + * Retrieves the generated ID for the savepoint that this Savepoint object + * represents. + * + * @return the numeric ID of this savepoint + */ + public int getSavepointId() throws SQLException { + if (id == null) { + throw exceptionFactory.create("Cannot retrieve savepoint id of a named savepoint"); + } + return id; + } + + /** + * Retrieves the name of the savepoint that this Savepoint object represents. + * + * @return the name of this savepoint + */ + public String getSavepointName() throws SQLException { + if (id != null) { + throw exceptionFactory.create("Cannot retrieve savepoint name of an unnamed savepoint"); + } + return name; + } + + public String rawValue() { + if (id != null) { + return "_jid_" + id; + } + return name; + } + } } diff --git a/src/main/java/org/mariadb/jdbc/DatabaseMetaData.java b/src/main/java/org/mariadb/jdbc/DatabaseMetaData.java index ef0b75733..5da04808f 100644 --- a/src/main/java/org/mariadb/jdbc/DatabaseMetaData.java +++ b/src/main/java/org/mariadb/jdbc/DatabaseMetaData.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; import java.sql.*; @@ -84,9 +83,7 @@ private static int parseIdentifier(char[] part, int startPos, Identifier identif if (ch == '`') { quotes++; } else { - for (int j = 0; j < quotes / 2; j++) { - sb.append('`'); - } + sb.append("`".repeat(quotes / 2)); if (quotes % 2 == 1) { if (ch == '.') { if (identifier.schema != null) { @@ -201,7 +198,7 @@ private int parseIdentifierList(char[] part, int startPos, List list */ private ResultSet getImportedKeys( String tableDef, String tableName, String database, org.mariadb.jdbc.Connection connection) - throws Exception, SQLException { + throws Exception { boolean importedKeysWithConstraintNames = Boolean.parseBoolean( conf.nonMappedOptions().getProperty("importedKeysWithConstraintNames", "true")); @@ -300,7 +297,10 @@ private ResultSet getImportedKeys( break; } } - if (!foundKey) foundAll = false; + if (!foundKey) { + foundAll = false; + break; + } } if (foundAll) { row[12] = entry.getValue(); @@ -671,7 +671,8 @@ public ResultSet getPrimaryKeys(String catalog, String schema, String table) thr patternCond(false, sb, "A.TABLE_NAME", table); patternCond(false, sb, "B.TABLE_NAME", table); sb.append( - " AND A.TABLE_SCHEMA = B.TABLE_SCHEMA AND A.TABLE_NAME = B.TABLE_NAME AND A.COLUMN_NAME = B.COLUMN_NAME ORDER BY A.COLUMN_NAME"); + " AND A.TABLE_SCHEMA = B.TABLE_SCHEMA AND A.TABLE_NAME = B.TABLE_NAME AND A.COLUMN_NAME =" + + " B.COLUMN_NAME ORDER BY A.COLUMN_NAME"); return executeQuery(sb.toString()); } @@ -720,11 +721,11 @@ public ResultSet getTables( StringBuilder sb = new StringBuilder( - "SELECT TABLE_SCHEMA TABLE_CAT, NULL TABLE_SCHEM, TABLE_NAME," - + " IF(TABLE_TYPE='BASE TABLE' or TABLE_TYPE='SYSTEM VERSIONED', 'TABLE', TABLE_TYPE) as TABLE_TYPE," - + " TABLE_COMMENT REMARKS, NULL TYPE_CAT, NULL TYPE_SCHEM, NULL TYPE_NAME, NULL SELF_REFERENCING_COL_NAME, " - + " NULL REF_GENERATION" - + " FROM INFORMATION_SCHEMA.TABLES"); + "SELECT TABLE_SCHEMA TABLE_CAT, NULL TABLE_SCHEM, TABLE_NAME, IF(TABLE_TYPE='BASE" + + " TABLE' or TABLE_TYPE='SYSTEM VERSIONED', 'TABLE', IF(TABLE_TYPE='TEMPORARY', 'LOCAL TEMPORARY', TABLE_TYPE)) as TABLE_TYPE," + + " TABLE_COMMENT REMARKS, NULL TYPE_CAT, NULL TYPE_SCHEM, NULL TYPE_NAME, NULL" + + " SELF_REFERENCING_COL_NAME, NULL REF_GENERATION FROM" + + " INFORMATION_SCHEMA.TABLES"); String database = conf.useCatalogTerm() == CatalogTerm.UseCatalog ? catalog : schemaPattern; boolean firstCondition = databaseCond( @@ -737,14 +738,22 @@ public ResultSet getTables( StringBuilder sqlType = new StringBuilder(((firstCondition) ? " WHERE " : " AND ") + " TABLE_TYPE IN ("); for (String s : types) { - if (mustAddType) sqlType.append(","); - mustAddType = true; if (s == null) { - mustAddType = false; continue; } - String type = "TABLE".equals(s) ? "'BASE TABLE','SYSTEM VERSIONED'" : escapeQuote(s); - sqlType.append(type); + if (mustAddType) sqlType.append(","); + mustAddType = true; + switch (s) { + case "TABLE": + sqlType.append("'BASE TABLE','SYSTEM VERSIONED'"); + break; + case "LOCAL TEMPORARY": + sqlType.append("'TEMPORARY'"); + break; + default: + sqlType.append(escapeQuote(s)); + break; + } } sqlType.append(")"); if (mustAddType) sb.append(sqlType); @@ -864,14 +873,11 @@ public ResultSet getColumns( conf.useCatalogTerm() == CatalogTerm.UseCatalog ? "TABLE_SCHEMA TABLE_CAT, NULL TABLE_SCHEM" : "TABLE_CATALOG TABLE_CAT, TABLE_SCHEMA TABLE_SCHEM") - .append( - ", TABLE_NAME, COLUMN_NAME," - + dataTypeClause("COLUMN_TYPE") - + " DATA_TYPE," - + DataTypeClause(conf) - + " TYPE_NAME, " - + " CASE DATA_TYPE" - + " WHEN 'date' THEN 10"); + .append(", TABLE_NAME, COLUMN_NAME,") + .append(dataTypeClause("COLUMN_TYPE")) + .append(" DATA_TYPE,") + .append(DataTypeClause(conf)) + .append(" TYPE_NAME, CASE DATA_TYPE WHEN 'date' THEN 10"); if (supportsFractionalSeconds) { sb.append( " WHEN 'time' THEN " @@ -884,35 +890,36 @@ public ResultSet getColumns( // Older versions do not include the DATETIME_PRECISION column in INFORMATION_SCHEMA.COLUMNS. sb.append(" WHEN 'time' THEN 10 WHEN 'datetime' THEN 19 WHEN 'timestamp' THEN 19"); } - sb.append( - (conf.yearIsDateType() ? "" : " WHEN 'year' THEN 5") - + " ELSE " - + " IF(NUMERIC_PRECISION IS NULL, LEAST(CHARACTER_MAXIMUM_LENGTH," - + Integer.MAX_VALUE - + "), NUMERIC_PRECISION) " - + " END" - + " COLUMN_SIZE, 65535 BUFFER_LENGTH, " - + " CONVERT (CASE DATA_TYPE" - + " WHEN 'year' THEN " - + (conf.yearIsDateType() ? "NUMERIC_SCALE" : "0") - + " WHEN 'tinyint' THEN " - + (conf.tinyInt1isBit() ? "0" : "NUMERIC_SCALE") - + " ELSE NUMERIC_SCALE END, UNSIGNED INTEGER) DECIMAL_DIGITS," - + " 10 NUM_PREC_RADIX, IF(IS_NULLABLE = 'yes',1,0) NULLABLE,COLUMN_COMMENT REMARKS," - + " COLUMN_DEFAULT COLUMN_DEF, 0 SQL_DATA_TYPE, 0 SQL_DATETIME_SUB, " - + " LEAST(CHARACTER_OCTET_LENGTH," - + Integer.MAX_VALUE - + ") CHAR_OCTET_LENGTH," - + " ORDINAL_POSITION, IS_NULLABLE, NULL SCOPE_CATALOG, NULL SCOPE_SCHEMA, NULL SCOPE_TABLE, NULL SOURCE_DATA_TYPE," - + " IF(EXTRA = 'auto_increment','YES','NO') IS_AUTOINCREMENT, " - + " IF(EXTRA in ('VIRTUAL', 'PERSISTENT', 'VIRTUAL GENERATED', 'STORED GENERATED') ,'YES','NO') IS_GENERATEDCOLUMN " - + " FROM INFORMATION_SCHEMA.COLUMNS"); + sb.append((conf.yearIsDateType() ? "" : " WHEN 'year' THEN 5")) + .append( + " ELSE " + + " IF(NUMERIC_PRECISION IS NULL, LEAST(CHARACTER_MAXIMUM_LENGTH," + + Integer.MAX_VALUE + + "), NUMERIC_PRECISION) " + + " END" + + " COLUMN_SIZE, 65535 BUFFER_LENGTH, " + + " CONVERT (CASE DATA_TYPE" + + " WHEN 'year' THEN ") + .append((conf.yearIsDateType() ? "NUMERIC_SCALE" : "0")) + .append(" WHEN 'tinyint' THEN ") + .append(conf.tinyInt1isBit() ? "0" : "NUMERIC_SCALE") + .append( + " ELSE NUMERIC_SCALE END, UNSIGNED INTEGER) DECIMAL_DIGITS," + + " 10 NUM_PREC_RADIX, IF(IS_NULLABLE = 'yes',1,0) NULLABLE,COLUMN_COMMENT REMARKS," + + " COLUMN_DEFAULT COLUMN_DEF, 0 SQL_DATA_TYPE, 0 SQL_DATETIME_SUB, " + + " LEAST(CHARACTER_OCTET_LENGTH," + + Integer.MAX_VALUE + + ") CHAR_OCTET_LENGTH, ORDINAL_POSITION, IS_NULLABLE, NULL SCOPE_CATALOG, NULL" + + " SCOPE_SCHEMA, NULL SCOPE_TABLE, NULL SOURCE_DATA_TYPE, IF(EXTRA =" + + " 'auto_increment','YES','NO') IS_AUTOINCREMENT, IF(EXTRA in ('VIRTUAL'," + + " 'PERSISTENT', 'VIRTUAL GENERATED', 'STORED GENERATED') ,'YES','NO')" + + " IS_GENERATEDCOLUMN FROM INFORMATION_SCHEMA.COLUMNS"); String database = conf.useCatalogTerm() == CatalogTerm.UseCatalog ? catalog : schemaPattern; boolean firstCondition = databaseCond( true, sb, "TABLE_SCHEMA", database, conf.useCatalogTerm() == CatalogTerm.UseSchema); firstCondition = patternCond(firstCondition, sb, "TABLE_NAME", tableNamePattern); - firstCondition = patternCond(firstCondition, sb, "COLUMN_NAME", columnNamePattern); + patternCond(firstCondition, sb, "COLUMN_NAME", columnNamePattern); sb.append(" ORDER BY TABLE_CAT, TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION"); return executeQuery(sb.toString()); } @@ -989,7 +996,8 @@ public ResultSet getExportedKeys(String catalog, String schema, String table) .append( conf.useCatalogTerm() == CatalogTerm.UseCatalog ? "KCU.REFERENCED_TABLE_SCHEMA PKTABLE_CAT, NULL PKTABLE_SCHEM" - : "KCU.CONSTRAINT_CATALOG PKTABLE_CAT, KCU.REFERENCED_TABLE_SCHEMA PKTABLE_SCHEM") + : "KCU.CONSTRAINT_CATALOG PKTABLE_CAT, KCU.REFERENCED_TABLE_SCHEMA" + + " PKTABLE_SCHEM") .append( ", KCU.REFERENCED_TABLE_NAME PKTABLE_NAME," + " KCU.REFERENCED_COLUMN_NAME PKCOLUMN_NAME, ") @@ -998,23 +1006,13 @@ public ResultSet getExportedKeys(String catalog, String schema, String table) ? "KCU.TABLE_SCHEMA FKTABLE_CAT, NULL FKTABLE_SCHEM" : " TABLE_CATALOG FKTABLE_CAT, KCU.TABLE_SCHEMA FKTABLE_SCHEM") .append( - ", KCU.TABLE_NAME FKTABLE_NAME, KCU.COLUMN_NAME FKCOLUMN_NAME, KCU.POSITION_IN_UNIQUE_CONSTRAINT KEY_SEQ," - + " CASE update_rule " - + " WHEN 'RESTRICT' THEN 1" - + " WHEN 'NO ACTION' THEN 3" - + " WHEN 'CASCADE' THEN 0" - + " WHEN 'SET NULL' THEN 2" - + " WHEN 'SET DEFAULT' THEN 4" - + " END UPDATE_RULE," - + " CASE DELETE_RULE" - + " WHEN 'RESTRICT' THEN 1" - + " WHEN 'NO ACTION' THEN 3" - + " WHEN 'CASCADE' THEN 0" - + " WHEN 'SET NULL' THEN 2" - + " WHEN 'SET DEFAULT' THEN 4" - + " END DELETE_RULE," - + " RC.CONSTRAINT_NAME FK_NAME," - + " RC.UNIQUE_CONSTRAINT_NAME PK_NAME," + ", KCU.TABLE_NAME FKTABLE_NAME, KCU.COLUMN_NAME FKCOLUMN_NAME," + + " KCU.POSITION_IN_UNIQUE_CONSTRAINT KEY_SEQ, CASE update_rule WHEN" + + " 'RESTRICT' THEN 1 WHEN 'NO ACTION' THEN 3 WHEN 'CASCADE' THEN 0 WHEN" + + " 'SET NULL' THEN 2 WHEN 'SET DEFAULT' THEN 4 END UPDATE_RULE, CASE" + + " DELETE_RULE WHEN 'RESTRICT' THEN 1 WHEN 'NO ACTION' THEN 3 WHEN" + + " 'CASCADE' THEN 0 WHEN 'SET NULL' THEN 2 WHEN 'SET DEFAULT' THEN 4 END" + + " DELETE_RULE, RC.CONSTRAINT_NAME FK_NAME, RC.UNIQUE_CONSTRAINT_NAME PK_NAME," + importedKeyNotDeferrable + " DEFERRABILITY" + " FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU" @@ -1029,7 +1027,7 @@ public ResultSet getExportedKeys(String catalog, String schema, String table) "KCU.REFERENCED_TABLE_SCHEMA", database, conf.useCatalogTerm() == CatalogTerm.UseSchema); - firstCondition = patternCond(firstCondition, sb, "KCU.REFERENCED_TABLE_NAME", table); + patternCond(firstCondition, sb, "KCU.REFERENCED_TABLE_NAME", table); sb.append(" ORDER BY FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, KEY_SEQ"); return executeQuery(sb.toString()); @@ -1062,23 +1060,13 @@ public ResultSet getImportedKeysUsingInformationSchema(final String database, St ? "KCU.TABLE_SCHEMA FKTABLE_CAT, NULL FKTABLE_SCHEM" : "KCU.TABLE_CATALOG FKTABLE_CAT, KCU.TABLE_SCHEMA FKTABLE_SCHEM") .append( - ", KCU.TABLE_NAME FKTABLE_NAME, KCU.COLUMN_NAME FKCOLUMN_NAME, KCU.POSITION_IN_UNIQUE_CONSTRAINT KEY_SEQ," - + " CASE update_rule " - + " WHEN 'RESTRICT' THEN 1" - + " WHEN 'NO ACTION' THEN 3" - + " WHEN 'CASCADE' THEN 0" - + " WHEN 'SET NULL' THEN 2" - + " WHEN 'SET DEFAULT' THEN 4" - + " END UPDATE_RULE," - + " CASE DELETE_RULE" - + " WHEN 'RESTRICT' THEN 1" - + " WHEN 'NO ACTION' THEN 3" - + " WHEN 'CASCADE' THEN 0" - + " WHEN 'SET NULL' THEN 2" - + " WHEN 'SET DEFAULT' THEN 4" - + " END DELETE_RULE," - + " RC.CONSTRAINT_NAME FK_NAME," - + " RC.UNIQUE_CONSTRAINT_NAME PK_NAME," + ", KCU.TABLE_NAME FKTABLE_NAME, KCU.COLUMN_NAME FKCOLUMN_NAME," + + " KCU.POSITION_IN_UNIQUE_CONSTRAINT KEY_SEQ, CASE update_rule WHEN" + + " 'RESTRICT' THEN 1 WHEN 'NO ACTION' THEN 3 WHEN 'CASCADE' THEN 0 WHEN" + + " 'SET NULL' THEN 2 WHEN 'SET DEFAULT' THEN 4 END UPDATE_RULE, CASE" + + " DELETE_RULE WHEN 'RESTRICT' THEN 1 WHEN 'NO ACTION' THEN 3 WHEN" + + " 'CASCADE' THEN 0 WHEN 'SET NULL' THEN 2 WHEN 'SET DEFAULT' THEN 4 END" + + " DELETE_RULE, RC.CONSTRAINT_NAME FK_NAME, RC.UNIQUE_CONSTRAINT_NAME PK_NAME," + importedKeyNotDeferrable + " DEFERRABILITY" + " FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU" @@ -1187,8 +1175,8 @@ public ResultSet getBestRowIdentifier( + bestRowSession + " SCOPE, COLUMN_NAME," + dataTypeClause("COLUMN_TYPE") - + " DATA_TYPE, DATA_TYPE TYPE_NAME," - + " IF(NUMERIC_PRECISION IS NULL, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION) COLUMN_SIZE, 0 BUFFER_LENGTH," + + " DATA_TYPE, DATA_TYPE TYPE_NAME, IF(NUMERIC_PRECISION IS NULL," + + " CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION) COLUMN_SIZE, 0 BUFFER_LENGTH," + " NUMERIC_SCALE DECIMAL_DIGITS," + (hasIsGeneratedCol ? ("IF(IS_GENERATED='NEVER'," + bestRowNotPseudo + "," + bestRowPseudo + ")") @@ -1275,9 +1263,9 @@ public ResultSet getPseudoColumns( return connection .createStatement() .executeQuery( - "SELECT ' ' TABLE_CAT, ' ' TABLE_SCHEM, ' ' TABLE_NAME, ' ' COLUMN_NAME, 0 DATA_TYPE, 0 COLUMN_SIZE, " - + "0 DECIMAL_DIGITS, 10 NUM_PREC_RADIX, ' ' COLUMN_USAGE, ' ' REMARKS, 0 CHAR_OCTET_LENGTH, " - + "'YES' IS_NULLABLE FROM DUAL WHERE 1=0"); + "SELECT ' ' TABLE_CAT, ' ' TABLE_SCHEM, ' ' TABLE_NAME, ' ' COLUMN_NAME, 0 DATA_TYPE, 0" + + " COLUMN_SIZE, 0 DECIMAL_DIGITS, 10 NUM_PREC_RADIX, ' ' COLUMN_USAGE, ' '" + + " REMARKS, 0 CHAR_OCTET_LENGTH, 'YES' IS_NULLABLE FROM DUAL WHERE 1=0"); } public boolean allProceduresAreCallable() { @@ -1406,17 +1394,17 @@ public String getIdentifierQuoteString() { @Override public String getSQLKeywords() { return "ACCESSIBLE,ANALYZE,ASENSITIVE,BEFORE,BIGINT,BINARY,BLOB,CALL,CHANGE,CONDITION,DATABASE,DATABASES," - + "DAY_HOUR,DAY_MICROSECOND,DAY_MINUTE,DAY_SECOND,DELAYED,DETERMINISTIC,DISTINCTROW,DIV,DUAL,EACH," - + "ELSEIF,ENCLOSED,ESCAPED,EXIT,EXPLAIN,FLOAT4,FLOAT8,FORCE,FULLTEXT,GENERAL,HIGH_PRIORITY," - + "HOUR_MICROSECOND,HOUR_MINUTE,HOUR_SECOND,IF,IGNORE,IGNORE_SERVER_IDS,INDEX,INFILE,INOUT,INT1,INT2," - + "INT3,INT4,INT8,ITERATE,KEY,KEYS,KILL,LEAVE,LIMIT,LINEAR,LINES,LOAD,LOCALTIME,LOCALTIMESTAMP,LOCK," - + "LONG,LONGBLOB,LONGTEXT,LOOP,LOW_PRIORITY,MASTER_HEARTBEAT_PERIOD,MASTER_SSL_VERIFY_SERVER_CERT," - + "MAXVALUE,MEDIUMBLOB,MEDIUMINT,MEDIUMTEXT,MIDDLEINT,MINUTE_MICROSECOND,MINUTE_SECOND,MOD,MODIFIES," - + "NO_WRITE_TO_BINLOG,OPTIMIZE,OPTIONALLY,OUT,OUTFILE,PURGE,RANGE,READ_WRITE,READS,REGEXP,RELEASE," - + "RENAME,REPEAT,REPLACE,REQUIRE,RESIGNAL,RESTRICT,RETURN,RLIKE,SCHEMAS,SECOND_MICROSECOND,SENSITIVE," - + "SEPARATOR,SHOW,SIGNAL,SLOW,SPATIAL,SPECIFIC,SQL_BIG_RESULT,SQL_CALC_FOUND_ROWS,SQL_SMALL_RESULT," - + "SQLEXCEPTION,SSL,STARTING,STRAIGHT_JOIN,TERMINATED,TINYBLOB,TINYINT,TINYTEXT,TRIGGER,UNDO,UNLOCK," - + "UNSIGNED,USE,UTC_DATE,UTC_TIME,UTC_TIMESTAMP,VARBINARY,VARCHARACTER,WHILE,XOR,YEAR_MONTH,ZEROFILL"; + + "DAY_HOUR,DAY_MICROSECOND,DAY_MINUTE,DAY_SECOND,DELAYED,DETERMINISTIC,DISTINCTROW,DIV,DUAL,EACH," + + "ELSEIF,ENCLOSED,ESCAPED,EXIT,EXPLAIN,FLOAT4,FLOAT8,FORCE,FULLTEXT,GENERAL,HIGH_PRIORITY," + + "HOUR_MICROSECOND,HOUR_MINUTE,HOUR_SECOND,IF,IGNORE,IGNORE_SERVER_IDS,INDEX,INFILE,INOUT,INT1,INT2," + + "INT3,INT4,INT8,ITERATE,KEY,KEYS,KILL,LEAVE,LIMIT,LINEAR,LINES,LOAD,LOCALTIME,LOCALTIMESTAMP,LOCK," + + "LONG,LONGBLOB,LONGTEXT,LOOP,LOW_PRIORITY,MASTER_HEARTBEAT_PERIOD,MASTER_SSL_VERIFY_SERVER_CERT," + + "MAXVALUE,MEDIUMBLOB,MEDIUMINT,MEDIUMTEXT,MIDDLEINT,MINUTE_MICROSECOND,MINUTE_SECOND,MOD,MODIFIES," + + "NO_WRITE_TO_BINLOG,OPTIMIZE,OPTIONALLY,OUT,OUTFILE,PURGE,RANGE,READ_WRITE,READS,REGEXP,RELEASE," + + "RENAME,REPEAT,REPLACE,REQUIRE,RESIGNAL,RESTRICT,RETURN,RLIKE,SCHEMAS,SECOND_MICROSECOND,SENSITIVE," + + "SEPARATOR,SHOW,SIGNAL,SLOW,SPATIAL,SPECIFIC,SQL_BIG_RESULT,SQL_CALC_FOUND_ROWS,SQL_SMALL_RESULT," + + "SQLEXCEPTION,SSL,STARTING,STRAIGHT_JOIN,TERMINATED,TINYBLOB,TINYINT,TINYTEXT,TRIGGER,UNDO,UNLOCK," + + "UNSIGNED,USE,UTC_DATE,UTC_TIME,UTC_TIMESTAMP,VARBINARY,VARCHARACTER,WHILE,XOR,YEAR_MONTH,ZEROFILL"; } /** @@ -1427,7 +1415,7 @@ public String getSQLKeywords() { @Override public String getNumericFunctions() { return "DIV,ABS,ACOS,ASIN,ATAN,ATAN2,CEIL,CEILING,CONV,COS,COT,CRC32,DEGREES,EXP,FLOOR,GREATEST,LEAST,LN,LOG," - + "LOG10,LOG2,MOD,OCT,PI,POW,POWER,RADIANS,RAND,ROUND,SIGN,SIN,SQRT,TAN,TRUNCATE"; + + "LOG10,LOG2,MOD,OCT,PI,POW,POWER,RADIANS,RAND,ROUND,SIGN,SIN,SQRT,TAN,TRUNCATE"; } /** @@ -1438,10 +1426,11 @@ public String getNumericFunctions() { @Override public String getStringFunctions() { return "ASCII,BIN,BIT_LENGTH,CAST,CHARACTER_LENGTH,CHAR_LENGTH,CONCAT,CONCAT_WS,CONVERT,ELT,EXPORT_SET," - + "EXTRACTVALUE,FIELD,FIND_IN_SET,FORMAT,FROM_BASE64,HEX,INSTR,LCASE,LEFT,LENGTH,LIKE,LOAD_FILE,LOCATE," - + "LOWER,LPAD,LTRIM,MAKE_SET,MATCH AGAINST,MID,NOT LIKE,NOT REGEXP,OCTET_LENGTH,ORD,POSITION,QUOTE," - + "REPEAT,REPLACE,REVERSE,RIGHT,RPAD,RTRIM,SOUNDEX,SOUNDS LIKE,SPACE,STRCMP,SUBSTR,SUBSTRING," - + "SUBSTRING_INDEX,TO_BASE64,TRIM,UCASE,UNHEX,UPDATEXML,UPPER,WEIGHT_STRING"; + + "EXTRACTVALUE,FIELD,FIND_IN_SET,FORMAT,FROM_BASE64,HEX,INSTR,LCASE,LEFT,LENGTH,LIKE,LOAD_FILE,LOCATE,LOWER,LPAD,LTRIM,MAKE_SET,MATCH" + + " AGAINST,MID,NOT LIKE,NOT" + + " REGEXP,OCTET_LENGTH,ORD,POSITION,QUOTE,REPEAT,REPLACE,REVERSE,RIGHT,RPAD,RTRIM,SOUNDEX,SOUNDS" + + " LIKE,SPACE,STRCMP,SUBSTR,SUBSTRING," + + "SUBSTRING_INDEX,TO_BASE64,TRIM,UCASE,UNHEX,UPDATEXML,UPPER,WEIGHT_STRING"; } /** @@ -1462,11 +1451,11 @@ public String getSystemFunctions() { @Override public String getTimeDateFunctions() { return "ADDDATE,ADDTIME,CONVERT_TZ,CURDATE,CURRENT_DATE,CURRENT_TIME,CURRENT_TIMESTAMP,CURTIME,DATEDIFF," - + "DATE_ADD,DATE_FORMAT,DATE_SUB,DAY,DAYNAME,DAYOFMONTH,DAYOFWEEK,DAYOFYEAR,EXTRACT,FROM_DAYS," - + "FROM_UNIXTIME,GET_FORMAT,HOUR,LAST_DAY,LOCALTIME,LOCALTIMESTAMP,MAKEDATE,MAKETIME,MICROSECOND," - + "MINUTE,MONTH,MONTHNAME,NOW,PERIOD_ADD,PERIOD_DIFF,QUARTER,SECOND,SEC_TO_TIME,STR_TO_DATE,SUBDATE," - + "SUBTIME,SYSDATE,TIMEDIFF,TIMESTAMPADD,TIMESTAMPDIFF,TIME_FORMAT,TIME_TO_SEC,TO_DAYS,TO_SECONDS," - + "UNIX_TIMESTAMP,UTC_DATE,UTC_TIME,UTC_TIMESTAMP,WEEK,WEEKDAY,WEEKOFYEAR,YEAR,YEARWEEK"; + + "DATE_ADD,DATE_FORMAT,DATE_SUB,DAY,DAYNAME,DAYOFMONTH,DAYOFWEEK,DAYOFYEAR,EXTRACT,FROM_DAYS," + + "FROM_UNIXTIME,GET_FORMAT,HOUR,LAST_DAY,LOCALTIME,LOCALTIMESTAMP,MAKEDATE,MAKETIME,MICROSECOND," + + "MINUTE,MONTH,MONTHNAME,NOW,PERIOD_ADD,PERIOD_DIFF,QUARTER,SECOND,SEC_TO_TIME,STR_TO_DATE,SUBDATE," + + "SUBTIME,SYSDATE,TIMEDIFF,TIMESTAMPADD,TIMESTAMPDIFF,TIME_FORMAT,TIME_TO_SEC,TO_DAYS,TO_SECONDS," + + "UNIX_TIMESTAMP,UTC_DATE,UTC_TIME,UTC_TIMESTAMP,WEEK,WEEKDAY,WEEKOFYEAR,YEAR,YEARWEEK"; } public String getSearchStringEscape() { @@ -2070,7 +2059,7 @@ public ResultSet getProcedures(String catalog, String schemaPattern, String proc boolean firstCondition = databaseCond( true, sb, "ROUTINE_SCHEMA", database, conf.useCatalogTerm() == CatalogTerm.UseSchema); - firstCondition = patternCond(firstCondition, sb, "ROUTINE_NAME", procedureNamePattern); + patternCond(firstCondition, sb, "ROUTINE_NAME", procedureNamePattern); return executeQuery(sb.toString()); } @@ -2176,10 +2165,9 @@ public ResultSet getProcedureColumns( */ StringBuilder sb = new StringBuilder( - "SELECT SPECIFIC_SCHEMA PROCEDURE_CAT, NULL PROCEDURE_SCHEM, SPECIFIC_NAME PROCEDURE_NAME," - + " PARAMETER_NAME COLUMN_NAME, " - + " CASE PARAMETER_MODE " - + " WHEN 'IN' THEN " + "SELECT SPECIFIC_SCHEMA PROCEDURE_CAT, NULL PROCEDURE_SCHEM, SPECIFIC_NAME" + + " PROCEDURE_NAME, PARAMETER_NAME COLUMN_NAME, CASE PARAMETER_MODE WHEN 'IN'" + + " THEN " + procedureColumnIn + " WHEN 'OUT' THEN " + procedureColumnOut @@ -2228,15 +2216,15 @@ public ResultSet getProcedureColumns( + " END `SCALE`," + "10 RADIX," + procedureNullableUnknown - + " NULLABLE,NULL REMARKS,NULL COLUMN_DEF,0 SQL_DATA_TYPE,0 SQL_DATETIME_SUB," - + "CHARACTER_OCTET_LENGTH CHAR_OCTET_LENGTH ,ORDINAL_POSITION, '' IS_NULLABLE, SPECIFIC_NAME " - + " FROM INFORMATION_SCHEMA.PARAMETERS"); + + " NULLABLE,NULL REMARKS,NULL COLUMN_DEF,0 SQL_DATA_TYPE,0" + + " SQL_DATETIME_SUB,CHARACTER_OCTET_LENGTH CHAR_OCTET_LENGTH ,ORDINAL_POSITION, ''" + + " IS_NULLABLE, SPECIFIC_NAME FROM INFORMATION_SCHEMA.PARAMETERS"); String database = conf.useCatalogTerm() == CatalogTerm.UseCatalog ? catalog : schemaPattern; boolean firstCondition = databaseCond( true, sb, "SPECIFIC_SCHEMA", database, conf.useCatalogTerm() == CatalogTerm.UseCatalog); firstCondition = patternCond(firstCondition, sb, "SPECIFIC_NAME", procedureNamePattern); - firstCondition = patternCond(firstCondition, sb, "PARAMETER_NAME", columnNamePattern); + patternCond(firstCondition, sb, "PARAMETER_NAME", columnNamePattern); sb.append(" ORDER BY SPECIFIC_SCHEMA, SPECIFIC_NAME, ORDINAL_POSITION"); return executeQuery(sb.toString()); @@ -2349,14 +2337,15 @@ public ResultSet getFunctionColumns( + functionColumnInOut + " ELSE " + functionReturn - + " END COLUMN_TYPE," - + dataTypeClause("DTD_IDENTIFIER") - + " DATA_TYPE," - + "DATA_TYPE TYPE_NAME,NUMERIC_PRECISION `PRECISION`,CHARACTER_MAXIMUM_LENGTH LENGTH,NUMERIC_SCALE SCALE,10 RADIX," + + " END COLUMN_TYPE,") + .append(dataTypeClause("DTD_IDENTIFIER")) + .append( + " DATA_TYPE,DATA_TYPE TYPE_NAME,NUMERIC_PRECISION" + + " `PRECISION`,CHARACTER_MAXIMUM_LENGTH LENGTH,NUMERIC_SCALE SCALE,10 RADIX," + procedureNullableUnknown - + " NULLABLE,NULL REMARKS," - + "CHARACTER_OCTET_LENGTH CHAR_OCTET_LENGTH ,ORDINAL_POSITION, '' IS_NULLABLE, SPECIFIC_NAME " - + " FROM INFORMATION_SCHEMA.PARAMETERS"); + + " NULLABLE,NULL REMARKS,CHARACTER_OCTET_LENGTH CHAR_OCTET_LENGTH" + + " ,ORDINAL_POSITION, '' IS_NULLABLE, SPECIFIC_NAME FROM" + + " INFORMATION_SCHEMA.PARAMETERS"); String database = conf.useCatalogTerm() == CatalogTerm.UseCatalog ? catalog : schemaPattern; boolean firstCondition = databaseCond( @@ -2372,7 +2361,8 @@ public ResultSet getFunctionColumns( public ResultSet getSchemas() throws SQLException { if (conf.useCatalogTerm() == CatalogTerm.UseSchema) { return executeQuery( - "SELECT SCHEMA_NAME as TABLE_SCHEM, CATALOG_NAME as TABLE_CATALOG FROM information_schema.SCHEMATA ORDER BY SCHEMA_NAME"); + "SELECT SCHEMA_NAME as TABLE_SCHEM, CATALOG_NAME as TABLE_CATALOG FROM" + + " information_schema.SCHEMATA ORDER BY SCHEMA_NAME"); } return executeQuery("SELECT '' TABLE_SCHEM, '' TABLE_CATALOG FROM DUAL WHERE 1=0"); } @@ -2381,8 +2371,9 @@ public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLExce if (conf.useCatalogTerm() == CatalogTerm.UseSchema) { StringBuilder sb = new StringBuilder( - "SELECT SCHEMA_NAME as TABLE_SCHEM, CATALOG_NAME as TABLE_CATALOG FROM information_schema.SCHEMATA "); - boolean firstCondition = databaseCond(true, sb, "SCHEMA_NAME", schemaPattern, true); + "SELECT SCHEMA_NAME as TABLE_SCHEM, CATALOG_NAME as TABLE_CATALOG FROM" + + " information_schema.SCHEMATA "); + databaseCond(true, sb, "SCHEMA_NAME", schemaPattern, true); sb.append(" ORDER BY SCHEMA_NAME"); return executeQuery(sb.toString()); } @@ -2399,7 +2390,10 @@ public ResultSet getCatalogs() throws SQLException { public ResultSet getTableTypes() throws SQLException { return executeQuery( - "SELECT 'TABLE' TABLE_TYPE UNION SELECT 'SYSTEM VIEW' TABLE_TYPE UNION SELECT 'VIEW' TABLE_TYPE"); + "SELECT 'TABLE' TABLE_TYPE " + + "UNION SELECT 'SYSTEM VIEW' TABLE_TYPE " + + "UNION SELECT 'VIEW' TABLE_TYPE " + + "UNION SELECT 'LOCAL TEMPORARY' TABLE_TYPE"); } /** @@ -2516,7 +2510,7 @@ public ResultSet getTablePrivileges(String catalog, String schemaPattern, String boolean firstCondition = databaseCond( true, sb, "TABLE_SCHEMA", database, conf.useCatalogTerm() == CatalogTerm.UseSchema); - firstCondition = patternCond(firstCondition, sb, "TABLE_NAME", tableNamePattern); + patternCond(firstCondition, sb, "TABLE_NAME", tableNamePattern); sb.append(" ORDER BY TABLE_SCHEMA, TABLE_NAME, PRIVILEGE_TYPE "); return executeQuery(sb.toString()); @@ -2671,23 +2665,13 @@ public ResultSet getCrossReference( ? "KCU.TABLE_SCHEMA FKTABLE_CAT, NULL FKTABLE_SCHEM" : "KCU.TABLE_CATALOG FKTABLE_CAT, KCU.TABLE_SCHEMA FKTABLE_SCHEM") .append( - ", KCU.TABLE_NAME FKTABLE_NAME, KCU.COLUMN_NAME FKCOLUMN_NAME, KCU.POSITION_IN_UNIQUE_CONSTRAINT KEY_SEQ," - + " CASE update_rule " - + " WHEN 'RESTRICT' THEN 1" - + " WHEN 'NO ACTION' THEN 3" - + " WHEN 'CASCADE' THEN 0" - + " WHEN 'SET NULL' THEN 2" - + " WHEN 'SET DEFAULT' THEN 4" - + " END UPDATE_RULE," - + " CASE DELETE_RULE" - + " WHEN 'RESTRICT' THEN 1" - + " WHEN 'NO ACTION' THEN 3" - + " WHEN 'CASCADE' THEN 0" - + " WHEN 'SET NULL' THEN 2" - + " WHEN 'SET DEFAULT' THEN 4" - + " END DELETE_RULE," - + " RC.CONSTRAINT_NAME FK_NAME," - + " RC.UNIQUE_CONSTRAINT_NAME PK_NAME," + ", KCU.TABLE_NAME FKTABLE_NAME, KCU.COLUMN_NAME FKCOLUMN_NAME," + + " KCU.POSITION_IN_UNIQUE_CONSTRAINT KEY_SEQ, CASE update_rule WHEN" + + " 'RESTRICT' THEN 1 WHEN 'NO ACTION' THEN 3 WHEN 'CASCADE' THEN 0 WHEN" + + " 'SET NULL' THEN 2 WHEN 'SET DEFAULT' THEN 4 END UPDATE_RULE, CASE" + + " DELETE_RULE WHEN 'RESTRICT' THEN 1 WHEN 'NO ACTION' THEN 3 WHEN" + + " 'CASCADE' THEN 0 WHEN 'SET NULL' THEN 2 WHEN 'SET DEFAULT' THEN 4 END" + + " DELETE_RULE, RC.CONSTRAINT_NAME FK_NAME, RC.UNIQUE_CONSTRAINT_NAME PK_NAME," + importedKeyNotDeferrable + " DEFERRABILITY " + "FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU" @@ -2702,7 +2686,7 @@ public ResultSet getCrossReference( databaseCond(true, sb, "KCU.REFERENCED_TABLE_SCHEMA", parentDatabase, false); firstCondition = databaseCond(firstCondition, sb, "KCU.TABLE_SCHEMA", foreignDatabase, false); firstCondition = patternCond(firstCondition, sb, "KCU.REFERENCED_TABLE_NAME", parentTable); - firstCondition = patternCond(firstCondition, sb, "KCU.TABLE_NAME", foreignTable); + patternCond(firstCondition, sb, "KCU.TABLE_NAME", foreignTable); sb.append("ORDER BY FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, KEY_SEQ"); return executeQuery(sb.toString()); @@ -3647,8 +3631,8 @@ public ResultSet getUDTs( String catalog, String schemaPattern, String typeNamePattern, int[] types) throws SQLException { String sql = - "SELECT ' ' TYPE_CAT, NULL TYPE_SCHEM, ' ' TYPE_NAME, ' ' CLASS_NAME, 0 DATA_TYPE, ' ' REMARKS, 0 BASE_TYPE" - + " FROM DUAL WHERE 1=0"; + "SELECT ' ' TYPE_CAT, NULL TYPE_SCHEM, ' ' TYPE_NAME, ' ' CLASS_NAME, 0 DATA_TYPE, ' '" + + " REMARKS, 0 BASE_TYPE FROM DUAL WHERE 1=0"; return executeQuery(sql); } @@ -3710,8 +3694,8 @@ public boolean supportsGetGeneratedKeys() { public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException { String sql = - "SELECT ' ' TYPE_CAT, NULL TYPE_SCHEM, ' ' TYPE_NAME, ' ' SUPERTYPE_CAT, ' ' SUPERTYPE_SCHEM, ' ' SUPERTYPE_NAME" - + " FROM DUAL WHERE 1=0"; + "SELECT ' ' TYPE_CAT, NULL TYPE_SCHEM, ' ' TYPE_NAME, ' ' SUPERTYPE_CAT, ' '" + + " SUPERTYPE_SCHEM, ' ' SUPERTYPE_NAME FROM DUAL WHERE 1=0"; return executeQuery(sql); } @@ -3750,7 +3734,8 @@ public ResultSet getSuperTypes(String catalog, String schemaPattern, String type public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException { String sql = - "SELECT ' ' TABLE_CAT, ' ' TABLE_SCHEM, ' ' TABLE_NAME, ' ' SUPERTABLE_NAME FROM DUAL WHERE 1=0"; + "SELECT ' ' TABLE_CAT, ' ' TABLE_SCHEM, ' ' TABLE_NAME, ' ' SUPERTABLE_NAME FROM DUAL" + + " WHERE 1=0"; return executeQuery(sql); } @@ -3827,13 +3812,11 @@ public ResultSet getAttributes( throws SQLException { String sql = - "SELECT ' ' TYPE_CAT, ' ' TYPE_SCHEM, ' ' TYPE_NAME, ' ' ATTR_NAME, 0 DATA_TYPE," - + " ' ' ATTR_TYPE_NAME, 0 ATTR_SIZE, 0 DECIMAL_DIGITS, 0 NUM_PREC_RADIX, 0 NULLABLE," - + " ' ' REMARKS, ' ' ATTR_DEF, 0 SQL_DATA_TYPE, 0 SQL_DATETIME_SUB, 0 CHAR_OCTET_LENGTH," - + " 0 ORDINAL_POSITION, ' ' IS_NULLABLE, ' ' SCOPE_CATALOG, ' ' SCOPE_SCHEMA, ' ' SCOPE_TABLE," - + " 0 SOURCE_DATA_TYPE" - + " FROM DUAL " - + " WHERE 1=0"; + "SELECT ' ' TYPE_CAT, ' ' TYPE_SCHEM, ' ' TYPE_NAME, ' ' ATTR_NAME, 0 DATA_TYPE, ' '" + + " ATTR_TYPE_NAME, 0 ATTR_SIZE, 0 DECIMAL_DIGITS, 0 NUM_PREC_RADIX, 0 NULLABLE, ' '" + + " REMARKS, ' ' ATTR_DEF, 0 SQL_DATA_TYPE, 0 SQL_DATETIME_SUB, 0 CHAR_OCTET_LENGTH, 0" + + " ORDINAL_POSITION, ' ' IS_NULLABLE, ' ' SCOPE_CATALOG, ' ' SCOPE_SCHEMA, ' '" + + " SCOPE_TABLE, 0 SOURCE_DATA_TYPE FROM DUAL WHERE 1=0"; return executeQuery(sql); } @@ -3924,8 +3907,9 @@ public ResultSet getClientInfoProperties() { "ClientUser", "16777215", "", - "The name of the user that the application using the connection is performing work for. " - + "This may not be the same as the user name that was used in establishing the connection." + "The name of the user that the application using the connection is performing work for." + + " This may not be the same as the user name that was used in establishing the" + + " connection." }, new String[] { "ClientHostname", diff --git a/src/main/java/org/mariadb/jdbc/Driver.java b/src/main/java/org/mariadb/jdbc/Driver.java index e9e913d8a..5143d4cc6 100644 --- a/src/main/java/org/mariadb/jdbc/Driver.java +++ b/src/main/java/org/mariadb/jdbc/Driver.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; import java.io.IOException; @@ -80,11 +79,6 @@ public static Connection connect(Configuration configuration) throws SQLExceptio return new Connection(configuration, lock, client); } - @FunctionalInterface - private interface ClientInstance { - R apply(T t, U u, V v, W w) throws SQLException; - } - /** * Connect to the given connection string. * @@ -186,4 +180,9 @@ public boolean jdbcCompliant() { public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException { throw new SQLFeatureNotSupportedException("Use logging parameters for enabling logging."); } + + @FunctionalInterface + private interface ClientInstance { + R apply(T t, U u, V v, W w) throws SQLException; + } } diff --git a/src/main/java/org/mariadb/jdbc/FunctionStatement.java b/src/main/java/org/mariadb/jdbc/FunctionStatement.java index 1d5993480..444f5e04e 100644 --- a/src/main/java/org/mariadb/jdbc/FunctionStatement.java +++ b/src/main/java/org/mariadb/jdbc/FunctionStatement.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; import java.sql.*; @@ -26,6 +25,7 @@ public class FunctionStatement extends BaseCallableStatement implements Callable * @param resultSetConcurrency concurrency type * @throws SQLException if any error occurs */ + @SuppressWarnings({"this-escape"}) public FunctionStatement( Connection con, String databaseName, diff --git a/src/main/java/org/mariadb/jdbc/HostAddress.java b/src/main/java/org/mariadb/jdbc/HostAddress.java index 2a14bf066..8294331e1 100644 --- a/src/main/java/org/mariadb/jdbc/HostAddress.java +++ b/src/main/java/org/mariadb/jdbc/HostAddress.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; import java.sql.SQLException; @@ -12,7 +11,6 @@ /** Host entry */ public class HostAddress { - private long CONNECTED_VALUE_TIMEOUT = 3 * 60 * 1000; // 3 minutes /** host address */ public final String host; @@ -194,15 +192,16 @@ public int hashCode() { return Objects.hash(host, port, primary); } - public void setThreadsConnected(long threadsConnected) { - this.threadsConnected = threadsConnected; - this.threadConnectedTimeout = System.currentTimeMillis() + CONNECTED_VALUE_TIMEOUT; - } - public Long getThreadsConnected() { return threadsConnected; } + public void setThreadsConnected(long threadsConnected) { + this.threadsConnected = threadsConnected; + // timeout in 3 minutes + this.threadConnectedTimeout = System.currentTimeMillis() + 3 * 60 * 1000; + } + public void forceThreadsConnected(long threadsConnected, long threadConnectedTimeout) { this.threadsConnected = threadsConnected; this.threadConnectedTimeout = threadConnectedTimeout; diff --git a/src/main/java/org/mariadb/jdbc/MariaDbBlob.java b/src/main/java/org/mariadb/jdbc/MariaDbBlob.java index b6dd1d99e..cd8f07aab 100644 --- a/src/main/java/org/mariadb/jdbc/MariaDbBlob.java +++ b/src/main/java/org/mariadb/jdbc/MariaDbBlob.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; import java.io.*; diff --git a/src/main/java/org/mariadb/jdbc/MariaDbClob.java b/src/main/java/org/mariadb/jdbc/MariaDbClob.java index 52f82109e..e66035c4d 100644 --- a/src/main/java/org/mariadb/jdbc/MariaDbClob.java +++ b/src/main/java/org/mariadb/jdbc/MariaDbClob.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; import java.io.*; diff --git a/src/main/java/org/mariadb/jdbc/MariaDbDataSource.java b/src/main/java/org/mariadb/jdbc/MariaDbDataSource.java index 37889691c..e714cc731 100644 --- a/src/main/java/org/mariadb/jdbc/MariaDbDataSource.java +++ b/src/main/java/org/mariadb/jdbc/MariaDbDataSource.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; import java.io.PrintWriter; @@ -232,6 +231,16 @@ public XAConnection getXAConnection(String username, String password) throws SQL return new MariaDbPoolConnection(Driver.connect(conf)); } + /** + * Returns the URL for this datasource + * + * @return the URL for this datasource + */ + public String getUrl() { + if (conf == null) return url; + return conf.initialUrl(); + } + /** * Sets the URL for this datasource * @@ -247,16 +256,6 @@ public void setUrl(String url) throws SQLException { } } - /** - * Returns the URL for this datasource - * - * @return the URL for this datasource - */ - public String getUrl() { - if (conf == null) return url; - return conf.initialUrl(); - } - /** * get User * diff --git a/src/main/java/org/mariadb/jdbc/MariaDbPoolConnection.java b/src/main/java/org/mariadb/jdbc/MariaDbPoolConnection.java index 2ae12ad32..d6700f6c0 100644 --- a/src/main/java/org/mariadb/jdbc/MariaDbPoolConnection.java +++ b/src/main/java/org/mariadb/jdbc/MariaDbPoolConnection.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; import java.sql.PreparedStatement; @@ -28,6 +27,7 @@ public class MariaDbPoolConnection implements PooledConnection, XAConnection { * * @param connection connection to retrieve connection options */ + @SuppressWarnings({"this-escape"}) public MariaDbPoolConnection(Connection connection) { this.connection = connection; this.connection.setPoolConnection(this); @@ -35,6 +35,21 @@ public MariaDbPoolConnection(Connection connection) { connectionEventListeners = new CopyOnWriteArrayList<>(); } + /** + * Create XID string + * + * @param xid xid value + * @return XID string + */ + public static String xidToString(Xid xid) { + return "0x" + + StringUtils.byteArrayToHexString(xid.getGlobalTransactionId()) + + ",0x" + + StringUtils.byteArrayToHexString(xid.getBranchQualifier()) + + ",0x" + + Integer.toHexString(xid.getFormatId()); + } + @Override public Connection getConnection() { return connection; @@ -120,21 +135,6 @@ public void close() throws SQLException { connection.close(); } - /** - * Create XID string - * - * @param xid xid value - * @return XID string - */ - public static String xidToString(Xid xid) { - return "0x" - + StringUtils.byteArrayToHexString(xid.getGlobalTransactionId()) - + ",0x" - + StringUtils.byteArrayToHexString(xid.getBranchQualifier()) - + ",0x" - + Integer.toHexString(xid.getFormatId()); - } - @Override public XAResource getXAResource() { return new MariaDbXAResource(); diff --git a/src/main/java/org/mariadb/jdbc/MariaDbPoolDataSource.java b/src/main/java/org/mariadb/jdbc/MariaDbPoolDataSource.java index d04aedd74..ff79469cc 100644 --- a/src/main/java/org/mariadb/jdbc/MariaDbPoolDataSource.java +++ b/src/main/java/org/mariadb/jdbc/MariaDbPoolDataSource.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; import java.io.Closeable; @@ -227,6 +226,16 @@ public XAConnection getXAConnection(String username, String password) throws SQL return pool.getPoolConnection(username, password); } + /** + * Returns the URL for this datasource + * + * @return the URL for this datasource + */ + public String getUrl() { + if (conf == null) return url; + return conf.initialUrl(); + } + /** * Sets the URL for this datasource * @@ -242,16 +251,6 @@ public void setUrl(String url) throws SQLException { } } - /** - * Returns the URL for this datasource - * - * @return the URL for this datasource - */ - public String getUrl() { - if (conf == null) return url; - return conf.initialUrl(); - } - /** * return user * diff --git a/src/main/java/org/mariadb/jdbc/MariaDbXid.java b/src/main/java/org/mariadb/jdbc/MariaDbXid.java index f206a1ee2..0f805448d 100644 --- a/src/main/java/org/mariadb/jdbc/MariaDbXid.java +++ b/src/main/java/org/mariadb/jdbc/MariaDbXid.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; import java.util.Arrays; diff --git a/src/main/java/org/mariadb/jdbc/ParameterMetaData.java b/src/main/java/org/mariadb/jdbc/ParameterMetaData.java index f20685f9f..4cdc019d0 100644 --- a/src/main/java/org/mariadb/jdbc/ParameterMetaData.java +++ b/src/main/java/org/mariadb/jdbc/ParameterMetaData.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; import java.sql.SQLException; diff --git a/src/main/java/org/mariadb/jdbc/ProcedureStatement.java b/src/main/java/org/mariadb/jdbc/ProcedureStatement.java index 2e7818116..e7fc8bbba 100644 --- a/src/main/java/org/mariadb/jdbc/ProcedureStatement.java +++ b/src/main/java/org/mariadb/jdbc/ProcedureStatement.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; import java.sql.CallableStatement; diff --git a/src/main/java/org/mariadb/jdbc/ServerPreparedStatement.java b/src/main/java/org/mariadb/jdbc/ServerPreparedStatement.java index 563d42a2b..6bc02be06 100644 --- a/src/main/java/org/mariadb/jdbc/ServerPreparedStatement.java +++ b/src/main/java/org/mariadb/jdbc/ServerPreparedStatement.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; import static org.mariadb.jdbc.util.constants.Capabilities.*; @@ -49,6 +48,7 @@ public class ServerPreparedStatement extends BasePreparedStatement { * @param defaultFetchSize default fetch size * @throws SQLException if prepare fails */ + @SuppressWarnings({"this-escape"}) public ServerPreparedStatement( String sql, Connection con, diff --git a/src/main/java/org/mariadb/jdbc/SimpleParameterMetaData.java b/src/main/java/org/mariadb/jdbc/SimpleParameterMetaData.java index 60730c1bd..bdf70e761 100644 --- a/src/main/java/org/mariadb/jdbc/SimpleParameterMetaData.java +++ b/src/main/java/org/mariadb/jdbc/SimpleParameterMetaData.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; import java.sql.SQLException; diff --git a/src/main/java/org/mariadb/jdbc/Statement.java b/src/main/java/org/mariadb/jdbc/Statement.java index 85a761439..83c171d4a 100644 --- a/src/main/java/org/mariadb/jdbc/Statement.java +++ b/src/main/java/org/mariadb/jdbc/Statement.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; import static org.mariadb.jdbc.util.constants.Capabilities.LOCAL_FILES; @@ -27,7 +26,7 @@ /** Statement implementation */ public class Statement implements java.sql.Statement { private static final Pattern identifierPattern = - Pattern.compile("[0-9a-zA-Z\\$_\\u0080-\\uFFFF]*", Pattern.UNICODE_CASE | Pattern.CANON_EQ); + Pattern.compile("[0-9a-zA-Z$_\\u0080-\\uFFFF]*", Pattern.UNICODE_CASE | Pattern.CANON_EQ); private static final Pattern escapePattern = Pattern.compile("[\u0000'\"\b\n\r\t\u001A\\\\]"); private static final Map mapper = new HashMap<>(); @@ -43,41 +42,56 @@ public class Statement implements java.sql.Statement { mapper.put("\\", "\\\\"); } - private List batchQueries; - /** result-set type */ protected final int resultSetType; + /** concurrency */ protected final int resultSetConcurrency; + /** thread safe locker */ protected final ReentrantLock lock; + /** can use server query timeout */ protected final boolean canUseServerTimeout; + /** can use server row limitation */ protected final boolean canUseServerMaxRows; + /** connection */ protected final Connection con; + /** required query timeout */ protected int queryTimeout; + /** maximum row number */ protected long maxRows; + /** fetch size */ protected int fetchSize; + /** automatic generated keys result required */ protected int autoGeneratedKeys; + /** close statement on resultset completion */ protected boolean closeOnCompletion; + /** closed flag */ protected boolean closed; + /** escape processing */ protected boolean escape; + /** last execution results */ protected List results; + /** current results */ protected Completion currResult; + /** streaming load data infile data */ protected InputStream localInfileInputStream; + private List batchQueries; + /** * Constructor * @@ -731,8 +745,8 @@ public int[] executeBatch() throws SQLException { boolean possibleLoadLocal = con.getContext().hasClientCapability(LOCAL_FILES); if (possibleLoadLocal) { possibleLoadLocal = false; - for (int i = 0; i < batchQueries.size(); i++) { - String sql = batchQueries.get(i).toUpperCase(Locale.ROOT); + for (String batchQuery : batchQueries) { + String sql = batchQuery.toUpperCase(Locale.ROOT); if (sql.contains(" LOCAL ") && sql.contains("LOAD") && sql.contains(" INFILE")) { possibleLoadLocal = true; break; @@ -1484,13 +1498,14 @@ public long[] executeLargeBatch() throws SQLException { // ensure pipelining is possible (no LOAD DATA/XML INFILE commands) boolean possibleLoadLocal = con.getContext().hasClientCapability(LOCAL_FILES); if (possibleLoadLocal) { - for (int i = 0; i < batchQueries.size(); i++) { - String sql = batchQueries.get(i).toUpperCase(Locale.ROOT); + possibleLoadLocal = false; + for (String batchQuery : batchQueries) { + String sql = batchQuery.toUpperCase(Locale.ROOT); if (sql.contains(" LOCAL ") && sql.contains("LOAD") && sql.contains(" INFILE")) { + possibleLoadLocal = true; break; } } - possibleLoadLocal = false; } List res = @@ -1578,12 +1593,11 @@ public List executeInternalBatchStandard() throws SQLException { * * @param val string value to enquote * @return enquoted string value - * @throws SQLException -not possible- */ @Override - public String enquoteLiteral(String val) throws SQLException { + public String enquoteLiteral(String val) { Matcher matcher = escapePattern.matcher(val); - StringBuffer escapedVal = new StringBuffer("'"); + StringBuilder escapedVal = new StringBuilder("'"); while (matcher.find()) { matcher.appendReplacement(escapedVal, mapper.get(matcher.group())); @@ -1626,10 +1640,9 @@ public String enquoteIdentifier(String identifier, boolean alwaysQuote) throws S * @param identifier identifier * @return true if identifier doesn't have to be quoted * @see mariadb identifier name - * @throws SQLException exception */ @Override - public boolean isSimpleIdentifier(String identifier) throws SQLException { + public boolean isSimpleIdentifier(String identifier) { return identifier != null && !identifier.isEmpty() && identifierPattern.matcher(identifier).matches(); @@ -1640,10 +1653,9 @@ public boolean isSimpleIdentifier(String identifier) throws SQLException { * * @param val value to enquote * @return enquoted String value - * @throws SQLException - not possible - */ @Override - public String enquoteNCharLiteral(String val) throws SQLException { + public String enquoteNCharLiteral(String val) { return "N'" + val.replace("'", "''") + "'"; } } diff --git a/src/main/java/org/mariadb/jdbc/TransactionIsolation.java b/src/main/java/org/mariadb/jdbc/TransactionIsolation.java index a910ecbd8..d69f9338a 100644 --- a/src/main/java/org/mariadb/jdbc/TransactionIsolation.java +++ b/src/main/java/org/mariadb/jdbc/TransactionIsolation.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc; import java.sql.Connection; @@ -45,24 +44,6 @@ public enum TransactionIsolation { this.level = level; } - /** - * Get transaction isolation command - * - * @return transaction isolation command - */ - public String getValue() { - return value; - } - - /** - * Get transaction isolation level - * - * @return transaction isolation level - */ - public int getLevel() { - return level; - } - /** * Get TransactionIsolation from value * @@ -81,4 +62,22 @@ public static TransactionIsolation from(String value) { throw new IllegalArgumentException( String.format("Wrong argument value '%s' for TransactionIsolation", value)); } + + /** + * Get transaction isolation command + * + * @return transaction isolation command + */ + public String getValue() { + return value; + } + + /** + * Get transaction isolation level + * + * @return transaction isolation level + */ + public int getLevel() { + return level; + } } diff --git a/src/main/java/org/mariadb/jdbc/client/Client.java b/src/main/java/org/mariadb/jdbc/client/Client.java index 768a8a698..5da199855 100644 --- a/src/main/java/org/mariadb/jdbc/client/Client.java +++ b/src/main/java/org/mariadb/jdbc/client/Client.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client; import java.sql.SQLException; @@ -190,4 +189,11 @@ void readStreamingResults( * @return connection host */ HostAddress getHostAddress(); + + /** + * Get current socket IP or null (for Pipe / unix socket) + * + * @return Socket current IP + */ + String getSocketIp(); } diff --git a/src/main/java/org/mariadb/jdbc/client/Column.java b/src/main/java/org/mariadb/jdbc/client/Column.java index b7bd667c5..43927c228 100644 --- a/src/main/java/org/mariadb/jdbc/client/Column.java +++ b/src/main/java/org/mariadb/jdbc/client/Column.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client; public interface Column { diff --git a/src/main/java/org/mariadb/jdbc/client/ColumnDecoder.java b/src/main/java/org/mariadb/jdbc/client/ColumnDecoder.java index d95225f72..a4d63df08 100644 --- a/src/main/java/org/mariadb/jdbc/client/ColumnDecoder.java +++ b/src/main/java/org/mariadb/jdbc/client/ColumnDecoder.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client; import java.nio.charset.StandardCharsets; @@ -18,6 +17,128 @@ public interface ColumnDecoder extends Column { + /** + * Decode Column from mysql packet + * + * @param buf packet + * @param extendedInfo is extended datatype information capability enable + * @return column + */ + static ColumnDecoder decode(ReadableByteBuf buf, boolean extendedInfo) { + // skip first strings + int[] stringPos = new int[5]; + stringPos[0] = buf.skipIdentifier(); // schema pos + stringPos[1] = buf.skipIdentifier(); // table alias pos + stringPos[2] = buf.skipIdentifier(); // table pos + stringPos[3] = buf.skipIdentifier(); // column alias pos + stringPos[4] = buf.skipIdentifier(); // column pos + buf.skipIdentifier(); + + String extTypeName = null; + String extTypeFormat = null; + if (extendedInfo) { + // fast skipping extended info (usually not set) + if (buf.readByte() != 0) { + // revert position, because has extended info. + buf.pos(buf.pos() - 1); + + ReadableByteBuf subPacket = buf.readLengthBuffer(); + while (subPacket.readableBytes() > 0) { + switch (subPacket.readByte()) { + case 0: + extTypeName = subPacket.readAscii(subPacket.readLength()); + break; + case 1: + extTypeFormat = subPacket.readAscii(subPacket.readLength()); + break; + default: // skip data + subPacket.skip(subPacket.readLength()); + break; + } + } + } + } + + buf.skip(); // skip length always 0x0c + short charset = buf.readShort(); + int length = buf.readInt(); + DataType dataType = DataType.of(buf.readUnsignedByte()); + int flags = buf.readUnsignedShort(); + byte decimals = buf.readByte(); + DataType.ColumnConstructor constructor = + (extTypeName != null && extTypeName.equals("uuid")) + ? UuidColumn::new + : (flags & ColumnFlags.UNSIGNED) == 0 + ? dataType.getColumnConstructor() + : dataType.getUnsignedColumnConstructor(); + return constructor.create( + buf, charset, length, dataType, decimals, flags, stringPos, extTypeName, extTypeFormat); + } + + /** + * Create fake MySQL column definition packet with indicated datatype + * + * @param name column name + * @param type data type + * @param flags column flags + * @return Column + */ + static ColumnDecoder create(String name, DataType type, int flags) { + byte[] nameBytes = name.getBytes(StandardCharsets.UTF_8); + byte[] arr = new byte[9 + 2 * nameBytes.length]; + arr[0] = 3; + arr[1] = 'D'; + arr[2] = 'E'; + arr[3] = 'F'; + + int[] stringPos = new int[5]; + stringPos[0] = 4; // schema pos + stringPos[1] = 5; // table alias pos + stringPos[2] = 6; // table pos + + // lenenc_str name + // lenenc_str org_name + int pos = 7; + for (int i = 0; i < 2; i++) { + stringPos[i + 3] = pos; + arr[pos++] = (byte) nameBytes.length; + System.arraycopy(nameBytes, 0, arr, pos, nameBytes.length); + pos += nameBytes.length; + } + int len; + + /* Sensible predefined length - since we're dealing with I_S here, most char fields are 64 char long */ + switch (type) { + case VARCHAR: + case VARSTRING: + len = 64 * 3; /* 3 bytes per UTF8 char */ + break; + case SMALLINT: + len = 5; + break; + case NULL: + len = 0; + break; + default: + len = 1; + break; + } + DataType.ColumnConstructor constructor = + (flags & ColumnFlags.UNSIGNED) == 0 + ? type.getColumnConstructor() + : type.getUnsignedColumnConstructor(); + return constructor.create( + new StandardReadableByteBuf(arr, arr.length), + 33, + len, + type, + (byte) 0, + flags, + stringPos, + null, + null); + } + /** * Returns default class name depending on server column datatype * @@ -192,6 +313,7 @@ Timestamp decodeTimestampText(final ReadableByteBuf buf, final MutableInt length */ Timestamp decodeTimestampBinary(final ReadableByteBuf buf, final MutableInt length, Calendar cal) throws SQLDataException; + /** * Return boolean text encoded value * @@ -213,6 +335,7 @@ boolean decodeBooleanText(final ReadableByteBuf buf, final MutableInt length) */ boolean decodeBooleanBinary(final ReadableByteBuf buf, final MutableInt length) throws SQLDataException; + /** * Parse short text encoded value * @@ -222,6 +345,7 @@ boolean decodeBooleanBinary(final ReadableByteBuf buf, final MutableInt length) * @throws SQLDataException if any decoding error occurs */ short decodeShortText(final ReadableByteBuf buf, final MutableInt length) throws SQLDataException; + /** * Parse short binary encoded value * @@ -232,6 +356,7 @@ boolean decodeBooleanBinary(final ReadableByteBuf buf, final MutableInt length) */ short decodeShortBinary(final ReadableByteBuf buf, final MutableInt length) throws SQLDataException; + /** * Parse int text encoded value * @@ -261,6 +386,7 @@ short decodeShortBinary(final ReadableByteBuf buf, final MutableInt length) * @throws SQLDataException if any decoding error occurs */ long decodeLongText(final ReadableByteBuf buf, final MutableInt length) throws SQLDataException; + /** * Parse long binary encoded value * @@ -313,126 +439,4 @@ float decodeFloatBinary(final ReadableByteBuf buf, final MutableInt length) */ double decodeDoubleBinary(final ReadableByteBuf buf, final MutableInt length) throws SQLDataException; - - /** - * Decode Column from mysql packet - * - * @param buf packet - * @param extendedInfo is extended datatype information capability enable - * @return column - */ - static ColumnDecoder decode(ReadableByteBuf buf, boolean extendedInfo) { - // skip first strings - int[] stringPos = new int[5]; - stringPos[0] = buf.skipIdentifier(); // schema pos - stringPos[1] = buf.skipIdentifier(); // table alias pos - stringPos[2] = buf.skipIdentifier(); // table pos - stringPos[3] = buf.skipIdentifier(); // column alias pos - stringPos[4] = buf.skipIdentifier(); // column pos - buf.skipIdentifier(); - - String extTypeName = null; - String extTypeFormat = null; - if (extendedInfo) { - // fast skipping extended info (usually not set) - if (buf.readByte() != 0) { - // revert position, because has extended info. - buf.pos(buf.pos() - 1); - - ReadableByteBuf subPacket = buf.readLengthBuffer(); - while (subPacket.readableBytes() > 0) { - switch (subPacket.readByte()) { - case 0: - extTypeName = subPacket.readAscii(subPacket.readLength()); - break; - case 1: - extTypeFormat = subPacket.readAscii(subPacket.readLength()); - break; - default: // skip data - subPacket.skip(subPacket.readLength()); - break; - } - } - } - } - - buf.skip(); // skip length always 0x0c - short charset = buf.readShort(); - int length = buf.readInt(); - DataType dataType = DataType.of(buf.readUnsignedByte()); - int flags = buf.readUnsignedShort(); - byte decimals = buf.readByte(); - DataType.ColumnConstructor constructor = - (extTypeName != null && extTypeName.equals("uuid")) - ? UuidColumn::new - : (flags & ColumnFlags.UNSIGNED) == 0 - ? dataType.getColumnConstructor() - : dataType.getUnsignedColumnConstructor(); - return constructor.create( - buf, charset, length, dataType, decimals, flags, stringPos, extTypeName, extTypeFormat); - } - - /** - * Create fake MySQL column definition packet with indicated datatype - * - * @param name column name - * @param type data type - * @param flags column flags - * @return Column - */ - static ColumnDecoder create(String name, DataType type, int flags) { - byte[] nameBytes = name.getBytes(StandardCharsets.UTF_8); - byte[] arr = new byte[9 + 2 * nameBytes.length]; - arr[0] = 3; - arr[1] = 'D'; - arr[2] = 'E'; - arr[3] = 'F'; - - int[] stringPos = new int[5]; - stringPos[0] = 4; // schema pos - stringPos[1] = 5; // table alias pos - stringPos[2] = 6; // table pos - - // lenenc_str name - // lenenc_str org_name - int pos = 7; - for (int i = 0; i < 2; i++) { - stringPos[i + 3] = pos; - arr[pos++] = (byte) nameBytes.length; - System.arraycopy(nameBytes, 0, arr, pos, nameBytes.length); - pos += nameBytes.length; - } - int len; - - /* Sensible predefined length - since we're dealing with I_S here, most char fields are 64 char long */ - switch (type) { - case VARCHAR: - case VARSTRING: - len = 64 * 3; /* 3 bytes per UTF8 char */ - break; - case SMALLINT: - len = 5; - break; - case NULL: - len = 0; - break; - default: - len = 1; - break; - } - DataType.ColumnConstructor constructor = - (flags & ColumnFlags.UNSIGNED) == 0 - ? type.getColumnConstructor() - : type.getUnsignedColumnConstructor(); - return constructor.create( - new StandardReadableByteBuf(arr, arr.length), - 33, - len, - type, - (byte) 0, - flags, - stringPos, - null, - null); - } } diff --git a/src/main/java/org/mariadb/jdbc/client/Completion.java b/src/main/java/org/mariadb/jdbc/client/Completion.java index 27e7c1a05..3020d552d 100644 --- a/src/main/java/org/mariadb/jdbc/client/Completion.java +++ b/src/main/java/org/mariadb/jdbc/client/Completion.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client; import org.mariadb.jdbc.message.ServerMessage; diff --git a/src/main/java/org/mariadb/jdbc/client/Context.java b/src/main/java/org/mariadb/jdbc/client/Context.java index 500e79058..438c0f57a 100644 --- a/src/main/java/org/mariadb/jdbc/client/Context.java +++ b/src/main/java/org/mariadb/jdbc/client/Context.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client; import org.mariadb.jdbc.Configuration; @@ -16,6 +15,13 @@ public interface Context { */ long getThreadId(); + /** + * Indicate server connection Id (not truncated) + * + * @param connectionId connection id + */ + void setThreadId(long connectionId); + /** * Get connection initial seed * @@ -171,20 +177,6 @@ public interface Context { */ void addStateFlag(int state); - /** - * Indicate server charset change - * - * @param charset server charset - */ - void setCharset(String charset); - - /** - * Indicate server connection Id (not truncated) - * - * @param connectionId connection id - */ - void setThreadId(long connectionId); - /** Indicate the number of connection on this server */ void setTreadsConnected(long threadsConnected); @@ -194,4 +186,11 @@ public interface Context { * @return current charset */ String getCharset(); + + /** + * Indicate server charset change + * + * @param charset server charset + */ + void setCharset(String charset); } diff --git a/src/main/java/org/mariadb/jdbc/client/DataType.java b/src/main/java/org/mariadb/jdbc/client/DataType.java index 8a3ca8c5d..b6f307d27 100644 --- a/src/main/java/org/mariadb/jdbc/client/DataType.java +++ b/src/main/java/org/mariadb/jdbc/client/DataType.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client; import org.mariadb.jdbc.client.column.*; @@ -58,14 +57,14 @@ public enum DataType { this.unsignedColumnConstructor = unsignedColumnConstructor; } - public int get() { - return mariadbType; - } - public static DataType of(int typeValue) { return typeMap[typeValue]; } + public int get() { + return mariadbType; + } + public ColumnConstructor getColumnConstructor() { return columnConstructor; } diff --git a/src/main/java/org/mariadb/jdbc/client/PrepareCache.java b/src/main/java/org/mariadb/jdbc/client/PrepareCache.java index 32e5f9dcb..14ff197ea 100644 --- a/src/main/java/org/mariadb/jdbc/client/PrepareCache.java +++ b/src/main/java/org/mariadb/jdbc/client/PrepareCache.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client; import org.mariadb.jdbc.ServerPreparedStatement; diff --git a/src/main/java/org/mariadb/jdbc/client/ReadableByteBuf.java b/src/main/java/org/mariadb/jdbc/client/ReadableByteBuf.java index e811b38ab..21f5edd54 100644 --- a/src/main/java/org/mariadb/jdbc/client/ReadableByteBuf.java +++ b/src/main/java/org/mariadb/jdbc/client/ReadableByteBuf.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client; import org.mariadb.jdbc.MariaDbBlob; @@ -90,19 +89,20 @@ public interface ReadableByteBuf { short getUnsignedByte(); /** - * Read encoded length value that cannot be null see - * https://mariadb.com/kb/en/protocol-data-types/#length-encoded-integers + * Read encoded length value that cannot be null * + * @see length + * encoded integer * @return encoded length */ long readLongLengthEncodedNotNull(); /** - * Read encoded length value that cannot be null see - * https://mariadb.com/kb/en/protocol-data-types/#length-encoded-integers - * - *

this is readLongLengthEncodedNotNull limited to 32 bits + * Read encoded length value that cannot be null * + * @see length + * encoded integer + *

this is readLongLengthEncodedNotNull limited to 32 bits * @return encoded length */ int readIntLengthEncodedNotNull(); @@ -129,10 +129,12 @@ public interface ReadableByteBuf { * @return long value */ long atoull(int length); + /** - * Read encoded length value see - * https://mariadb.com/kb/en/protocol-data-types/#length-encoded-integers + * Read encoded length value * + * @see length + * encoded integer * @return encoded length */ Integer readLength(); diff --git a/src/main/java/org/mariadb/jdbc/client/ServerVersion.java b/src/main/java/org/mariadb/jdbc/client/ServerVersion.java index e789b2cf2..303dbb928 100644 --- a/src/main/java/org/mariadb/jdbc/client/ServerVersion.java +++ b/src/main/java/org/mariadb/jdbc/client/ServerVersion.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client; public interface ServerVersion { diff --git a/src/main/java/org/mariadb/jdbc/client/SocketHelper.java b/src/main/java/org/mariadb/jdbc/client/SocketHelper.java index fc34be30f..7a82308c6 100644 --- a/src/main/java/org/mariadb/jdbc/client/SocketHelper.java +++ b/src/main/java/org/mariadb/jdbc/client/SocketHelper.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/client/column/BigDecimalColumn.java b/src/main/java/org/mariadb/jdbc/client/column/BigDecimalColumn.java index 1994f71fa..0a436b790 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/BigDecimalColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/BigDecimalColumn.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.column; import java.math.BigDecimal; diff --git a/src/main/java/org/mariadb/jdbc/client/column/BitColumn.java b/src/main/java/org/mariadb/jdbc/client/column/BitColumn.java index 019af86cf..c9fec9cd2 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/BitColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/BitColumn.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.column; import java.sql.*; diff --git a/src/main/java/org/mariadb/jdbc/client/column/BlobColumn.java b/src/main/java/org/mariadb/jdbc/client/column/BlobColumn.java index 23477674a..5c9f2123e 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/BlobColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/BlobColumn.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.column; import java.math.BigDecimal; diff --git a/src/main/java/org/mariadb/jdbc/client/column/DateColumn.java b/src/main/java/org/mariadb/jdbc/client/column/DateColumn.java index 59b3ccda9..d51ecaa34 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/DateColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/DateColumn.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.column; import static org.mariadb.jdbc.client.result.Result.NULL_LENGTH; @@ -188,13 +187,22 @@ public Date decodeDateText(ReadableByteBuf buf, MutableInt length, Calendar cal) return null; } - Calendar c = cal == null ? Calendar.getInstance() : cal; - synchronized (c) { + if (cal == null) { + Calendar c = Calendar.getInstance(); c.clear(); c.set(Calendar.YEAR, year); c.set(Calendar.MONTH, month - 1); c.set(Calendar.DAY_OF_MONTH, dayOfMonth); return new Date(c.getTimeInMillis()); + } else { + synchronized (cal) { + cal.clear(); + cal.set(Calendar.YEAR, year); + cal.set(Calendar.MONTH, month - 1); + cal.set(Calendar.DAY_OF_MONTH, dayOfMonth); + return new Date(cal.getTimeInMillis()); + } + } } @@ -206,13 +214,21 @@ public Date decodeDateBinary(ReadableByteBuf buf, MutableInt length, Calendar ca return null; } - Calendar c = cal == null ? Calendar.getInstance() : cal; - synchronized (c) { + if (cal == null) { + Calendar c = Calendar.getInstance(); c.clear(); c.set(Calendar.YEAR, buf.readShort()); c.set(Calendar.MONTH, buf.readByte() - 1); c.set(Calendar.DAY_OF_MONTH, buf.readByte()); return new Date(c.getTimeInMillis()); + } else { + synchronized (cal) { + cal.clear(); + cal.set(Calendar.YEAR, buf.readShort()); + cal.set(Calendar.MONTH, buf.readByte() - 1); + cal.set(Calendar.DAY_OF_MONTH, buf.readByte()); + return new Date(cal.getTimeInMillis()); + } } } @@ -261,7 +277,6 @@ public Timestamp decodeTimestampBinary(ReadableByteBuf buf, MutableInt length, C return null; } - Calendar cal = calParam == null ? Calendar.getInstance() : calParam; int year; int month; long dayOfMonth; @@ -276,10 +291,17 @@ public Timestamp decodeTimestampBinary(ReadableByteBuf buf, MutableInt length, C } Timestamp timestamp; - synchronized (cal) { + if (calParam == null) { + Calendar cal = Calendar.getInstance(); cal.clear(); cal.set(year, month - 1, (int) dayOfMonth, 0, 0, 0); timestamp = new Timestamp(cal.getTimeInMillis()); + } else { + synchronized (calParam) { + calParam.clear(); + calParam.set(year, month - 1, (int) dayOfMonth, 0, 0, 0); + timestamp = new Timestamp(calParam.getTimeInMillis()); + } } timestamp.setNanos(0); return timestamp; diff --git a/src/main/java/org/mariadb/jdbc/client/column/DoubleColumn.java b/src/main/java/org/mariadb/jdbc/client/column/DoubleColumn.java index 0291442c1..8511baf90 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/DoubleColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/DoubleColumn.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.column; import java.math.BigDecimal; diff --git a/src/main/java/org/mariadb/jdbc/client/column/FloatColumn.java b/src/main/java/org/mariadb/jdbc/client/column/FloatColumn.java index b4a283975..2fb2a0b80 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/FloatColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/FloatColumn.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.column; import java.math.BigDecimal; diff --git a/src/main/java/org/mariadb/jdbc/client/column/GeometryColumn.java b/src/main/java/org/mariadb/jdbc/client/column/GeometryColumn.java index 9ba3a07d3..c65b9d60f 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/GeometryColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/GeometryColumn.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.column; import java.sql.*; diff --git a/src/main/java/org/mariadb/jdbc/client/column/JsonColumn.java b/src/main/java/org/mariadb/jdbc/client/column/JsonColumn.java index d27519810..813d0428e 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/JsonColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/JsonColumn.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.column; import java.sql.*; diff --git a/src/main/java/org/mariadb/jdbc/client/column/SignedBigIntColumn.java b/src/main/java/org/mariadb/jdbc/client/column/SignedBigIntColumn.java index b6e8b6884..4a0f8f9b1 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/SignedBigIntColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/SignedBigIntColumn.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.column; import java.math.BigInteger; diff --git a/src/main/java/org/mariadb/jdbc/client/column/SignedIntColumn.java b/src/main/java/org/mariadb/jdbc/client/column/SignedIntColumn.java index 88766d1c8..c364d71c5 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/SignedIntColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/SignedIntColumn.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.column; import java.sql.*; diff --git a/src/main/java/org/mariadb/jdbc/client/column/SignedMediumIntColumn.java b/src/main/java/org/mariadb/jdbc/client/column/SignedMediumIntColumn.java index 62d25fd0a..90346ae10 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/SignedMediumIntColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/SignedMediumIntColumn.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.column; import java.sql.*; diff --git a/src/main/java/org/mariadb/jdbc/client/column/SignedSmallIntColumn.java b/src/main/java/org/mariadb/jdbc/client/column/SignedSmallIntColumn.java index b7299e6a3..6cf59a6ff 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/SignedSmallIntColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/SignedSmallIntColumn.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.column; import java.sql.*; diff --git a/src/main/java/org/mariadb/jdbc/client/column/SignedTinyIntColumn.java b/src/main/java/org/mariadb/jdbc/client/column/SignedTinyIntColumn.java index 5853a5d3a..1457101e6 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/SignedTinyIntColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/SignedTinyIntColumn.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.column; import java.sql.*; diff --git a/src/main/java/org/mariadb/jdbc/client/column/StringColumn.java b/src/main/java/org/mariadb/jdbc/client/column/StringColumn.java index 17e2388b9..80e90eb29 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/StringColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/StringColumn.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.column; import static org.mariadb.jdbc.client.result.Result.NULL_LENGTH; @@ -260,13 +259,21 @@ public Date decodeDateText(ReadableByteBuf buf, MutableInt length, Calendar cal) int year = Integer.parseInt(stDatePart[0]); int month = Integer.parseInt(stDatePart[1]); int dayOfMonth = Integer.parseInt(stDatePart[2]); - Calendar c = cal == null ? Calendar.getInstance() : cal; - synchronized (c) { + if (cal == null) { + Calendar c = Calendar.getInstance(); c.clear(); c.set(Calendar.YEAR, year); c.set(Calendar.MONTH, month - 1); c.set(Calendar.DAY_OF_MONTH, dayOfMonth); return new Date(c.getTimeInMillis()); + } else { + synchronized (cal) { + cal.clear(); + cal.set(Calendar.YEAR, year); + cal.set(Calendar.MONTH, month - 1); + cal.set(Calendar.DAY_OF_MONTH, dayOfMonth); + return new Date(cal.getTimeInMillis()); + } } } catch (NumberFormatException nfe) { @@ -297,27 +304,45 @@ public Time decodeTimeText(ReadableByteBuf buf, MutableInt length, Calendar cal) @Override public Time decodeTimeBinary(ReadableByteBuf buf, MutableInt length, Calendar calParam) throws SQLDataException { - Calendar cal = calParam == null ? Calendar.getInstance() : calParam; int[] parts = LocalTimeCodec.parseTime(buf, length, this); Time t; // specific case for TIME, to handle value not in 00:00:00-23:59:59 - synchronized (cal) { + if (calParam == null) { + Calendar cal = Calendar.getInstance(); cal.clear(); cal.setLenient(true); if (parts[0] == -1) { cal.set( - 1970, - Calendar.JANUARY, - 1, - parts[0] * parts[1], - parts[0] * parts[2], - parts[0] * parts[3] - 1); + 1970, + Calendar.JANUARY, + 1, + parts[0] * parts[1], + parts[0] * parts[2], + parts[0] * parts[3] - 1); t = new Time(cal.getTimeInMillis() + (1000 - parts[4])); } else { cal.set(1970, Calendar.JANUARY, 1, parts[1], parts[2], parts[3]); t = new Time(cal.getTimeInMillis() + parts[4] / 1_000_000); } + } else { + synchronized (calParam) { + calParam.clear(); + calParam.setLenient(true); + if (parts[0] == -1) { + calParam.set( + 1970, + Calendar.JANUARY, + 1, + parts[0] * parts[1], + parts[0] * parts[2], + parts[0] * parts[3] - 1); + t = new Time(calParam.getTimeInMillis() + (1000 - parts[4])); + } else { + calParam.set(1970, Calendar.JANUARY, 1, parts[1], parts[2], parts[3]); + t = new Time(calParam.getTimeInMillis() + parts[4] / 1_000_000); + } + } } return t; } @@ -379,7 +404,6 @@ public Timestamp decodeTimestampText(ReadableByteBuf buf, MutableInt length, Cal timestampsPart[4], timestampsPart[5]); timestamp = new Timestamp(c.getTime().getTime()); - timestamp.setNanos(timestampsPart[6] * 1000); } else { synchronized (calParam) { calParam.clear(); @@ -391,17 +415,15 @@ public Timestamp decodeTimestampText(ReadableByteBuf buf, MutableInt length, Cal timestampsPart[4], timestampsPart[5]); timestamp = new Timestamp(calParam.getTime().getTime()); - timestamp.setNanos(timestampsPart[6] * 1000); } } + timestamp.setNanos(timestampsPart[6] * 1000); return timestamp; } @Override public Timestamp decodeTimestampBinary(ReadableByteBuf buf, MutableInt length, Calendar calParam) throws SQLDataException { - Calendar cal = calParam == null ? Calendar.getInstance() : calParam; - String val = buf.readString(length.get()); try { int[] parts = LocalDateTimeCodec.parseTimestamp(val); @@ -417,10 +439,17 @@ public Timestamp decodeTimestampBinary(ReadableByteBuf buf, MutableInt length, C int seconds = parts[5]; int microseconds = parts[6] / 1000; Timestamp timestamp; - synchronized (cal) { + if (calParam == null) { + Calendar cal = Calendar.getInstance(); cal.clear(); cal.set(year, month - 1, dayOfMonth, hour, minutes, seconds); timestamp = new Timestamp(cal.getTimeInMillis()); + } else { + synchronized (calParam) { + calParam.clear(); + calParam.set(year, month - 1, dayOfMonth, hour, minutes, seconds); + timestamp = new Timestamp(calParam.getTimeInMillis()); + } } timestamp.setNanos(microseconds * 1000); return timestamp; diff --git a/src/main/java/org/mariadb/jdbc/client/column/TimeColumn.java b/src/main/java/org/mariadb/jdbc/client/column/TimeColumn.java index d9d9e28c2..0844788ce 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/TimeColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/TimeColumn.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.column; import java.sql.*; @@ -317,8 +316,8 @@ public Timestamp decodeTimestampText(ReadableByteBuf buf, MutableInt length, Cal Timestamp t; // specific case for TIME, to handle value not in 00:00:00-23:59:59 - Calendar cal = calParam == null ? Calendar.getInstance() : calParam; - synchronized (cal) { + if (calParam == null) { + Calendar cal = Calendar.getInstance(); cal.clear(); cal.setLenient(true); if (parts[0] == -1) { @@ -336,6 +335,26 @@ public Timestamp decodeTimestampText(ReadableByteBuf buf, MutableInt length, Cal t = new Timestamp(cal.getTimeInMillis()); t.setNanos(parts[4]); } + } else { + synchronized (calParam) { + calParam.clear(); + calParam.setLenient(true); + if (parts[0] == -1) { + calParam.set( + 1970, + Calendar.JANUARY, + 1, + parts[0] * parts[1], + parts[0] * parts[2], + parts[0] * parts[3] - 1); + t = new Timestamp(calParam.getTimeInMillis()); + t.setNanos(1_000_000_000 - parts[4]); + } else { + calParam.set(1970, Calendar.JANUARY, 1, parts[1], parts[2], parts[3]); + t = new Timestamp(calParam.getTimeInMillis()); + t.setNanos(parts[4]); + } + } } return t; } diff --git a/src/main/java/org/mariadb/jdbc/client/column/TimestampColumn.java b/src/main/java/org/mariadb/jdbc/client/column/TimestampColumn.java index 19f3f3840..e640b22aa 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/TimestampColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/TimestampColumn.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.column; import static org.mariadb.jdbc.client.result.Result.NULL_LENGTH; @@ -297,8 +296,6 @@ public Date decodeDateText(ReadableByteBuf buf, MutableInt length, Calendar cal) @Override public Date decodeDateBinary(ReadableByteBuf buf, MutableInt length, Calendar calParam) throws SQLDataException { - Calendar cal = calParam == null ? Calendar.getInstance() : calParam; - if (length.get() == 0) { length.set(NULL_LENGTH); return null; @@ -334,10 +331,17 @@ public Date decodeDateBinary(ReadableByteBuf buf, MutableInt length, Calendar ca } Timestamp timestamp; - synchronized (cal) { + if (calParam == null) { + Calendar cal = Calendar.getInstance(); cal.clear(); cal.set(year, month - 1, dayOfMonth, hour, minutes, seconds); timestamp = new Timestamp(cal.getTimeInMillis()); + } else { + synchronized (calParam) { + calParam.clear(); + calParam.set(year, month - 1, dayOfMonth, hour, minutes, seconds); + timestamp = new Timestamp(calParam.getTimeInMillis()); + } } timestamp.setNanos((int) (microseconds * 1000)); String st = timestamp.toString(); @@ -362,7 +366,6 @@ public Time decodeTimeBinary(ReadableByteBuf buf, MutableInt length, Calendar ca length.set(NULL_LENGTH); return null; } - Calendar cal = calParam == null ? Calendar.getInstance() : calParam; int year = buf.readUnsignedShort(); int month = buf.readByte(); @@ -388,10 +391,17 @@ public Time decodeTimeBinary(ReadableByteBuf buf, MutableInt length, Calendar ca return null; } - synchronized (cal) { + if (calParam == null) { + Calendar cal = Calendar.getInstance(); cal.clear(); cal.set(1970, Calendar.JANUARY, 1, hour, minutes, seconds); return new Time(cal.getTimeInMillis() + microseconds / 1_000); + } else { + synchronized (calParam) { + calParam.clear(); + calParam.set(1970, Calendar.JANUARY, 1, hour, minutes, seconds); + return new Time(calParam.getTimeInMillis() + microseconds / 1_000); + } } } @@ -477,7 +487,6 @@ public Timestamp decodeTimestampBinary(ReadableByteBuf buf, MutableInt length, C length.set(NULL_LENGTH); return null; } - Calendar cal = calParam == null ? Calendar.getInstance() : calParam; int year = buf.readUnsignedShort(); int month = buf.readByte(); @@ -509,10 +518,17 @@ public Timestamp decodeTimestampBinary(ReadableByteBuf buf, MutableInt length, C return null; } Timestamp timestamp; - synchronized (cal) { + if (calParam == null) { + Calendar cal = Calendar.getInstance(); cal.clear(); cal.set(year, month - 1, dayOfMonth, hour, minutes, seconds); timestamp = new Timestamp(cal.getTimeInMillis()); + } else { + synchronized (calParam) { + calParam.clear(); + calParam.set(year, month - 1, dayOfMonth, hour, minutes, seconds); + timestamp = new Timestamp(calParam.getTimeInMillis()); + } } timestamp.setNanos((int) (microseconds * 1000)); return timestamp; diff --git a/src/main/java/org/mariadb/jdbc/client/column/UnsignedBigIntColumn.java b/src/main/java/org/mariadb/jdbc/client/column/UnsignedBigIntColumn.java index b8f231cb9..09bfcb8f6 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/UnsignedBigIntColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/UnsignedBigIntColumn.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.column; import java.math.BigInteger; diff --git a/src/main/java/org/mariadb/jdbc/client/column/UnsignedIntColumn.java b/src/main/java/org/mariadb/jdbc/client/column/UnsignedIntColumn.java index bf8b574e3..1bdf6ee18 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/UnsignedIntColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/UnsignedIntColumn.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.column; import java.sql.*; diff --git a/src/main/java/org/mariadb/jdbc/client/column/UnsignedMediumIntColumn.java b/src/main/java/org/mariadb/jdbc/client/column/UnsignedMediumIntColumn.java index 74725fb5f..2e3456e14 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/UnsignedMediumIntColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/UnsignedMediumIntColumn.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.column; import java.sql.*; diff --git a/src/main/java/org/mariadb/jdbc/client/column/UnsignedSmallIntColumn.java b/src/main/java/org/mariadb/jdbc/client/column/UnsignedSmallIntColumn.java index bd0608062..344d84a28 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/UnsignedSmallIntColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/UnsignedSmallIntColumn.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.column; import java.sql.*; diff --git a/src/main/java/org/mariadb/jdbc/client/column/UnsignedTinyIntColumn.java b/src/main/java/org/mariadb/jdbc/client/column/UnsignedTinyIntColumn.java index 040d6671c..8bb83d3ea 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/UnsignedTinyIntColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/UnsignedTinyIntColumn.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.column; import java.sql.*; diff --git a/src/main/java/org/mariadb/jdbc/client/column/UuidColumn.java b/src/main/java/org/mariadb/jdbc/client/column/UuidColumn.java index 62093e93e..da465adea 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/UuidColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/UuidColumn.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.column; import java.sql.*; diff --git a/src/main/java/org/mariadb/jdbc/client/column/YearColumn.java b/src/main/java/org/mariadb/jdbc/client/column/YearColumn.java index fddce5a0d..e7127b54e 100644 --- a/src/main/java/org/mariadb/jdbc/client/column/YearColumn.java +++ b/src/main/java/org/mariadb/jdbc/client/column/YearColumn.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.column; import java.sql.*; @@ -122,30 +121,41 @@ public Date decodeDateBinary(ReadableByteBuf buf, MutableInt length, Calendar ca @Override public Timestamp decodeTimestampText(ReadableByteBuf buf, MutableInt length, Calendar calParam) throws SQLDataException { - Calendar cal1 = calParam == null ? Calendar.getInstance() : calParam; - int year = Integer.parseInt(buf.readAscii(length.get())); if (columnLength <= 2) year += year >= 70 ? 1900 : 2000; - synchronized (cal1) { + + if (calParam == null) { + Calendar cal1 = Calendar.getInstance(); cal1.clear(); cal1.set(year, Calendar.JANUARY, 1); return new Timestamp(cal1.getTimeInMillis()); + } else { + synchronized (calParam) { + calParam.clear(); + calParam.set(year, Calendar.JANUARY, 1); + return new Timestamp(calParam.getTimeInMillis()); + } } } @Override public Timestamp decodeTimestampBinary(ReadableByteBuf buf, MutableInt length, Calendar calParam) throws SQLDataException { - Calendar cal = calParam == null ? Calendar.getInstance() : calParam; - int year = buf.readUnsignedShort(); if (columnLength <= 2) year += year >= 70 ? 1900 : 2000; Timestamp timestamp; - synchronized (cal) { + if (calParam == null) { + Calendar cal = Calendar.getInstance(); cal.clear(); cal.set(year, 0, 1, 0, 0, 0); timestamp = new Timestamp(cal.getTimeInMillis()); + } else { + synchronized (calParam) { + calParam.clear(); + calParam.set(year, 0, 1, 0, 0, 0); + timestamp = new Timestamp(calParam.getTimeInMillis()); + } } timestamp.setNanos(0); return timestamp; diff --git a/src/main/java/org/mariadb/jdbc/client/context/BaseContext.java b/src/main/java/org/mariadb/jdbc/client/context/BaseContext.java index d5e99a81c..b268e6fd8 100644 --- a/src/main/java/org/mariadb/jdbc/client/context/BaseContext.java +++ b/src/main/java/org/mariadb/jdbc/client/context/BaseContext.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.context; import static org.mariadb.jdbc.util.constants.Capabilities.STMT_BULK_OPERATIONS; @@ -18,7 +17,6 @@ /** Context (current connection state) of a connection */ public class BaseContext implements Context { - private long threadId; private final long serverCapabilities; private final long clientCapabilities; private final byte[] seed; @@ -29,11 +27,17 @@ public class BaseContext implements Context { private final Configuration conf; private final ExceptionFactory exceptionFactory; - private String charset; + /** LRU prepare cache object */ + private final PrepareCache prepareCache; + + private final HostAddress hostAddress; /** Server status context */ protected int serverStatus; + private long threadId; + private String charset; + /** Server current database */ private String database; @@ -43,14 +47,9 @@ public class BaseContext implements Context { /** Server current warning count */ private int warning; - /** LRU prepare cache object */ - private final PrepareCache prepareCache; - /** Connection state use flag */ private int stateFlag = 0; - private final HostAddress hostAddress; - /** * Constructor of connection context * @@ -61,6 +60,7 @@ public class BaseContext implements Context { * @param exceptionFactory connection exception factory * @param prepareCache LRU prepare cache */ + @SuppressWarnings({"this-escape"}) public BaseContext( HostAddress hostAddress, InitialHandshakePacket handshake, @@ -88,6 +88,10 @@ public long getThreadId() { return threadId; } + public void setThreadId(long connectionId) { + threadId = connectionId; + } + public byte[] getSeed() { return seed; } @@ -180,14 +184,6 @@ public void addStateFlag(int state) { stateFlag |= state; } - public void setCharset(String charset) { - this.charset = charset; - } - - public void setThreadId(long connectionId) { - threadId = connectionId; - } - public void setTreadsConnected(long threadsConnected) { if (hostAddress != null) hostAddress.setThreadsConnected(threadsConnected); } @@ -195,4 +191,8 @@ public void setTreadsConnected(long threadsConnected) { public String getCharset() { return charset; } + + public void setCharset(String charset) { + this.charset = charset; + } } diff --git a/src/main/java/org/mariadb/jdbc/client/context/RedoContext.java b/src/main/java/org/mariadb/jdbc/client/context/RedoContext.java index 43d128e9f..ef39ce3dd 100644 --- a/src/main/java/org/mariadb/jdbc/client/context/RedoContext.java +++ b/src/main/java/org/mariadb/jdbc/client/context/RedoContext.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.context; import org.mariadb.jdbc.Configuration; diff --git a/src/main/java/org/mariadb/jdbc/client/impl/ConnectionHelper.java b/src/main/java/org/mariadb/jdbc/client/impl/ConnectionHelper.java index fb5ba8b63..90458a122 100644 --- a/src/main/java/org/mariadb/jdbc/client/impl/ConnectionHelper.java +++ b/src/main/java/org/mariadb/jdbc/client/impl/ConnectionHelper.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.impl; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/client/impl/MultiPrimaryClient.java b/src/main/java/org/mariadb/jdbc/client/impl/MultiPrimaryClient.java index 6a288ba70..7eb3ff521 100644 --- a/src/main/java/org/mariadb/jdbc/client/impl/MultiPrimaryClient.java +++ b/src/main/java/org/mariadb/jdbc/client/impl/MultiPrimaryClient.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.impl; import java.sql.*; @@ -36,23 +35,23 @@ * supported proxy class. */ public class MultiPrimaryClient implements Client { - private static final Logger logger = Loggers.getLogger(MultiPrimaryClient.class); - /** temporary blacklisted hosts */ protected static final ConcurrentMap denyList = new ConcurrentHashMap<>(); + private static final Logger logger = Loggers.getLogger(MultiPrimaryClient.class); + /** denied timeout */ protected final long deniedListTimeout; /** configuration */ protected final Configuration conf; - /** is connections explicitly closed */ - protected boolean closed = false; - /** thread locker */ protected final ReentrantLock lock; + /** is connections explicitly closed */ + protected boolean closed = false; + /** current client */ protected Client currentClient; @@ -63,6 +62,7 @@ public class MultiPrimaryClient implements Client { * @param lock thread locker * @throws SQLException if fail to connect */ + @SuppressWarnings({"this-escape"}) public MultiPrimaryClient(Configuration conf, ReentrantLock lock) throws SQLException { this.conf = conf; this.lock = lock; @@ -150,8 +150,7 @@ protected Client connectHost(boolean readOnly, boolean failFast) throws SQLExcep } } } - - throw lastSqle; + throw (lastSqle != null) ? lastSqle : new SQLNonTransientConnectionException("No host"); } /** @@ -199,7 +198,8 @@ protected void replayIfPossible(Client oldClient, boolean canRedo) throws SQLExc // changing exception to SQLTransientConnectionException throw new SQLTransientConnectionException( String.format( - "Driver has reconnect connection after a communications link failure with %s. In progress transaction was lost", + "Driver has reconnect connection after a communications link failure with %s. In" + + " progress transaction was lost", oldClient.getHostAddress()), "25S03"); } @@ -228,7 +228,8 @@ protected void executeTransactionReplay(Client oldCli) throws SQLException { ctx.getTransactionSaver().clear(); throw new SQLTransientConnectionException( String.format( - "Driver has reconnect connection after a communications link failure with %s. In progress transaction was too big to be replayed, and was lost", + "Driver has reconnect connection after a communications link failure with %s. In" + + " progress transaction was too big to be replayed, and was lost", oldCli.getHostAddress()), "25S03"); } @@ -276,8 +277,9 @@ public void syncNewState(Client oldCli) throws SQLException { } if ((oldCtx.getStateFlag() & ConnectionState.STATE_TRANSACTION_ISOLATION) > 0 - && currentClient.getContext().getTransactionIsolationLevel() - != oldCtx.getTransactionIsolationLevel()) { + && !oldCtx + .getTransactionIsolationLevel() + .equals(currentClient.getContext().getTransactionIsolationLevel())) { String query = "SET SESSION TRANSACTION ISOLATION LEVEL"; switch (oldCtx.getTransactionIsolationLevel()) { case java.sql.Connection.TRANSACTION_READ_UNCOMMITTED: @@ -360,7 +362,8 @@ public List execute( if (message instanceof QueryPacket && ((QueryPacket) message).isCommit()) { throw new SQLTransientConnectionException( String.format( - "Driver has reconnect connection after a communications failure with %s during a COMMIT statement", + "Driver has reconnect connection after a communications failure with %s during a" + + " COMMIT statement", hostAddress), "25S03"); } @@ -537,6 +540,11 @@ public HostAddress getHostAddress() { return currentClient.getHostAddress(); } + @Override + public String getSocketIp() { + return currentClient.getSocketIp(); + } + public boolean isPrimary() { return true; } diff --git a/src/main/java/org/mariadb/jdbc/client/impl/MultiPrimaryReplicaClient.java b/src/main/java/org/mariadb/jdbc/client/impl/MultiPrimaryReplicaClient.java index c736136c9..ac4bd7aba 100644 --- a/src/main/java/org/mariadb/jdbc/client/impl/MultiPrimaryReplicaClient.java +++ b/src/main/java/org/mariadb/jdbc/client/impl/MultiPrimaryReplicaClient.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.impl; import java.sql.SQLException; @@ -47,6 +46,7 @@ public class MultiPrimaryReplicaClient extends MultiPrimaryClient { * @param lock thread locker * @throws SQLException if any error occurs */ + @SuppressWarnings({"this-escape"}) public MultiPrimaryReplicaClient(Configuration conf, ReentrantLock lock) throws SQLException { super(conf, lock); primaryClient = currentClient; diff --git a/src/main/java/org/mariadb/jdbc/client/impl/PrepareCache.java b/src/main/java/org/mariadb/jdbc/client/impl/PrepareCache.java index 4e77e2588..37ca2d2c7 100644 --- a/src/main/java/org/mariadb/jdbc/client/impl/PrepareCache.java +++ b/src/main/java/org/mariadb/jdbc/client/impl/PrepareCache.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.impl; import java.util.LinkedHashMap; @@ -16,10 +15,12 @@ public final class PrepareCache extends LinkedHashMap executePipeline( return results; } catch (SQLException sqlException) { if (!closed) { + results.add(null); // read remaining results perMsgCounter++; for (; perMsgCounter < responseMsg[readCounter - 1]; perMsgCounter++) { @@ -624,7 +627,7 @@ public List executePipeline( resultSetType, closeOnCompletion)); } catch (SQLException e) { - // eat + results.add(null); } } } @@ -1023,6 +1026,12 @@ public void close() { } } + public String getSocketIp() { + return this.socket.getInetAddress() == null + ? null + : this.socket.getInetAddress().getHostAddress(); + } + public boolean isPrimary() { return hostAddress.primary; } diff --git a/src/main/java/org/mariadb/jdbc/client/impl/StandardReadableByteBuf.java b/src/main/java/org/mariadb/jdbc/client/impl/StandardReadableByteBuf.java index 586d5a25c..2e177017b 100644 --- a/src/main/java/org/mariadb/jdbc/client/impl/StandardReadableByteBuf.java +++ b/src/main/java/org/mariadb/jdbc/client/impl/StandardReadableByteBuf.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.impl; import java.nio.charset.StandardCharsets; @@ -10,15 +9,15 @@ /** Packet buffer */ public final class StandardReadableByteBuf implements ReadableByteBuf { - /** row data limit */ - private int limit; - /** buffer */ public byte[] buf; /** current position reading buffer */ public int pos; + /** row data limit */ + private int limit; + /** * Packet buffer constructor * @@ -88,7 +87,6 @@ public void skipLengthEncoded() { return; default: pos += len & 0xff; - return; } } diff --git a/src/main/java/org/mariadb/jdbc/client/impl/TransactionSaver.java b/src/main/java/org/mariadb/jdbc/client/impl/TransactionSaver.java index ace7eab12..f77c23c2d 100644 --- a/src/main/java/org/mariadb/jdbc/client/impl/TransactionSaver.java +++ b/src/main/java/org/mariadb/jdbc/client/impl/TransactionSaver.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.impl; import java.util.Arrays; diff --git a/src/main/java/org/mariadb/jdbc/client/result/CompleteResult.java b/src/main/java/org/mariadb/jdbc/client/result/CompleteResult.java index 100b8b598..11296d997 100644 --- a/src/main/java/org/mariadb/jdbc/client/result/CompleteResult.java +++ b/src/main/java/org/mariadb/jdbc/client/result/CompleteResult.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.result; import java.io.ByteArrayOutputStream; @@ -38,6 +37,7 @@ public class CompleteResult extends Result { * @throws IOException if Socket error occurs * @throws SQLException for all other kind of errors */ + @SuppressWarnings({"this-escape"}) public CompleteResult( Statement stmt, boolean binaryProtocol, diff --git a/src/main/java/org/mariadb/jdbc/client/result/Result.java b/src/main/java/org/mariadb/jdbc/client/result/Result.java index 982f39aa9..a49ccf0a4 100644 --- a/src/main/java/org/mariadb/jdbc/client/result/Result.java +++ b/src/main/java/org/mariadb/jdbc/client/result/Result.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.result; import java.io.IOException; @@ -10,7 +9,7 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.math.RoundingMode; -import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.sql.*; import java.sql.Date; @@ -31,15 +30,11 @@ /** Result-set common */ public abstract class Result implements ResultSet, Completion { - private static BinaryRowDecoder BINARY_ROW_DECODER = new BinaryRowDecoder(); - private static TextRowDecoder TEXT_ROW_DECODER = new TextRowDecoder(); /** null length value */ public static final int NULL_LENGTH = -1; - private final int maxIndex; - private final boolean closeOnCompletion; - private boolean forceAlias; - private final boolean traceEnable; + private static final BinaryRowDecoder BINARY_ROW_DECODER = new BinaryRowDecoder(); + private static final TextRowDecoder TEXT_ROW_DECODER = new TextRowDecoder(); /** result-set type */ protected final int resultSetType; @@ -59,24 +54,22 @@ public abstract class Result implements ResultSet, Completion { /** binary/text row decoder */ protected final RowDecoder rowDecoder; + /** reusable row buffer decoder */ + protected final StandardReadableByteBuf rowBuf = new StandardReadableByteBuf(null, 0); + + private final int maxIndex; + private final boolean closeOnCompletion; + private final boolean traceEnable; + /** data size */ protected int dataSize = 0; /** rows */ protected byte[][] data; - private byte[] nullBitmap; - - /** reusable row buffer decoder */ - protected final StandardReadableByteBuf rowBuf = new StandardReadableByteBuf(null, 0); - - private MutableInt fieldLength = new MutableInt(0); - /** mutable field index */ protected MutableInt fieldIndex = new MutableInt(); - private Map mapper = null; - /** is fully loaded */ protected boolean loaded; @@ -95,6 +88,11 @@ public abstract class Result implements ResultSet, Completion { /** row number limit */ protected long maxRows; + private final MutableInt fieldLength = new MutableInt(0); + private boolean forceAlias; + private byte[] nullBitmap; + private Map mapper = null; + /** * Constructor for server's data * @@ -852,6 +850,16 @@ public boolean isBeforeFirst() throws SQLException { @Override public abstract int getRow() throws SQLException; + /** + * set row decoder to current row data + * + * @param row row + */ + public void setRow(byte[] row) { + rowBuf.buf(row, row.length, 0); + fieldIndex.set(-1); + } + @Override public abstract boolean absolute(int row) throws SQLException; @@ -870,7 +878,8 @@ public int getFetchDirection() { public void setFetchDirection(int direction) throws SQLException { if (direction == FETCH_REVERSE) { throw exceptionFactory.create( - "Invalid operation. Allowed direction are ResultSet.FETCH_FORWARD and ResultSet.FETCH_UNKNOWN"); + "Invalid operation. Allowed direction are ResultSet.FETCH_FORWARD and" + + " ResultSet.FETCH_UNKNOWN"); } } @@ -1154,7 +1163,8 @@ public Object getObject(int columnIndex, Map> map) throws SQLEx return getObject(columnIndex); } throw exceptionFactory.notSupported( - "Method ResultSet.getObject(int columnIndex, Map> map) not supported for non empty map"); + "Method ResultSet.getObject(int columnIndex, Map> map) not supported for" + + " non empty map"); } @Override @@ -1288,8 +1298,8 @@ public URL getURL(int columnIndex) throws SQLException { StringCodec.INSTANCE, null, rowBuf, fieldLength, metadataList, fieldIndex); if (s == null) return null; try { - return new URL(s); - } catch (MalformedURLException e) { + return new URI(s).toURL(); + } catch (Exception e) { throw exceptionFactory.create(String.format("Could not parse '%s' as URL", s)); } } @@ -1680,16 +1690,6 @@ protected void setNullRowBuf() { rowBuf.buf(null, 0, 0); } - /** - * set row decoder to current row data - * - * @param row row - */ - public void setRow(byte[] row) { - rowBuf.buf(row, row.length, 0); - fieldIndex.set(-1); - } - public int findColumn(String label) throws SQLException { if (label == null) throw new SQLException("null is not a valid label value"); if (mapper == null) { diff --git a/src/main/java/org/mariadb/jdbc/client/result/ResultSetMetaData.java b/src/main/java/org/mariadb/jdbc/client/result/ResultSetMetaData.java index ee49039d4..21fd88adf 100644 --- a/src/main/java/org/mariadb/jdbc/client/result/ResultSetMetaData.java +++ b/src/main/java/org/mariadb/jdbc/client/result/ResultSetMetaData.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.result; import java.sql.SQLException; diff --git a/src/main/java/org/mariadb/jdbc/client/result/StreamingResult.java b/src/main/java/org/mariadb/jdbc/client/result/StreamingResult.java index c3c9ce38c..75b3168a9 100644 --- a/src/main/java/org/mariadb/jdbc/client/result/StreamingResult.java +++ b/src/main/java/org/mariadb/jdbc/client/result/StreamingResult.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.result; import java.io.IOException; @@ -60,6 +59,7 @@ public class StreamingResult extends Result { * @param traceEnable can network log be logged * @throws SQLException if any error occurs */ + @SuppressWarnings({"this-escape"}) public StreamingResult( Statement stmt, boolean binaryProtocol, diff --git a/src/main/java/org/mariadb/jdbc/client/result/UpdatableResult.java b/src/main/java/org/mariadb/jdbc/client/result/UpdatableResult.java index fc429b700..1352f5cc1 100644 --- a/src/main/java/org/mariadb/jdbc/client/result/UpdatableResult.java +++ b/src/main/java/org/mariadb/jdbc/client/result/UpdatableResult.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.result; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/client/result/rowdecoder/BinaryRowDecoder.java b/src/main/java/org/mariadb/jdbc/client/result/rowdecoder/BinaryRowDecoder.java index 47a36e1dd..a218e87e3 100644 --- a/src/main/java/org/mariadb/jdbc/client/result/rowdecoder/BinaryRowDecoder.java +++ b/src/main/java/org/mariadb/jdbc/client/result/rowdecoder/BinaryRowDecoder.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.result.rowdecoder; import static org.mariadb.jdbc.client.result.Result.NULL_LENGTH; diff --git a/src/main/java/org/mariadb/jdbc/client/result/rowdecoder/RowDecoder.java b/src/main/java/org/mariadb/jdbc/client/result/rowdecoder/RowDecoder.java index b39e6fc7d..cafb0ef60 100644 --- a/src/main/java/org/mariadb/jdbc/client/result/rowdecoder/RowDecoder.java +++ b/src/main/java/org/mariadb/jdbc/client/result/rowdecoder/RowDecoder.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.result.rowdecoder; import java.sql.Date; @@ -120,6 +119,7 @@ boolean decodeBoolean( StandardReadableByteBuf rowBuf, MutableInt fieldLength) throws SQLException; + /** * Decode data according to Date. * @@ -138,6 +138,7 @@ Date decodeDate( MutableInt fieldLength, Calendar cal) throws SQLException; + /** * Decode data according to Time. * @@ -156,6 +157,7 @@ Time decodeTime( MutableInt fieldLength, Calendar cal) throws SQLException; + /** * Decode data according to Timestamp. * @@ -174,6 +176,7 @@ Timestamp decodeTimestamp( MutableInt fieldLength, Calendar cal) throws SQLException; + /** * Decode data according to short. * @@ -190,6 +193,7 @@ short decodeShort( StandardReadableByteBuf rowBuf, MutableInt fieldLength) throws SQLException; + /** * Decode data according to int. * @@ -206,6 +210,7 @@ int decodeInt( StandardReadableByteBuf rowBuf, MutableInt fieldLength) throws SQLException; + /** * Decode data according to String. * @@ -222,6 +227,7 @@ String decodeString( StandardReadableByteBuf rowBuf, MutableInt fieldLength) throws SQLException; + /** * Decode data according to long. * @@ -238,6 +244,7 @@ long decodeLong( StandardReadableByteBuf rowBuf, MutableInt fieldLength) throws SQLException; + /** * Decode data according to float. * @@ -254,6 +261,7 @@ float decodeFloat( StandardReadableByteBuf rowBuf, MutableInt fieldLength) throws SQLException; + /** * Decode data according to double. * diff --git a/src/main/java/org/mariadb/jdbc/client/result/rowdecoder/TextRowDecoder.java b/src/main/java/org/mariadb/jdbc/client/result/rowdecoder/TextRowDecoder.java index 42bf6c533..9e7f429df 100644 --- a/src/main/java/org/mariadb/jdbc/client/result/rowdecoder/TextRowDecoder.java +++ b/src/main/java/org/mariadb/jdbc/client/result/rowdecoder/TextRowDecoder.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.result.rowdecoder; import static org.mariadb.jdbc.client.result.Result.NULL_LENGTH; diff --git a/src/main/java/org/mariadb/jdbc/client/socket/Reader.java b/src/main/java/org/mariadb/jdbc/client/socket/Reader.java index 55aef8ecb..61e278673 100644 --- a/src/main/java/org/mariadb/jdbc/client/socket/Reader.java +++ b/src/main/java/org/mariadb/jdbc/client/socket/Reader.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.socket; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/client/socket/Writer.java b/src/main/java/org/mariadb/jdbc/client/socket/Writer.java index 4569d52a0..f3d052bce 100644 --- a/src/main/java/org/mariadb/jdbc/client/socket/Writer.java +++ b/src/main/java/org/mariadb/jdbc/client/socket/Writer.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.socket; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/client/socket/impl/CompressInputStream.java b/src/main/java/org/mariadb/jdbc/client/socket/impl/CompressInputStream.java index 6c75f2ccf..6f96c9330 100644 --- a/src/main/java/org/mariadb/jdbc/client/socket/impl/CompressInputStream.java +++ b/src/main/java/org/mariadb/jdbc/client/socket/impl/CompressInputStream.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.socket.impl; import java.io.EOFException; @@ -23,11 +22,14 @@ public class CompressInputStream extends InputStream { private int end; private int pos; - private byte[] buf; + private volatile byte[] buf; /** * Constructor. When this handler is used, driver expect packet with 7 byte compression header * + * Implementation doesn't use synchronized/semaphore because all used are already locked by + * Statement/PreparedStatement Reentrant lock + * * @param in socket input stream * @param compressionSequence compression sequence */ @@ -88,7 +90,6 @@ public int read(byte[] b, int off, int len) throws IOException { } int totalReads = 0; - do { if (end - pos <= 0) { retrieveBuffer(); @@ -258,7 +259,7 @@ public void close() throws IOException { * @see InputStream#reset() */ @Override - public synchronized void mark(int readlimit) { + public void mark(int readlimit) { in.mark(readlimit); } @@ -300,7 +301,7 @@ public synchronized void mark(int readlimit) { * @see IOException */ @Override - public synchronized void reset() throws IOException { + public void reset() throws IOException { in.reset(); } diff --git a/src/main/java/org/mariadb/jdbc/client/socket/impl/CompressOutputStream.java b/src/main/java/org/mariadb/jdbc/client/socket/impl/CompressOutputStream.java index 7a9b2b8ac..726b636b8 100644 --- a/src/main/java/org/mariadb/jdbc/client/socket/impl/CompressOutputStream.java +++ b/src/main/java/org/mariadb/jdbc/client/socket/impl/CompressOutputStream.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.socket.impl; import java.io.ByteArrayOutputStream; diff --git a/src/main/java/org/mariadb/jdbc/client/socket/impl/NamedPipeSocket.java b/src/main/java/org/mariadb/jdbc/client/socket/impl/NamedPipeSocket.java index ad8d980b0..02cb0ef6b 100644 --- a/src/main/java/org/mariadb/jdbc/client/socket/impl/NamedPipeSocket.java +++ b/src/main/java/org/mariadb/jdbc/client/socket/impl/NamedPipeSocket.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.socket.impl; import com.sun.jna.platform.win32.Kernel32; @@ -71,8 +70,10 @@ public void connect(SocketAddress endpoint, int timeout) throws IOException { if (timeout == 0) { throw new FileNotFoundException( fileNotFoundException.getMessage() - + "\nplease consider set connectTimeout option, so connection can retry having access to named pipe. " - + "\n(Named pipe can throw ERROR_PIPE_BUSY error)"); + + "\n" + + "please consider set connectTimeout option, so connection can retry having" + + " access to named pipe. \n" + + "(Named pipe can throw ERROR_PIPE_BUSY error)"); } throw fileNotFoundException; } diff --git a/src/main/java/org/mariadb/jdbc/client/socket/impl/PacketReader.java b/src/main/java/org/mariadb/jdbc/client/socket/impl/PacketReader.java index e7234e2de..cf17d07e6 100644 --- a/src/main/java/org/mariadb/jdbc/client/socket/impl/PacketReader.java +++ b/src/main/java/org/mariadb/jdbc/client/socket/impl/PacketReader.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.socket.impl; import java.io.EOFException; @@ -20,18 +19,15 @@ /** Packet reader */ public class PacketReader implements Reader { - private StandardReadableByteBuf readBuf = new StandardReadableByteBuf(null, 0); - private static final int REUSABLE_BUFFER_LENGTH = 1024; private static final int MAX_PACKET_SIZE = 0xffffff; private static final Logger logger = Loggers.getLogger(PacketReader.class); - private final byte[] header = new byte[4]; private final byte[] reusableArray = new byte[REUSABLE_BUFFER_LENGTH]; private final InputStream inputStream; private final int maxQuerySizeToLog; - private final MutableByte sequence; + private final StandardReadableByteBuf readBuf = new StandardReadableByteBuf(null, 0); private String serverThreadLog = ""; /** @@ -259,7 +255,7 @@ public void skipPacket() throws IOException { remaining = lastPacketLength; do { - remaining -= inputStream.skip(remaining); + remaining -= (int) inputStream.skip(remaining); } while (remaining > 0); // *************************************************** @@ -283,7 +279,7 @@ public void skipPacket() throws IOException { remaining = packetLength; do { - remaining -= inputStream.skip(remaining); + remaining -= (int) inputStream.skip(remaining); } while (remaining > 0); lastPacketLength += packetLength; diff --git a/src/main/java/org/mariadb/jdbc/client/socket/impl/PacketWriter.java b/src/main/java/org/mariadb/jdbc/client/socket/impl/PacketWriter.java index 9807bb937..1170972f4 100644 --- a/src/main/java/org/mariadb/jdbc/client/socket/impl/PacketWriter.java +++ b/src/main/java/org/mariadb/jdbc/client/socket/impl/PacketWriter.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.socket.impl; import java.io.IOException; @@ -31,24 +30,29 @@ public class PacketWriter implements Writer { private static final int MEDIUM_BUFFER_SIZE = 128 * 1024; private static final int LARGE_BUFFER_SIZE = 1024 * 1024; private static final int MAX_PACKET_LENGTH = 0x00ffffff + 4; + + /** packet sequence */ + protected final MutableByte sequence; + + /** compressed packet sequence */ + protected final MutableByte compressSequence; + private final int maxQuerySizeToLog; private final OutputStream out; - private int maxPacketLength = MAX_PACKET_LENGTH; - private Integer maxAllowedPacket; - private long cmdLength; - private boolean permitTrace = true; - private String serverThreadLog = ""; - private int mark = -1; - private boolean bufContainDataAfterMark = false; + private final int maxPacketLength = MAX_PACKET_LENGTH; + private final Integer maxAllowedPacket; /** internal buffer */ protected byte[] buf; + /** buffer position */ protected int pos = 4; - /** packet sequence */ - protected final MutableByte sequence; - /** compressed packet sequence */ - protected final MutableByte compressSequence; + + private long cmdLength; + private boolean permitTrace = true; + private String serverThreadLog = ""; + private int mark = -1; + private boolean bufContainDataAfterMark = false; /** * Common feature to write data into socket, creating MariaDB Packet. diff --git a/src/main/java/org/mariadb/jdbc/client/socket/impl/ReadAheadBufferedStream.java b/src/main/java/org/mariadb/jdbc/client/socket/impl/ReadAheadBufferedStream.java index b58c1f331..e649b3d0a 100644 --- a/src/main/java/org/mariadb/jdbc/client/socket/impl/ReadAheadBufferedStream.java +++ b/src/main/java/org/mariadb/jdbc/client/socket/impl/ReadAheadBufferedStream.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.socket.impl; import java.io.FilterInputStream; @@ -22,6 +21,9 @@ public class ReadAheadBufferedStream extends FilterInputStream { /** * Constructor * + * Implementation doesn't use synchronized/semaphore because all used are already locked by + * Statement/PreparedStatement Reentrant lock + * * @param in socket input stream */ public ReadAheadBufferedStream(InputStream in) { @@ -40,12 +42,11 @@ public ReadAheadBufferedStream(InputStream in) { * @return number of added bytes * @throws IOException if exception during socket reading */ - public synchronized int read(byte[] externalBuf, int off, int len) throws IOException { + public int read(byte[] externalBuf, int off, int len) throws IOException { if (len == 0) { return 0; } - int totalReads = 0; while (true) { @@ -104,7 +105,7 @@ public void close() throws IOException { pos = 0; } - public synchronized int available() throws IOException { + public int available() throws IOException { return end - pos + super.available(); } diff --git a/src/main/java/org/mariadb/jdbc/client/socket/impl/SocketHandlerFunction.java b/src/main/java/org/mariadb/jdbc/client/socket/impl/SocketHandlerFunction.java index 99932408c..99a6b19cd 100644 --- a/src/main/java/org/mariadb/jdbc/client/socket/impl/SocketHandlerFunction.java +++ b/src/main/java/org/mariadb/jdbc/client/socket/impl/SocketHandlerFunction.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.socket.impl; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/client/socket/impl/SocketUtility.java b/src/main/java/org/mariadb/jdbc/client/socket/impl/SocketUtility.java index 17ff0bbaa..a63f0607d 100644 --- a/src/main/java/org/mariadb/jdbc/client/socket/impl/SocketUtility.java +++ b/src/main/java/org/mariadb/jdbc/client/socket/impl/SocketUtility.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.socket.impl; import com.sun.jna.Platform; diff --git a/src/main/java/org/mariadb/jdbc/client/socket/impl/UnixDomainSocket.java b/src/main/java/org/mariadb/jdbc/client/socket/impl/UnixDomainSocket.java index 5bac1f005..3122a7484 100644 --- a/src/main/java/org/mariadb/jdbc/client/socket/impl/UnixDomainSocket.java +++ b/src/main/java/org/mariadb/jdbc/client/socket/impl/UnixDomainSocket.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.socket.impl; import com.sun.jna.LastErrorException; @@ -57,8 +56,9 @@ public UnixDomainSocket(String path) throws IOException { /** * creates an endpoint for communication and returns a file descriptor that refers to that - * endpoint. see https://man7.org/linux/man-pages/man2/socket.2.html + * endpoint. * + * @see Socket * @param domain domain * @param type type * @param protocol protocol @@ -85,7 +85,8 @@ public static native int connect(int sockfd, SockAddr sockaddr, int addrlen) * @param fd file descriptor * @param buffer buffer * @param count length - * @param flags flag. see https://man7.org/linux/man-pages/man2/recvmsg.2.html + * @param flags flag. @see flags * @return zero on success. -1 on error * @throws LastErrorException if error occurs */ @@ -98,7 +99,8 @@ public static native int recv(int fd, byte[] buffer, int count, int flags) * @param fd file descriptor * @param buffer buffer * @param count length - * @param flags flag. see https://man7.org/linux/man-pages/man2/sendmsg.2.html + * @param flags flag. @see flags * @return zero on success. -1 on error * @throws LastErrorException if error occurs */ @@ -158,6 +160,7 @@ public void connect(SocketAddress endpoint, int timeout) throws IOException { try { close(); } catch (IOException e) { + // eat } throw new IOException("native connect() failed : " + formatError(lee)); @@ -202,6 +205,7 @@ public void shutdownOutput() { public static class SockAddr extends Structure { /** socket family */ public short sun_family = AF_UNIX; + /** pathname */ public byte[] sun_path; @@ -210,7 +214,9 @@ public static class SockAddr extends Structure { * * @param sunPath path */ + @SuppressWarnings({"this-escape"}) public SockAddr(String sunPath) { + byte[] arr = sunPath.getBytes(); sun_path = new byte[arr.length + 1]; System.arraycopy(arr, 0, sun_path, 0, Math.min(sun_path.length - 1, arr.length)); diff --git a/src/main/java/org/mariadb/jdbc/client/tls/HostnameVerifier.java b/src/main/java/org/mariadb/jdbc/client/tls/HostnameVerifier.java index cb0e9aa72..1f952da6c 100644 --- a/src/main/java/org/mariadb/jdbc/client/tls/HostnameVerifier.java +++ b/src/main/java/org/mariadb/jdbc/client/tls/HostnameVerifier.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.tls; import java.net.InetAddress; diff --git a/src/main/java/org/mariadb/jdbc/client/tls/MariaDbX509KeyManager.java b/src/main/java/org/mariadb/jdbc/client/tls/MariaDbX509KeyManager.java index de32f5c34..46846ebef 100644 --- a/src/main/java/org/mariadb/jdbc/client/tls/MariaDbX509KeyManager.java +++ b/src/main/java/org/mariadb/jdbc/client/tls/MariaDbX509KeyManager.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.tls; import java.net.Socket; diff --git a/src/main/java/org/mariadb/jdbc/client/tls/MariaDbX509TrustingManager.java b/src/main/java/org/mariadb/jdbc/client/tls/MariaDbX509TrustingManager.java index ff463e2b6..f6026dbf9 100644 --- a/src/main/java/org/mariadb/jdbc/client/tls/MariaDbX509TrustingManager.java +++ b/src/main/java/org/mariadb/jdbc/client/tls/MariaDbX509TrustingManager.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.tls; import java.security.cert.X509Certificate; diff --git a/src/main/java/org/mariadb/jdbc/client/util/MutableByte.java b/src/main/java/org/mariadb/jdbc/client/util/MutableByte.java index fe043e266..f94284163 100644 --- a/src/main/java/org/mariadb/jdbc/client/util/MutableByte.java +++ b/src/main/java/org/mariadb/jdbc/client/util/MutableByte.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.util; /** Mutable int, permitting to update packet sequence */ diff --git a/src/main/java/org/mariadb/jdbc/client/util/MutableInt.java b/src/main/java/org/mariadb/jdbc/client/util/MutableInt.java index e97338ef3..6010e27a5 100644 --- a/src/main/java/org/mariadb/jdbc/client/util/MutableInt.java +++ b/src/main/java/org/mariadb/jdbc/client/util/MutableInt.java @@ -1,11 +1,12 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.util; /** Mutable int */ public class MutableInt { + private int value; + public MutableInt() { this.value = -1; } @@ -14,8 +15,6 @@ public MutableInt(int value) { this.value = value; } - private int value; - /** * Set new sequence value * diff --git a/src/main/java/org/mariadb/jdbc/client/util/Parameter.java b/src/main/java/org/mariadb/jdbc/client/util/Parameter.java index 3b260ee8b..d983cf692 100644 --- a/src/main/java/org/mariadb/jdbc/client/util/Parameter.java +++ b/src/main/java/org/mariadb/jdbc/client/util/Parameter.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.util; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/client/util/Parameters.java b/src/main/java/org/mariadb/jdbc/client/util/Parameters.java index 6e8726b28..8273017b2 100644 --- a/src/main/java/org/mariadb/jdbc/client/util/Parameters.java +++ b/src/main/java/org/mariadb/jdbc/client/util/Parameters.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.client.util; /** Parameters list */ diff --git a/src/main/java/org/mariadb/jdbc/codec/NonNullParameter.java b/src/main/java/org/mariadb/jdbc/codec/NonNullParameter.java index a7df9f2f8..86570225a 100644 --- a/src/main/java/org/mariadb/jdbc/codec/NonNullParameter.java +++ b/src/main/java/org/mariadb/jdbc/codec/NonNullParameter.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.codec; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/codec/Parameter.java b/src/main/java/org/mariadb/jdbc/codec/Parameter.java index 2e66b4416..69c71ea46 100644 --- a/src/main/java/org/mariadb/jdbc/codec/Parameter.java +++ b/src/main/java/org/mariadb/jdbc/codec/Parameter.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.codec; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/codec/ParameterWithCal.java b/src/main/java/org/mariadb/jdbc/codec/ParameterWithCal.java index 990483b66..0ee9d8c28 100644 --- a/src/main/java/org/mariadb/jdbc/codec/ParameterWithCal.java +++ b/src/main/java/org/mariadb/jdbc/codec/ParameterWithCal.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.codec; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/export/ExceptionFactory.java b/src/main/java/org/mariadb/jdbc/export/ExceptionFactory.java index c85b37948..1c1f5931b 100644 --- a/src/main/java/org/mariadb/jdbc/export/ExceptionFactory.java +++ b/src/main/java/org/mariadb/jdbc/export/ExceptionFactory.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.export; import java.sql.*; @@ -15,6 +14,7 @@ import org.mariadb.jdbc.MariaDbPoolConnection; import org.mariadb.jdbc.client.Completion; import org.mariadb.jdbc.message.server.OkPacket; +import org.mariadb.jdbc.util.ThreadUtils; /** * Exception factory. This permit common error logging, with thread id, dump query, and specific @@ -103,7 +103,7 @@ private static String buildMsgText( msg.append("\n name:\"") .append(thread.getName()) .append("\" pid:") - .append(thread.getId()) + .append(ThreadUtils.getId(thread)) .append(" status:") .append(thread.getState()); for (StackTraceElement trace : traces) { @@ -193,8 +193,6 @@ public BatchUpdateException createBatchUpdate( public BatchUpdateException createBatchUpdate( List res, int length, int[] responseMsg, SQLException sqle) { int[] updateCounts = new int[length]; - - int responseIncrement = 0; for (int i = 0; i < length; i++) { if (i >= responseMsg.length) { Arrays.fill(updateCounts, i, length, Statement.EXECUTE_FAILED); @@ -202,10 +200,18 @@ public BatchUpdateException createBatchUpdate( } int MsgResponseNo = responseMsg[i]; if (MsgResponseNo < 1) { - updateCounts[responseIncrement++] = Statement.EXECUTE_FAILED; + updateCounts[0] = Statement.EXECUTE_FAILED; return new BatchUpdateException(updateCounts, sqle); - } else if (MsgResponseNo == 1 && res.size() > i && res.get(i) instanceof OkPacket) { - updateCounts[i] = (int) ((OkPacket) res.get(i)).getAffectedRows(); + } else if (MsgResponseNo == 1) { + if (i >= res.size() || res.get(i) == null) { + updateCounts[i] = Statement.EXECUTE_FAILED; + continue; + } + if (res.get(i) instanceof OkPacket) { + updateCounts[i] = (int) ((OkPacket) res.get(i)).getAffectedRows(); + continue; + } + updateCounts[i] = Statement.SUCCESS_NO_INFO; } else { // unknown. updateCounts[i] = Statement.SUCCESS_NO_INFO; @@ -261,7 +267,8 @@ private SQLException createException( // 3948 : mysql load data infile disable if ((errorCode == 4166 || errorCode == 3948 || errorCode == 1148) && !conf.allowLocalInfile()) { return new SQLException( - "Local infile is disabled by connector. Enable `allowLocalInfile` to allow local infile commands", + "Local infile is disabled by connector. Enable `allowLocalInfile` to allow local infile" + + " commands", sqlState, errorCode, cause); @@ -358,6 +365,7 @@ public SQLException create(String message, String sqlState) { public SQLException create(String message, String sqlState, Exception cause) { return createException(message, sqlState, -1, cause); } + /** * Creation of an exception * diff --git a/src/main/java/org/mariadb/jdbc/export/HaMode.java b/src/main/java/org/mariadb/jdbc/export/HaMode.java index 95d5ee26e..71cd5baff 100644 --- a/src/main/java/org/mariadb/jdbc/export/HaMode.java +++ b/src/main/java/org/mariadb/jdbc/export/HaMode.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.export; import java.util.*; @@ -64,12 +63,6 @@ public Optional getAvailableHost( this.value = value; } - /** For testing purpose only */ - public void resetLast() { - lastRoundRobinPrimaryHost = null; - lastRoundRobinSecondaryHost = null; - } - /** * Get HAMode from values or aliases * @@ -201,6 +194,12 @@ public static Optional getAvailableRoundRobinHost( return Optional.empty(); } + /** For testing purpose only */ + public void resetLast() { + lastRoundRobinPrimaryHost = null; + lastRoundRobinSecondaryHost = null; + } + /** * List of hosts without blacklist entries, ordered according to HA mode * diff --git a/src/main/java/org/mariadb/jdbc/export/MaxAllowedPacketException.java b/src/main/java/org/mariadb/jdbc/export/MaxAllowedPacketException.java index 23e0da7b4..00036a42f 100644 --- a/src/main/java/org/mariadb/jdbc/export/MaxAllowedPacketException.java +++ b/src/main/java/org/mariadb/jdbc/export/MaxAllowedPacketException.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.export; import java.io.IOException; @@ -13,6 +12,7 @@ public class MaxAllowedPacketException extends IOException { private static final long serialVersionUID = 5669184960442818475L; + /** is connection in wrong state */ private final boolean mustReconnect; diff --git a/src/main/java/org/mariadb/jdbc/export/Prepare.java b/src/main/java/org/mariadb/jdbc/export/Prepare.java index de3a86cdb..6c7d997dd 100644 --- a/src/main/java/org/mariadb/jdbc/export/Prepare.java +++ b/src/main/java/org/mariadb/jdbc/export/Prepare.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.export; import java.sql.SQLException; diff --git a/src/main/java/org/mariadb/jdbc/export/SslMode.java b/src/main/java/org/mariadb/jdbc/export/SslMode.java index fa28d1552..0d1ab2178 100644 --- a/src/main/java/org/mariadb/jdbc/export/SslMode.java +++ b/src/main/java/org/mariadb/jdbc/export/SslMode.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.export; /** SSl requirement */ diff --git a/src/main/java/org/mariadb/jdbc/message/ClientMessage.java b/src/main/java/org/mariadb/jdbc/message/ClientMessage.java index 979832937..1bc5c35fb 100644 --- a/src/main/java/org/mariadb/jdbc/message/ClientMessage.java +++ b/src/main/java/org/mariadb/jdbc/message/ClientMessage.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message; import java.io.FileInputStream; @@ -29,6 +28,45 @@ public interface ClientMessage { + /** + * Check that file requested correspond to request. + * + * @param sql current command sql + * @param parameters current command parameter + * @param fileName file path request + * @param context current connection context + * @return true if file name correspond to demand and query is a load local infile + */ + static boolean validateLocalFileName( + String sql, Parameters parameters, String fileName, Context context) { + String reg = + "^(\\s*/\\*([^*]|\\*[^/])*\\*/)*\\s*LOAD\\s+(DATA|XML)\\s+((LOW_PRIORITY|CONCURRENT)\\s+)?LOCAL\\s+INFILE\\s+'" + + Pattern.quote(fileName.replace("\\", "\\\\")) + + "'"; + + Pattern pattern = Pattern.compile(reg, Pattern.CASE_INSENSITIVE); + if (pattern.matcher(sql).find()) { + return true; + } + + if (parameters != null) { + pattern = + Pattern.compile( + "^(\\s*/\\*([^*]|\\*[^/])*\\*/)*\\s*LOAD\\s+(DATA|XML)\\s+((LOW_PRIORITY|CONCURRENT)\\s+)?LOCAL\\s+INFILE\\s+\\?", + Pattern.CASE_INSENSITIVE); + if (pattern.matcher(sql).find() && parameters.size() > 0) { + String paramString = parameters.get(0).bestEffortStringValue(context); + if (paramString != null) { + return paramString + .toLowerCase() + .equals("'" + fileName.replace("\\", "\\\\").toLowerCase() + "'"); + } + return true; + } + } + return false; + } + /** * Encode client message to socket. * @@ -146,7 +184,9 @@ default Completion readPacket( .withSql(this.description()) .create( String.format( - "LOAD DATA LOCAL INFILE asked for file '%s' that doesn't correspond to initial query %s. Possible malicious proxy changing server answer ! Command interrupted", + "LOAD DATA LOCAL INFILE asked for file '%s' that doesn't correspond to" + + " initial query %s. Possible malicious proxy changing server" + + " answer ! Command interrupted", fileName, this.description()), "HY000"); } else { @@ -206,7 +246,7 @@ default Completion readPacket( ColumnDecoder[] ci; boolean canSkipMeta = context.canSkipMeta() && this.canSkipMeta(); - boolean skipMeta = canSkipMeta ? buf.readByte() == 0 : false; + boolean skipMeta = canSkipMeta && buf.readByte() == 0; if (canSkipMeta && skipMeta) { ci = ((BasePreparedStatement) stmt).getMeta(); } else { @@ -291,43 +331,4 @@ default InputStream getLocalInfileInputStream() { default boolean validateLocalFileName(String fileName, Context context) { return false; } - - /** - * Check that file requested correspond to request. - * - * @param sql current command sql - * @param parameters current command parameter - * @param fileName file path request - * @param context current connection context - * @return true if file name correspond to demand and query is a load local infile - */ - static boolean validateLocalFileName( - String sql, Parameters parameters, String fileName, Context context) { - String reg = - "^(\\s*\\/\\*([^\\*]|\\*[^\\/])*\\*\\/)*\\s*LOAD\\s+(DATA|XML)\\s+((LOW_PRIORITY|CONCURRENT)\\s+)?LOCAL\\s+INFILE\\s+'" - + Pattern.quote(fileName.replace("\\", "\\\\")) - + "'"; - - Pattern pattern = Pattern.compile(reg, Pattern.CASE_INSENSITIVE); - if (pattern.matcher(sql).find()) { - return true; - } - - if (parameters != null) { - pattern = - Pattern.compile( - "^(\\s*\\/\\*([^\\*]|\\*[^\\/])*\\*\\/)*\\s*LOAD\\s+(DATA|XML)\\s+((LOW_PRIORITY|CONCURRENT)\\s+)?LOCAL\\s+INFILE\\s+\\?", - Pattern.CASE_INSENSITIVE); - if (pattern.matcher(sql).find() && parameters.size() > 0) { - String paramString = parameters.get(0).bestEffortStringValue(context); - if (paramString != null) { - return paramString - .toLowerCase() - .equals("'" + fileName.replace("\\", "\\\\").toLowerCase() + "'"); - } - return true; - } - } - return false; - } } diff --git a/src/main/java/org/mariadb/jdbc/message/ServerMessage.java b/src/main/java/org/mariadb/jdbc/message/ServerMessage.java index 7028c3ebe..58c38321f 100644 --- a/src/main/java/org/mariadb/jdbc/message/ServerMessage.java +++ b/src/main/java/org/mariadb/jdbc/message/ServerMessage.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message; public interface ServerMessage {} diff --git a/src/main/java/org/mariadb/jdbc/message/client/AuthMoreRawPacket.java b/src/main/java/org/mariadb/jdbc/message/client/AuthMoreRawPacket.java index ad84bce06..68d809030 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/AuthMoreRawPacket.java +++ b/src/main/java/org/mariadb/jdbc/message/client/AuthMoreRawPacket.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message.client; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/message/client/BulkExecutePacket.java b/src/main/java/org/mariadb/jdbc/message/client/BulkExecutePacket.java index f5b70e984..0deb44072 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/BulkExecutePacket.java +++ b/src/main/java/org/mariadb/jdbc/message/client/BulkExecutePacket.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message.client; import java.io.IOException; @@ -19,13 +18,14 @@ import org.mariadb.jdbc.message.server.PrepareResultPacket; /** - * batch execution. This relies on COM_STMT_BULK_EXECUTE see - * https://mariadb.com/kb/en/com_stmt_bulk_execute/ + * batch execution. This relies on COM_STMT_BULK_EXECUTE + * + * @see documentation */ public final class BulkExecutePacket implements RedoableWithPrepareClientMessage { - private List batchParameterList; private final String command; private final ServerPreparedStatement prep; + private List batchParameterList; private Prepare prepareResult; /** diff --git a/src/main/java/org/mariadb/jdbc/message/client/ChangeDbPacket.java b/src/main/java/org/mariadb/jdbc/message/client/ChangeDbPacket.java index cdceafcc5..f4c525b33 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/ChangeDbPacket.java +++ b/src/main/java/org/mariadb/jdbc/message/client/ChangeDbPacket.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message.client; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/message/client/ClosePreparePacket.java b/src/main/java/org/mariadb/jdbc/message/client/ClosePreparePacket.java index 575d6be4b..b49cdbb7b 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/ClosePreparePacket.java +++ b/src/main/java/org/mariadb/jdbc/message/client/ClosePreparePacket.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message.client; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/message/client/ExecutePacket.java b/src/main/java/org/mariadb/jdbc/message/client/ExecutePacket.java index 4f8e9b9eb..68f1528ef 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/ExecutePacket.java +++ b/src/main/java/org/mariadb/jdbc/message/client/ExecutePacket.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message.client; import java.io.IOException; @@ -18,15 +17,16 @@ import org.mariadb.jdbc.plugin.codec.ByteArrayCodec; /** - * Execute command (COM_STMT_EXECUTE) See https://mariadb.com/kb/en/com_stmt_execute/ for - * documentation + * Execute command (COM_STMT_EXECUTE) + * + * @see Execute documentation */ public final class ExecutePacket implements RedoableWithPrepareClientMessage { - private Parameters parameters; private final String command; private final ServerPreparedStatement prep; + private final InputStream localInfileInputStream; private Prepare prepareResult; - private InputStream localInfileInputStream; + private Parameters parameters; /** * Constructor @@ -107,7 +107,7 @@ public int encode(Writer writer, Context context, Prepare newPrepareResult) writer.writeByte(p.getBinaryEncodeType()); writer.writeByte(0); if (p.isNull()) { - nullBitsBuffer[i / 8] |= (1 << (i % 8)); + nullBitsBuffer[i / 8] |= (byte) (1 << (i % 8)); } } diff --git a/src/main/java/org/mariadb/jdbc/message/client/HandshakeResponse.java b/src/main/java/org/mariadb/jdbc/message/client/HandshakeResponse.java index 209e53a85..8d8bc3006 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/HandshakeResponse.java +++ b/src/main/java/org/mariadb/jdbc/message/client/HandshakeResponse.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message.client; import static org.mariadb.jdbc.util.constants.Capabilities.*; @@ -16,11 +15,13 @@ import org.mariadb.jdbc.message.ClientMessage; import org.mariadb.jdbc.plugin.Credential; import org.mariadb.jdbc.plugin.authentication.standard.NativePasswordPlugin; +import org.mariadb.jdbc.util.ThreadUtils; import org.mariadb.jdbc.util.VersionFactory; /** - * Server handshake response builder. see - * https://mariadb.com/kb/en/connection/#client-handshake-response + * Server handshake response builder. + * + * @see documentation */ public final class HandshakeResponse implements ClientMessage { @@ -102,7 +103,7 @@ private static void writeConnectAttributes( writeStringLength(tmpWriter, System.getProperty("os.name")); writeStringLengthAscii(tmpWriter, _THREAD); - writeStringLength(tmpWriter, Long.toString(Thread.currentThread().getId())); + writeStringLength(tmpWriter, Long.toString(ThreadUtils.getId(Thread.currentThread()))); writeStringLengthAscii(tmpWriter, _JAVA_VENDOR); writeStringLength(tmpWriter, System.getProperty("java.vendor")); diff --git a/src/main/java/org/mariadb/jdbc/message/client/LongDataPacket.java b/src/main/java/org/mariadb/jdbc/message/client/LongDataPacket.java index c54f5ec47..beddc5f82 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/LongDataPacket.java +++ b/src/main/java/org/mariadb/jdbc/message/client/LongDataPacket.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message.client; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/message/client/PingPacket.java b/src/main/java/org/mariadb/jdbc/message/client/PingPacket.java index 02870f223..7bc3a34f6 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/PingPacket.java +++ b/src/main/java/org/mariadb/jdbc/message/client/PingPacket.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message.client; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/message/client/PrepareExecutePacket.java b/src/main/java/org/mariadb/jdbc/message/client/PrepareExecutePacket.java index 8a5023733..cd3d3f55b 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/PrepareExecutePacket.java +++ b/src/main/java/org/mariadb/jdbc/message/client/PrepareExecutePacket.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message.client; import java.io.IOException; @@ -28,14 +27,16 @@ /** * Send a client COM_STMT_PREPARE + COM_STMT_EXECUTE packets see - * https://mariadb.com/kb/en/com_stmt_prepare/ + * + * @see Prepare packet */ public final class PrepareExecutePacket implements RedoableWithPrepareClientMessage { private final String sql; - private Parameters parameters; private final ServerPreparedStatement prep; + private final InputStream localInfileInputStream; private PrepareResultPacket prepareResult; - private InputStream localInfileInputStream; + private Parameters parameters; + /** * Construct prepare packet * @@ -102,7 +103,7 @@ public int encode(Writer writer, Context context, Prepare newPrepareResult) writer.writeByte(p.getBinaryEncodeType()); writer.writeByte(0); if (p.isNull()) { - nullBitsBuffer[i / 8] |= (1 << (i % 8)); + nullBitsBuffer[i / 8] |= (byte) (1 << (i % 8)); } } diff --git a/src/main/java/org/mariadb/jdbc/message/client/PreparePacket.java b/src/main/java/org/mariadb/jdbc/message/client/PreparePacket.java index e09b9eb99..42dab25ac 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/PreparePacket.java +++ b/src/main/java/org/mariadb/jdbc/message/client/PreparePacket.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message.client; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/message/client/QueryPacket.java b/src/main/java/org/mariadb/jdbc/message/client/QueryPacket.java index 133403058..3e0dec19b 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/QueryPacket.java +++ b/src/main/java/org/mariadb/jdbc/message/client/QueryPacket.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message.client; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/message/client/QueryWithParametersPacket.java b/src/main/java/org/mariadb/jdbc/message/client/QueryWithParametersPacket.java index 62e71faa3..f31e4847e 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/QueryWithParametersPacket.java +++ b/src/main/java/org/mariadb/jdbc/message/client/QueryWithParametersPacket.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message.client; import java.io.IOException; @@ -24,7 +23,7 @@ public final class QueryWithParametersPacket implements RedoableClientMessage { private final String preSqlCmd; private final ClientParser parser; private Parameters parameters; - private InputStream localInfileInputStream; + private final InputStream localInfileInputStream; /** * Constructor diff --git a/src/main/java/org/mariadb/jdbc/message/client/QuitPacket.java b/src/main/java/org/mariadb/jdbc/message/client/QuitPacket.java index 211e6ab3e..71cb2d47d 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/QuitPacket.java +++ b/src/main/java/org/mariadb/jdbc/message/client/QuitPacket.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message.client; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/message/client/RedoableClientMessage.java b/src/main/java/org/mariadb/jdbc/message/client/RedoableClientMessage.java index d1ec53f07..55afff173 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/RedoableClientMessage.java +++ b/src/main/java/org/mariadb/jdbc/message/client/RedoableClientMessage.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message.client; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/message/client/RedoableWithPrepareClientMessage.java b/src/main/java/org/mariadb/jdbc/message/client/RedoableWithPrepareClientMessage.java index 34fa0717a..e07b3894c 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/RedoableWithPrepareClientMessage.java +++ b/src/main/java/org/mariadb/jdbc/message/client/RedoableWithPrepareClientMessage.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message.client; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/message/client/ResetPacket.java b/src/main/java/org/mariadb/jdbc/message/client/ResetPacket.java index 64141b391..64458f352 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/ResetPacket.java +++ b/src/main/java/org/mariadb/jdbc/message/client/ResetPacket.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message.client; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/message/client/SslRequestPacket.java b/src/main/java/org/mariadb/jdbc/message/client/SslRequestPacket.java index 0009a5847..1cb069258 100644 --- a/src/main/java/org/mariadb/jdbc/message/client/SslRequestPacket.java +++ b/src/main/java/org/mariadb/jdbc/message/client/SslRequestPacket.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message.client; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/message/server/AuthSwitchPacket.java b/src/main/java/org/mariadb/jdbc/message/server/AuthSwitchPacket.java index 3beecb895..706e082c9 100644 --- a/src/main/java/org/mariadb/jdbc/message/server/AuthSwitchPacket.java +++ b/src/main/java/org/mariadb/jdbc/message/server/AuthSwitchPacket.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message.server; import java.util.Arrays; @@ -9,8 +8,10 @@ import org.mariadb.jdbc.message.ServerMessage; /** - * Authentication switch packet. See - * https://mariadb.com/kb/en/connection/#authentication-switch-request + * Authentication switch packet. + * + * @see Authentication + * switch packet */ public class AuthSwitchPacket implements ServerMessage { @@ -43,6 +44,16 @@ public static AuthSwitchPacket decode(ReadableByteBuf buf) { return new AuthSwitchPacket(plugin, seed); } + /** + * Get truncated seed (seed without ending 0x00 byte) + * + * @param seed connection seed + * @return truncated seed + */ + public static byte[] getTruncatedSeed(byte[] seed) { + return (seed.length > 0) ? Arrays.copyOfRange(seed, 0, seed.length - 1) : new byte[0]; + } + /** * Get authentication switch plugin information * @@ -60,14 +71,4 @@ public String getPlugin() { public byte[] getSeed() { return seed; } - - /** - * Get truncated seed (seed without ending 0x00 byte) - * - * @param seed connection seed - * @return truncated seed - */ - public static byte[] getTruncatedSeed(byte[] seed) { - return (seed.length > 0) ? Arrays.copyOfRange(seed, 0, seed.length - 1) : new byte[0]; - } } diff --git a/src/main/java/org/mariadb/jdbc/message/server/CachedPrepareResultPacket.java b/src/main/java/org/mariadb/jdbc/message/server/CachedPrepareResultPacket.java index 4ae9166ec..db3033828 100644 --- a/src/main/java/org/mariadb/jdbc/message/server/CachedPrepareResultPacket.java +++ b/src/main/java/org/mariadb/jdbc/message/server/CachedPrepareResultPacket.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message.server; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/message/server/ColumnDefinitionPacket.java b/src/main/java/org/mariadb/jdbc/message/server/ColumnDefinitionPacket.java index 9ca8ade63..e33b96d91 100644 --- a/src/main/java/org/mariadb/jdbc/message/server/ColumnDefinitionPacket.java +++ b/src/main/java/org/mariadb/jdbc/message/server/ColumnDefinitionPacket.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message.server; import java.util.Objects; @@ -15,23 +14,37 @@ /** Column metadata definition */ public class ColumnDefinitionPacket implements Column, ServerMessage { - private final ReadableByteBuf buf; /** charset */ protected final int charset; + /** column maximum length */ protected final long columnLength; - /** data type see https://mariadb.com/kb/en/result-set-packets/#field-types */ + + /** + * data type @see Field + * type + */ protected final DataType dataType; + /** number of decimal */ protected final byte decimals; - /** flags see https://mariadb.com/kb/en/result-set-packets/#field-details-flag */ - private final int flags; - /** string offset position in buffer */ - private final int[] stringPos; + /** extended type name */ protected final String extTypeName; + /** extended type format */ protected final String extTypeFormat; + + private final ReadableByteBuf buf; + + /** + * @see flags + */ + private final int flags; + + /** string offset position in buffer */ + private final int[] stringPos; + /** configuration: use alias as name */ private boolean useAliasAsName; diff --git a/src/main/java/org/mariadb/jdbc/message/server/ErrorPacket.java b/src/main/java/org/mariadb/jdbc/message/server/ErrorPacket.java index 822650897..36bc21228 100644 --- a/src/main/java/org/mariadb/jdbc/message/server/ErrorPacket.java +++ b/src/main/java/org/mariadb/jdbc/message/server/ErrorPacket.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message.server; import org.mariadb.jdbc.client.Context; diff --git a/src/main/java/org/mariadb/jdbc/message/server/InitialHandshakePacket.java b/src/main/java/org/mariadb/jdbc/message/server/InitialHandshakePacket.java index bb1492b20..2efae3ba8 100644 --- a/src/main/java/org/mariadb/jdbc/message/server/InitialHandshakePacket.java +++ b/src/main/java/org/mariadb/jdbc/message/server/InitialHandshakePacket.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message.server; import org.mariadb.jdbc.client.ReadableByteBuf; diff --git a/src/main/java/org/mariadb/jdbc/message/server/OkPacket.java b/src/main/java/org/mariadb/jdbc/message/server/OkPacket.java index d05fda5d6..d4e8013c4 100644 --- a/src/main/java/org/mariadb/jdbc/message/server/OkPacket.java +++ b/src/main/java/org/mariadb/jdbc/message/server/OkPacket.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message.server; import org.mariadb.jdbc.client.Completion; diff --git a/src/main/java/org/mariadb/jdbc/message/server/PrepareResultPacket.java b/src/main/java/org/mariadb/jdbc/message/server/PrepareResultPacket.java index 982159f12..4a25dd670 100644 --- a/src/main/java/org/mariadb/jdbc/message/server/PrepareResultPacket.java +++ b/src/main/java/org/mariadb/jdbc/message/server/PrepareResultPacket.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message.server; import java.io.IOException; @@ -15,9 +14,15 @@ import org.mariadb.jdbc.util.log.Logger; import org.mariadb.jdbc.util.log.Loggers; -/** Prepare result packet See https://mariadb.com/kb/en/com_stmt_prepare/#COM_STMT_PREPARE_OK */ +/** + * Prepare result packet + * + * @see Prepare result + * packet * + */ public class PrepareResultPacket implements Completion, Prepare { static final ColumnDecoder CONSTANT_PARAMETER; + private static final Logger logger = Loggers.getLogger(PrepareResultPacket.class); static { byte[] bytes = @@ -51,13 +56,13 @@ public class PrepareResultPacket implements Completion, Prepare { ColumnDecoder.decode(new StandardReadableByteBuf(bytes, bytes.length), true); } - private static final Logger logger = Loggers.getLogger(PrepareResultPacket.class); private final ColumnDecoder[] parameters; - private ColumnDecoder[] columns; /** prepare statement id */ protected int statementId; + private ColumnDecoder[] columns; + /** * Prepare packet constructor (parsing) * diff --git a/src/main/java/org/mariadb/jdbc/message/server/util/ServerVersionUtility.java b/src/main/java/org/mariadb/jdbc/message/server/util/ServerVersionUtility.java index aa8905d8b..8d729ffe8 100644 --- a/src/main/java/org/mariadb/jdbc/message/server/util/ServerVersionUtility.java +++ b/src/main/java/org/mariadb/jdbc/message/server/util/ServerVersionUtility.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.message.server.util; import org.mariadb.jdbc.client.ServerVersion; diff --git a/src/main/java/org/mariadb/jdbc/plugin/AuthenticationPlugin.java b/src/main/java/org/mariadb/jdbc/plugin/AuthenticationPlugin.java index 6f06c3128..4c8fb517e 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/AuthenticationPlugin.java +++ b/src/main/java/org/mariadb/jdbc/plugin/AuthenticationPlugin.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/Codec.java b/src/main/java/org/mariadb/jdbc/plugin/Codec.java index 8df9ee260..75c132541 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/Codec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/Codec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/Credential.java b/src/main/java/org/mariadb/jdbc/plugin/Credential.java index a5b71ab69..4e8ac1741 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/Credential.java +++ b/src/main/java/org/mariadb/jdbc/plugin/Credential.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin; /** basic Credential (couple of user/password) */ diff --git a/src/main/java/org/mariadb/jdbc/plugin/CredentialPlugin.java b/src/main/java/org/mariadb/jdbc/plugin/CredentialPlugin.java index de25dc904..1042d752e 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/CredentialPlugin.java +++ b/src/main/java/org/mariadb/jdbc/plugin/CredentialPlugin.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin; import java.sql.SQLException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/TlsSocketPlugin.java b/src/main/java/org/mariadb/jdbc/plugin/TlsSocketPlugin.java index 3c4cb93cd..ae9c978c1 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/TlsSocketPlugin.java +++ b/src/main/java/org/mariadb/jdbc/plugin/TlsSocketPlugin.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/AuthenticationPluginLoader.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/AuthenticationPluginLoader.java index 4a997b7a4..1d2899a07 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/AuthenticationPluginLoader.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/AuthenticationPluginLoader.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.authentication; import java.sql.SQLException; @@ -32,13 +31,14 @@ public static AuthenticationPlugin get(String type, Configuration conf) throws S for (AuthenticationPlugin implClass : loader) { if (type.equals(implClass.type())) { - if (conf.restrictedAuth() == null || Arrays.stream(authList).anyMatch(type::contains)) { + if (authList == null || Arrays.stream(authList).anyMatch(type::contains)) { return implClass; } else { throw new SQLException( String.format( - "Client restrict authentication plugin to a limited set of authentication plugin and doesn't permit requested plugin ('%s'). " - + "Current list is `restrictedAuth=%s`", + "Client restrict authentication plugin to a limited set of authentication plugin" + + " and doesn't permit requested plugin ('%s'). Current list is" + + " `restrictedAuth=%s`", type, conf.restrictedAuth()), "08004", 1251); diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/ClearPasswordPlugin.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/ClearPasswordPlugin.java index 0e4730f9b..bd23dfbe3 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/ClearPasswordPlugin.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/ClearPasswordPlugin.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.authentication.addon; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/SendGssApiAuthPacket.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/SendGssApiAuthPacket.java index 8de9e88ba..e40f105a6 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/SendGssApiAuthPacket.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/SendGssApiAuthPacket.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.authentication.addon; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/GssUtility.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/GssUtility.java index 07e8436f4..214c1e89d 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/GssUtility.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/GssUtility.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.authentication.addon.gssapi; import com.sun.jna.Platform; diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/GssapiAuth.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/GssapiAuth.java index 5f970ae88..7d0946268 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/GssapiAuth.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/GssapiAuth.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.authentication.addon.gssapi; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/StandardGssapiAuthentication.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/StandardGssapiAuthentication.java index 3ce75b9ee..4d81d18c1 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/StandardGssapiAuthentication.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/StandardGssapiAuthentication.java @@ -1,11 +1,9 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.authentication.addon.gssapi; import java.io.*; -import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.sql.SQLException; import javax.security.auth.Subject; @@ -15,6 +13,7 @@ import org.mariadb.jdbc.client.ReadableByteBuf; import org.mariadb.jdbc.client.socket.Reader; import org.mariadb.jdbc.client.socket.Writer; +import org.mariadb.jdbc.util.ThreadUtils; /** Basic GSSAPI implementation if waffle is not on classpath */ public class StandardGssapiAuthentication implements GssapiAuth { @@ -35,8 +34,8 @@ public void authenticate( if ("".equals(servicePrincipalName)) { throw new SQLException( - "No principal name defined on server. " - + "Please set server variable \"gssapi-principal-name\" or set option \"servicePrincipalName\"", + "No principal name defined on server. Please set server variable" + + " \"gssapi-principal-name\" or set option \"servicePrincipalName\"", "28000"); } @@ -103,8 +102,9 @@ public void authenticate( } return null; }; - Subject.doAs(mySubject, action); - } catch (PrivilegedActionException exception) { + + ThreadUtils.callAs(mySubject, () -> action); + } catch (Exception exception) { throw new SQLException("GSS-API authentication exception", "28000", 1045, exception); } } else { diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/WindowsNativeSspiAuthentication.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/WindowsNativeSspiAuthentication.java index d87c376aa..9f297ae0a 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/WindowsNativeSspiAuthentication.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/addon/gssapi/WindowsNativeSspiAuthentication.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.authentication.addon.gssapi; import com.sun.jna.platform.win32.Sspi; diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/CachingSha2PasswordPlugin.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/CachingSha2PasswordPlugin.java index 0dbeeaeec..9c3caddc6 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/CachingSha2PasswordPlugin.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/CachingSha2PasswordPlugin.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.authentication.standard; import java.io.IOException; @@ -72,6 +71,83 @@ public static byte[] sha256encryptPassword(final CharSequence password, final by } } + /** + * Read public Key from file. + * + * @param serverRsaPublicKeyFile RSA public key file + * @return public key + * @throws SQLException if having an error reading file or file content is not a public key. + */ + public static PublicKey readPublicKeyFromFile(String serverRsaPublicKeyFile) throws SQLException { + byte[] keyBytes; + try { + keyBytes = Files.readAllBytes(Paths.get(serverRsaPublicKeyFile)); + } catch (IOException ex) { + throw new SQLException( + "Could not read server RSA public key from file : " + + "serverRsaPublicKeyFile=" + + serverRsaPublicKeyFile, + "S1009", + ex); + } + return generatePublicKey(keyBytes); + } + + /** + * Read public pem key from String. + * + * @param publicKeyBytes public key bytes value + * @return public key + * @throws SQLException if key cannot be parsed + */ + public static PublicKey generatePublicKey(byte[] publicKeyBytes) throws SQLException { + try { + String publicKey = + new String(publicKeyBytes, StandardCharsets.US_ASCII) + .replaceAll("(-+BEGIN PUBLIC KEY-+\\r?\\n|\\n?-+END PUBLIC KEY-+\\r?\\n?)", ""); + + byte[] keyBytes = Base64.getMimeDecoder().decode(publicKey); + X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes); + KeyFactory kf = KeyFactory.getInstance("RSA"); + return kf.generatePublic(spec); + } catch (Exception ex) { + throw new SQLException("Could read server RSA public key: " + ex.getMessage(), "S1009", ex); + } + } + + /** + * Encode password with seed and public key. + * + * @param publicKey public key + * @param password password + * @param seed seed + * @return encoded password + * @throws SQLException if cannot encode password + */ + public static byte[] encrypt(PublicKey publicKey, String password, byte[] seed) + throws SQLException { + + byte[] correctedSeed = Arrays.copyOfRange(seed, 0, seed.length - 1); + byte[] bytePwd = password.getBytes(StandardCharsets.UTF_8); + + byte[] nullFinishedPwd = Arrays.copyOf(bytePwd, bytePwd.length + 1); + byte[] xorBytes = new byte[nullFinishedPwd.length]; + int seedLength = correctedSeed.length; + + for (int i = 0; i < xorBytes.length; i++) { + xorBytes[i] = (byte) (nullFinishedPwd[i] ^ correctedSeed[i % seedLength]); + } + + try { + Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding"); + cipher.init(Cipher.ENCRYPT_MODE, publicKey); + return cipher.doFinal(xorBytes); + } catch (Exception ex) { + throw new SQLException( + "Error encoding password with public key : " + ex.getMessage(), "S1009", ex); + } + } + @Override public String type() { return TYPE; @@ -143,7 +219,8 @@ public ReadableByteBuf process(Writer out, Reader in, Context context) // read public key from socket if (!conf.allowPublicKeyRetrieval()) { throw new SQLException( - "RSA public key is not available client side (option serverRsaPublicKeyFile not set)", + "RSA public key is not available client side (option serverRsaPublicKeyFile" + + " not set)", "S1009"); } @@ -180,81 +257,4 @@ public ReadableByteBuf process(Writer out, Reader in, Context context) } } } - - /** - * Read public Key from file. - * - * @param serverRsaPublicKeyFile RSA public key file - * @return public key - * @throws SQLException if having an error reading file or file content is not a public key. - */ - public static PublicKey readPublicKeyFromFile(String serverRsaPublicKeyFile) throws SQLException { - byte[] keyBytes; - try { - keyBytes = Files.readAllBytes(Paths.get(serverRsaPublicKeyFile)); - } catch (IOException ex) { - throw new SQLException( - "Could not read server RSA public key from file : " - + "serverRsaPublicKeyFile=" - + serverRsaPublicKeyFile, - "S1009", - ex); - } - return generatePublicKey(keyBytes); - } - - /** - * Read public pem key from String. - * - * @param publicKeyBytes public key bytes value - * @return public key - * @throws SQLException if key cannot be parsed - */ - public static PublicKey generatePublicKey(byte[] publicKeyBytes) throws SQLException { - try { - String publicKey = - new String(publicKeyBytes, StandardCharsets.US_ASCII) - .replaceAll("(-+BEGIN PUBLIC KEY-+\\r?\\n|\\n?-+END PUBLIC KEY-+\\r?\\n?)", ""); - - byte[] keyBytes = Base64.getMimeDecoder().decode(publicKey); - X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes); - KeyFactory kf = KeyFactory.getInstance("RSA"); - return kf.generatePublic(spec); - } catch (Exception ex) { - throw new SQLException("Could read server RSA public key: " + ex.getMessage(), "S1009", ex); - } - } - - /** - * Encode password with seed and public key. - * - * @param publicKey public key - * @param password password - * @param seed seed - * @return encoded password - * @throws SQLException if cannot encode password - */ - public static byte[] encrypt(PublicKey publicKey, String password, byte[] seed) - throws SQLException { - - byte[] correctedSeed = Arrays.copyOfRange(seed, 0, seed.length - 1); - byte[] bytePwd = password.getBytes(StandardCharsets.UTF_8); - - byte[] nullFinishedPwd = Arrays.copyOf(bytePwd, bytePwd.length + 1); - byte[] xorBytes = new byte[nullFinishedPwd.length]; - int seedLength = correctedSeed.length; - - for (int i = 0; i < xorBytes.length; i++) { - xorBytes[i] = (byte) (nullFinishedPwd[i] ^ correctedSeed[i % seedLength]); - } - - try { - Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding"); - cipher.init(Cipher.ENCRYPT_MODE, publicKey); - return cipher.doFinal(xorBytes); - } catch (Exception ex) { - throw new SQLException( - "Error encoding password with public key : " + ex.getMessage(), "S1009", ex); - } - } } diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/Ed25519PasswordPlugin.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/Ed25519PasswordPlugin.java index 2968b3f04..c963af900 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/Ed25519PasswordPlugin.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/Ed25519PasswordPlugin.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.authentication.standard; import java.io.IOException; @@ -47,7 +46,7 @@ private static byte[] ed25519SignWithPassword(final String password, final byte[ final byte[] sm = new byte[64 + mlen]; byte[] az = hash.digest(bytePwd); - az[0] &= 248; + az[0] &= (byte) 248; az[31] &= 63; az[31] |= 64; diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/NativePasswordPlugin.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/NativePasswordPlugin.java index 3d8721e9b..de7422a77 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/NativePasswordPlugin.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/NativePasswordPlugin.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.authentication.standard; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/SendPamAuthPacket.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/SendPamAuthPacket.java index a9c40c3e0..93c1270bb 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/SendPamAuthPacket.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/SendPamAuthPacket.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.authentication.standard; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/Utils.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/Utils.java index 650e92569..0c0405333 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/Utils.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/Utils.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +// Copyright (c) 2012-2014 Monty Program Ab +// Copyright (c) 2015-2023 MariaDB Corporation Ab package org.mariadb.jdbc.plugin.authentication.standard.ed25519; /** diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/Curve.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/Curve.java index 049f123e4..b96191560 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/Curve.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/Curve.java @@ -19,6 +19,7 @@ public class Curve implements Serializable { private final GroupElement zeroP3PrecomputedDouble; private final GroupElement zeroPrecomp; + @SuppressWarnings({"this-escape"}) public Curve(Field f, byte[] d, FieldElement I) { this.f = f; this.d = f.fromByteArray(d); diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/Field.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/Field.java index 2eecde671..a556eb5b3 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/Field.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/Field.java @@ -7,6 +7,7 @@ * * @author str4d */ +@SuppressWarnings("all") public class Field implements Serializable { private static final long serialVersionUID = 8746587465875676L; @@ -19,13 +20,16 @@ public class Field implements Serializable { private final int b; private final FieldElement q; + /** q-2 */ private final FieldElement qm2; + /** (q-5) / 8 */ private final FieldElement qm5d8; private final Encoding enc; + @SuppressWarnings({"this-escape"}) public Field(int b, byte[] q, Encoding enc) { this.b = b; this.enc = enc; @@ -54,6 +58,18 @@ public int getb() { return b; } + public FieldElement getQ() { + return q; + } + + public FieldElement getQm2() { + return qm2; + } + + public FieldElement getQm5d8() { + return qm5d8; + } + public Encoding getEncoding() { return enc; } diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/GroupElement.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/GroupElement.java index feb9ffa5b..1df002360 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/GroupElement.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/GroupElement.java @@ -24,147 +24,15 @@ * * @author str4d */ +@SuppressWarnings("all") public class GroupElement implements Serializable { private static final long serialVersionUID = 2395879087349587L; - /** - * Available representations for a group element. - * - *

    - *
  • P2: Projective representation $(X:Y:Z)$ satisfying $x=X/Z, y=Y/Z$. - *
  • P3: Extended projective representation $(X:Y:Z:T)$ satisfying $x=X/Z, y=Y/Z, XY=ZT$. - *
  • P3PrecomputedDouble: P3 but with dblPrecmp populated. - *
  • P1P1: Completed representation $((X:Z), (Y:T))$ satisfying $x=X/Z, y=Y/T$. - *
  • PRECOMP: Precomputed representation $(y+x, y-x, 2dxy)$. - *
  • CACHED: Cached representation $(Y+X, Y-X, Z, 2dT)$ - *
- */ - public enum Representation { - /** Projective ($P^2$): $(X:Y:Z)$ satisfying $x=X/Z, y=Y/Z$ */ - P2, - /** Extended ($P^3$): $(X:Y:Z:T)$ satisfying $x=X/Z, y=Y/Z, XY=ZT$ */ - P3, - /** Can only be requested. Results in P3 representation but also populates dblPrecmp. */ - P3PrecomputedDouble, - /** Completed ($P \times P$): $((X:Z),(Y:T))$ satisfying $x=X/Z, y=Y/T$ */ - P1P1, - /** Precomputed (Duif): $(y+x,y-x,2dxy)$ */ - PRECOMP, - /** Cached: $(Y+X,Y-X,Z,2dT)$ */ - CACHED - } - - /** - * Creates a new group element in P2 representation. - * - * @param curve The curve. - * @param X The $X$ coordinate. - * @param Y The $Y$ coordinate. - * @param Z The $Z$ coordinate. - * @return The group element in P2 representation. - */ - public static GroupElement p2( - final Curve curve, final FieldElement X, final FieldElement Y, final FieldElement Z) { - return new GroupElement(curve, Representation.P2, X, Y, Z, null); - } - - /** - * Creates a new group element in P3 representation, without pre-computation. - * - * @param curve The curve. - * @param X The $X$ coordinate. - * @param Y The $Y$ coordinate. - * @param Z The $Z$ coordinate. - * @param T The $T$ coordinate. - * @return The group element in P3 representation. - */ - public static GroupElement p3( - final Curve curve, - final FieldElement X, - final FieldElement Y, - final FieldElement Z, - final FieldElement T) { - return p3(curve, X, Y, Z, T, false); - } - - /** - * Creates a new group element in P3 representation, potentially with pre-computation. - * - * @param curve The curve. - * @param X The $X$ coordinate. - * @param Y The $Y$ coordinate. - * @param Z The $Z$ coordinate. - * @param T The $T$ coordinate. - * @param precomputeDoubleOnly If true, populate dblPrecmp, else set to null. - * @return The group element in P3 representation. - */ - public static GroupElement p3( - final Curve curve, - final FieldElement X, - final FieldElement Y, - final FieldElement Z, - final FieldElement T, - final boolean precomputeDoubleOnly) { - return new GroupElement(curve, Representation.P3, X, Y, Z, T, precomputeDoubleOnly); - } - - /** - * Creates a new group element in P1P1 representation. - * - * @param curve The curve. - * @param X The $X$ coordinate. - * @param Y The $Y$ coordinate. - * @param Z The $Z$ coordinate. - * @param T The $T$ coordinate. - * @return The group element in P1P1 representation. - */ - public static GroupElement p1p1( - final Curve curve, - final FieldElement X, - final FieldElement Y, - final FieldElement Z, - final FieldElement T) { - return new GroupElement(curve, Representation.P1P1, X, Y, Z, T); - } - - /** - * Creates a new group element in PRECOMP representation. - * - * @param curve The curve. - * @param ypx The $y + x$ value. - * @param ymx The $y - x$ value. - * @param xy2d The $2 * d * x * y$ value. - * @return The group element in PRECOMP representation. - */ - public static GroupElement precomp( - final Curve curve, final FieldElement ypx, final FieldElement ymx, final FieldElement xy2d) { - return new GroupElement(curve, Representation.PRECOMP, ypx, ymx, xy2d, null); - } - - /** - * Creates a new group element in CACHED representation. - * - * @param curve The curve. - * @param YpX The $Y + X$ value. - * @param YmX The $Y - X$ value. - * @param Z The $Z$ coordinate. - * @param T2d The $2 * d * T$ value. - * @return The group element in CACHED representation. - */ - public static GroupElement cached( - final Curve curve, - final FieldElement YpX, - final FieldElement YmX, - final FieldElement Z, - final FieldElement T2d) { - return new GroupElement(curve, Representation.CACHED, YpX, YmX, Z, T2d); - } - /** Variable is package private only so that tests run. */ final Curve curve; /** Variable is package private only so that tests run. */ - final Representation repr; + final GroupElement.Representation repr; /** Variable is package private only so that tests run. */ final FieldElement X; @@ -186,7 +54,8 @@ public static GroupElement cached( final GroupElement[][] precmp; /** - * Precomputed table for , filled if necessary. + * Precomputed table for {@link #doubleScalarMultiplyVariableTime(GroupElement, byte[], byte[])}, + * filled if necessary. * *

Variable is package private only so that tests run. */ @@ -202,9 +71,10 @@ public static GroupElement cached( * @param Z The $Z$ coordinate. * @param T The $T$ coordinate. */ + @SuppressWarnings({"this-escape"}) public GroupElement( final Curve curve, - final Representation repr, + final GroupElement.Representation repr, final FieldElement X, final FieldElement Y, final FieldElement Z, @@ -223,9 +93,10 @@ public GroupElement( * @param T The $T$ coordinate. * @param precomputeDouble If true, populate dblPrecmp, else set to null. */ + @SuppressWarnings({"this-escape"}) public GroupElement( final Curve curve, - final Representation repr, + final GroupElement.Representation repr, final FieldElement X, final FieldElement Y, final FieldElement Z, @@ -283,6 +154,7 @@ public GroupElement(final Curve curve, final byte[] s) { * @param precomputeSingleAndDouble If true, populate both precmp and dblPrecmp, else set both to * null. */ + @SuppressWarnings({"this-escape"}) public GroupElement(final Curve curve, final byte[] s, boolean precomputeSingleAndDouble) { FieldElement x, y, yy, u, v, v3, vxx, check; y = curve.getField().fromByteArray(s); @@ -320,7 +192,7 @@ public GroupElement(final Curve curve, final byte[] s, boolean precomputeSingleA } this.curve = curve; - this.repr = Representation.P3; + this.repr = GroupElement.Representation.P3; this.X = x; this.Y = y; this.Z = curve.getField().ONE; @@ -334,15 +206,248 @@ public GroupElement(final Curve curve, final byte[] s, boolean precomputeSingleA } } + /** + * Creates a new group element in P2 representation. + * + * @param curve The curve. + * @param X The $X$ coordinate. + * @param Y The $Y$ coordinate. + * @param Z The $Z$ coordinate. + * @return The group element in P2 representation. + */ + public static GroupElement p2( + final Curve curve, final FieldElement X, final FieldElement Y, final FieldElement Z) { + return new GroupElement(curve, GroupElement.Representation.P2, X, Y, Z, null); + } + + /** + * Creates a new group element in P3 representation, without pre-computation. + * + * @param curve The curve. + * @param X The $X$ coordinate. + * @param Y The $Y$ coordinate. + * @param Z The $Z$ coordinate. + * @param T The $T$ coordinate. + * @return The group element in P3 representation. + */ + public static GroupElement p3( + final Curve curve, + final FieldElement X, + final FieldElement Y, + final FieldElement Z, + final FieldElement T) { + return p3(curve, X, Y, Z, T, false); + } + + /** + * Creates a new group element in P3 representation, potentially with pre-computation. + * + * @param curve The curve. + * @param X The $X$ coordinate. + * @param Y The $Y$ coordinate. + * @param Z The $Z$ coordinate. + * @param T The $T$ coordinate. + * @param precomputeDoubleOnly If true, populate dblPrecmp, else set to null. + * @return The group element in P3 representation. + */ + public static GroupElement p3( + final Curve curve, + final FieldElement X, + final FieldElement Y, + final FieldElement Z, + final FieldElement T, + final boolean precomputeDoubleOnly) { + return new GroupElement( + curve, GroupElement.Representation.P3, X, Y, Z, T, precomputeDoubleOnly); + } + + /** + * Creates a new group element in P1P1 representation. + * + * @param curve The curve. + * @param X The $X$ coordinate. + * @param Y The $Y$ coordinate. + * @param Z The $Z$ coordinate. + * @param T The $T$ coordinate. + * @return The group element in P1P1 representation. + */ + public static GroupElement p1p1( + final Curve curve, + final FieldElement X, + final FieldElement Y, + final FieldElement Z, + final FieldElement T) { + return new GroupElement(curve, GroupElement.Representation.P1P1, X, Y, Z, T); + } + + /** + * Creates a new group element in PRECOMP representation. + * + * @param curve The curve. + * @param ypx The $y + x$ value. + * @param ymx The $y - x$ value. + * @param xy2d The $2 * d * x * y$ value. + * @return The group element in PRECOMP representation. + */ + public static GroupElement precomp( + final Curve curve, final FieldElement ypx, final FieldElement ymx, final FieldElement xy2d) { + return new GroupElement(curve, GroupElement.Representation.PRECOMP, ypx, ymx, xy2d, null); + } + + /** + * Creates a new group element in CACHED representation. + * + * @param curve The curve. + * @param YpX The $Y + X$ value. + * @param YmX The $Y - X$ value. + * @param Z The $Z$ coordinate. + * @param T2d The $2 * d * T$ value. + * @return The group element in CACHED representation. + */ + public static GroupElement cached( + final Curve curve, + final FieldElement YpX, + final FieldElement YmX, + final FieldElement Z, + final FieldElement T2d) { + return new GroupElement(curve, GroupElement.Representation.CACHED, YpX, YmX, Z, T2d); + } + + /** + * Convert a to radix 16. + * + *

Method is package private only so that tests run. + * + * @param a $= a[0]+256*a[1]+...+256^{31} a[31]$ + * @return 64 bytes, each between -8 and 7 + */ + static byte[] toRadix16(final byte[] a) { + final byte[] e = new byte[64]; + int i; + // Radix 16 notation + for (i = 0; i < 32; i++) { + e[2 * i] = (byte) (a[i] & 15); + e[2 * i + 1] = (byte) ((a[i] >> 4) & 15); + } + /* each e[i] is between 0 and 15 */ + /* e[63] is between 0 and 7 */ + int carry = 0; + for (i = 0; i < 63; i++) { + e[i] += carry; + carry = e[i] + 8; + carry >>= 4; + e[i] -= carry << 4; + } + e[63] += carry; + /* each e[i] is between -8 and 7 */ + return e; + } + + /** + * Calculates a sliding-windows base 2 representation for a given value $a$. To learn more about + * it see [6] page 8. + * + *

Output: $r$ which satisfies $a = r0 * 2^0 + r1 * 2^1 + \dots + r255 * 2^{255}$ with $ri$ in + * $\{-15, -13, -11, -9, -7, -5, -3, -1, 0, 1, 3, 5, 7, 9, 11, 13, 15\}$ + * + *

Method is package private only so that tests run. + * + * @param a $= a[0]+256*a[1]+\dots+256^{31} a[31]$. + * @return The byte array $r$ in the above described form. + */ + static byte[] slide(final byte[] a) { + byte[] r = new byte[256]; + + // Put each bit of 'a' into a separate byte, 0 or 1 + for (int i = 0; i < 256; ++i) { + r[i] = (byte) (1 & (a[i >> 3] >> (i & 7))); + } + + // Note: r[i] will always be odd. + for (int i = 0; i < 256; ++i) { + if (r[i] != 0) { + for (int b = 1; b <= 6 && i + b < 256; ++b) { + // Accumulate bits if possible + if (r[i + b] != 0) { + if (r[i] + (r[i + b] << b) <= 15) { + r[i] += r[i + b] << b; + r[i + b] = 0; + } else if (r[i] - (r[i + b] << b) >= -15) { + r[i] -= r[i + b] << b; + for (int k = i + b; k < 256; ++k) { + if (r[k] == 0) { + r[k] = 1; + break; + } + r[k] = 0; + } + } else break; + } + } + } + } + + return r; + } + + /** + * Gets the curve of the group element. + * + * @return The curve. + */ + public Curve getCurve() { + return this.curve; + } + /** * Gets the representation of the group element. * * @return The representation. */ - public Representation getRepresentation() { + public GroupElement.Representation getRepresentation() { return this.repr; } + /** + * Gets the $X$ value of the group element. This is for most representation the projective $X$ + * coordinate. + * + * @return The $X$ value. + */ + public FieldElement getX() { + return this.X; + } + + /** + * Gets the $Y$ value of the group element. This is for most representation the projective $Y$ + * coordinate. + * + * @return The $Y$ value. + */ + public FieldElement getY() { + return this.Y; + } + + /** + * Gets the $Z$ value of the group element. This is for most representation the projective $Z$ + * coordinate. + * + * @return The $Z$ value. + */ + public FieldElement getZ() { + return this.Z; + } + + /** + * Gets the $T$ value of the group element. This is for most representation the projective $T$ + * coordinate. + * + * @return The $T$ value. + */ + public FieldElement getT() { + return this.T; + } + /** * Converts the group element to an encoded point on the curve. * @@ -369,7 +474,7 @@ public byte[] toByteArray() { * @return The group element in the P2 representation. */ public GroupElement toP2() { - return toRep(Representation.P2); + return toRep(GroupElement.Representation.P2); } /** @@ -378,7 +483,7 @@ public GroupElement toP2() { * @return The group element in the P3 representation. */ public GroupElement toP3() { - return toRep(Representation.P3); + return toRep(GroupElement.Representation.P3); } /** @@ -387,7 +492,7 @@ public GroupElement toP3() { * @return The group element in the P3 representation. */ public GroupElement toP3PrecomputeDouble() { - return toRep(Representation.P3PrecomputedDouble); + return toRep(GroupElement.Representation.P3PrecomputedDouble); } /** @@ -396,7 +501,7 @@ public GroupElement toP3PrecomputeDouble() { * @return The group element in the CACHED representation. */ public GroupElement toCached() { - return toRep(Representation.CACHED); + return toRep(GroupElement.Representation.CACHED); } /** @@ -416,13 +521,15 @@ public GroupElement toCached() { * @param repr The representation to convert to. * @return A new group element in the given representation. */ - private GroupElement toRep(final Representation repr) { + private GroupElement toRep(final GroupElement.Representation repr) { switch (this.repr) { case P2: - if (repr == Representation.P2) { - return p2(this.curve, this.X, this.Y, this.Z); + switch (repr) { + case P2: + return p2(this.curve, this.X, this.Y, this.Z); + default: + throw new IllegalArgumentException(); } - throw new IllegalArgumentException(); case P3: switch (repr) { case P2: @@ -466,15 +573,19 @@ private GroupElement toRep(final Representation repr) { throw new IllegalArgumentException(); } case PRECOMP: - if (repr == Representation.PRECOMP) { - return precomp(this.curve, this.X, this.Y, this.Z); + switch (repr) { + case PRECOMP: + return precomp(this.curve, this.X, this.Y, this.Z); + default: + throw new IllegalArgumentException(); } - throw new IllegalArgumentException(); case CACHED: - if (repr == Representation.CACHED) { - return cached(this.curve, this.X, this.Y, this.Z, this.T); + switch (repr) { + case CACHED: + return cached(this.curve, this.X, this.Y, this.Z, this.T); + default: + throw new IllegalArgumentException(); } - throw new IllegalArgumentException(); default: throw new UnsupportedOperationException(); } @@ -505,7 +616,9 @@ private GroupElement[][] precomputeSingle() { return precmp; } - /** Precomputes table for . */ + /** + * Precomputes table for {@link #doubleScalarMultiplyVariableTime(GroupElement, byte[], byte[])}. + */ private GroupElement[] precomputeDouble() { // Precomputation for double scalar multiplication. // P,3P,5P,7P,9P,11P,13P,15P @@ -635,8 +748,8 @@ public GroupElement dbl() { * @return the P1P1 representation of the result. */ private GroupElement madd(GroupElement q) { - if (this.repr != Representation.P3) throw new UnsupportedOperationException(); - if (q.repr != Representation.PRECOMP) throw new IllegalArgumentException(); + if (this.repr != GroupElement.Representation.P3) throw new UnsupportedOperationException(); + if (q.repr != GroupElement.Representation.PRECOMP) throw new IllegalArgumentException(); FieldElement YpX, YmX, A, B, C, D; YpX = this.Y.add(this.X); @@ -663,8 +776,8 @@ private GroupElement madd(GroupElement q) { * @return the P1P1 representation of the result. */ private GroupElement msub(GroupElement q) { - if (this.repr != Representation.P3) throw new UnsupportedOperationException(); - if (q.repr != Representation.PRECOMP) throw new IllegalArgumentException(); + if (this.repr != GroupElement.Representation.P3) throw new UnsupportedOperationException(); + if (q.repr != GroupElement.Representation.PRECOMP) throw new IllegalArgumentException(); FieldElement YpX, YmX, A, B, C, D; YpX = this.Y.add(this.X); @@ -708,8 +821,8 @@ private GroupElement msub(GroupElement q) { * @return the P1P1 representation of the result. */ public GroupElement add(GroupElement q) { - if (this.repr != Representation.P3) throw new UnsupportedOperationException(); - if (q.repr != Representation.CACHED) throw new IllegalArgumentException(); + if (this.repr != GroupElement.Representation.P3) throw new UnsupportedOperationException(); + if (q.repr != GroupElement.Representation.CACHED) throw new IllegalArgumentException(); FieldElement YpX, YmX, A, B, C, ZZ, D; YpX = this.Y.add(this.X); @@ -735,8 +848,8 @@ public GroupElement add(GroupElement q) { * @return the P1P1 representation of the result. */ public GroupElement sub(GroupElement q) { - if (this.repr != Representation.P3) throw new UnsupportedOperationException(); - if (q.repr != Representation.CACHED) throw new IllegalArgumentException(); + if (this.repr != GroupElement.Representation.P3) throw new UnsupportedOperationException(); + if (q.repr != GroupElement.Representation.CACHED) throw new IllegalArgumentException(); FieldElement YpX, YmX, A, B, C, ZZ, D; YpX = Y.add(X); @@ -757,8 +870,11 @@ public GroupElement sub(GroupElement q) { * @return The negative of this group element. */ public GroupElement negate() { - if (this.repr != Representation.P3) throw new UnsupportedOperationException(); - return this.curve.getZero(Representation.P3).sub(toCached()).toP3PrecomputeDouble(); + if (this.repr != GroupElement.Representation.P3) throw new UnsupportedOperationException(); + return this.curve + .getZero(GroupElement.Representation.P3) + .sub(toCached()) + .toP3PrecomputeDouble(); } @Override @@ -811,36 +927,6 @@ public boolean equals(Object obj) { } } - /** - * Convert a to radix 16. - * - *

Method is package private only so that tests run. - * - * @param a $= a[0]+256*a[1]+...+256^{31} a[31]$ - * @return 64 bytes, each between -8 and 7 - */ - static byte[] toRadix16(final byte[] a) { - final byte[] e = new byte[64]; - int i; - // Radix 16 notation - for (i = 0; i < 32; i++) { - e[2 * i] = (byte) (a[i] & 15); - e[2 * i + 1] = (byte) ((a[i] >> 4) & 15); - } - /* each e[i] is between 0 and 15 */ - /* e[63] is between 0 and 7 */ - int carry = 0; - for (i = 0; i < 63; i++) { - e[i] += carry; - carry = e[i] + 8; - carry >>= 4; - e[i] -= carry << 4; - } - e[63] += carry; - /* each e[i] is between -8 and 7 */ - return e; - } - /** * Constant-time conditional move. * @@ -879,7 +965,7 @@ GroupElement select(final int pos, final int b) { // 16^i |r_i| B final GroupElement t = this.curve - .getZero(Representation.PRECOMP) + .getZero(GroupElement.Representation.PRECOMP) .cmov(this.precmp[pos][0], Utils.equal(babs, 1)) .cmov(this.precmp[pos][1], Utils.equal(babs, 2)) .cmov(this.precmp[pos][2], Utils.equal(babs, 3)) @@ -910,7 +996,7 @@ public GroupElement scalarMultiply(final byte[] a) { final byte[] e = toRadix16(a); - GroupElement h = this.curve.getZero(Representation.P3); + GroupElement h = this.curve.getZero(GroupElement.Representation.P3); for (i = 1; i < 64; i += 2) { t = select(i / 2, e[i]); h = h.madd(t).toP3(); @@ -927,52 +1013,59 @@ public GroupElement scalarMultiply(final byte[] a) { } /** - * Calculates a sliding-windows base 2 representation for a given value $a$. To learn more about - * it see [6] page 8. - * - *

Output: $r$ which satisfies $a = r0 * 2^0 + r1 * 2^1 + \dots + r255 * 2^{255}$ with $ri$ in - * $\{-15, -13, -11, -9, -7, -5, -3, -1, 0, 1, 3, 5, 7, 9, 11, 13, 15\}$ + * $r = a * A + b * B$ where $a = a[0]+256*a[1]+\dots+256^{31} a[31]$, $b = + * b[0]+256*b[1]+\dots+256^{31} b[31]$ and $B$ is this point. * - *

Method is package private only so that tests run. + *

$A$ must have been previously precomputed. * - * @param a $= a[0]+256*a[1]+\dots+256^{31} a[31]$. - * @return The byte array $r$ in the above described form. + * @param A in P3 representation. + * @param a $= a[0]+256*a[1]+\dots+256^{31} a[31]$ + * @param b $= b[0]+256*b[1]+\dots+256^{31} b[31]$ + * @return the GroupElement */ - static byte[] slide(final byte[] a) { - byte[] r = new byte[256]; + public GroupElement doubleScalarMultiplyVariableTime( + final GroupElement A, final byte[] a, final byte[] b) { + // TODO-CR BR: A check that this is the base point is needed. + final byte[] aslide = slide(a); + final byte[] bslide = slide(b); - // Put each bit of 'a' into a separate byte, 0 or 1 - for (int i = 0; i < 256; ++i) { - r[i] = (byte) (1 & (a[i >> 3] >> (i & 7))); + GroupElement r = this.curve.getZero(GroupElement.Representation.P2); + + int i; + for (i = 255; i >= 0; --i) { + if (aslide[i] != 0 || bslide[i] != 0) break; } - // Note: r[i] will always be odd. - for (int i = 0; i < 256; ++i) { - if (r[i] != 0) { - for (int b = 1; b <= 6 && i + b < 256; ++b) { - // Accumulate bits if possible - if (r[i + b] != 0) { - if (r[i] + (r[i + b] << b) <= 15) { - r[i] += r[i + b] << b; - r[i + b] = 0; - } else if (r[i] - (r[i + b] << b) >= -15) { - r[i] -= r[i + b] << b; - for (int k = i + b; k < 256; ++k) { - if (r[k] == 0) { - r[k] = 1; - break; - } - r[k] = 0; - } - } else break; - } - } + for (; i >= 0; --i) { + GroupElement t = r.dbl(); + + if (aslide[i] > 0) { + t = t.toP3().madd(A.dblPrecmp[aslide[i] / 2]); + } else if (aslide[i] < 0) { + t = t.toP3().msub(A.dblPrecmp[(-aslide[i]) / 2]); } + + if (bslide[i] > 0) { + t = t.toP3().madd(this.dblPrecmp[bslide[i] / 2]); + } else if (bslide[i] < 0) { + t = t.toP3().msub(this.dblPrecmp[(-bslide[i]) / 2]); + } + + r = t.toP2(); } return r; } + /** + * Verify that a point is on its curve. + * + * @return true if the point lies on its curve. + */ + public boolean isOnCurve() { + return isOnCurve(curve); + } + /** * Verify that a point is on the curve. * @@ -1000,4 +1093,31 @@ public boolean isOnCurve(Curve curve) { public String toString() { return "[GroupElement\nX=" + X + "\nY=" + Y + "\nZ=" + Z + "\nT=" + T + "\n]"; } + + /** + * Available representations for a group element. + * + *

    + *
  • P2: Projective representation $(X:Y:Z)$ satisfying $x=X/Z, y=Y/Z$. + *
  • P3: Extended projective representation $(X:Y:Z:T)$ satisfying $x=X/Z, y=Y/Z, XY=ZT$. + *
  • P3PrecomputedDouble: P3 but with dblPrecmp populated. + *
  • P1P1: Completed representation $((X:Z), (Y:T))$ satisfying $x=X/Z, y=Y/T$. + *
  • PRECOMP: Precomputed representation $(y+x, y-x, 2dxy)$. + *
  • CACHED: Cached representation $(Y+X, Y-X, Z, 2dT)$ + *
+ */ + public enum Representation { + /** Projective ($P^2$): $(X:Y:Z)$ satisfying $x=X/Z, y=Y/Z$ */ + P2, + /** Extended ($P^3$): $(X:Y:Z:T)$ satisfying $x=X/Z, y=Y/Z, XY=ZT$ */ + P3, + /** Can only be requested. Results in P3 representation but also populates dblPrecmp. */ + P3PrecomputedDouble, + /** Completed ($P \times P$): $((X:Z),(Y:T))$ satisfying $x=X/Z, y=Y/T$ */ + P1P1, + /** Precomputed (Duif): $(y+x,y-x,2dxy)$ */ + PRECOMP, + /** Cached: $(Y+X,Y-X,Z,2dT)$ */ + CACHED + } } diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ScalarOps.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ScalarOps.java index c52b7f26f..2779e4e07 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ScalarOps.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ScalarOps.java @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +// Copyright (c) 2012-2014 Monty Program Ab +// Copyright (c) 2015-2023 MariaDB Corporation Ab package org.mariadb.jdbc.plugin.authentication.standard.ed25519.math; public interface ScalarOps { diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519FieldElement.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519FieldElement.java index 37fb78bab..c2a413a58 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519FieldElement.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519FieldElement.java @@ -2,8 +2,7 @@ import java.util.Arrays; import org.mariadb.jdbc.plugin.authentication.standard.ed25519.Utils; -import org.mariadb.jdbc.plugin.authentication.standard.ed25519.math.Field; -import org.mariadb.jdbc.plugin.authentication.standard.ed25519.math.FieldElement; +import org.mariadb.jdbc.plugin.authentication.standard.ed25519.math.*; /** * Class to represent a field element of the finite field $p = 2^{255} - 19$ elements. @@ -16,6 +15,8 @@ */ public class Ed25519FieldElement extends FieldElement { private static final long serialVersionUID = -2455098303824960263L; + private static final byte[] ZERO = new byte[32]; + /** Variable is package private for encoding. */ final int[] t; @@ -31,8 +32,6 @@ public Ed25519FieldElement(Field f, int[] t) { this.t = t; } - private static final byte[] ZERO = new byte[32]; - /** * Gets a value indicating whether or not the field element is non-zero. * @@ -286,6 +285,16 @@ public FieldElement multiply(FieldElement val) { long f9g8_19 = t[9] * (long) g8_19; long f9g9_38 = f9_2 * (long) g9_19; + /** + * Remember: 2^255 congruent 19 modulo p. h = h0 * 2^0 + h1 * 2^26 + h2 * 2^(26+25) + h3 * + * 2^(26+25+26) + ... + h9 * 2^(5*26+5*25). So to get the real number we would have to multiply + * the coefficients with the corresponding powers of 2. To get an idea what is going on below, + * look at the calculation of h0: h0 is the coefficient to the power 2^0 so it collects (sums) + * all products that have the power 2^0. f0 * g0 really is f0 * 2^0 * g0 * 2^0 = (f0 * g0) * + * 2^0. f1 * g9 really is f1 * 2^26 * g9 * 2^230 = f1 * g9 * 2^256 = 2 * f1 * g9 * 2^255 + * congruent 2 * 19 * f1 * g9 * 2^0 modulo p. f2 * g8 really is f2 * 2^51 * g8 * 2^204 = f2 * g8 + * * 2^255 congruent 19 * f2 * g8 * 2^0 modulo p. and so on... + */ long h0 = f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38; @@ -501,6 +510,11 @@ public FieldElement square() { long f8f9_38 = f8 * (long) f9_38; long f9f9_38 = f9 * (long) f9_38; + /** + * Same procedure as in multiply, but this time we have a higher symmetry leading to less + * summands. e.g. f1f9_76 really stands for f1 * 2^26 * f9 * 2^230 + f9 * 2^230 + f1 * 2^26 + * congruent 2 * 2 * 19 * f1 * f9 2^0 modulo p. + */ long h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38; long h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38; long h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19; diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519LittleEndianEncoding.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519LittleEndianEncoding.java index 7c171690d..61885e112 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519LittleEndianEncoding.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519LittleEndianEncoding.java @@ -1,7 +1,6 @@ package org.mariadb.jdbc.plugin.authentication.standard.ed25519.math.ed25519; -import org.mariadb.jdbc.plugin.authentication.standard.ed25519.math.Encoding; -import org.mariadb.jdbc.plugin.authentication.standard.ed25519.math.FieldElement; +import org.mariadb.jdbc.plugin.authentication.standard.ed25519.math.*; /** * Helper class for encoding/decoding from/to the 32 byte representation. @@ -9,6 +8,21 @@ *

Reviewed/commented by Bloody Rookie (nemproject@gmx.de) */ public class Ed25519LittleEndianEncoding extends Encoding { + static int load_3(byte[] in, int offset) { + int result = in[offset++] & 0xff; + result |= (in[offset++] & 0xff) << 8; + result |= (in[offset] & 0xff) << 16; + return result; + } + + static long load_4(byte[] in, int offset) { + int result = in[offset++] & 0xff; + result |= (in[offset++] & 0xff) << 8; + result |= (in[offset++] & 0xff) << 16; + result |= in[offset] << 24; + return ((long) result) & 0xffffffffL; + } + /** * Encodes a given field element in its 32 byte representation. This is done in two steps: * @@ -19,6 +33,8 @@ public class Ed25519LittleEndianEncoding extends Encoding { * *

The idea for the modulo $p$ reduction algorithm is as follows: * + *

Assumption:

+ * *
    *
  • $p = 2^{255} - 19$ *
  • $h = h_0 + 2^{25} * h_1 + 2^{(26+25)} * h_2 + \dots + 2^{230} * h_9$ where $0 \le |h_i| @@ -29,7 +45,7 @@ public class Ed25519LittleEndianEncoding extends Encoding { * *

    Then $q = [2^{-255} * (h + 19 * 2^{-25} * h_9 + 1/2)]$ where $[x] = floor(x)$. * - *

    Proof: + *

    Proof:

    * *

    We begin with some very raw estimation for the bounds of some expressions: * @@ -167,21 +183,6 @@ public byte[] encode(FieldElement x) { return s; } - static int load_3(byte[] in, int offset) { - int result = in[offset++] & 0xff; - result |= (in[offset++] & 0xff) << 8; - result |= (in[offset] & 0xff) << 16; - return result; - } - - static long load_4(byte[] in, int offset) { - int result = in[offset++] & 0xff; - result |= (in[offset++] & 0xff) << 8; - result |= (in[offset++] & 0xff) << 16; - result |= in[offset] << 24; - return ((long) result) & 0xffffffffL; - } - /** * Decodes a given field element in its 10 byte $2^{25.5}$ representation. * @@ -190,14 +191,14 @@ static long load_4(byte[] in, int offset) { */ public FieldElement decode(byte[] in) { long h0 = load_4(in, 0); - long h1 = load_3(in, 4) << 6; - long h2 = load_3(in, 7) << 5; - long h3 = load_3(in, 10) << 3; - long h4 = load_3(in, 13) << 2; + long h1 = (long) load_3(in, 4) << 6; + long h2 = (long) load_3(in, 7) << 5; + long h3 = (long) load_3(in, 10) << 3; + long h4 = (long) load_3(in, 13) << 2; long h5 = load_4(in, 16); - long h6 = load_3(in, 20) << 7; - long h7 = load_3(in, 23) << 5; - long h8 = load_3(in, 26) << 4; + long h6 = (long) load_3(in, 20) << 7; + long h7 = (long) load_3(in, 23) << 5; + long h8 = (long) load_3(in, 26) << 4; long h9 = (load_3(in, 29) & 0x7FFFFF) << 2; long carry0; long carry1; diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519ScalarOps.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519ScalarOps.java index 0f9a518f5..ca892394c 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519ScalarOps.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/math/ed25519/Ed25519ScalarOps.java @@ -9,6 +9,9 @@ */ package org.mariadb.jdbc.plugin.authentication.standard.ed25519.math.ed25519; +import static org.mariadb.jdbc.plugin.authentication.standard.ed25519.math.ed25519.Ed25519LittleEndianEncoding.load_3; +import static org.mariadb.jdbc.plugin.authentication.standard.ed25519.math.ed25519.Ed25519LittleEndianEncoding.load_4; + import org.mariadb.jdbc.plugin.authentication.standard.ed25519.math.ScalarOps; /** @@ -31,30 +34,30 @@ public class Ed25519ScalarOps implements ScalarOps { */ public byte[] reduce(byte[] s) { // s0,..., s22 have 21 bits, s23 has 29 bits - long s0 = 0x1FFFFF & Ed25519LittleEndianEncoding.load_3(s, 0); - long s1 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(s, 2) >> 5); - long s2 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(s, 5) >> 2); - long s3 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(s, 7) >> 7); - long s4 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(s, 10) >> 4); - long s5 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(s, 13) >> 1); - long s6 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(s, 15) >> 6); - long s7 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(s, 18) >> 3); - long s8 = 0x1FFFFF & Ed25519LittleEndianEncoding.load_3(s, 21); - long s9 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(s, 23) >> 5); - long s10 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(s, 26) >> 2); - long s11 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(s, 28) >> 7); - long s12 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(s, 31) >> 4); - long s13 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(s, 34) >> 1); - long s14 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(s, 36) >> 6); - long s15 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(s, 39) >> 3); - long s16 = 0x1FFFFF & Ed25519LittleEndianEncoding.load_3(s, 42); - long s17 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(s, 44) >> 5); - long s18 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(s, 47) >> 2); - long s19 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(s, 49) >> 7); - long s20 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(s, 52) >> 4); - long s21 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(s, 55) >> 1); - long s22 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(s, 57) >> 6); - long s23 = (Ed25519LittleEndianEncoding.load_4(s, 60) >> 3); + long s0 = 0x1FFFFF & load_3(s, 0); + long s1 = 0x1FFFFF & (load_4(s, 2) >> 5); + long s2 = 0x1FFFFF & (load_3(s, 5) >> 2); + long s3 = 0x1FFFFF & (load_4(s, 7) >> 7); + long s4 = 0x1FFFFF & (load_4(s, 10) >> 4); + long s5 = 0x1FFFFF & (load_3(s, 13) >> 1); + long s6 = 0x1FFFFF & (load_4(s, 15) >> 6); + long s7 = 0x1FFFFF & (load_3(s, 18) >> 3); + long s8 = 0x1FFFFF & load_3(s, 21); + long s9 = 0x1FFFFF & (load_4(s, 23) >> 5); + long s10 = 0x1FFFFF & (load_3(s, 26) >> 2); + long s11 = 0x1FFFFF & (load_4(s, 28) >> 7); + long s12 = 0x1FFFFF & (load_4(s, 31) >> 4); + long s13 = 0x1FFFFF & (load_3(s, 34) >> 1); + long s14 = 0x1FFFFF & (load_4(s, 36) >> 6); + long s15 = 0x1FFFFF & (load_3(s, 39) >> 3); + long s16 = 0x1FFFFF & load_3(s, 42); + long s17 = 0x1FFFFF & (load_4(s, 44) >> 5); + long s18 = 0x1FFFFF & (load_3(s, 47) >> 2); + long s19 = 0x1FFFFF & (load_4(s, 49) >> 7); + long s20 = 0x1FFFFF & (load_4(s, 52) >> 4); + long s21 = 0x1FFFFF & (load_3(s, 55) >> 1); + long s22 = 0x1FFFFF & (load_4(s, 57) >> 6); + long s23 = (load_4(s, 60) >> 3); long carry0; long carry1; long carry2; @@ -73,6 +76,21 @@ public byte[] reduce(byte[] s) { long carry15; long carry16; + /** + * Lots of magic numbers :) To understand what's going on below, note that + * + *

    (1) q = 2^252 + q0 where q0 = 27742317777372353535851937790883648493. (2) s11 is the + * coefficient of 2^(11*21), s23 is the coefficient of 2^(^23*21) and 2^252 = 2^((23-11) * 21)). + * (3) 2^252 congruent -q0 modulo q. (4) -q0 = 666643 * 2^0 + 470296 * 2^21 + 654183 * 2^(2*21) + * - 997805 * 2^(3*21) + 136657 * 2^(4*21) - 683901 * 2^(5*21) + * + *

    Thus s23 * 2^(23*11) = s23 * 2^(12*21) * 2^(11*21) = s3 * 2^252 * 2^(11*21) congruent s23 + * * (666643 * 2^0 + 470296 * 2^21 + 654183 * 2^(2*21) - 997805 * 2^(3*21) + 136657 * 2^(4*21) - + * 683901 * 2^(5*21)) * 2^(11*21) modulo q = s23 * (666643 * 2^(11*21) + 470296 * 2^(12*21) + + * 654183 * 2^(13*21) - 997805 * 2^(14*21) + 136657 * 2^(15*21) - 683901 * 2^(16*21)). + * + *

    The same procedure is then applied for s22,...,s18. + */ s11 += s23 * 666643; s12 += s23 * 470296; s13 += s23 * 654183; @@ -127,6 +145,7 @@ public byte[] reduce(byte[] s) { // not used again // s18 = 0; + /** Time to reduce the coefficient in order not to get an overflow. */ carry6 = (s6 + (1 << 20)) >> 21; s7 += carry6; s6 -= carry6 << 21; @@ -162,6 +181,7 @@ public byte[] reduce(byte[] s) { s16 += carry15; s15 -= carry15 << 21; + /** Continue with above procedure. */ s5 += s17 * 666643; s6 += s17 * 470296; s7 += s17 * 654183; @@ -216,6 +236,7 @@ public byte[] reduce(byte[] s) { // set below // s12 = 0; + /** Reduce coefficients again. */ carry0 = (s0 + (1 << 20)) >> 21; s1 += carry0; s0 -= carry0 << 21; @@ -400,42 +421,42 @@ public byte[] reduce(byte[] s) { *

    See the comments in {@link #reduce(byte[])} for an explanation of the algorithm. */ public byte[] multiplyAndAdd(byte[] a, byte[] b, byte[] c) { - long a0 = 0x1FFFFF & Ed25519LittleEndianEncoding.load_3(a, 0); - long a1 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(a, 2) >> 5); - long a2 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(a, 5) >> 2); - long a3 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(a, 7) >> 7); - long a4 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(a, 10) >> 4); - long a5 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(a, 13) >> 1); - long a6 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(a, 15) >> 6); - long a7 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(a, 18) >> 3); - long a8 = 0x1FFFFF & Ed25519LittleEndianEncoding.load_3(a, 21); - long a9 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(a, 23) >> 5); - long a10 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(a, 26) >> 2); - long a11 = (Ed25519LittleEndianEncoding.load_4(a, 28) >> 7); - long b0 = 0x1FFFFF & Ed25519LittleEndianEncoding.load_3(b, 0); - long b1 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(b, 2) >> 5); - long b2 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(b, 5) >> 2); - long b3 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(b, 7) >> 7); - long b4 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(b, 10) >> 4); - long b5 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(b, 13) >> 1); - long b6 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(b, 15) >> 6); - long b7 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(b, 18) >> 3); - long b8 = 0x1FFFFF & Ed25519LittleEndianEncoding.load_3(b, 21); - long b9 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(b, 23) >> 5); - long b10 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(b, 26) >> 2); - long b11 = (Ed25519LittleEndianEncoding.load_4(b, 28) >> 7); - long c0 = 0x1FFFFF & Ed25519LittleEndianEncoding.load_3(c, 0); - long c1 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(c, 2) >> 5); - long c2 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(c, 5) >> 2); - long c3 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(c, 7) >> 7); - long c4 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(c, 10) >> 4); - long c5 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(c, 13) >> 1); - long c6 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(c, 15) >> 6); - long c7 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(c, 18) >> 3); - long c8 = 0x1FFFFF & Ed25519LittleEndianEncoding.load_3(c, 21); - long c9 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_4(c, 23) >> 5); - long c10 = 0x1FFFFF & (Ed25519LittleEndianEncoding.load_3(c, 26) >> 2); - long c11 = (Ed25519LittleEndianEncoding.load_4(c, 28) >> 7); + long a0 = 0x1FFFFF & load_3(a, 0); + long a1 = 0x1FFFFF & (load_4(a, 2) >> 5); + long a2 = 0x1FFFFF & (load_3(a, 5) >> 2); + long a3 = 0x1FFFFF & (load_4(a, 7) >> 7); + long a4 = 0x1FFFFF & (load_4(a, 10) >> 4); + long a5 = 0x1FFFFF & (load_3(a, 13) >> 1); + long a6 = 0x1FFFFF & (load_4(a, 15) >> 6); + long a7 = 0x1FFFFF & (load_3(a, 18) >> 3); + long a8 = 0x1FFFFF & load_3(a, 21); + long a9 = 0x1FFFFF & (load_4(a, 23) >> 5); + long a10 = 0x1FFFFF & (load_3(a, 26) >> 2); + long a11 = (load_4(a, 28) >> 7); + long b0 = 0x1FFFFF & load_3(b, 0); + long b1 = 0x1FFFFF & (load_4(b, 2) >> 5); + long b2 = 0x1FFFFF & (load_3(b, 5) >> 2); + long b3 = 0x1FFFFF & (load_4(b, 7) >> 7); + long b4 = 0x1FFFFF & (load_4(b, 10) >> 4); + long b5 = 0x1FFFFF & (load_3(b, 13) >> 1); + long b6 = 0x1FFFFF & (load_4(b, 15) >> 6); + long b7 = 0x1FFFFF & (load_3(b, 18) >> 3); + long b8 = 0x1FFFFF & load_3(b, 21); + long b9 = 0x1FFFFF & (load_4(b, 23) >> 5); + long b10 = 0x1FFFFF & (load_3(b, 26) >> 2); + long b11 = (load_4(b, 28) >> 7); + long c0 = 0x1FFFFF & load_3(c, 0); + long c1 = 0x1FFFFF & (load_4(c, 2) >> 5); + long c2 = 0x1FFFFF & (load_3(c, 5) >> 2); + long c3 = 0x1FFFFF & (load_4(c, 7) >> 7); + long c4 = 0x1FFFFF & (load_4(c, 10) >> 4); + long c5 = 0x1FFFFF & (load_3(c, 13) >> 1); + long c6 = 0x1FFFFF & (load_4(c, 15) >> 6); + long c7 = 0x1FFFFF & (load_3(c, 18) >> 3); + long c8 = 0x1FFFFF & load_3(c, 21); + long c9 = 0x1FFFFF & (load_4(c, 23) >> 5); + long c10 = 0x1FFFFF & (load_3(c, 26) >> 2); + long c11 = (load_4(c, 28) >> 7); long s0; long s1; long s2; diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/spec/EdDSANamedCurveTable.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/spec/EdDSANamedCurveTable.java index f15c33858..209d9f96c 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/spec/EdDSANamedCurveTable.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/spec/EdDSANamedCurveTable.java @@ -42,6 +42,11 @@ public class EdDSANamedCurveTable { private static volatile HashMap curves = new HashMap<>(); + static { + // RFC 8032 + defineCurve(ED_25519_CURVE_SPEC); + } + private static synchronized void putCurve(String name, EdDSANamedCurveSpec curve) { HashMap newCurves = new HashMap<>(curves); newCurves.put(name, curve); @@ -52,11 +57,6 @@ public static void defineCurve(EdDSANamedCurveSpec curve) { putCurve(curve.getName().toLowerCase(Locale.ENGLISH), curve); } - static { - // RFC 8032 - defineCurve(ED_25519_CURVE_SPEC); - } - public static EdDSANamedCurveSpec getByName(String name) { return curves.get(name.toLowerCase(Locale.ENGLISH)); } diff --git a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/spec/EdDSAParameterSpec.java b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/spec/EdDSAParameterSpec.java index 30dfe3440..e81547f11 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/spec/EdDSAParameterSpec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/authentication/standard/ed25519/spec/EdDSAParameterSpec.java @@ -22,6 +22,7 @@ * * @author str4d */ +@SuppressWarnings("all") public class EdDSAParameterSpec implements AlgorithmParameterSpec, Serializable { private static final long serialVersionUID = 8274987108472012L; private final Curve curve; @@ -60,7 +61,13 @@ public String getHashAlgorithm() { return hashAlgo; } - /** @return the base (generator) */ + public ScalarOps getScalarOps() { + return sc; + } + + /** + * @return the base (generator) + */ public GroupElement getB() { return B; } diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/BigDecimalCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/BigDecimalCodec.java index 01d1fda09..bc475c644 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/BigDecimalCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/BigDecimalCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.IOException; @@ -43,6 +42,21 @@ public class BigDecimalCodec implements Codec { DataType.MEDIUMBLOB, DataType.LONGBLOB); + static BigInteger getBigInteger(ReadableByteBuf buf, ColumnDecoder column) { + BigInteger val; + if (column.isSigned()) { + val = BigInteger.valueOf(buf.readLong()); + } else { + // need BIG ENDIAN, so reverse order + byte[] bb = new byte[8]; + for (int i = 7; i >= 0; i--) { + bb[i] = buf.readByte(); + } + val = new BigInteger(1, bb); + } + return val; + } + public String className() { return BigDecimal.class.getName(); } @@ -196,21 +210,6 @@ public BigDecimal decodeBinary( } } - static BigInteger getBigInteger(ReadableByteBuf buf, ColumnDecoder column) { - BigInteger val; - if (column.isSigned()) { - val = BigInteger.valueOf(buf.readLong()); - } else { - // need BIG ENDIAN, so reverse order - byte[] bb = new byte[8]; - for (int i = 7; i >= 0; i--) { - bb[i] = buf.readByte(); - } - val = new BigInteger(1, bb); - } - return val; - } - @Override public void encodeText(Writer encoder, Context context, Object value, Calendar cal, Long length) throws IOException { diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/BigIntegerCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/BigIntegerCodec.java index fa07f8300..597f33442 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/BigIntegerCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/BigIntegerCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/BitSetCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/BitSetCodec.java index 45855bc5b..b47432b2a 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/BitSetCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/BitSetCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/BlobCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/BlobCodec.java index 3f3107401..852b51dd7 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/BlobCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/BlobCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.ByteArrayOutputStream; diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/BooleanCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/BooleanCodec.java index 9f1eca923..ffe6cf924 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/BooleanCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/BooleanCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/ByteArrayCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/ByteArrayCodec.java index fc9dda8f3..070d98cfa 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/ByteArrayCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/ByteArrayCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/ByteCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/ByteCodec.java index e2a1cbbc1..befec5b10 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/ByteCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/ByteCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/ClobCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/ClobCodec.java index 718abab61..a4f5f6036 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/ClobCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/ClobCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.ByteArrayOutputStream; diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/DateCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/DateCodec.java index f9dceeb55..b8635a22f 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/DateCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/DateCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.IOException; @@ -80,14 +79,23 @@ public void encodeText( @Override public void encodeBinary(Writer encoder, Object value, Calendar providedCal, Long maxLength) throws IOException { - Calendar cal = providedCal == null ? Calendar.getInstance() : providedCal; - synchronized (cal) { + if (providedCal == null) { + Calendar cal = Calendar.getInstance(); cal.clear(); cal.setTimeInMillis(((java.util.Date) value).getTime()); encoder.writeByte(4); // length encoder.writeShort((short) cal.get(Calendar.YEAR)); encoder.writeByte(((cal.get(Calendar.MONTH) + 1) & 0xff)); encoder.writeByte((cal.get(Calendar.DAY_OF_MONTH) & 0xff)); + } else { + synchronized (providedCal) { + providedCal.clear(); + providedCal.setTimeInMillis(((java.util.Date) value).getTime()); + encoder.writeByte(4); // length + encoder.writeShort((short) providedCal.get(Calendar.YEAR)); + encoder.writeByte(((providedCal.get(Calendar.MONTH) + 1) & 0xff)); + encoder.writeByte((providedCal.get(Calendar.DAY_OF_MONTH) & 0xff)); + } } } diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/DoubleCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/DoubleCodec.java index 58fb773dd..d5cca4411 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/DoubleCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/DoubleCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/DurationCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/DurationCodec.java index 5460d0929..b4a23fd18 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/DurationCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/DurationCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import static org.mariadb.jdbc.client.result.Result.NULL_LENGTH; diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/FloatCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/FloatCodec.java index 3976a8172..478845649 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/FloatCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/FloatCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/GeometryCollectionCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/GeometryCollectionCodec.java index ecec9d2cf..ff0c7d21e 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/GeometryCollectionCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/GeometryCollectionCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/InstantCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/InstantCodec.java index cb422f7c1..40acfb46a 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/InstantCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/InstantCodec.java @@ -1,13 +1,11 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.IOException; import java.sql.SQLDataException; import java.time.*; -import java.time.temporal.ChronoField; import java.util.Calendar; import java.util.EnumSet; import org.mariadb.jdbc.client.*; @@ -105,21 +103,21 @@ public void encodeBinary(Writer encoder, Object value, Calendar calParam, Long m int nano = zonedDateTime.getNano(); if (nano > 0) { encoder.writeByte((byte) 11); - encoder.writeShort((short) zonedDateTime.get(ChronoField.YEAR)); - encoder.writeByte(zonedDateTime.get(ChronoField.MONTH_OF_YEAR)); - encoder.writeByte(zonedDateTime.get(ChronoField.DAY_OF_MONTH)); - encoder.writeByte(zonedDateTime.get(ChronoField.HOUR_OF_DAY)); - encoder.writeByte(zonedDateTime.get(ChronoField.MINUTE_OF_HOUR)); - encoder.writeByte(zonedDateTime.get(ChronoField.SECOND_OF_MINUTE)); + encoder.writeShort((short) zonedDateTime.getYear()); + encoder.writeByte(zonedDateTime.getMonth().getValue()); + encoder.writeByte(zonedDateTime.getDayOfMonth()); + encoder.writeByte(zonedDateTime.getHour()); + encoder.writeByte(zonedDateTime.getMinute()); + encoder.writeByte(zonedDateTime.getSecond()); encoder.writeInt(nano / 1000); } else { encoder.writeByte((byte) 7); - encoder.writeShort((short) zonedDateTime.get(ChronoField.YEAR)); - encoder.writeByte(zonedDateTime.get(ChronoField.MONTH_OF_YEAR)); - encoder.writeByte(zonedDateTime.get(ChronoField.DAY_OF_MONTH)); - encoder.writeByte(zonedDateTime.get(ChronoField.HOUR_OF_DAY)); - encoder.writeByte(zonedDateTime.get(ChronoField.MINUTE_OF_HOUR)); - encoder.writeByte(zonedDateTime.get(ChronoField.SECOND_OF_MINUTE)); + encoder.writeShort((short) zonedDateTime.getYear()); + encoder.writeByte(zonedDateTime.getMonthValue()); + encoder.writeByte(zonedDateTime.getDayOfMonth()); + encoder.writeByte(zonedDateTime.getHour()); + encoder.writeByte(zonedDateTime.getMinute()); + encoder.writeByte(zonedDateTime.getSecond()); } } diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/IntCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/IntCodec.java index bb5ab8358..0b39cdc77 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/IntCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/IntCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/LineStringCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/LineStringCodec.java index 4a942c830..106bd7609 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/LineStringCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/LineStringCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/LocalDateCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/LocalDateCodec.java index 55c6ab154..1647af1f9 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/LocalDateCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/LocalDateCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import static org.mariadb.jdbc.client.result.Result.NULL_LENGTH; @@ -10,7 +9,6 @@ import java.sql.SQLDataException; import java.time.LocalDate; import java.time.format.DateTimeFormatter; -import java.time.temporal.ChronoField; import java.util.Calendar; import java.util.EnumSet; import org.mariadb.jdbc.client.*; @@ -276,9 +274,9 @@ public void encodeBinary(Writer encoder, Object value, Calendar providedCal, Lon throws IOException { LocalDate val = (LocalDate) value; encoder.writeByte(7); // length - encoder.writeShort((short) val.get(ChronoField.YEAR)); - encoder.writeByte(val.get(ChronoField.MONTH_OF_YEAR)); - encoder.writeByte(val.get(ChronoField.DAY_OF_MONTH)); + encoder.writeShort((short) val.getYear()); + encoder.writeByte(val.getMonthValue()); + encoder.writeByte(val.getDayOfMonth()); encoder.writeBytes(new byte[] {0, 0, 0}); } diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/LocalDateTimeCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/LocalDateTimeCodec.java index b1d1057b9..64bd62e80 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/LocalDateTimeCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/LocalDateTimeCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import static org.mariadb.jdbc.client.result.Result.NULL_LENGTH; @@ -12,7 +11,6 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; -import java.time.temporal.ChronoField; import java.util.Calendar; import java.util.EnumSet; import org.mariadb.jdbc.client.*; @@ -330,21 +328,21 @@ public void encodeBinary(Writer encoder, Object value, Calendar cal, Long maxLen int nano = val.getNano(); if (nano > 0) { encoder.writeByte((byte) 11); - encoder.writeShort((short) val.get(ChronoField.YEAR)); - encoder.writeByte(val.get(ChronoField.MONTH_OF_YEAR)); - encoder.writeByte(val.get(ChronoField.DAY_OF_MONTH)); - encoder.writeByte(val.get(ChronoField.HOUR_OF_DAY)); - encoder.writeByte(val.get(ChronoField.MINUTE_OF_HOUR)); - encoder.writeByte(val.get(ChronoField.SECOND_OF_MINUTE)); + encoder.writeShort((short) val.getYear()); + encoder.writeByte(val.getMonthValue()); + encoder.writeByte(val.getDayOfMonth()); + encoder.writeByte(val.getHour()); + encoder.writeByte(val.getMinute()); + encoder.writeByte(val.getSecond()); encoder.writeInt(nano / 1000); } else { encoder.writeByte((byte) 7); - encoder.writeShort((short) val.get(ChronoField.YEAR)); - encoder.writeByte(val.get(ChronoField.MONTH_OF_YEAR)); - encoder.writeByte(val.get(ChronoField.DAY_OF_MONTH)); - encoder.writeByte(val.get(ChronoField.HOUR_OF_DAY)); - encoder.writeByte(val.get(ChronoField.MINUTE_OF_HOUR)); - encoder.writeByte(val.get(ChronoField.SECOND_OF_MINUTE)); + encoder.writeShort((short) val.getYear()); + encoder.writeByte(val.getMonthValue()); + encoder.writeByte(val.getDayOfMonth()); + encoder.writeByte(val.getHour()); + encoder.writeByte(val.getMinute()); + encoder.writeByte(val.getSecond()); } } diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/LocalTimeCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/LocalTimeCodec.java index 03e37bf08..be68219b2 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/LocalTimeCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/LocalTimeCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import static org.mariadb.jdbc.client.result.Result.NULL_LENGTH; @@ -12,7 +11,6 @@ import java.time.LocalTime; import java.time.ZoneId; import java.time.format.DateTimeParseException; -import java.time.temporal.ChronoField; import java.util.Calendar; import java.util.EnumSet; import java.util.TimeZone; @@ -316,17 +314,17 @@ public void encodeBinary(Writer encoder, Object value, Calendar cal, Long maxLen encoder.writeByte((byte) 12); encoder.writeByte((byte) 0); encoder.writeInt(0); - encoder.writeByte((byte) val.get(ChronoField.HOUR_OF_DAY)); - encoder.writeByte((byte) val.get(ChronoField.MINUTE_OF_HOUR)); - encoder.writeByte((byte) val.get(ChronoField.SECOND_OF_MINUTE)); + encoder.writeByte((byte) val.getHour()); + encoder.writeByte((byte) val.getMinute()); + encoder.writeByte((byte) val.getSecond()); encoder.writeInt(nano / 1000); } else { encoder.writeByte((byte) 8); encoder.writeByte((byte) 0); encoder.writeInt(0); - encoder.writeByte((byte) val.get(ChronoField.HOUR_OF_DAY)); - encoder.writeByte((byte) val.get(ChronoField.MINUTE_OF_HOUR)); - encoder.writeByte((byte) val.get(ChronoField.SECOND_OF_MINUTE)); + encoder.writeByte((byte) val.getHour()); + encoder.writeByte((byte) val.getMinute()); + encoder.writeByte((byte) val.getSecond()); } } diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/LongCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/LongCodec.java index 9199baa7e..db44913b3 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/LongCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/LongCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/MultiLinestringCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/MultiLinestringCodec.java index ad23a9210..cf403ba95 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/MultiLinestringCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/MultiLinestringCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/MultiPointCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/MultiPointCodec.java index 9fe876fe2..7d2cb6e51 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/MultiPointCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/MultiPointCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/MultiPolygonCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/MultiPolygonCodec.java index 220ed2861..8aae116bd 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/MultiPolygonCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/MultiPolygonCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/OffsetDateTimeCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/OffsetDateTimeCodec.java index 79f454a1f..94e0b5738 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/OffsetDateTimeCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/OffsetDateTimeCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.IOException; @@ -9,7 +8,6 @@ import java.time.LocalDateTime; import java.time.OffsetDateTime; import java.time.ZonedDateTime; -import java.time.temporal.ChronoField; import java.util.Calendar; import java.util.EnumSet; import org.mariadb.jdbc.client.*; @@ -143,21 +141,21 @@ public void encodeBinary(Writer encoder, Object value, Calendar calParam, Long m int nano = convertedZdt.getNano(); if (nano > 0) { encoder.writeByte((byte) 11); - encoder.writeShort((short) convertedZdt.get(ChronoField.YEAR)); - encoder.writeByte(convertedZdt.get(ChronoField.MONTH_OF_YEAR)); - encoder.writeByte(convertedZdt.get(ChronoField.DAY_OF_MONTH)); - encoder.writeByte(convertedZdt.get(ChronoField.HOUR_OF_DAY)); - encoder.writeByte(convertedZdt.get(ChronoField.MINUTE_OF_HOUR)); - encoder.writeByte(convertedZdt.get(ChronoField.SECOND_OF_MINUTE)); + encoder.writeShort((short) convertedZdt.getYear()); + encoder.writeByte(convertedZdt.getMonthValue()); + encoder.writeByte(convertedZdt.getDayOfMonth()); + encoder.writeByte(convertedZdt.getHour()); + encoder.writeByte(convertedZdt.getMinute()); + encoder.writeByte(convertedZdt.getSecond()); encoder.writeInt(nano / 1000); } else { encoder.writeByte((byte) 7); - encoder.writeShort((short) convertedZdt.get(ChronoField.YEAR)); - encoder.writeByte(convertedZdt.get(ChronoField.MONTH_OF_YEAR)); - encoder.writeByte(convertedZdt.get(ChronoField.DAY_OF_MONTH)); - encoder.writeByte(convertedZdt.get(ChronoField.HOUR_OF_DAY)); - encoder.writeByte(convertedZdt.get(ChronoField.MINUTE_OF_HOUR)); - encoder.writeByte(convertedZdt.get(ChronoField.SECOND_OF_MINUTE)); + encoder.writeShort((short) convertedZdt.getYear()); + encoder.writeByte(convertedZdt.getMonthValue()); + encoder.writeByte(convertedZdt.getDayOfMonth()); + encoder.writeByte(convertedZdt.getHour()); + encoder.writeByte(convertedZdt.getMinute()); + encoder.writeByte(convertedZdt.getSecond()); } } diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/PointCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/PointCodec.java index d356c8120..734d9da1d 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/PointCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/PointCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/PolygonCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/PolygonCodec.java index fac094439..76ce76b4c 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/PolygonCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/PolygonCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/ReaderCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/ReaderCodec.java index 38d5d8e1a..9b2ea70db 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/ReaderCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/ReaderCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.*; diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/ShortCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/ShortCodec.java index 217096557..323bf5050 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/ShortCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/ShortCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/StreamCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/StreamCodec.java index 829e4d4c0..b056cab08 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/StreamCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/StreamCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.*; diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/StringCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/StringCodec.java index b42d34e01..fa6f00019 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/StringCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/StringCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.IOException; diff --git a/src/main/java/org/mariadb/jdbc/plugin/codec/TimeCodec.java b/src/main/java/org/mariadb/jdbc/plugin/codec/TimeCodec.java index 4d4ebf199..78a72077c 100644 --- a/src/main/java/org/mariadb/jdbc/plugin/codec/TimeCodec.java +++ b/src/main/java/org/mariadb/jdbc/plugin/codec/TimeCodec.java @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (c) 2012-2014 Monty Program Ab // Copyright (c) 2015-2023 MariaDB Corporation Ab - package org.mariadb.jdbc.plugin.codec; import java.io.IOException; @@ -21,6 +20,7 @@ public class TimeCodec implements Codec