From 9071db4be4d51f7a4042e7fb81704f490e90cf38 Mon Sep 17 00:00:00 2001 From: Yuriy Movchan Date: Wed, 26 Jan 2022 14:41:51 +0300 Subject: [PATCH] feat: support MySQL with MariaDB engine gluu #18 (#712) --- .gitignore | 1 + .../operation/impl/SqlConnectionProvider.java | 52 ++++++++++++++++--- .../impl/SqlOperationServiceImpl.java | 32 ++++++++---- 3 files changed, 68 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index fe51cf420cc..19ea6519177 100644 --- a/.gitignore +++ b/.gitignore @@ -147,3 +147,4 @@ PyCharm # Mac .DS_STORE tmp +/.metadata/ diff --git a/jans-orm/sql/src/main/java/io/jans/orm/sql/operation/impl/SqlConnectionProvider.java b/jans-orm/sql/src/main/java/io/jans/orm/sql/operation/impl/SqlConnectionProvider.java index c907ba9e58f..0380c672ee0 100644 --- a/jans-orm/sql/src/main/java/io/jans/orm/sql/operation/impl/SqlConnectionProvider.java +++ b/jans-orm/sql/src/main/java/io/jans/orm/sql/operation/impl/SqlConnectionProvider.java @@ -8,14 +8,17 @@ import java.sql.Connection; import java.sql.DatabaseMetaData; +import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; +import java.util.Set; import org.apache.commons.dbcp2.ConnectionFactory; import org.apache.commons.dbcp2.DriverManagerConnectionFactory; @@ -52,7 +55,12 @@ */ public class SqlConnectionProvider { - private static final Logger LOG = LoggerFactory.getLogger(SqlConnectionProvider.class); + private static final String JSON_TYPE_NAME = "json"; + + private static final Logger LOG = LoggerFactory.getLogger(SqlConnectionProvider.class); + + private static final String QUERY_ENGINE_TYPE = + "SELECT TABLE_NAME, ENGINE FROM information_schema.tables WHERE table_schema = ?"; private static final String DRIVER_PROPERTIES_PREFIX = "connection.driver-property"; @@ -78,6 +86,7 @@ public class SqlConnectionProvider { private SQLQueryFactory sqlQueryFactory; private Map> tableColumnsMap; + private Map tableEnginesMap = new HashMap<>(); protected SqlConnectionProvider() { } @@ -184,27 +193,48 @@ protected void init() throws Exception { DatabaseMetaData databaseMetaData = con.getMetaData(); this.dbType = databaseMetaData.getDatabaseProductName().toLowerCase(); LOG.debug("Database product name: '{}'", dbType); - loadTableMetaData(databaseMetaData); + loadTableMetaData(databaseMetaData, con); } catch (Exception ex) { - throw new ConnectionException("Failed to detect database product name", ex); + throw new ConnectionException("Failed to detect database product name and load metadata", ex); } this.creationResultCode = ResultCode.SUCCESS_INT_VALUE; } - private void loadTableMetaData(DatabaseMetaData databaseMetaData) throws SQLException { - LOG.info("Scanning DB metadata..."); - + private void loadTableMetaData(DatabaseMetaData databaseMetaData, Connection con) throws SQLException { long takes = System.currentTimeMillis(); - ResultSet tableResultSet = databaseMetaData.getTables(null, schemaName, null, new String[]{"TABLE"}); + + LOG.info("Detecting engine types..."); + PreparedStatement preparedStatement = con.prepareStatement(QUERY_ENGINE_TYPE); + preparedStatement.setString(1, schemaName); + + ResultSet tableEnginesResultSet = preparedStatement.executeQuery(); + while (tableEnginesResultSet.next()) { + String tableName = tableEnginesResultSet.getString("TABLE_NAME"); + String engineName = tableEnginesResultSet.getString("ENGINE"); + + tableEnginesMap.put(tableName, engineName); + } + + LOG.info("Scanning DB metadata..."); + ResultSet tableResultSet = databaseMetaData.getTables(null, schemaName, null, new String[]{"TABLE"}); while (tableResultSet.next()) { String tableName = tableResultSet.getString("TABLE_NAME"); Map tableColumns = new HashMap<>(); + String engineType = tableEnginesMap.get(tableName); + LOG.debug("Found table: '{}'.", tableName); ResultSet columnResultSet = databaseMetaData.getColumns(null, schemaName, tableName, null); while (columnResultSet.next()) { - tableColumns.put(columnResultSet.getString("COLUMN_NAME").toLowerCase(), columnResultSet.getString("TYPE_NAME").toLowerCase()); + String columnName = columnResultSet.getString("COLUMN_NAME").toLowerCase(); + String columTypeName = columnResultSet.getString("TYPE_NAME").toLowerCase(); + + String remark = columnResultSet.getString("REMARKS"); + if ("mariadb".equalsIgnoreCase(engineType) && "longtext".equalsIgnoreCase(columTypeName) && "json".equalsIgnoreCase(remark)) { + columTypeName = JSON_TYPE_NAME; + } + tableColumns.put(columnName, columTypeName); } tableColumnsMap.put(tableName, tableColumns); @@ -374,6 +404,12 @@ public TableMapping getTableMappingByKey(String key, String objectClass) { return tableMapping; } + public String getEngineType(String objectClass) { + String tableName = objectClass; + + return tableEnginesMap.get(tableName); + } + public Connection getConnection() { try { return this.poolingDataSource.getConnection(); diff --git a/jans-orm/sql/src/main/java/io/jans/orm/sql/operation/impl/SqlOperationServiceImpl.java b/jans-orm/sql/src/main/java/io/jans/orm/sql/operation/impl/SqlOperationServiceImpl.java index c3d0d870028..506131114d5 100644 --- a/jans-orm/sql/src/main/java/io/jans/orm/sql/operation/impl/SqlOperationServiceImpl.java +++ b/jans-orm/sql/src/main/java/io/jans/orm/sql/operation/impl/SqlOperationServiceImpl.java @@ -179,7 +179,7 @@ private boolean addEntryImpl(TableMapping tableMapping, String key, Collection lookupImpl(TableMapping tableMapping, String key, St .where(whereExp).limit(1); try (ResultSet resultSet = sqlSelectQuery.getResults();) { - List result = getAttributeDataList(resultSet, true); + List result = getAttributeDataList(tableMapping, resultSet, true); if (result != null) { return result; } @@ -441,7 +441,7 @@ private PagedResult searchImpl(TableMapping tableMapping, String LOG.debug("Executing query: '" + queryStr + "'"); try (ResultSet resultSet = query.getResults()) { - lastResult = getEntryDataList(resultSet); + lastResult = getEntryDataList(tableMapping, resultSet); } lastCountRows = lastResult.size(); @@ -484,7 +484,7 @@ private PagedResult searchImpl(TableMapping tableMapping, String LOG.debug("Execution query: '" + queryStr + "'"); try (ResultSet resultSet = query.getResults()) { - lastResult = getEntryDataList(resultSet); + lastResult = getEntryDataList(tableMapping, resultSet); searchResultList.addAll(lastResult); } } catch (QueryException ex) { @@ -551,7 +551,7 @@ public String[] createStoragePassword(String[] passwords) { return results; } - private List getAttributeDataList(ResultSet resultSet, boolean skipDn) throws EntryConvertationException { + private List getAttributeDataList(TableMapping tableMapping, ResultSet resultSet, boolean skipDn) throws EntryConvertationException { try { if ((resultSet == null)) { return null; @@ -593,7 +593,7 @@ private List getAttributeDataList(ResultSet resultSet, boolean sk continue; } } else { - if ("json".equals(columnTypeName)) { + if (isJsonColumn(tableMapping.getTableName(), columnTypeName)) { attributeValueObjects = convertDbJsonToValue(attributeObject.toString()); multiValued = Boolean.TRUE; } else if (attributeObject instanceof Integer) { @@ -641,12 +641,12 @@ private List getAttributeDataList(ResultSet resultSet, boolean sk } } - private List getEntryDataList(ResultSet resultSet) throws EntryConvertationException, SQLException { + private List getEntryDataList(TableMapping tableMapping, ResultSet resultSet) throws EntryConvertationException, SQLException { List entryDataList = new LinkedList<>(); List attributeDataList = null; while (!resultSet.isLast()) { - attributeDataList = getAttributeDataList(resultSet, false); + attributeDataList = getAttributeDataList(tableMapping, resultSet, false); if (attributeDataList == null) { break; } @@ -869,4 +869,18 @@ private Object[] convertDbJsonToValue(String jsonValue) { } } + private boolean isJsonColumn(String tableName, String columnTypeName) { + if (columnTypeName == null) { + return false; + } + +// String engineType = connectionProvider.getEngineType(tableName); +// if ((engineType != null) && engineType.equalsIgnoreCase("mariadb")) { +// return "longtext".equals(columnTypeName); +// } + + return "json".equals(columnTypeName); + + } + }