diff --git a/full/src/main/java/apoc/load/Jdbc.java b/full/src/main/java/apoc/load/Jdbc.java index f7d10e1ff5..d71d2c5302 100644 --- a/full/src/main/java/apoc/load/Jdbc.java +++ b/full/src/main/java/apoc/load/Jdbc.java @@ -281,7 +281,8 @@ private Object convert(Object value, int sqlType) { ZoneId zoneId = config.getZoneId(); if (Types.TIMESTAMP == sqlType) { if (zoneId != null) { - return ((java.sql.Timestamp)value).toInstant() + return ((java.sql.Timestamp) value) + .toInstant() .atZone(zoneId) .toOffsetDateTime(); } else { @@ -290,7 +291,8 @@ private Object convert(Object value, int sqlType) { } if (Types.TIMESTAMP_WITH_TIMEZONE == sqlType) { if (zoneId != null) { - return ((java.sql.Timestamp)value).toInstant() + return ((java.sql.Timestamp) value) + .toInstant() .atZone(zoneId) .toOffsetDateTime(); } else { diff --git a/core/src/main/java/apoc/load/util/JdbcUtil.java b/full/src/main/java/apoc/load/util/JdbcUtil.java similarity index 79% rename from core/src/main/java/apoc/load/util/JdbcUtil.java rename to full/src/main/java/apoc/load/util/JdbcUtil.java index fe10c08604..b6ff935de7 100644 --- a/core/src/main/java/apoc/load/util/JdbcUtil.java +++ b/full/src/main/java/apoc/load/util/JdbcUtil.java @@ -18,26 +18,18 @@ */ package apoc.load.util; -import us.fatehi.utility.datasource.DatabaseConnectionSource; -import us.fatehi.utility.datasource.DatabaseConnectionSources; -import us.fatehi.utility.datasource.MultiUseUserCredentials; - -import javax.security.auth.Subject; -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.NameCallback; -import javax.security.auth.callback.PasswordCallback; -import javax.security.auth.login.LoginContext; import apoc.util.Util; import java.net.URI; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; -import java.sql.Connection; -import java.sql.DriverManager; import javax.security.auth.Subject; import javax.security.auth.callback.Callback; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.login.LoginContext; +import us.fatehi.utility.datasource.DatabaseConnectionSource; +import us.fatehi.utility.datasource.DatabaseConnectionSources; +import us.fatehi.utility.datasource.MultiUseUserCredentials; public class JdbcUtil { @@ -47,8 +39,11 @@ public class JdbcUtil { private JdbcUtil() {} public static DatabaseConnectionSource getConnection(String jdbcUrl, LoadJdbcConfig config) throws Exception { - if(config.hasCredentials()) { - return createConnection(jdbcUrl, config.getCredentials().getUser(), config.getCredentials().getPassword()); + if (config.hasCredentials()) { + return createConnection( + jdbcUrl, + config.getCredentials().getUser(), + config.getCredentials().getPassword()); } else { URI uri = new URI(jdbcUrl.substring("jdbc:".length())); String userInfo = uri.getUserInfo(); @@ -58,11 +53,12 @@ public static DatabaseConnectionSource getConnection(String jdbcUrl, LoadJdbcCon String[] user = userInfo.split(":"); return createConnection(cleanUrl, user[0], user[1]); } - return DriverManager.getConnection(jdbcUrl); + return DatabaseConnectionSources.newDatabaseConnectionSource(jdbcUrl, new MultiUseUserCredentials()); } } - private static Connection createConnection(String jdbcUrl, String userName, String password) throws Exception { + private static DatabaseConnectionSource createConnection(String jdbcUrl, String userName, String password) + throws Exception { if (jdbcUrl.contains(";auth=kerberos")) { String client = System.getProperty("java.security.auth.login.config.client", "KerberosClient"); LoginContext lc = new LoginContext(client, callbacks -> { @@ -74,12 +70,15 @@ private static Connection createConnection(String jdbcUrl, String userName, Stri lc.login(); Subject subject = lc.getSubject(); try { - return Subject.doAs(subject, (PrivilegedExceptionAction) () -> DatabaseConnectionSources.newDatabaseConnectionSource(jdbcUrl, new MultiUseUserCredentials(userName, password))); + return Subject.doAs(subject, (PrivilegedExceptionAction) + () -> DatabaseConnectionSources.newDatabaseConnectionSource( + jdbcUrl, new MultiUseUserCredentials(userName, password))); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { - return DriverManager.getConnection(jdbcUrl, userName, password); + return DatabaseConnectionSources.newDatabaseConnectionSource( + jdbcUrl, new MultiUseUserCredentials(userName, password)); } } diff --git a/core/src/main/java/apoc/load/util/LoadJdbcConfig.java b/full/src/main/java/apoc/load/util/LoadJdbcConfig.java similarity index 100% rename from core/src/main/java/apoc/load/util/LoadJdbcConfig.java rename to full/src/main/java/apoc/load/util/LoadJdbcConfig.java diff --git a/full/src/main/java/apoc/model/Model.java b/full/src/main/java/apoc/model/Model.java index 7febf5364c..541e3226ef 100644 --- a/full/src/main/java/apoc/model/Model.java +++ b/full/src/main/java/apoc/model/Model.java @@ -36,8 +36,7 @@ import schemacrawler.schema.*; import schemacrawler.schemacrawler.SchemaCrawlerOptions; import schemacrawler.schemacrawler.SchemaCrawlerOptionsBuilder; -import schemacrawler.schemacrawler.SchemaInfoLevelBuilder; -import schemacrawler.utility.SchemaCrawlerUtility; +import schemacrawler.tools.utility.SchemaCrawlerUtility; @Extended public class Model { diff --git a/full/src/test/java/apoc/load/MySQLJdbcTest.java b/full/src/test/java/apoc/load/MySQLJdbcTest.java index 4e8150e0b5..51c6dde248 100644 --- a/full/src/test/java/apoc/load/MySQLJdbcTest.java +++ b/full/src/test/java/apoc/load/MySQLJdbcTest.java @@ -2,10 +2,15 @@ import static apoc.util.TestUtil.testCall; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import apoc.util.MySQLContainerExtension; import apoc.util.TestUtil; import apoc.util.Util; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZonedDateTime; import java.util.Map; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -16,37 +21,29 @@ import org.neo4j.test.rule.DbmsRule; import org.neo4j.test.rule.ImpermanentDbmsRule; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.ZonedDateTime; -import java.util.Map; - -import static apoc.util.TestUtil.testCall; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - @RunWith(Enclosed.class) public class MySQLJdbcTest extends AbstractJdbcTest { - + public static class MySQLJdbcLatestVersionTest { - + @ClassRule public static MySQLContainerExtension mysql = new MySQLContainerExtension("mysql:8.0.31"); @ClassRule public static DbmsRule db = new ImpermanentDbmsRule(); - + @BeforeClass public static void setUpContainer() { mysql.start(); TestUtil.registerProcedure(db, Jdbc.class); } + @AfterClass public static void tearDown() { mysql.stop(); db.shutdown(); } + @Test public void testLoadJdbc() { MySQLJdbcTest.testLoadJdbc(db, mysql); @@ -57,9 +54,9 @@ public void testIssue3496() { MySQLJdbcTest.testIssue3496(db, mysql); } } - + public static class MySQLJdbcFiveVersionTest { - + @ClassRule public static MySQLContainerExtension mysql = new MySQLContainerExtension("mysql:5.7"); @@ -90,34 +87,58 @@ public void testIssue3496() { } private static void testLoadJdbc(DbmsRule db, MySQLContainerExtension mysql) { - // with the config {timezone: 'UTC'} and `preserveInstants=true&connectionTimeZone=SERVER` to make the result deterministic, - // since `TIMESTAMP` values are automatically converted from the session time zone to UTC for storage, and vice versa. - testCall(db, "CALL apoc.load.jdbc($url, $table, [], {timezone: 'UTC'})", + // with the config {timezone: 'UTC'} and `preserveInstants=true&connectionTimeZone=SERVER` to make the result + // deterministic, + // since `TIMESTAMP` values are automatically converted from the session time zone to UTC for storage, and vice + // versa. + testCall( + db, + "CALL apoc.load.jdbc($url, $table, [], {timezone: 'UTC'})", Util.map( - "url", mysql.getJdbcUrl() + "&preserveInstants=true&connectionTimeZone=SERVER", - "table", "country"), + "url", + mysql.getJdbcUrl() + "&preserveInstants=true&connectionTimeZone=SERVER", + "table", + "country"), row -> { Map expected = Util.map( - "Code", "NLD", - "Name", "Netherlands", - "Continent", "Europe", - "Region", "Western Europe", - "SurfaceArea", 41526f, - "IndepYear", 1581, - "Population", 15864000, - "LifeExpectancy", 78.3f, - "GNP", 371362f, - "GNPOld", 360478f, - "LocalName", "Nederland", - "GovernmentForm", "Constitutional Monarchy", - "HeadOfState", "Beatrix", - "Capital", 5, - "Code2", "NL", - "myTime", LocalTime.of(1, 0, 0), - "myTimeStamp", ZonedDateTime.parse("2003-01-01T01:00Z"), - "myDate", LocalDate.parse("2003-01-01"), - "myYear", LocalDate.parse("2003-01-01") - ); + "Code", + "NLD", + "Name", + "Netherlands", + "Continent", + "Europe", + "Region", + "Western Europe", + "SurfaceArea", + 41526f, + "IndepYear", + 1581, + "Population", + 15864000, + "LifeExpectancy", + 78.3f, + "GNP", + 371362f, + "GNPOld", + 360478f, + "LocalName", + "Nederland", + "GovernmentForm", + "Constitutional Monarchy", + "HeadOfState", + "Beatrix", + "Capital", + 5, + "Code2", + "NL", + "myTime", + LocalTime.of(1, 0, 0), + "myTimeStamp", + ZonedDateTime.parse("2003-01-01T01:00Z"), + "myDate", + LocalDate.parse("2003-01-01"), + "myYear", + LocalDate.parse("2003-01-01")); Map actual = (Map) row.get("row"); Object myDateTime = actual.remove("myDateTime"); assertTrue(myDateTime instanceof LocalDateTime); @@ -126,22 +147,24 @@ private static void testLoadJdbc(DbmsRule db, MySQLContainerExtension mysql) { } private static void testIssue3496(DbmsRule db, MySQLContainerExtension mysql) { - testCall(db, "CALL apoc.load.jdbc($url,'SELECT DATE(NOW()), NOW(), CURDATE(), CURTIME(), UTC_DATE(), UTC_TIME(), UTC_TIMESTAMP(), DATE(UTC_TIMESTAMP());')", + testCall( + db, + "CALL apoc.load.jdbc($url,'SELECT DATE(NOW()), NOW(), CURDATE(), CURTIME(), UTC_DATE(), UTC_TIME(), UTC_TIMESTAMP(), DATE(UTC_TIMESTAMP());')", Util.map("url", mysql.getJdbcUrl()), r -> { Map row = (Map) r.get("row"); assertEquals(8, row.size()); - + assertTrue(row.get("UTC_DATE()") instanceof LocalDate); assertTrue(row.get("CURDATE()") instanceof LocalDate); - + assertTrue(row.get("UTC_TIMESTAMP()") instanceof LocalDateTime); assertTrue(row.get("NOW()") instanceof LocalDateTime); assertTrue(row.get("DATE(UTC_TIMESTAMP())") instanceof LocalDate); assertTrue(row.get("DATE(NOW())") instanceof LocalDate); - + assertTrue(row.get("CURTIME()") instanceof LocalTime); assertTrue(row.get("UTC_TIME()") instanceof LocalTime); }); } -} \ No newline at end of file +} diff --git a/full/src/test/java/apoc/model/ModelTest.java b/full/src/test/java/apoc/model/ModelTest.java index 9aef8c691f..e281503ba7 100644 --- a/full/src/test/java/apoc/model/ModelTest.java +++ b/full/src/test/java/apoc/model/ModelTest.java @@ -126,8 +126,27 @@ public void testLoadJdbcSchema() { assertEquals(29, columns.size()); List countryNodes = filterColumnsByTableName(columns, "country"); - List expectedCountryCols = Arrays.asList("Code", "Name", "Continent", "Region", "SurfaceArea", "IndepYear", "Population", "LifeExpectancy", "GNP", "GNPOld", "LocalName", "GovernmentForm", "HeadOfState", "Capital", "Code2", - "myTime", "myDateTime", "myTimeStamp", "myDate", "myYear"); + List expectedCountryCols = Arrays.asList( + "Code", + "Name", + "Continent", + "Region", + "SurfaceArea", + "IndepYear", + "Population", + "LifeExpectancy", + "GNP", + "GNPOld", + "LocalName", + "GovernmentForm", + "HeadOfState", + "Capital", + "Code2", + "myTime", + "myDateTime", + "myTimeStamp", + "myDate", + "myYear"); assertEquals(expectedCountryCols, countryNodes); List cityNodes = filterColumnsByTableName(columns, "city"); @@ -195,8 +214,27 @@ public void testLoadJdbcSchemaWithWriteOperation() { assertEquals(29, columns.size()); List countryNodes = filterColumnsByTableName(columns, "country"); - List expectedCountryCols = Arrays.asList("Code", "Name", "Continent", "Region", "SurfaceArea", "IndepYear", "Population", "LifeExpectancy", "GNP", "GNPOld", "LocalName", "GovernmentForm", "HeadOfState", "Capital", "Code2", - "myTime", "myDateTime", "myTimeStamp", "myDate", "myYear"); + List expectedCountryCols = Arrays.asList( + "Code", + "Name", + "Continent", + "Region", + "SurfaceArea", + "IndepYear", + "Population", + "LifeExpectancy", + "GNP", + "GNPOld", + "LocalName", + "GovernmentForm", + "HeadOfState", + "Capital", + "Code2", + "myTime", + "myDateTime", + "myTimeStamp", + "myDate", + "myYear"); assertEquals(expectedCountryCols, countryNodes); List cityNodes = filterColumnsByTableName(columns, "city");