From 32a3ec43a137c7de807aeda14aeb8df90019dd06 Mon Sep 17 00:00:00 2001 From: Markus Spann Date: Thu, 21 Mar 2024 10:51:55 +0100 Subject: [PATCH] Review and fix Sonarcloud findings --- .../java/net/ucanaccess/console/Main.java | 3 +- .../net/ucanaccess/converters/Functions.java | 5 +- .../net/ucanaccess/converters/Metadata.java | 30 +++--- .../java/net/ucanaccess/converters/Pivot.java | 20 ++-- .../ucanaccess/converters/SQLConverter.java | 101 ++++++++---------- .../exception/UcanaccessSQLException.java | 4 +- .../java/net/ucanaccess/jdbc/DBReference.java | 8 +- .../ucanaccess/jdbc/UcanaccessConnection.java | 7 +- .../net/ucanaccess/jdbc/UcanaccessDriver.java | 28 ++--- .../jdbc/UcanaccessPreparedStatement.java | 3 + src/main/java/net/ucanaccess/util/Try.java | 22 ++-- .../net/ucanaccess/jdbc/NotNullDdlTest.java | 2 +- 12 files changed, 109 insertions(+), 124 deletions(-) diff --git a/src/main/java/net/ucanaccess/console/Main.java b/src/main/java/net/ucanaccess/console/Main.java index c73fbc9f..fefd5a60 100644 --- a/src/main/java/net/ucanaccess/console/Main.java +++ b/src/main/java/net/ucanaccess/console/Main.java @@ -278,7 +278,6 @@ private void executeExport(String cmd) throws SQLException, IOException { // Process the command line flags. int i = 1; // skip the first token which will always be "export" - label: for (; i < tokens.size(); i++) { String arg = tokens.get(i); if (!arg.startsWith("-")) { @@ -323,7 +322,7 @@ private void executeExport(String cmd) throws SQLException, IOException { return; case "--": ++i; - break label; + break; default: prompt("Unknown flag " + arg); prompt(EXPORT_PROMPT); diff --git a/src/main/java/net/ucanaccess/converters/Functions.java b/src/main/java/net/ucanaccess/converters/Functions.java index 9d55a925..2152e3ff 100644 --- a/src/main/java/net/ucanaccess/converters/Functions.java +++ b/src/main/java/net/ucanaccess/converters/Functions.java @@ -11,6 +11,8 @@ import net.ucanaccess.ext.FunctionType; import net.ucanaccess.util.Try; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; @@ -28,6 +30,7 @@ import java.util.regex.Pattern; public final class Functions { + private static final Logger LOGGER = System.getLogger(Functions.class.getName()); private static Double rnd; private static Double lastRnd; private static final double APPROX = 0.00000001; @@ -547,7 +550,7 @@ private static Timestamp dateValue(String _dt, boolean _onlyDate) { } return t; } catch (ParseException _ignored) { - continue; + LOGGER.log(Level.DEBUG, "Ignoring {0}", _ignored.toString()); } } return null; diff --git a/src/main/java/net/ucanaccess/converters/Metadata.java b/src/main/java/net/ucanaccess/converters/Metadata.java index c42f6899..54b7a617 100644 --- a/src/main/java/net/ucanaccess/converters/Metadata.java +++ b/src/main/java/net/ucanaccess/converters/Metadata.java @@ -7,6 +7,8 @@ import net.ucanaccess.type.ObjectType; import net.ucanaccess.util.Try; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import java.sql.*; import java.util.ArrayList; import java.util.Arrays; @@ -15,6 +17,8 @@ public class Metadata { + private static final Logger LOGGER = System.getLogger(Metadata.class.getName()); + private static final String SCHEMA = "CREATE SCHEMA UCA_METADATA AUTHORIZATION DBA"; private static final String TABLES = @@ -233,7 +237,7 @@ public void newColumn(String _name, String _escaped, String _originalType, Integ ps.setInt(4, _idTable); ps.executeUpdate(); } catch (SQLException _ignored) { - return; + LOGGER.log(Level.DEBUG, "Ignoring {0}", _ignored.toString()); } } @@ -246,7 +250,7 @@ public List getColumnNames(String _tableName) throws SQLException { result.add(rs.getString(COLUMN_NAME)); } return !SYSTEM_SUBQUERY.equals(_tableName) ? result : null; - }).orThrow(); + }).orThrow(ex -> ex); } public String getColumnName(String _escapedTableName, String _escapedColumnName) throws SQLException { @@ -261,7 +265,7 @@ public String getColumnName(String _escapedTableName, String _escapedColumnName) } } return null; - }).orThrow(); + }).orThrow(ex -> ex); } public String getEscapedColumnName(String _tableName, String _columnName) throws SQLException { @@ -270,7 +274,7 @@ public String getEscapedColumnName(String _tableName, String _columnName) throws ps.setString(2, _columnName); ResultSet rs = ps.executeQuery(); return rs.next() ? rs.getString(ESCAPED_COLUMN_NAME) : null; - }).orThrow(); + }).orThrow(ex -> ex); } public String getEscapedTableName(String _tableName) throws SQLException { @@ -278,7 +282,7 @@ public String getEscapedTableName(String _tableName) throws SQLException { ps.setString(1, _tableName); ResultSet rs = ps.executeQuery(); return rs.next() ? rs.getString(ESCAPED_TABLE_NAME) : null; - }).orThrow(); + }).orThrow(ex -> ex); } public boolean isAutoIncrement(String _tableName, String _columnName) throws SQLException { @@ -287,7 +291,7 @@ public boolean isAutoIncrement(String _tableName, String _columnName) throws SQL ps.setString(2, _columnName); ResultSet rs = ps.executeQuery(); return rs.next() && rs.getBoolean(IS_AUTOINCREMENT); - }).orThrow(); + }).orThrow(ex -> ex); } public boolean isCurrency(String _tableName, String _columnName) throws SQLException { @@ -296,7 +300,7 @@ public boolean isCurrency(String _tableName, String _columnName) throws SQLExcep ps.setString(2, _columnName); ResultSet rs = ps.executeQuery(); return rs.next() && rs.getBoolean(IS_CURRENCY); - }).orThrow(); + }).orThrow(ex -> ex); } public Integer getTableId(String _escapedName) throws SQLException { @@ -304,7 +308,7 @@ public Integer getTableId(String _escapedName) throws SQLException { ps.setString(1, _escapedName); ResultSet rs = ps.executeQuery(); return rs.next() ? rs.getInt(TABLE_ID) : -1; - }).orThrow(); + }).orThrow(ex -> ex); } public String getTableName(String _escapedName) throws SQLException { @@ -312,14 +316,14 @@ public String getTableName(String _escapedName) throws SQLException { ps.setString(1, _escapedName); ResultSet rs = ps.executeQuery(); return rs.next() ? rs.getString(TABLE_NAME) : null; - }).orThrow(); + }).orThrow(ex -> ex); } public void dropTable(String _tableName) throws SQLException { Try.withResources(() -> conn.prepareStatement(DROP_TABLE), ps -> { ps.setString(1, _tableName); ps.execute(); - }).orThrow(); + }).orThrow(ex -> ex); } public void columnDef(String _tableName, String _columnName, String _def) throws SQLException { @@ -328,7 +332,7 @@ public void columnDef(String _tableName, String _columnName, String _def) throws ps.setString(2, _columnName); ps.setString(3, _tableName); ps.execute(); - }).orThrow(); + }).orThrow(ex -> ex); } public void calculatedField(String _tableName, String _columnName) throws SQLException { @@ -336,7 +340,7 @@ public void calculatedField(String _tableName, String _columnName) throws SQLExc ps.setString(1, _columnName); ps.setString(2, _tableName); ps.execute(); - }).orThrow(); + }).orThrow(ex -> ex); } public void rename(String _oldTableName, String _newTableName, String _newEscapedTableName) throws SQLException { @@ -345,7 +349,7 @@ public void rename(String _oldTableName, String _newTableName, String _newEscape ps.setString(2, _newEscapedTableName); ps.setString(3, _oldTableName); ps.executeUpdate(); - }).orThrow(); + }).orThrow(ex -> ex); } } diff --git a/src/main/java/net/ucanaccess/converters/Pivot.java b/src/main/java/net/ucanaccess/converters/Pivot.java index 02e9d2fc..17eb0343 100644 --- a/src/main/java/net/ucanaccess/converters/Pivot.java +++ b/src/main/java/net/ucanaccess/converters/Pivot.java @@ -31,7 +31,7 @@ public class Pivot { private String select; private String from; private String expression; - private String pivot; + private String pivotStr; private List pivotIn; private String aggregateFun; private final Connection conn; @@ -135,15 +135,15 @@ public boolean parsePivot(String _originalQuery) { select = mtc.group(2); from = mtc.group(3); String pe = mtc.group(4); - Matcher mtcExpr = PIVOT_EXPR_PATT.matcher(pe); - if (mtcExpr.find()) { - if (mtcExpr.groupCount() < 2) { + Matcher matcher = PIVOT_EXPR_PATT.matcher(pe); + if (matcher.find()) { + if (matcher.groupCount() < 2) { return false; } - pivot = mtcExpr.group(1); - pivotIn = Arrays.asList(mtcExpr.group(2).split(",")); + pivotStr = matcher.group(1); + pivotIn = Arrays.asList(matcher.group(2).split(",")); } else { - pivot = pe; + pivotStr = pe; } return true; } else { @@ -159,8 +159,8 @@ private void appendCaseWhen(StringBuilder _sb, String _condition, String _cn) { public String verifySQL() { StringBuilder sb = new StringBuilder(); String[] fromS = from.split(PIVOT_GROUP_BY); - sb.append("SELECT DISTINCT ").append(pivot).append(" AS PIVOT ") - .append(" FROM ").append(fromS[0]).append(" GROUP BY ").append(pivot).append(",").append(fromS[1]); + sb.append("SELECT DISTINCT ").append(pivotStr).append(" AS PIVOT ") + .append(" FROM ").append(fromS[0]).append(" GROUP BY ").append(pivotStr).append(",").append(fromS[1]); return SQLConverter.convertSQL(sb.toString()).getSql(); } @@ -230,7 +230,7 @@ public String toSQL(String name) { .append(select); for (String s : pivotIn) { sb.append(","); - appendCaseWhen(sb, pivot + "=" + s, replaceQuotation(s)); + appendCaseWhen(sb, pivotStr + "=" + s, replaceQuotation(s)); } sb.append(" FROM ").append(from); diff --git a/src/main/java/net/ucanaccess/converters/SQLConverter.java b/src/main/java/net/ucanaccess/converters/SQLConverter.java index 88afa771..6e15bd82 100644 --- a/src/main/java/net/ucanaccess/converters/SQLConverter.java +++ b/src/main/java/net/ucanaccess/converters/SQLConverter.java @@ -16,48 +16,45 @@ public final class SQLConverter { private static final Pattern QUOTE_S_PATTERN = Pattern.compile("(')+"); private static final Pattern DOUBLE_QUOTE_S_PATTERN = Pattern.compile("(\")+"); - private static final Pattern SELECT_FROM_PATTERN_START = Pattern.compile("\\s*(?i)SELECT\\s+"); - private static final Pattern SELECT_FROM_PATTERN_END = Pattern.compile("\\s*(?i)FROM[\\s\n\r\\[]+"); - private static final Pattern UNESCAPED_ALIAS = Pattern.compile("\\s*(?i)AS\\s*"); + private static final Pattern SELECT_FROM_PATTERN_START = Pattern.compile("\\s*SELECT\\s+", Pattern.CASE_INSENSITIVE); + private static final Pattern SELECT_FROM_PATTERN_END = Pattern.compile("\\s*FROM[\\s\\[]+", Pattern.CASE_INSENSITIVE); + private static final Pattern UNESCAPED_ALIAS = Pattern.compile("\\s*AS\\s*", Pattern.CASE_INSENSITIVE); private static final Pattern QUOTE_M_PATTERN = Pattern.compile("'(([^'])*)'"); private static final Pattern DOUBLE_QUOTE_M_PATTERN = Pattern.compile("\"(([^\"])*)\""); private static final Pattern FIND_LIKE_PATTERN = Pattern - .compile("[\\s\n\r\\(]*([\\w\\.]*)([\\s\n\r\\)]*)((?i)NOT\\s*)*(?i)LIKE\\s*'([^']*(?:'')*)'"); + .compile("[\\s\\(]*([\\w\\.]*)([\\s\\)]*)(NOT\\s*)*LIKE\\s*'([^']*(?:'')*)'", Pattern.CASE_INSENSITIVE); private static final Pattern ACCESS_LIKE_CHARINTERVAL_PATTERN = Pattern.compile("\\[(?:\\!*[a-zA-Z0-9]\\-[a-zA-Z0-9])+\\]"); private static final Pattern ACCESS_LIKE_ESCAPE_PATTERN = Pattern.compile("\\[[\\*|_|#]\\]"); private static final Pattern CHECK_DDL = - Pattern.compile("^([\n\r\\s]*(?i)(create|alter|drop|enable|disable))[\n\r\\s]+.*"); + Pattern.compile("^([\n\r\\s]*(create|alter|drop|enable|disable))[\n\r\\s]+.*", Pattern.CASE_INSENSITIVE); private static final Pattern KIND_OF_SUBQUERY = - Pattern.compile("(\\[)(((?i) FROM )*((?i)SELECT )*([^\\]])*)(\\]\\.\\s)"); + Pattern.compile("(\\[)(( FROM )*(SELECT )*([^\\]])*)(\\]\\.\\s)", Pattern.CASE_INSENSITIVE); - private static final Pattern NO_DATA_PATTERN = Pattern.compile(" (?i)WITH\\s+(?i)NO\\s+(?i)DATA"); + private static final Pattern NO_DATA_PATTERN = Pattern.compile(" WITH\\s+NO\\s+DATA", Pattern.CASE_INSENSITIVE); private static final Pattern NO_ALFANUMERIC = Pattern.compile("\\W"); private static final String IDENTITY = "(\\W+)((?i)@@identity)(\\W*)"; - private static final Pattern SELECT_IDENTITY = Pattern.compile("(?i)select\\s+(?i)@@identity.*"); - private static final Pattern HAS_FROM = Pattern.compile("\\s+(?i)from\\s+"); + private static final Pattern SELECT_IDENTITY = Pattern.compile("select\\s+@@identity.*", Pattern.CASE_INSENSITIVE); + private static final Pattern HAS_FROM = Pattern.compile("\\s+from\\s+", Pattern.CASE_INSENSITIVE); private static final Pattern FORMULA_DEPENDENCIES = Pattern.compile("\\[([^\\]]*)\\]"); private static final String EXCLAMATION_POINT = "(\\!)([\n\r\\s]*)([^\\=])"; private static final String YES = "(\\W)((?i)YES)(\\W)"; private static final String NO = "(\\W)((?i)NO)(\\W)"; - private static final String WITH_OWNERACCESS_OPTION = - "(\\W)(?i)WITH\\s+(?i)OWNERACCESS\\s+(?i)OPTION(\\W)"; - private static final Pattern DIGIT_STARTING_IDENTIFIERS = - Pattern.compile("(\\W)(([0-9])+(([_a-zA-Z])+([0-9])*)+)(\\W)"); + private static final String WITH_OWNERACCESS_OPTION = "(\\W)(?i)WITH\\s+(?i)OWNERACCESS\\s+(?i)OPTION(\\W)"; + private static final Pattern DIGIT_STARTING_IDENTIFIERS = Pattern.compile("(\\W)(([0-9])+(([_a-zA-Z])+([0-9])*)+)(\\W)"); private static final String UNDERSCORE_IDENTIFIERS = "(\\W)((_)+([_a-zA-Z0-9])+)(\\W)"; private static final String XESCAPED = "(\\W)((?i)X)((?i)_)(\\W)"; private static final String[] DEFAULT_CATCH = new String[] { - "(\\s*(?i)DEFAULT\\s+)('(?:[^']*(?:'')*)*')([\\s\n\r\\)\\,])", - "(\\s*(?i)DEFAULT\\s+)(\"(?:[^\"]*(?:\"\")*)*\")([\\s\n\r\\)\\,])", - "(\\s*(?i)DEFAULT\\s+)([0-9\\.\\-\\+]+)([\\s\n\r\\)\\,])", - "(\\s*(?i)DEFAULT\\s+)([_0-9a-zA-Z]*\\([^\\)]*\\))([\\s\n\r\\)\\,])"}; - private static final Pattern DEFAULT_CATCH_0 = Pattern.compile("(\\s*(?i)DEFAULT\\s+)"); + "(\\s*(?i)DEFAULT\\s+)('(?:[^']*(?:'')*)*')([\\s\\)\\,])", + "(\\s*(?i)DEFAULT\\s+)(\"(?:[^\"]*(?:\"\")*)*\")([\\s\\)\\,])", + "(\\s*(?i)DEFAULT\\s+)([0-9\\.\\-\\+]+)([\\s\\)\\,])", + "(\\s*(?i)DEFAULT\\s+)([_0-9a-zA-Z]*\\([^\\)]*\\))([\\s\\)\\,])"}; + private static final Pattern DEFAULT_CATCH_0 = Pattern.compile("(\\s*DEFAULT\\s+)", Pattern.CASE_INSENSITIVE); public static final String NOT_NULL = "\\s(?i)NOT\\s(?i)NULL"; - private static final Pattern QUOTED_ALIAS = - Pattern.compile("(\\s+(?i)AS\\s*)(\\[[^\\]]*\\])(\\W)"); + private static final Pattern QUOTED_ALIAS = Pattern.compile("(\\s+AS\\s*)(\\[[^\\]]*\\])(\\W)", Pattern.CASE_INSENSITIVE); private static final String TYPES_TRANSLATE = "(?i)_(\\W)"; public static final String DATE_ACCESS_FORMAT = "(0[1-9]|[1-9]|1[012])/(0[1-9]|[1-9]|[12][0-9]|3[01])/(\\d\\d\\d\\d)"; @@ -72,7 +69,7 @@ public final class SQLConverter { private static final int NAME_PATTERN_STEP = 4; private static final String UNION = "(;)(\\s*)((?i)UNION)(\\s*)"; private static final String DISTINCT_ROW = "\\s+(?i)DISTINCTROW\\s+"; - private static final String DEFAULT_VARCHAR = "(\\W)(?i)VARCHAR([\\s\n\r,\\)])"; + private static final String DEFAULT_VARCHAR = "(\\W)(?i)VARCHAR([\\s,\\)])"; private static final String DEFAULT_VARCHAR_0 = "(\\W)(?i)VARCHAR([^\\(])"; private static final String BACKTICK = "(`)([^`]*)(`)"; @@ -227,34 +224,34 @@ private static int[] getDoubleQuoteGroup(String _s) { public enum DDLType { CREATE_TABLE_AS_SELECT(Pattern.compile( - "\\s*(?i)create\\s+(?i)table\\s+" + NAME_PATTERN + "\\s*(?)AS\\s*\\(\\s*((?)SELECT)")), - CREATE_TABLE(Pattern.compile("\\s*(?i)create\\s+(?i)table\\s+" + NAME_PATTERN)), - DROP_TABLE_CASCADE(Pattern.compile("\\s*(?i)drop\\s+(?i)table\\s+" + NAME_PATTERN + "\\s+(?i)cascade")), + "\\s*create\\s+table\\s+" + NAME_PATTERN + "\\s*(?)AS\\s*\\(\\s*((?)SELECT)", Pattern.CASE_INSENSITIVE)), + CREATE_TABLE(Pattern.compile( + "\\s*create\\s+table\\s+" + NAME_PATTERN, Pattern.CASE_INSENSITIVE)), + DROP_TABLE_CASCADE(Pattern.compile( + "\\s*drop\\s+table\\s+" + NAME_PATTERN + "\\s+cascade", Pattern.CASE_INSENSITIVE)), DROP_TABLE(Pattern.compile( - "\\s*(?i)drop\\s+(?i)table\\s+" + NAME_PATTERN)), + "\\s*drop\\s+table\\s+" + NAME_PATTERN, Pattern.CASE_INSENSITIVE)), ALTER_RENAME(Pattern.compile( - "\\s*(?i)alter\\s+(?i)table\\s+" + NAME_PATTERN - + "\\s+(?i)rename\\s+(?i)to\\s+" + NAME_PATTERN)), + "\\s*alter\\s+table\\s+" + NAME_PATTERN + "\\s+rename\\s+to\\s+" + NAME_PATTERN, Pattern.CASE_INSENSITIVE)), CREATE_PRIMARY_KEY(Pattern.compile( - "\\s*(?i)alter\\s+(?i)table\\s+" + NAME_PATTERN - + "\\s+(?i)add\\s+(?:(?i)constraint\\s+" + NAME_PATTERN + "\\s+)?(?i)primary\\s+(?i)key(.*)")), + "\\s*alter\\s+table\\s+" + NAME_PATTERN + "\\s+add\\s+(?:constraint\\s+" + NAME_PATTERN + "\\s+)?primary\\s+key(.*)", Pattern.CASE_INSENSITIVE)), CREATE_FOREIGN_KEY(Pattern.compile( - "\\s*(?i)alter\\s+(?i)table\\s+" + NAME_PATTERN + "\\s+(?i)add\\s+(?:(?i)constraint\\s+" + NAME_PATTERN - + "\\s+)?(?i)foreign\\s+(?i)key\\s+" + "(?:\\(.*\\))\\s*(?i)references\\s+" + NAME_PATTERN + "(.*)")), + "\\s*alter\\s+table\\s+" + NAME_PATTERN + "\\s+add\\s+(?:constraint\\s+" + NAME_PATTERN + + "\\s+)?foreign\\s+key\\s+" + "(?:\\(.*\\))\\s*references\\s+" + NAME_PATTERN + "(.*)", Pattern.CASE_INSENSITIVE)), DROP_FOREIGN_KEY(Pattern.compile( - "\\s*(?i)alter\\s+(?i)table\\s+" + NAME_PATTERN + "\\s+(?i)drop\\s+(?i)constraint\\s+" + NAME_PATTERN)), + "\\s*alter\\s+table\\s+" + NAME_PATTERN + "\\s+drop\\s+constraint\\s+" + NAME_PATTERN, Pattern.CASE_INSENSITIVE)), ADD_COLUMN(Pattern.compile( - "\\s*(?i)alter\\s+(?i)table\\s+" + NAME_PATTERN + "\\s+(?i)add\\s+(?:(?i)column\\s+)?" + NAME_PATTERN + "(.*)")), + "\\s*alter\\s+table\\s+" + NAME_PATTERN + "\\s+add\\s+(?:column\\s+)?" + NAME_PATTERN + "(.*)", Pattern.CASE_INSENSITIVE)), CREATE_INDEX(Pattern.compile( - "(?i)CREATE\\s+(?:(?i)unique)?\\s*(?i)index\\s+" + NAME_PATTERN + "\\s+(?i)ON\\s+" + NAME_PATTERN + "\\s+")), + "CREATE\\s+(?:unique)?\\s*index\\s+" + NAME_PATTERN + "\\s+ON\\s+" + NAME_PATTERN + "\\s+", Pattern.CASE_INSENSITIVE)), DISABLE_AUTOINCREMENT(Pattern.compile( - "\\s*(?i)disable\\s+(?i)autoincrement\\s+(?i)on\\s*" + NAME_PATTERN)), + "\\s*disable\\s+autoincrement\\s+on\\s*" + NAME_PATTERN, Pattern.CASE_INSENSITIVE)), ENABLE_AUTOINCREMENT(Pattern.compile( - "\\s*(?i)enable\\s+(?i)autoincrement\\s+(?i)on\\s*" + NAME_PATTERN)); + "\\s*enable\\s+autoincrement\\s+on\\s*" + NAME_PATTERN, Pattern.CASE_INSENSITIVE)); private final Pattern pattern; private String ddl; @@ -343,7 +340,6 @@ public static DDLType getDDLType(String s) { } private static String replaceWorkAroundFunctions(String sql) { - for (String waFun : WORKAROUND_FUNCTIONS) { sql = sql.replaceAll("(\\W)(?i)" + waFun + "\\s*\\(", "$1" + waFun + "WA("); } @@ -493,24 +489,19 @@ public static NormalizedSQL convertSQL(String sql, UcanaccessConnection conn) { public static String convertAccessDate(String sql) { sql = sql.replaceAll("#" + DATE_ACCESS_FORMAT + "#", "Timestamp('$3-$1-$2 00:00:00')") // FORMAT MM/dd/yyyy - .replaceAll("#" + DATE_ACCESS_FORMAT + "\\s*(" + HHMMSS_ACCESS_FORMAT + ")#", - "Timestamp0('$3-$1-$2 $4')") + .replaceAll("#" + DATE_ACCESS_FORMAT + "\\s*(" + HHMMSS_ACCESS_FORMAT + ")#", "Timestamp0('$3-$1-$2 $4')") - .replaceAll("#" + DATE_ACCESS_FORMAT + "\\s*(" + HHMMSS_ACCESS_FORMAT + ")\\s*(?i)AM#", - "Timestamp0('$3-$1-$2 $4')") + .replaceAll("#" + DATE_ACCESS_FORMAT + "\\s*(" + HHMMSS_ACCESS_FORMAT + ")\\s*(?i)AM#", "Timestamp0('$3-$1-$2 $4')") - .replaceAll("#" + DATE_ACCESS_FORMAT + "\\s*(" + HHMMSS_ACCESS_FORMAT + ")\\s*(?i)PM#", - "(Timestamp0('$3-$1-$2 $4')+ 12 Hour) ") + .replaceAll("#" + DATE_ACCESS_FORMAT + "\\s*(" + HHMMSS_ACCESS_FORMAT + ")\\s*(?i)PM#", "(Timestamp0('$3-$1-$2 $4')+ 12 Hour) ") // FORMAT yyyy-MM-dd .replaceAll("#" + DATE_FORMAT + "#", "Timestamp0('$1-$2-$3 00:00:00')") .replaceAll("#" + DATE_FORMAT + "\\s*(" + HHMMSS_ACCESS_FORMAT + ")#", "Timestamp0('$1-$2-$3 $4')") - .replaceAll("#" + DATE_FORMAT + "\\s*(" + HHMMSS_ACCESS_FORMAT + ")\\s*(?i)AM#", - "Timestamp0('$1-$2-$3 $4')") + .replaceAll("#" + DATE_FORMAT + "\\s*(" + HHMMSS_ACCESS_FORMAT + ")\\s*(?i)AM#", "Timestamp0('$1-$2-$3 $4')") - .replaceAll("#" + DATE_FORMAT + "\\s*(" + HHMMSS_ACCESS_FORMAT + ")\\s*(?i)PM#", - "(Timestamp0('$1-$2-$3 $4')+ 12 Hour)") + .replaceAll("#" + DATE_FORMAT + "\\s*(" + HHMMSS_ACCESS_FORMAT + ")\\s*(?i)PM#", "(Timestamp0('$1-$2-$3 $4')+ 12 Hour)") .replaceAll("#(" + HHMMSS_ACCESS_FORMAT + ")#", "Timestamp'" + BIG_BANG + " $1'") .replaceAll("#(" + HHMMSS_ACCESS_FORMAT + ")\\s*(?i)AM#", "Timestamp'" + BIG_BANG + " $1'") @@ -625,7 +616,7 @@ private static String replaceDigitStartingIdentifiers(String sql) { private static String convertXescaped(String sqlc) { for (String xidt : ESCAPED_IDENTIFIERS) { - sqlc = sqlc.replaceAll(XESCAPED.replaceAll("_", xidt), "$1$3$4"); + sqlc = sqlc.replaceAll(XESCAPED.replace("_", xidt), "$1$3$4"); } return sqlc; } @@ -790,7 +781,7 @@ public static String convertAddColumn(String tableName, String columnName, Strin private static String convertTypeDeclaration(String typeDecl) { typeDecl = " " + typeDecl + " "; // padding for a generic RE use for (Map.Entry entry : TypesMap.getAccess2HsqlTypesMap().entrySet()) { - typeDecl = typeDecl.replaceAll("(\\s+)((?i)" + entry.getKey() + ")([\\s\n\r\\(]+)", + typeDecl = typeDecl.replaceAll("(\\s+)((?i)" + entry.getKey() + ")([\\s\\(]+)", "$1" + entry.getValue() + "$3"); } return typeDecl.replaceAll(DEFAULT_VARCHAR_0, "$1VARCHAR(255)$2"); @@ -805,13 +796,9 @@ private static String convertCreateTable(String sql, Map _types2 String pre = sql.substring(0, sql.indexOf('(')); sql = sql.substring(sql.indexOf('(')); for (Map.Entry entry : _types2Convert.entrySet()) { - sql = sql - .replaceAll("([,\\(]\\s*)" + TYPES_TRANSLATE.replaceAll("_", entry.getKey()), - "$1___" + entry.getKey() + "___$2") - .replaceAll("(\\W)" + TYPES_TRANSLATE.replaceAll("_", entry.getKey()), - "$1" + entry.getValue() + "$2") - .replaceAll("(\\W)" + TYPES_TRANSLATE.replaceAll("_", "___" + entry.getKey() + "___"), - "$1" + entry.getKey() + "$2"); + sql = sql.replaceAll("([,\\(]\\s*)" + TYPES_TRANSLATE.replace("_", entry.getKey()), "$1___" + entry.getKey() + "___$2") + .replaceAll("(\\W)" + TYPES_TRANSLATE.replace("_", entry.getKey()), "$1" + entry.getValue() + "$2") + .replaceAll("(\\W)" + TYPES_TRANSLATE.replace("_", "___" + entry.getKey() + "___"), "$1" + entry.getKey() + "$2"); } sql = sql.replaceAll(DEFAULT_VARCHAR, "$1VARCHAR(255)$2"); return clearDefaultsCreateStatement(pre + sql); @@ -873,7 +860,7 @@ private static String convert2RegexMatches(String likeContent) { return convert2RegexMatches(likeContent.substring(0, mtc.start(0))) + mtc.group(0).charAt(1) + convert2RegexMatches(likeContent.substring(mtc.end(0))); } - return likeContent.replaceAll("#", "\\\\d").replaceAll("\\*", ".*").replaceAll("_", ".") + return likeContent.replaceAll("#", "\\\\d").replaceAll("\\*", ".*").replace("_", ".") .replaceAll("(\\[)\\!(\\w\\-\\w\\])", "$1^$2"); } diff --git a/src/main/java/net/ucanaccess/exception/UcanaccessSQLException.java b/src/main/java/net/ucanaccess/exception/UcanaccessSQLException.java index f682b1a9..5ea8d1ce 100644 --- a/src/main/java/net/ucanaccess/exception/UcanaccessSQLException.java +++ b/src/main/java/net/ucanaccess/exception/UcanaccessSQLException.java @@ -101,9 +101,7 @@ public String getMessage() { * @return wrapped exception or parameter if can be cast to {@link UcanaccessSQLException} */ public static final UcanaccessSQLException wrap(T _t) { - return UcanaccessSQLException.class.isInstance(_t) - ? UcanaccessSQLException.class.cast(_t) - : new UcanaccessSQLException(_t); + return _t instanceof UcanaccessSQLException ? (UcanaccessSQLException) _t : new UcanaccessSQLException(_t); } public static final void throwIf(BooleanSupplier _condition, Supplier _exceptionSupplier) throws T { diff --git a/src/main/java/net/ucanaccess/jdbc/DBReference.java b/src/main/java/net/ucanaccess/jdbc/DBReference.java index 711cc0e7..eb0903e3 100644 --- a/src/main/java/net/ucanaccess/jdbc/DBReference.java +++ b/src/main/java/net/ucanaccess/jdbc/DBReference.java @@ -148,7 +148,7 @@ Connection checkLastModified(Connection _conn, Session _session) throws Exceptio return _conn; } updateLastModified(); - closeHSQLDB(_session); + closeHsqlDb(_session); dbIO.flush(); dbIO.close(); dbIO = open(dbFile, pwd); @@ -226,7 +226,7 @@ private long getLastUpdateHSQLDB() { return lu; } - private void closeHSQLDB(Session session) throws IOException { + private void closeHsqlDb(Session session) throws IOException { closeHsqlDb(session, false); } @@ -380,7 +380,7 @@ private String getHsqlUrl(Session _session) throws SQLException { Runtime.getRuntime().addShutdownHook(new Thread(() -> { try { if (toKeepHsql == null) { - closeHSQLDB(_session); + closeHsqlDb(_session); } else { finalizeHsqlDb(_session); } @@ -501,7 +501,7 @@ void shutdown(Session _session) throws Exception { memoryTimer.timer.cancel(); dbIO.flush(); dbIO.close(); - closeHSQLDB(_session); + closeHsqlDb(_session); } diff --git a/src/main/java/net/ucanaccess/jdbc/UcanaccessConnection.java b/src/main/java/net/ucanaccess/jdbc/UcanaccessConnection.java index fe9ddda0..1153a8e9 100644 --- a/src/main/java/net/ucanaccess/jdbc/UcanaccessConnection.java +++ b/src/main/java/net/ucanaccess/jdbc/UcanaccessConnection.java @@ -24,7 +24,7 @@ public class UcanaccessConnection implements Connection { private static final ThreadLocal CTX = new ThreadLocal<>(); - private final transient Logger logger = System.getLogger(getClass().getName()); + private final Logger logger = System.getLogger(getClass().getName()); private boolean feedbackState; private final LinkedList commands = new LinkedList<>(); private Connection hsqlDBConnection; @@ -299,10 +299,7 @@ private void flushIO() throws SQLException { } catch (IOException _ex2) { logger.log(Level.WARNING, _ex2.toString()); } - if (UcanaccessSQLException.class.isInstance(_ex)) { - throw UcanaccessSQLException.class.cast(_ex); - } - throw new UcanaccessSQLException(_ex); + throw _ex instanceof UcanaccessSQLException ? (UcanaccessSQLException) _ex : new UcanaccessSQLException(_ex); } try { diff --git a/src/main/java/net/ucanaccess/jdbc/UcanaccessDriver.java b/src/main/java/net/ucanaccess/jdbc/UcanaccessDriver.java index 56706145..bacb0b6e 100644 --- a/src/main/java/net/ucanaccess/jdbc/UcanaccessDriver.java +++ b/src/main/java/net/ucanaccess/jdbc/UcanaccessDriver.java @@ -16,7 +16,6 @@ import java.io.IOException; import java.lang.System.Logger; import java.lang.System.Logger.Level; -import java.lang.reflect.InvocationTargetException; import java.sql.*; import java.util.*; import java.util.function.BiConsumer; @@ -26,7 +25,6 @@ public final class UcanaccessDriver implements Driver { public static final String URL_PREFIX = "jdbc:ucanaccess://"; private static final Logger LOGGER = System.getLogger(UcanaccessDriver.class.getName()); - private final Logger logger = System.getLogger(getClass().getName()); static { try { @@ -60,7 +58,7 @@ public Connection connect(String _url, Properties _props) throws SQLException { Map props = readProperties(_props, _url, (k, v) -> { unknownProps.put(k, v); - logger.log(Level.WARNING, "Unknown driver property {0} with value {1}", k, v); + LOGGER.log(Level.WARNING, "Unknown driver property {0} with value {1}", k, v); }); int idxSemicolon = _url.indexOf(';'); @@ -74,11 +72,8 @@ public Connection connect(String _url, Properties _props) throws SQLException { boolean alreadyLoaded = as.loaded(fileDb); FileFormat ff = null; - if (props.containsKey(newDatabaseVersion)) { - if (!fileDb.exists()) { - ff = FileFormat.parse(props.get(newDatabaseVersion)); - } - + if (props.containsKey(newDatabaseVersion) && !fileDb.exists()) { + ff = FileFormat.parse(props.get(newDatabaseVersion)); } boolean useCustomOpener = props.containsKey(jackcessOpener); @@ -108,7 +103,7 @@ public Connection connect(String _url, Properties _props) throws SQLException { if (props.containsKey(keepMirror)) { dbRef.setInMemory(false); if (dbRef.isEncryptHSQLDB()) { - logger.log(Level.WARNING, "{0} parameter cannot be combined with parameters {1} or {2}, {3} skipped", + LOGGER.log(Level.WARNING, "{0} parameter cannot be combined with parameters {1} or {2}, {3} skipped", keepMirror, jackcessOpener, encrypt, keepMirror); } else { File dbMirror = @@ -172,7 +167,7 @@ public Connection connect(String _url, Properties _props) throws SQLException { dbRef.getDbIO().setErrorHandler((cl, bt, location, ex) -> { if (cl.getType().isTextual()) { - logger.log(Level.WARNING, "Invalid textual value in table {0}, column {1}: it might look like {2}", + LOGGER.log(Level.WARNING, "Invalid textual value in table {0}, column {1}: it might look like {2}", cl.getTable().getName(), cl.getName(), new String(bt)); } throw new IOException(ex); @@ -248,7 +243,7 @@ private Integer validateLobScale(String _property) { } } catch (Exception _ignored) { } - logger.log(Level.WARNING, "Lobscale value must equal at least one of the following values: 1,2,4,8,16,32, skipping it"); + LOGGER.log(Level.WARNING, "Lobscale value must equal at least one of the following values: 1,2,4,8,16,32, skipping it"); return null; } @@ -290,14 +285,13 @@ public boolean jdbcCompliant() { return true; } - private IJackcessOpenerInterface newJackcessOpenerInstance(String className) - throws InstantiationException, IllegalAccessException, ClassNotFoundException, UcanaccessSQLException, InvocationTargetException, NoSuchMethodException, SecurityException { - Object newInstance = Class.forName(className).getConstructor().newInstance(); + private IJackcessOpenerInterface newJackcessOpenerInstance(String className) throws UcanaccessSQLException { + Object instance = Try.catching(() -> Class.forName(className).getConstructor().newInstance()).orThrow(ex -> new UcanaccessSQLException("Failed to instantiate " + className, ex)); - if (!IJackcessOpenerInterface.class.isInstance(newInstance)) { - throw new UcanaccessSQLException("Jackess Opener class must implement " + IJackcessOpenerInterface.class.getName()); + if (instance instanceof IJackcessOpenerInterface) { + return (IJackcessOpenerInterface) instance; } - return (IJackcessOpenerInterface) newInstance; + throw new UcanaccessSQLException("Jackess Opener class must implement " + IJackcessOpenerInterface.class.getName()); } /** diff --git a/src/main/java/net/ucanaccess/jdbc/UcanaccessPreparedStatement.java b/src/main/java/net/ucanaccess/jdbc/UcanaccessPreparedStatement.java index 56de8a47..8591f938 100644 --- a/src/main/java/net/ucanaccess/jdbc/UcanaccessPreparedStatement.java +++ b/src/main/java/net/ucanaccess/jdbc/UcanaccessPreparedStatement.java @@ -671,6 +671,9 @@ public void setTimestamp(int _parmIdx, Timestamp ts, Calendar cal) throws Ucanac }); } + /** + * @deprecated Use {@code setCharacterStream} + */ @Override @Deprecated public void setUnicodeStream(int _parmIdx, InputStream is, int length) throws UcanaccessSQLException { diff --git a/src/main/java/net/ucanaccess/util/Try.java b/src/main/java/net/ucanaccess/util/Try.java index 5e829668..65529de9 100644 --- a/src/main/java/net/ucanaccess/util/Try.java +++ b/src/main/java/net/ucanaccess/util/Try.java @@ -51,31 +51,31 @@ * * * @param the type of the optional value from the code block executed within @code try} - * @param the type of exception, if any, thrown by the executed code block. + * @param the type of exception, if any, thrown by the executed code block. * * @author Markus Spann * @since v5.1.0 */ -public final class Try { +public final class Try { /** The immutable value or {@code null} if an exception occurred during retrieval. */ private final V val; /** The immutable exception or {@code null} if value retrieval succeeded without exception. */ - private final EC t; + private final E t; /** * Creates a new instance from a throwing supplier. * * @param _catchable a throwing supplier */ - private Try(IThrowingSupplier _catchable) { + private Try(IThrowingSupplier _catchable) { V locVal = null; - EC locEx = null; + E locEx = null; try { locVal = _catchable.get(); } catch (Throwable _ex) { @SuppressWarnings("unchecked") - EC castEx = (EC) _ex; + E castEx = (E) _ex; locEx = castEx; } val = locVal; @@ -88,7 +88,7 @@ private Try(IThrowingSupplier _catchable) { * @param _val value, may be null * @param _ex exception, may be null */ - private Try(V _val, EC _ex) { + private Try(V _val, E _ex) { val = _val; t = _ex; } @@ -204,7 +204,7 @@ public V get() { * Gets the exception or {@code null} if none has occurred. * @return exception */ - public EC getException() { + public E getException() { return t; } @@ -232,7 +232,7 @@ public V orElse(V _other) { * If an exception occurs during execution of the throwing consumer, that exception is thrown. * @param _consumer consumer to execute in case of exception. The exception object is passed to the consumer. */ - public void orElse(IThrowingConsumer _consumer) { + public void orElse(IThrowingConsumer _consumer) { if (hasThrown()) { Try.catching(() -> _consumer.accept(t)).orThrow(); } @@ -244,7 +244,7 @@ public void orElse(IThrowingConsumer _consumer) { * @param _function function to execute in case of exception. The exception object is passed to the function. * @return the successful value or value returned by the function */ - public V orElseApply(IThrowingFunction _function) { + public V orElseApply(IThrowingFunction _function) { if (hasThrown()) { return Try.catching(() -> _function.apply(t)).orThrow(); } @@ -292,7 +292,7 @@ public V orThrow() { * @return the successful value * @throws T2 the exception returned by {@code _function} */ - public V orThrow(Function _function) throws T2 { + public V orThrow(Function _function) throws T2 { Objects.requireNonNull(_function, "Function required"); if (hasThrown()) { Throwable t2 = _function.apply(t); diff --git a/src/test/java/net/ucanaccess/jdbc/NotNullDdlTest.java b/src/test/java/net/ucanaccess/jdbc/NotNullDdlTest.java index d78bdb52..3e1585b1 100644 --- a/src/test/java/net/ucanaccess/jdbc/NotNullDdlTest.java +++ b/src/test/java/net/ucanaccess/jdbc/NotNullDdlTest.java @@ -53,7 +53,7 @@ void confirmNotNullColumnUsingJet(AccessVersion _accessVersion) throws Exception Process proc = Runtime.getRuntime().exec(command); proc.waitFor(15, TimeUnit.SECONDS); - assertThat(proc.exitValue()).isEqualTo(0); + assertThat(proc.exitValue()).isZero(); try (BufferedReader output = new BufferedReader(new InputStreamReader(proc.getErrorStream()))) { String stderr = output.lines().collect(Collectors.joining(System.lineSeparator()));