From b538c37db96da20ee35db9093d10539e929d0761 Mon Sep 17 00:00:00 2001 From: Nikita Kashin Date: Wed, 20 Nov 2024 11:28:50 +0300 Subject: [PATCH 01/41] Add install psutil. --- ci/test_robot.ps1 | 2 +- ci/test_robot.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/test_robot.ps1 b/ci/test_robot.ps1 index 425b4f5e2..1335539ec 100644 --- a/ci/test_robot.ps1 +++ b/ci/test_robot.ps1 @@ -29,7 +29,7 @@ git clone -q http://git.red-soft.biz/red-database/re-tests-robot echo "Installing components" start-process "${PYTHON}" "-m pip install git+http://git.red-soft.biz/red-database/python/red-database-python-driver.git" -wait -nonewwindow -start-process "${PYTHON}" "-m pip install robotframework" -wait -nonewwindow +start-process "${PYTHON}" "-m pip install robotframework psutil" -wait -nonewwindow echo "Set .xml" $BUILD_PATH="$env:USERPROFILE\.redexpert\${BUILD}" diff --git a/ci/test_robot.sh b/ci/test_robot.sh index c6de63f45..ba4fa39c7 100644 --- a/ci/test_robot.sh +++ b/ci/test_robot.sh @@ -27,7 +27,7 @@ git clone -q http://git.red-soft.biz/red-database/re-tests-robot echo "Installing components" $PYTHON -m pip install git+http://git.red-soft.biz/red-database/python/red-database-python-driver.git -$PYTHON -m pip install robotframework +$PYTHON -m pip install robotframework psutil export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/RedDatabase/lib From a94b1acf6fd79e3059905e9f6ee9871804b4a77d Mon Sep 17 00:00:00 2001 From: "mikhail.kalyashin" Date: Fri, 22 Nov 2024 15:58:58 +0300 Subject: [PATCH 02/41] See RS-205460 fix parsing "DECLARE VARIABLES" types REAL,LONG FLOAT, INT --- .../executequery/gui/browser/ColumnData.java | 3 +++ .../CreateProcedureFunctionPanel.java | 14 +++++++++-- .../procedureParser/ProcedureParser.g4 | 8 +++--- src/org/underworldlabs/util/SQLUtils.java | 25 ++++++++----------- 4 files changed, 29 insertions(+), 21 deletions(-) diff --git a/src/org/executequery/gui/browser/ColumnData.java b/src/org/executequery/gui/browser/ColumnData.java index c506a86eb..7fc9c4b9b 100644 --- a/src/org/executequery/gui/browser/ColumnData.java +++ b/src/org/executequery/gui/browser/ColumnData.java @@ -296,6 +296,9 @@ && getSize() > 0 if (getScale() > 0) sb.append(",").append(getScale()); sb.append(")"); + } else if (type == Types.FLOAT) { + if (getScale() > 0) + sb.append("(").append(getScale()).append(")"); } if (!MiscUtils.isNull(getCharset()) && connection != null && !getCharset().equalsIgnoreCase(connection.getDBCharset())) diff --git a/src/org/executequery/gui/procedure/CreateProcedureFunctionPanel.java b/src/org/executequery/gui/procedure/CreateProcedureFunctionPanel.java index bac699f5b..a0d61b6ce 100644 --- a/src/org/executequery/gui/procedure/CreateProcedureFunctionPanel.java +++ b/src/org/executequery/gui/procedure/CreateProcedureFunctionPanel.java @@ -390,8 +390,18 @@ public void enterDeclare_block_without_params(ProcedureParserParser.Declare_bloc if (type.datatypeSQL() != null && !type.datatypeSQL().isEmpty()) { - List children = type.datatypeSQL().children; - variable.setSqlType(children.get(0).getText()); + String sqlType = type.datatypeSQL().getText(); + int ind = sqlType.indexOf("("); + if (ind > 0) + sqlType = sqlType.substring(0, ind); + ind = sqlType.indexOf("["); + if (ind > 0) + sqlType = sqlType.substring(0, ind); + ind = sqlType.toUpperCase().indexOf("SEGMENT"); + if (ind > 0) + sqlType = sqlType.substring(0, ind); + sqlType = sqlType.replaceAll("(?i)CHARACTER\\s+SET.*", ""); + variable.setSqlType(MiscUtils.trimEnd(sqlType)); if (type.datatypeSQL().type_size() != null && !type.datatypeSQL().type_size().isEmpty()) variable.setSize(Integer.parseInt(type.datatypeSQL().type_size().getText().trim())); diff --git a/src/org/underworldlabs/procedureParser/ProcedureParser.g4 b/src/org/underworldlabs/procedureParser/ProcedureParser.g4 index 5b5f6db45..04b2ff8bd 100644 --- a/src/org/underworldlabs/procedureParser/ProcedureParser.g4 +++ b/src/org/underworldlabs/procedureParser/ProcedureParser.g4 @@ -168,9 +168,10 @@ body: ; datatypeSQL : K_BOOLEAN array_size? - | (K_SMALLINT | K_INTEGER | K_BIGINT | K_INT128)spases_or_comment? array_size? - | (K_FLOAT | K_DOUBLE spases_or_comment K_PRECISION)spases_or_comment? array_size? - | (K_DATE | K_TIME | K_TIMESTAMP| K_TIME spases_or_comment K_WITH spases_or_comment K_TIMEZONE | K_TIMESTAMP spases_or_comment K_WITH spases_or_comment K_TIMEZONE) spases_or_comment? array_size? + | (K_SMALLINT | K_INTEGER | K_BIGINT | K_INT128 | K_INT | K_LONG)spases_or_comment? array_size? + | (K_FLOAT | K_REAL ) spases_or_comment?('('scale')')?spases_or_comment? array_size? + | (K_DOUBLE spases_or_comment K_PRECISION| K_LONG spases_or_comment K_FLOAT) spases_or_comment? array_size? + | (K_DATE | K_TIME | K_TIMESTAMP| ((K_TIME | K_TIMESTAMP) spases_or_comment (K_WITH|K_WITHOUT) spases_or_comment K_TIME spases_or_comment K_ZONE )) spases_or_comment? array_size? | (K_DECIMAL | K_NUMERIC | K_DECFLOAT)spases_or_comment? ('(' type_size spases_or_comment?(',' spases_or_comment? scale)?')')?spases_or_comment? array_size? | (K_CHAR | K_CHARACTER | K_VARYING spases_or_comment K_CHARACTER | K_VARCHAR) spases_or_comment?('('type_size')')? (spases_or_comment K_CHARACTER spases_or_comment K_SET spases_or_comment charset_name)?spases_or_comment? array_size? @@ -1462,7 +1463,6 @@ K_TIES : T I E S ; K_TIME : T I M E ; K_TIMESTAMP : T I M E S T A M P ; K_TIMEOUT : T I M E O U T ; -K_TIMEZONE : T I M E Z O N E ; K_TIMEZONE_HOUR : T I M E Z O N E '_' H O U R ; K_TIMEZONE_MINUTE : T I M E Z O N E '_' M I N U T E ; K_TIMEZONE_NAME : T I M E Z O N E '_' N A M E ; diff --git a/src/org/underworldlabs/util/SQLUtils.java b/src/org/underworldlabs/util/SQLUtils.java index ec63e0e83..0a0e49ca2 100644 --- a/src/org/underworldlabs/util/SQLUtils.java +++ b/src/org/underworldlabs/util/SQLUtils.java @@ -824,9 +824,6 @@ public static String formattedParameter(ColumnData cd, boolean variable) { sb.append(SPACE).append(format(cd.getDefaultValue(), cd)); } - if (!MiscUtils.isNull(cd.getCheck())) - sb.append(" CHECK ( ").append(cd.getCheck()).append(")"); - } else sb.append("COMPUTED BY ( ").append(cd.getComputedBy()).append(")"); @@ -1673,11 +1670,10 @@ public static String generateDefaultUpdateStatement(String name, List = :"); - StringBuilder sb = new StringBuilder(); - sb.append("UPDATE ").append(format(name.trim(), dc)).append(" SET\n\t"); - sb.append(String.join(",\n\t", updateFields)).append(";\n"); + String sb = "UPDATE " + format(name.trim(), dc) + " SET\n\t" + + String.join(",\n\t", updateFields) + ";\n"; - return sb.toString(); + return sb; } public static String generateDefaultInsertStatement(String name, List columns, DatabaseConnection dc) { @@ -1691,14 +1687,13 @@ public static String generateDefaultInsertStatement(String name, List Date: Mon, 25 Nov 2024 18:28:39 +0300 Subject: [PATCH 03/41] See RS-205460 fix datatype parsing --- .../databaseobjects/DatabaseTypeConverter.java | 16 ++++++++++++++++ src/org/executequery/databaseobjects/T.java | 1 + src/org/executequery/gui/browser/ColumnData.java | 2 ++ .../procedureParser/ProcedureParser.g4 | 8 ++++---- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/org/executequery/databaseobjects/DatabaseTypeConverter.java b/src/org/executequery/databaseobjects/DatabaseTypeConverter.java index 309d20b0a..d9e7a4fca 100644 --- a/src/org/executequery/databaseobjects/DatabaseTypeConverter.java +++ b/src/org/executequery/databaseobjects/DatabaseTypeConverter.java @@ -201,20 +201,34 @@ public static int[] getSQLDataTypesFromNames(String[] databaseTypes) { } public static int getSQLDataTypeFromName(String databaseType) { + databaseType = databaseType.replaceAll("[\n\t\r]", " "); + databaseType = databaseType.replaceAll("[/][*].*[\\*][/]", " "); + while (databaseType.contains(" ")) + databaseType = databaseType.replaceAll(" ", " "); switch (databaseType.trim().toUpperCase()) { case T.BIGINT: return Types.BIGINT; case T.BLOB_SUB_TYPE_BINARY: return Types.LONGVARBINARY; case T.VARCHAR: + case "VARBINARY": return Types.VARCHAR; case T.CHAR: + case "BINARY": + case "CHARACTER": return Types.CHAR; + case T.NCHAR: + case "NATIONAL CHAR": + case "NATIONAL CHARACTER": + return Types.NCHAR; + case "NATIONAL CHARACTER VARYING": + return Types.NVARCHAR; case T.BLOB_SUB_TYPE_TEXT: return Types.LONGVARCHAR; case T.NUMERIC: return Types.NUMERIC; case T.DECIMAL: + case "DEC": return Types.DECIMAL; case T.INT128: return Types.INT128; @@ -223,8 +237,10 @@ public static int getSQLDataTypeFromName(String databaseType) { case T.SMALLINT: return Types.SMALLINT; case T.FLOAT: + case "REAL": return Types.FLOAT; case T.DOUBLE_PRECISION: + case "LONG FLOAT": return Types.DOUBLE; case T.BOOLEAN: return Types.BOOLEAN; diff --git a/src/org/executequery/databaseobjects/T.java b/src/org/executequery/databaseobjects/T.java index ef3cd0dc3..92c499bc1 100644 --- a/src/org/executequery/databaseobjects/T.java +++ b/src/org/executequery/databaseobjects/T.java @@ -24,6 +24,7 @@ public interface T { String CSTRING = "CSTRING"; String DECFLOAT = "DECFLOAT"; String INT128 = "INT128"; + String NCHAR = "NCHAR"; String[] DEFAULT_TYPES = { NUMERIC, diff --git a/src/org/executequery/gui/browser/ColumnData.java b/src/org/executequery/gui/browser/ColumnData.java index 7fc9c4b9b..986995ca3 100644 --- a/src/org/executequery/gui/browser/ColumnData.java +++ b/src/org/executequery/gui/browser/ColumnData.java @@ -429,6 +429,8 @@ public boolean isEditSize() { || getSQLType() == Types.BLOB || getSQLType() == Types.LONGVARCHAR || getSQLType() == Types.LONGVARBINARY + || getSQLType() == Types.NCHAR + || getSQLType() == Types.NVARCHAR || getTypeName().equalsIgnoreCase("CSTRING") || getTypeName().equalsIgnoreCase("VARCHAR") || getTypeName().equalsIgnoreCase("CHAR") diff --git a/src/org/underworldlabs/procedureParser/ProcedureParser.g4 b/src/org/underworldlabs/procedureParser/ProcedureParser.g4 index 04b2ff8bd..de2b085e7 100644 --- a/src/org/underworldlabs/procedureParser/ProcedureParser.g4 +++ b/src/org/underworldlabs/procedureParser/ProcedureParser.g4 @@ -168,14 +168,14 @@ body: ; datatypeSQL : K_BOOLEAN array_size? - | (K_SMALLINT | K_INTEGER | K_BIGINT | K_INT128 | K_INT | K_LONG)spases_or_comment? array_size? + | (K_SMALLINT | K_INTEGER | K_BIGINT | K_INT128 | K_INT | K_LONG )spases_or_comment? array_size? | (K_FLOAT | K_REAL ) spases_or_comment?('('scale')')?spases_or_comment? array_size? | (K_DOUBLE spases_or_comment K_PRECISION| K_LONG spases_or_comment K_FLOAT) spases_or_comment? array_size? | (K_DATE | K_TIME | K_TIMESTAMP| ((K_TIME | K_TIMESTAMP) spases_or_comment (K_WITH|K_WITHOUT) spases_or_comment K_TIME spases_or_comment K_ZONE )) spases_or_comment? array_size? - | (K_DECIMAL | K_NUMERIC | K_DECFLOAT)spases_or_comment? ('(' type_size spases_or_comment?(',' spases_or_comment? scale)?')')?spases_or_comment? array_size? - | (K_CHAR | K_CHARACTER | K_VARYING spases_or_comment K_CHARACTER | K_VARCHAR) spases_or_comment?('('type_size')')? + | (K_DECIMAL | K_NUMERIC | K_DECFLOAT| K_DEC)spases_or_comment? ('(' type_size spases_or_comment?(',' spases_or_comment? scale)?')')?spases_or_comment? array_size? + | (K_CHAR | K_CHARACTER | K_VARYING spases_or_comment K_CHARACTER | K_VARCHAR | K_VARBINARY ) spases_or_comment?('('type_size')')? (spases_or_comment K_CHARACTER spases_or_comment K_SET spases_or_comment charset_name)?spases_or_comment? array_size? - | (K_NCHAR | K_NATIONAL spases_or_comment K_CHARACTER | K_NATIONAL spases_or_comment K_CHAR) (K_VARYING)? spases_or_comment?('(' spases_or_comment? int_number spases_or_comment?')')? spases_or_comment? array_size? + | (K_NCHAR | K_BINARY | K_NATIONAL spases_or_comment K_CHARACTER | K_NATIONAL spases_or_comment K_CHAR) (spases_or_comment K_VARYING)? spases_or_comment?('(' spases_or_comment? type_size spases_or_comment?')')? spases_or_comment? array_size? | K_BLOB (spases_or_comment K_SUB_TYPE spases_or_comment subtype)? (spases_or_comment K_SEGMENT spases_or_comment K_SIZE spases_or_comment type_size)? (spases_or_comment K_CHARACTER spases_or_comment K_SET spases_or_comment charset_name)? | K_BLOB ('('spases_or_comment? (type_size spases_or_comment?)? (','spases_or_comment? subtype spases_or_comment?)?')')? From 0e16bb4fa1c3b418993ac0d3fef242881966a4ff Mon Sep 17 00:00:00 2001 From: "mikhail.kalyashin" Date: Tue, 26 Nov 2024 09:37:45 +0300 Subject: [PATCH 04/41] See RS-205460 delete "^" from query for creating --- src/org/underworldlabs/util/SQLUtils.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/org/underworldlabs/util/SQLUtils.java b/src/org/underworldlabs/util/SQLUtils.java index 0a0e49ca2..d9dd757ac 100644 --- a/src/org/underworldlabs/util/SQLUtils.java +++ b/src/org/underworldlabs/util/SQLUtils.java @@ -351,8 +351,8 @@ public static String generateCreateProcedure( if (fullProcedureBody != null && !fullProcedureBody.isEmpty()) sb.append("\nAS\n").append(fullProcedureBody); - - sb.append("\n^\n"); + if (setTerm) + sb.append("\n^\n"); if (setComment) { sb.append(generateComment(name, NamedObject.META_TYPES[PROCEDURE], comment, "^", false, dc)); @@ -369,24 +369,26 @@ public static String generateCreateProcedure( public static String generateDownCreateProcedureScript(String name, String comment, Vector inputParameters, Vector outputParameters, boolean setComment, DatabaseConnection dc) { StringBuilder sb = new StringBuilder(); - sb.append("\n^\n"); if (setComment) { sb.append(generateComment(name, NamedObject.META_TYPES[PROCEDURE], comment, "^", false, dc)); sb.append(generateCommentForColumns(name, inputParameters, "PARAMETER", "^")); sb.append(generateCommentForColumns(name, outputParameters, "PARAMETER", "^")); } + if (sb.length() > 0) + sb.insert(0, "\n^\n"); return sb.toString(); } public static String generateDownCreateFunctionScript(String name, String comment, Vector inputArguments, boolean setComment, DatabaseConnection dc) { StringBuilder sb = new StringBuilder(); - sb.append("\n^\n"); if (setComment) { sb.append(generateComment(name, NamedObject.META_TYPES[FUNCTION], comment, "^", false, dc)); sb.append(generateCommentForColumns(name, inputArguments, "PARAMETER", "^")); } + if (sb.length() > 0) + sb.insert(0, "\n^\n"); return sb.toString(); @@ -616,8 +618,8 @@ public static String generateCreateFunction( if (fullFunctionBody != null && !fullFunctionBody.isEmpty()) sb.append("\nAS\n").append(fullFunctionBody); - - sb.append("\n^\n"); + if (setTerm) + sb.append("\n^\n"); if (setComment) { sb.append(generateComment(name, NamedObject.META_TYPES[FUNCTION], comment, "^", false, dc)); @@ -1724,7 +1726,8 @@ public static String generateCreateTriggerStatement( } else if (!MiscUtils.isNull(sourceCode)) sb.append(sourceCode); - sb.append("^\n"); + if (setTerm) + sb.append("^\n"); if (!MiscUtils.isNull(comment) && !comment.equals("")) { comment = comment.replace("'", "''"); From 124be2921919643ffd4b4b306b0b83955903707f Mon Sep 17 00:00:00 2001 From: "mikhail.kalyashin" Date: Tue, 26 Nov 2024 10:23:50 +0300 Subject: [PATCH 05/41] See RS-205460 fix work with non-reserved keywords --- .../procedureParser/ProcedureParser.g4 | 352 ++++++++++++++++++ 1 file changed, 352 insertions(+) diff --git a/src/org/underworldlabs/procedureParser/ProcedureParser.g4 b/src/org/underworldlabs/procedureParser/ProcedureParser.g4 index de2b085e7..f5f80a9a3 100644 --- a/src/org/underworldlabs/procedureParser/ProcedureParser.g4 +++ b/src/org/underworldlabs/procedureParser/ProcedureParser.g4 @@ -142,6 +142,7 @@ body: variable_name : IDENTIFIER | STRING_LITERAL + | non_reserved_keyword ; input_parameter @@ -833,6 +834,357 @@ datatypeKeyword | K_VARCHAR ; + non_reserved_keyword: + K_ABS + | K_ABSENT + | K_ABSOLUTE + | K_ACCENT + | K_ACOS + | K_ACOSH + | K_ACTION + | K_ACTIVE + | K_ADAPTER + | K_AFTER + | K_ALWAYS + | K_ARRAY + | K_ASC + | K_ASCENDING + | K_ASCII_CHAR + | K_ASCII_VAL + | K_ASIN + | K_ASINH + | K_ATAN + | K_ATAN2 + | K_ATANH + | K_AUTHID + | K_AUTH_FACTORS + | K_AUTO + | K_AUTONOMOUS + | K_BACKUP + | K_BASE64_DECODE + | K_BASE64_ENCODE + | K_BEFORE + | K_BIND + | K_BIN_AND + | K_BIN_NOT + | K_BIN_OR + | K_BIN_SHL + | K_BIN_SHR + | K_BIN_XOR + | K_BLOB_APPEND + | K_BLOCK + | K_BODY + | K_BREAK + | K_CALLER + | K_CASCADE + | K_CEIL + | K_CEILING + | K_CERTIFICATE + | K_CHAR_TO_UUID + | K_CLEAR + | K_COALESCE + | K_COLLATION + | K_COLUMNS + | K_COMMAND + | K_COMMITTED + | K_COMMON + | K_COMPARE_DECFLOAT + | K_COMPUTED + | K_CONDITIONAL + | K_CONNECTIONS + | K_CONSISTENCY + | K_CONTAINING + | K_CONTENTS + | K_CONTINUE + | K_COS + | K_COSH + | K_COT + | K_COUNTER + | K_CPU_LOAD + | K_CREATE_FILE + | K_CRYPT_HASH + | K_CSTRING + | K_CTR_BIG_ENDIAN + | K_CTR_LENGTH + | K_CTR_LITTLE_ENDIAN + | K_CUME_DIST + | K_CURRENT_LABEL + | K_DAMLEV + | K_DATA + | K_DATABASE + | K_DATEADD + | K_DATEDIFF + | K_DDL + | K_DEBUG + | K_DECODE + | K_DECRYPT + | K_DEFINER + | K_DELETE_FILE + | K_DENSE_RANK + | K_DESC + | K_DESCENDING + | K_DESCRIPTOR + | K_DIFFERENCE + | K_DISABLE + | K_DO + | K_DOMAIN + | K_DUMP + | K_EMPTY + | K_ENABLE + | K_ENCRYPT + | K_ENGINE + | K_ENTRY_POINT + | K_ERROR + | K_EXCEPTION + | K_EXCESS + | K_EXCLUDE + | K_EXIT + | K_EXP + | K_EXTENDED + | K_FILE + | K_FIRST + | K_FIRSTNAME + | K_FIRST_DAY + | K_FIRST_VALUE + | K_FLOOR + | K_FOLLOWING + | K_FORMAT + | K_FREE_IT + | K_GENERATED + | K_GENERATOR + | K_GEN_ID + | K_GEN_UUID + | K_GOSTPASSWORD + | K_GRANTED + | K_GSS + | K_HASH + | K_HASH_CP + | K_HEX_DECODE + | K_HEX_ENCODE + | K_IDENTITY + | K_IDLE + | K_IF + | K_IGNORE + | K_IIF + | K_INACTIVE + | K_INCLUDE + | K_INCLUDING + | K_INCREMENT + | K_INITIAL_LABEL + | K_INPUT_TYPE + | K_INVOKER + | K_ISOLATION + | K_IS_LABEL_VALID + | K_IV + | K_JOB + | K_JSON + | K_JSON_ARRAY + | K_JSON_ARRAYAGG + | K_JSON_EXISTS + | K_JSON_MODIFY + | K_JSON_OBJECT + | K_JSON_OBJECTAGG + | K_JSON_QUERY + | K_JSON_TABLE + | K_JSON_VALUE + | K_KEEP + | K_KEY + | K_KEYS + | K_LAG + | K_LAST + | K_LASTNAME + | K_LAST_DAY + | K_LAST_VALUE + | K_LDAP_ATTR + | K_LDAP_GROUPS + | K_LDAP_USER_GROUPS + | K_LEAD + | K_LEAVE + | K_LEGACY + | K_LENGTH + | K_LEVEL + | K_LIFETIME + | K_LIMBO + | K_LINGER + | K_LIST + | K_LN + | K_LOCK + | K_LOCKED + | K_LOG + | K_LOG10 + | K_LPAD + | K_LPARAM + | K_MAKE_DBKEY + | K_MANUAL + | K_MAPPING + | K_MATCHED + | K_MATCHING + | K_MAXVALUE + | K_MAX_FAILED_COUNT + | K_MAX_IDLE_TIME + | K_MAX_SESSIONS + | K_MAX_UNUSED_DAYS + | K_MESSAGE + | K_MIDDLENAME + | K_MILLISECOND + | K_MINVALUE + | K_MOD + | K_MODE + | K_MODULE_NAME + | K_NAME + | K_NAMES + | K_NATIVE + | K_NEXT + | K_NORMALIZE_DECFLOAT + | K_NTH_VALUE + | K_NTILE + | K_NULLIF + | K_NULLS + | K_NUMBER + | K_OBJECT + | K_OFFLINE + | K_OLDEST + | K_OMIT + | K_ONCE + | K_ONLINE + | K_OPTIMIZE + | K_OPTION + | K_OS_NAME + | K_OTHERS + | K_OUTPUT_TYPE + | K_OVERFLOW + | K_OVERLAY + | K_OVERRIDING + | K_OWNER + | K_PACKAGE + | K_PAD + | K_PAGE + | K_PAGES + | K_PAGE_SIZE + | K_PARTITION + | K_PASSWORD + | K_PERCENT_RANK + | K_PI + | K_PIN + | K_PKCS_1_5 + | K_PLACING + | K_PLUGIN + | K_POLICY + | K_POOL + | K_POWER + | K_PRECEDING + | K_PRESERVE + | K_PRIMARY + | K_PRIOR + | K_PRIVILEGE + | K_PRIVILEGES + | K_PROTECTED + | K_PSWD_MIN_LEN + | K_PSWD_NEED_CHAR + | K_PSWD_NEED_DIFF_CASE + | K_PSWD_NEED_DIGIT + | K_PSWD_UNIQUE_COUNT + | K_PSWD_VALID_DAYS + | K_QUANTIZE + | K_QUOTES + | K_RAND + | K_RANGE + | K_RANK + | K_READ + | K_READ_FILE + | K_REGEXP_SUBSTR + | K_RELATIVE + | K_REPLACE + | K_REQUESTS + | K_RESERV + | K_RESERVING + | K_RESET + | K_RESTART + | K_RESTRICT + | K_RETAIN + | K_RETURNING + | K_REVERSE + | K_ROLE + | K_ROUND + | K_ROW_NUMBER + | K_RPAD + | K_RSA_DECRYPT + | K_RSA_ENCRYPT + | K_RSA_PRIVATE + | K_RSA_PUBLIC + | K_RSA_SIGN_HASH + | K_RSA_VERIFY_HASH + | K_RUN + | K_SALT_LENGTH + | K_SCALAR + | K_SCALAR_ARRAY + | K_SECURITY + | K_SEGMENT + | K_SEQUENCE + | K_SERVERWIDE + | K_SESSION + | K_SHADOW + | K_SHARED + | K_SIGN + | K_SIGNATURE + | K_SIN + | K_SINGULAR + | K_SINH + | K_SIZE + | K_SKIP + | K_SNAPSHOT + | K_SORT + | K_SOURCE + | K_SPACE + | K_SQL + | K_SQRT + | K_SRP + | K_STABILITY + | K_STARTING + | K_STARTS + | K_STATEMENT + | K_STATISTICS + | K_STRING + | K_SUBSTRING + | K_SUB_TYPE + | K_SUSPEND + | K_SYSTEM + | K_TABLESPACE + | K_TAGS + | K_TAN + | K_TANH + | K_TARGET + | K_TEMPORARY + | K_TIES + | K_TIMEOUT + | K_TIMEZONE_NAME + | K_TOTALORDER + | K_TRANSACTION + | K_TRAPS + | K_TRUNC + | K_TRUSTED + | K_TWO_PHASE + | K_TYPE + | K_UNCOMMITTED + | K_UNCONDITIONAL + | K_UNDO + | K_UNICODE_CHAR + | K_UNICODE_VAL + | K_USAGE + | K_UTC_TIMESTAMP + | K_UUID_TO_CHAR + | K_VERIFYSERVER + | K_WAIT + | K_WEEK + | K_WEEKDAY + | K_WIN_SSPI + | K_WORK + | K_WRAPPER + | K_WRITE + | K_YEARDAY + | K_ZONE; + + //[a-zA-Z_0-9\t \-\[\]\=]+ unknown : .+ From 269b5a742957c3115ca86eaa8081115a956a287f Mon Sep 17 00:00:00 2001 From: "mikhail.kalyashin" Date: Tue, 26 Nov 2024 15:00:40 +0300 Subject: [PATCH 06/41] See RS-205460 fix work with non-reserved keywords part2 --- .../databasemediators/DatabaseConnection.java | 2 + .../spi/DefaultDatabaseConnection.java | 39 +- .../spi/TemplateDatabaseConnection.java | 5 + .../executequery/keywords/firebird.keywords | 3 - .../keywords/firebird.reserved.keywords | 538 ++++++++++++++++ .../keywords/reddatabase.reserved.keywords | 590 ++++++++++++++++++ .../repository/KeywordRepository.java | 4 +- .../repository/spi/KeywordRepositoryImpl.java | 53 +- src/org/underworldlabs/util/MiscUtils.java | 2 +- 9 files changed, 1208 insertions(+), 28 deletions(-) create mode 100644 src/org/executequery/keywords/firebird.reserved.keywords create mode 100644 src/org/executequery/keywords/reddatabase.reserved.keywords diff --git a/src/org/executequery/databasemediators/DatabaseConnection.java b/src/org/executequery/databasemediators/DatabaseConnection.java index b83783191..2dfd8c508 100644 --- a/src/org/executequery/databasemediators/DatabaseConnection.java +++ b/src/org/executequery/databasemediators/DatabaseConnection.java @@ -231,6 +231,8 @@ public interface DatabaseConnection extends Serializable { TreeSet getKeywords(); + TreeSet getReservedKeywords(); + void setServerName(String serverName); void setAutoConnect(boolean val); diff --git a/src/org/executequery/databasemediators/spi/DefaultDatabaseConnection.java b/src/org/executequery/databasemediators/spi/DefaultDatabaseConnection.java index 016ea1771..d64a0dba7 100644 --- a/src/org/executequery/databasemediators/spi/DefaultDatabaseConnection.java +++ b/src/org/executequery/databasemediators/spi/DefaultDatabaseConnection.java @@ -40,6 +40,7 @@ import org.underworldlabs.util.MiscUtils; import javax.swing.tree.TreeNode; +import java.sql.ResultSet; import java.util.Enumeration; import java.util.Properties; import java.util.TreeSet; @@ -211,6 +212,7 @@ public class DefaultDatabaseConnection implements DatabaseConnection { private transient PasswordEncoderDecoder encoderDecoder; TreeSet keywords; + TreeSet reservedKeywords; String serverName; private boolean namesToUpperCase = true; @@ -877,11 +879,46 @@ public void setTunnelPort(int val) { public TreeSet getKeywords() { if (keywords == null) { keywords = new TreeSet(); - keywords.addAll(keywords().getServerKeywords(getMajorServerVersion(), getMinorServerVersion(), getServerName())); + if (getMajorServerVersion() >= 5) { + DefaultStatementExecutor querySender = new DefaultStatementExecutor(this); + try { + ResultSet rs = querySender.getResultSet("SELECT K.RDB$KEYWORD_NAME FROM RDB$KEYWORDS K").getResultSet(); + while (rs.next()) { + keywords.add(MiscUtils.trimEnd(rs.getString(1))); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + querySender.releaseResources(); + } + + } else + keywords.addAll(keywords().getServerKeywords(getMajorServerVersion(), getMinorServerVersion(), getServerName())); } return keywords; } + public TreeSet getReservedKeywords() { + if (reservedKeywords == null) { + reservedKeywords = new TreeSet(); + if (getMajorServerVersion() >= 5) { + DefaultStatementExecutor querySender = new DefaultStatementExecutor(this); + try { + ResultSet rs = querySender.getResultSet("SELECT K.RDB$KEYWORD_NAME FROM RDB$KEYWORDS K WHERE K.RDB$KEYWORD_RESERVED=TRUE").getResultSet(); + while (rs.next()) { + reservedKeywords.add(MiscUtils.trimEnd(rs.getString(1))); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + querySender.releaseResources(); + } + } else + reservedKeywords.addAll(keywords().getServerReservedKeywords(getMajorServerVersion(), getMinorServerVersion(), getServerName())); + } + return reservedKeywords; + } + @Override public void setValues(DatabaseConnection source) { setSourceName(source.getSourceName()); diff --git a/src/org/executequery/databasemediators/spi/TemplateDatabaseConnection.java b/src/org/executequery/databasemediators/spi/TemplateDatabaseConnection.java index 5bf2d8180..d8211da99 100644 --- a/src/org/executequery/databasemediators/spi/TemplateDatabaseConnection.java +++ b/src/org/executequery/databasemediators/spi/TemplateDatabaseConnection.java @@ -793,6 +793,11 @@ public TreeSet getKeywords() { return null; } + @Override + public TreeSet getReservedKeywords() { + return null; + } + @Override public void setAutoConnect(boolean val) { isAutoConnected = val; diff --git a/src/org/executequery/keywords/firebird.keywords b/src/org/executequery/keywords/firebird.keywords index a73273d30..df4333dce 100644 --- a/src/org/executequery/keywords/firebird.keywords +++ b/src/org/executequery/keywords/firebird.keywords @@ -52,7 +52,6 @@ DEFAULT DELETE DESC DESCRIPTOR -DESCRIPTOR DISTINCT DOMAIN DOUBLE @@ -67,7 +66,6 @@ EXTERNAL EXTRACT FETCH FIRST -FIRST FLOAT FOR FOREIGN @@ -146,7 +144,6 @@ SOME SPACE SQLCODE SUBSTRING -SUBSTRING SUM TABLE THEN diff --git a/src/org/executequery/keywords/firebird.reserved.keywords b/src/org/executequery/keywords/firebird.reserved.keywords new file mode 100644 index 000000000..a8248162c --- /dev/null +++ b/src/org/executequery/keywords/firebird.reserved.keywords @@ -0,0 +1,538 @@ +Firebird 1.0 + +ADD +ALL +ALTER +AND +ANY +AS +ASC +AT +AVG +BEGIN +BETWEEN +BIT_LENGTH +BOTH +BY +CASE +CAST +CHAR +CHARACTER +CHARACTER_LENGTH +CHAR_LENGTH +CHECK +CLOSE +COLLATE +COLUMN +COMMIT +COMMITTED +CONSTRAINT +COUNT +CREATE +CROSS +CURRENT +CURRENT_DATE +CURRENT_ROLE +CURRENT_TIME +CURRENT_TIMESTAMP +CURRENT_USER +CURRENT_USER +CURSOR +DATE +DAY +DEC +DECIMAL +DECLARE +DEFAULT +DELETE +DESC +DISTINCT +DOMAIN +DOUBLE +DROP +ELSE +END +ESCAPE +EXCEPTION +EXECUTE +EXISTS +EXTERNAL +EXTRACT +FETCH +FLOAT +FOR +FOREIGN +FROM +FULL +GRANT +GROUP +HAVING +HOUR +IN +INDEX +INNER +INSENSITIVE +INSERT +INT +INTEGER +INTO +IS +ISOLATION +JOIN +KEY +LEADING +LEFT +LENGTH +LEVEL +LIKE +LOWER +MAX +MIN +MINUTE +MONTH +NAMES +NATIONAL +NATURAL +NCHAR +NO +NOT +NULL +NUMERIC +OCTET_LENGTH +OF +ON +ONLY +OPEN +OPTION +OR +ORDER +OUTER +POSITION +PRECISION +PRIMARY +PRIVILEGES +PROCEDURE +READ +REAL +RECREATE +REFERENCES +REVOKE +RIGHT +ROLLBACK +ROWS +ROW_COUNT +SCHEMA +SECOND +SELECT +SET +SIZE +SMALLINT +SOME +SQLCODE +SUM +TABLE +THEN +TIME +TIMESTAMP +TO +TRAILING +TRANSACTION +TRIM +UNCOMMITTED +UNION +UNIQUE +UPDATE +UPPER +USER +USING +VALUE +VALUES +VARCHAR +VARYING +VIEW +WHEN +WHERE +WITH +WORK +WRITE +YEAR + +Firebird 1.5 + +BIGINT +CURRENT_CONNECTION +CURRENT_TRANSACTION +RELEASE +SAVEPOINT + +Firebird 2.0 + +ACTIVE +ADMIN +AFTER +ASCENDING +AUTO +BEFORE +BLOB +COMPUTED +CONDITIONAL +CONTAINING +CSTRING +DATABASE +DEBUG +DESCENDING +DO +ENTRY_POINT +EXIT +FILE +FILTER +FUNCTION +GDSCODE +GEN_ID +GENERATOR +IF +INACTIVE +INPUT_TYPE +LONG +MANUAL +MAXIMUM_SEGMENT +MERGE +MESSAGE +MODULE_NAME +OUTPUT_TYPE +OVERFLOW +PAGE +PAGE_SIZE +PAGES +PARAMETER +PASSWORD +PLAN +POST_EVENT +PROTECTED +RDB$DB_KEY +RECORD_VERSION +RESERV +RESERVING +RETAIN +RETURNING_VALUES +RETURNS +SEGMENT +SENSITIVE +SHADOW +SHARED +SINGULAR +SNAPSHOT +SORT +STABILITY +STARTING +STARTS +STATISTICS +SUB_TYPE +SUSPEND +TRIGGER +VARIABLE +WAIT +WHILE + +Firebird 2.1 + +ABS +ACOS +ASCII_CHAR +ASCII_VAL +ASIN +ATAN +ATAN2 +BIN_AND +BIN_OR +BIN_SHL +BIN_SHR +BIN_XOR +CEIL +CEILING +CONNECT +COS +COSH +COT +DATEADD +DATEDIFF +DECODE +DISCONNECT +EXP +FLOOR +GEN_UUID +GLOBAL +HASH +LIST +LN +LOG +LOG10 +LPAD +MATCHED +MATCHING +MAXVALUE +MILLISECOND +MINVALUE +MOD +OVERLAY +PI +PLACING +POWER +RAND +RECURSIVE +REPLACE +REVERSE +ROUND +RPAD +SIGN +SIN +SINH +SQRT +START +TAN +TANH +TRUNC +WEEK + +-MESSAGE + +Firebird 2.5 + +AUTONOMOUS +BIN_NOT +CHAR_TO_UUID +FIRSTNAME +GRANTED +LASTNAME +LOCALTIME +LOCALTIMESTAMP +MAPPING +MIDDLENAME +OS_NAME +SIMILAR +SQLSTATE +UUID_TO_CHAR + +-DEBUG + +Firebird 3.0 + +ACOSH +ASINH +ATANH +BOOLEAN +CORR +COVAR_POP +COVAR_SAMP +DDL +DENSE_RANK +DETERMINISTIC +FALSE +FIRST_VALUE +IDENTITY +INCREMENT +LAG +LAST_VALUE +LEAD +NTH_VALUE +OFFSET +OVER +PARTITION +RANK +RDB$RECORD_VERSION +REGR_AVGX +REGR_AVGY +REGR_COUNT +REGR_INTERCEPT +REGR_R2 +REGR_SLOPE +REGR_SXX +REGR_SXY +REGR_SYY +RETURN +ROW +ROW_NUMBER +SCROLL +STDDEV_POP +STDDEV_SAMP +TRUE +TRUSTED +UNKNOWN +VAR_POP +VAR_SAMP + +-LOCALTIME +-LOCALTIMESTAMP +-MAXIMUM_SEGMENT + +Firebird 4.0 + +BINARY +COMMENT +DECFLOAT +DELETING +INSERTING +INT128 +LATERAL +LOCAL +LOCALTIME +LOCALTIMESTAMP +PUBLICATION +RDB$ERROR +RDB$GET_CONTEXT +RDB$GET_TRANSACTION_CN +RDB$ROLE_IN_USE +RDB$SET_CONTEXT +RDB$SYSTEM_PRIVILEGE +RESETTING +TIMEZONE_HOUR +TIMEZONE_MINUTE +UNBOUNDED +UPDATING +VARBINARY +WINDOW +WITHOUT + +-ABS +-ACOS +-ACOSH +-ACTIVE +-AFTER +-ASC +-ASCENDING +-ASCII_CHAR +-ASCII_VAL +-ASIN +-ASINH +-ATAN +-ATAN2 +-ATANH +-AUTO +-AUTONOMOUS +-BEFORE +-BIN_AND +-BIN_NOT +-BIN_OR +-BIN_SHL +-BIN_SHR +-BIN_XOR +-CEIL +-CEILING +-CHAR_TO_UUID +-COMMITTED +-COMPUTED +-CONDITIONAL +-CONTAINING +-COS +-COSH +-COT +-CSTRING +-DATABASE +-DATEADD +-DATEDIFF +-DDL +-DECODE +-DENSE_RANK +-DESC +-DESCENDING +-DO +-DOMAIN +-ENTRY_POINT +-EXCEPTION +-EXIT +-EXP +-FILE +-FIRST_VALUE +-FIRSTNAME +-FLOOR +-GEN_ID +-GEN_UUID +-GENERATOR +-GRANTED +-HASH +-IDENTITY +-IF +-INACTIVE +-INCREMENT +-INPUT_TYPE +-ISOLATION +-KEY +-LAG +-LAST_VALUE +-LASTNAME +-LEAD +-LENGTH +-LEVEL +-LIST +-LN +-LOG +-LOG10 +-LPAD +-MANUAL +-MAPPING +-MATCHED +-MATCHING +-MAXVALUE +-MIDDLENAME +-MILLISECOND +-MINVALUE +-MOD +-MODULE_NAME +-NAMES +-NTH_VALUE +-OPTION +-OS_NAME +-OUTPUT_TYPE +-OVERFLOW +-OVERLAY +-PAGE +-PAGE_SIZE +-PAGES +-PARTITION +-PASSWORD +-PI +-PLACING +-POWER +-PRIVILEGES +-PROTECTED +-RAND +-RANK +-READ +-REPLACE +-RESERV +-RESERVING +-RETAIN +-REVERSE +-ROUND +-ROW_NUMBER +-RPAD +-SEGMENT +-SHADOW +-SHARED +-SIGN +-SIN +-SINGULAR +-SINH +-SIZE +-SNAPSHOT +-SORT +-SQRT +-STABILITY +-STARTING +-STARTS +-STATISTICS +-SUB_TYPE +-SUSPEND +-TAN +-TANH +-TRANSACTION +-TRUNC +-TRUSTED +-UNCOMMITTED +-UUID_TO_CHAR +-WAIT +-WEEK +-WORK +-WRITE + +Firebird 5.0 diff --git a/src/org/executequery/keywords/reddatabase.reserved.keywords b/src/org/executequery/keywords/reddatabase.reserved.keywords new file mode 100644 index 000000000..adfd42b44 --- /dev/null +++ b/src/org/executequery/keywords/reddatabase.reserved.keywords @@ -0,0 +1,590 @@ +RedDatabase 2.6 + +ABS +ACOS +ACTIVE +ADD +ADMIN +AFTER +ALL +ALTER +AND +ANY +AS +ASC +ASCENDING +ASCII_CHAR +ASCII_VAL +ASIN +AT +ATAN +ATAN2 +AUTO +AUTONOMOUS +AVG +BEFORE +BEGIN +BETWEEN +BIGINT +BIN_AND +BIN_NOT +BIN_OR +BIN_SHL +BIN_SHR +BIN_XOR +BIT_LENGTH +BLOB +BOTH +BY +CASE +CAST +CEIL +CEILING +CHAR +CHAR_LENGTH +CHAR_TO_UUID +CHARACTER +CHARACTER_LENGTH +CHECK +CLOSE +COLFILTER +COLLATE +COLUMN +COMMIT +COMMITTED +COMPUTED +CONDITIONAL +CONNECT +CONSTRAINT +CONTAINING +COS +COSH +COT +COUNT +CREATE +CROSS +CSTRING +CURRENT +CURRENT_CONNECTION +CURRENT_DATE +CURRENT_ROLE +CURRENT_TIME +CURRENT_TIMESTAMP +CURRENT_TRANSACTION +CURRENT_USER +CURSOR +DATABASE +DATE +DATEADD +DATEDIFF +DAY +DEC +DECIMAL +DECLARE +DECODE +DECRYPT +DEFAULT +DELETE +DESC +DESCENDING +DISCONNECT +DISTINCT +DO +DOMAIN +DOUBLE +DROP +ELSE +ENCRYPT +END +ENTRY_POINT +ESCAPE +EXCEPTION +EXECUTE +EXISTS +EXIT +EXP +EXTERNAL +EXTRACT +FETCH +FILE +FILTER +FIRSTNAME +FLOAT +FLOOR +FOR +FOREIGN +FROM +FULL +FUNCTION +GDSCODE +GEN_ID +GEN_UUID +GENERATOR +GLOBAL +GRANT +GRANTED +GROUP +HASH +HAVING +HOUR +IF +IN +INACTIVE +INDEX +INNER +INPUT_TYPE +INSENSITIVE +INSERT +INT +INTEGER +INTO +IS +ISOLATION +JOIN +KEY +LABEL +LASTNAME +LEADING +LEFT +LENGTH +LEVEL +LIKE +LIST +LN +LOCALTIME +LOCALTIMESTAMP +LOG +LOG10 +LONG +LOWER +LPAD +MAC +MANUAL +MAPPING +MATCHED +MATCHING +MAX +MAXIMUM_SEGMENT +MAXVALUE +MERGE +MIDDLENAME +MILLISECOND +MIN +MINUTE +MINVALUE +MOD +MODULE_NAME +MONTH +NAMES +NATIONAL +NATURAL +NCHAR +NO +NOT +NULL +NUMERIC +OCTET_LENGTH +OF +ON +ONLY +OPEN +OPTION +OR +ORDER +OS_NAME +OUTER +OUTPUT_TYPE +OVERFLOW +OVERLAY +PAGE +PAGE_SIZE +PAGES +PARAMETER +PASSWORD +PI +PLACING +PLAN +POLICY +POSITION +POST_EVENT +POWER +PRECISION +PRIMARY +PRIVILEGES +PROCEDURE +PROTECTED +RAND +RDB$DB_KEY +READ +REAL +RECFILTER +RECORD_VERSION +RECREATE +RECURSIVE +REFERENCES +REGEXP_SUBSTR +RELEASE +REPLACE +RESERV +RESERVING +RETAIN +RETURNING_VALUES +RETURNS +REVERSE +REVOKE +RIGHT +ROLLBACK +ROUND +ROW_COUNT +ROWS +RPAD +SAVEPOINT +SCHEMA +SECOND +SEGMENT +SELECT +SENSITIVE +SET +SHADOW +SHARED +SIGN +SIMILAR +SIN +SINGULAR +SINH +SIZE +SMALLINT +SNAPSHOT +SOME +SORT +SQLCODE +SQLSTATE +SQRT +STABILITY +START +STARTING +STARTS +STATISTICS +SUB_TYPE +SUM +SUSPEND +TABLE +TAN +TANH +THEN +TIME +TIMESTAMP +TO +TRAILING +TRANSACTION +TRIGGER +TRIM +TRUNC +UNCOMMITTED +UNION +UNIQUE +UPDATE +UPPER +USER +USING +UUID_TO_CHAR +VALUE +VALUES +VARCHAR +VARIABLE +VARYING +VIEW +WAIT +WEEK +WHEN +WHERE +WHILE +WITH +WORK +WRITE +YEAR + +RedDatabase 3.0 + +ACOSH +ASINH +ATANH +AUTH_FACTORS +BOOLEAN +CERT_X509 +CORR +COVAR_POP +COVAR_SAMP +CPU_LOAD +CREATE_FILE +DAMLEV +DDL +DELETE_FILE +DENSE_RANK +DETERMINISTIC +FALSE +FIRST_VALUE +HASH_CP +IDENTITY +INCREMENT +LAG +LAST_VALUE +LDAP_ATTR +LDAP_GROUPS +LDAP_USER_GROUPS +LEAD +MAKE_DBKEY +MAX_FAILED_COUNT +MAX_IDLE_TIME +MAX_SESSIONS +MAX_UNUSED_DAYS +NTH_VALUE +OFFSET +OVER +PARTITION +PSWD_MIN_LEN +PSWD_NEED_CHAR +PSWD_NEED_DIFF_CASE +PSWD_NEED_DIGIT +PSWD_UNIQUE_COUNT +PSWD_VALID_DAYS +RANK +RDB$RECORD_VERSION +RDB$ROLE_IN_USE +READ_FILE +REGR_AVGX +REGR_AVGY +REGR_COUNT +REGR_INTERCEPT +REGR_R2 +REGR_SLOPE +REGR_SXX +REGR_SXY +REGR_SYY +RESET +RETURN +ROW +ROW_NUMBER +SCROLL +STDDEV_POP +STDDEV_SAMP +TRUE +TRUSTED +UNKNOWN +UTC_TIMESTAMP +VAR_POP +VAR_SAMP +WINDOWS_NTLM + +-COLFILTER +-DECRYPT +-ENCRYPT +-LABEL +-LOCALTIME +-LOCALTIMESTAMP +-MAC +-MAXIMUM_SEGMENT +-RECFILTER + +RedDatabase 5.0 + +APPEND +BINARY +COMMENT +DECFLOAT +DELETING +GREATEST +HASHAGG +INSERTING +INT128 +LATERAL +LEAST +LOCAL +LOCALTIME +LOCALTIMESTAMP +PERMANENT +PUBLICATION +RDB$ERROR +RDB$GET_CONTEXT +RDB$GET_TRANSACTION_CN +RDB$SET_CONTEXT +RDB$SYSTEM_PRIVILEGE +RDB$TRACE_MSG +RESETTING +TIMEZONE_HOUR +TIMEZONE_MINUTE +UNBOUNDED +UPDATING +VARBINARY +WINDOW +WITHOUT + +-ABS +-ACOS +-ACOSH +-ACTIVE +-AFTER +-ASC +-ASCENDING +-ASCII_CHAR +-ASCII_VAL +-ASIN +-ASINH +-ATAN +-ATAN2 +-ATANH +-AUTH_FACTORS +-AUTO +-AUTONOMOUS +-BEFORE +-BIN_AND +-BIN_NOT +-BIN_OR +-BIN_SHL +-BIN_SHR +-BIN_XOR +-CEIL +-CEILING +-CERT_X509 +-CHAR_TO_UUID +-COMMITTED +-COMPUTED +-CONDITIONAL +-CONTAINING +-COS +-COSH +-COT +-CPU_LOAD +-CREATE_FILE +-CSTRING +-DAMLEV +-DATABASE +-DATEADD +-DATEDIFF +-DDL +-DECODE +-DELETE_FILE +-DENSE_RANK +-DESC +-DESCENDING +-DO +-DOMAIN +-ENTRY_POINT +-EXCEPTION +-EXIT +-EXP +-FILE +-FIRST_VALUE +-FIRSTNAME +-FLOOR +-GEN_ID +-GEN_UUID +-GENERATOR +-GRANTED +-HASH +-HASH_CP +-IDENTITY +-IF +-INACTIVE +-INCREMENT +-INPUT_TYPE +-ISOLATION +-KEY +-LAG +-LAST_VALUE +-LASTNAME +-LDAP_ATTR +-LDAP_GROUPS +-LDAP_USER_GROUPS +-LEAD +-LENGTH +-LEVEL +-LIST +-LN +-LOG +-LOG10 +-LPAD +-MAKE_DBKEY +-MANUAL +-MAPPING +-MATCHED +-MATCHING +-MAX_FAILED_COUNT +-MAX_IDLE_TIME +-MAX_SESSIONS +-MAX_UNUSED_DAYS +-MAXVALUE +-MIDDLENAME +-MILLISECOND +-MINVALUE +-MOD +-MODULE_NAME +-NAMES +-NTH_VALUE +-OPTION +-OS_NAME +-OUTPUT_TYPE +-OVERFLOW +-OVERLAY +-PAGE +-PAGE_SIZE +-PAGES +-PARTITION +-PASSWORD +-PI +-PLACING +-POLICY +-POWER +-PRIMARY +-PRIVILEGES +-PROTECTED +-PSWD_MIN_LEN +-PSWD_NEED_CHAR +-PSWD_NEED_DIFF_CASE +-PSWD_NEED_DIGIT +-PSWD_UNIQUE_COUNT +-PSWD_VALID_DAYS +-RAND +-RANK +-READ +-READ_FILE +-REGEXP_SUBSTR +-REPLACE +-RESERV +-RESERVING +-RESET +-RETAIN +-REVERSE +-ROUND +-ROW_NUMBER +-RPAD +-SEGMENT +-SHADOW +-SHARED +-SIGN +-SIN +-SINGULAR +-SINH +-SIZE +-SNAPSHOT +-SORT +-SQRT +-STABILITY +-STARTING +-STARTS +-STATISTICS +-SUB_TYPE +-SUSPEND +-TAN +-TANH +-TRANSACTION +-TRUNC +-TRUSTED +-UNCOMMITTED +-UTC_TIMESTAMP +-UUID_TO_CHAR +-WAIT +-WEEK +-WINDOWS_NTLM +-WORK +-WRITE \ No newline at end of file diff --git a/src/org/executequery/repository/KeywordRepository.java b/src/org/executequery/repository/KeywordRepository.java index 511a169dd..f106c3fcb 100644 --- a/src/org/executequery/repository/KeywordRepository.java +++ b/src/org/executequery/repository/KeywordRepository.java @@ -32,7 +32,7 @@ public interface KeywordRepository extends Repository { TreeSet getSQLKeywords(); - boolean contains(String word); - List getServerKeywords(int majorVersion, int minorVersion, String serverName); + + List getServerReservedKeywords(int majorVersion, int minorVersion, String serverName); } diff --git a/src/org/executequery/repository/spi/KeywordRepositoryImpl.java b/src/org/executequery/repository/spi/KeywordRepositoryImpl.java index aa387d436..f0d038514 100644 --- a/src/org/executequery/repository/spi/KeywordRepositoryImpl.java +++ b/src/org/executequery/repository/spi/KeywordRepositoryImpl.java @@ -38,11 +38,6 @@ public class KeywordRepositoryImpl implements KeywordRepository { private boolean keyWordsListUpdated; private TreeSet allWords; - @Override - public boolean contains(String word) { - return getSQLKeywords().contains(word); - } - @Override public synchronized TreeSet getSQLKeywords() { @@ -81,18 +76,8 @@ public List getDefaultKeywords() { } } - @Override - public List getServerKeywords(int majorVersion, int minorVersion, String serverName) { + List getKeywords(String path, int majorVersion, int minorVersion) { try { - - if (serverName != null && serverName.toLowerCase().contains("firebird")) { - serverName = "firebird"; - } else if (serverName != null && serverName.toLowerCase().contains("reddatabase")) { - serverName = "reddatabase"; - } else - serverName = "sql92"; - - String path = "org/executequery/keywords/" + serverName.toLowerCase() + ".keywords"; String values = FileUtils.loadResource(path); StringTokenizer st = new StringTokenizer(values, "\n"); @@ -133,11 +118,7 @@ public List getServerKeywords(int majorVersion, int minorVersion, String } else list.add(trim); } - - this.firebirdKeyWords = list; - keyWordsListUpdated = true; - list.addAll(getDefaultKeywords()); - return this.firebirdKeyWords; + return list; } catch (IOException e) { Log.error("Error retrieving SQL92 keyword list"); @@ -147,6 +128,36 @@ public List getServerKeywords(int majorVersion, int minorVersion, String } } + @Override + public List getServerKeywords(int majorVersion, int minorVersion, String serverName) { + if (serverName != null && serverName.toLowerCase().contains("firebird")) { + serverName = "firebird"; + } else if (serverName != null && serverName.toLowerCase().contains("reddatabase")) { + serverName = "reddatabase"; + } else + serverName = "sql92"; + + String path = "org/executequery/keywords/" + serverName.toLowerCase() + ".keywords"; + this.firebirdKeyWords = getKeywords(path, majorVersion, minorVersion); + keyWordsListUpdated = true; + this.firebirdKeyWords.addAll(getDefaultKeywords()); + return this.firebirdKeyWords; + + } + + @Override + public List getServerReservedKeywords(int majorVersion, int minorVersion, String serverName) { + if (serverName != null && serverName.toLowerCase().contains("firebird")) { + serverName = "firebird"; + } else if (serverName != null && serverName.toLowerCase().contains("reddatabase")) { + serverName = "reddatabase"; + } else + serverName = "sql92"; + + String path = "org/executequery/keywords/" + serverName.toLowerCase() + (serverName.contentEquals("sql92") ? "" : ".reserved") + ".keywords"; + return getKeywords(path, majorVersion, minorVersion); + } + @Override public String getId() { return REPOSITORY_ID; diff --git a/src/org/underworldlabs/util/MiscUtils.java b/src/org/underworldlabs/util/MiscUtils.java index 53eef9e28..3d58d31f5 100644 --- a/src/org/underworldlabs/util/MiscUtils.java +++ b/src/org/underworldlabs/util/MiscUtils.java @@ -783,7 +783,7 @@ public static boolean checkKeyword(String str, DatabaseConnection connection) { TreeSet keywords = keywords().getSQLKeywords(); if (connection != null) - keywords = connection.getKeywords(); + keywords = connection.getReservedKeywords(); return keywords.contains(str.toUpperCase()); } From e001e0636f59126421b1c3f9ab0317b7a7d14de3 Mon Sep 17 00:00:00 2001 From: "mikhail.kalyashin" Date: Thu, 28 Nov 2024 13:16:45 +0300 Subject: [PATCH 07/41] See RS-205460 fix generate sql for variables with collate --- src/org/executequery/databaseobjects/Parameter.java | 9 +++++++++ .../gui/procedure/CreateProcedureFunctionPanel.java | 2 ++ src/org/underworldlabs/util/SQLUtils.java | 3 +++ 3 files changed, 14 insertions(+) diff --git a/src/org/executequery/databaseobjects/Parameter.java b/src/org/executequery/databaseobjects/Parameter.java index 58a8ba9d3..3bd0ea8a3 100644 --- a/src/org/executequery/databaseobjects/Parameter.java +++ b/src/org/executequery/databaseobjects/Parameter.java @@ -28,6 +28,7 @@ public class Parameter { protected boolean defaultValueFromDomain = false; protected boolean descriptionAsSingleComment; protected String systemDomain; + protected String collate; public int getDataType() { return dataType; @@ -218,5 +219,13 @@ public boolean isDefaultValueFromDomain() { public void setDefaultValueFromDomain(boolean defaultValueFromDomain) { this.defaultValueFromDomain = defaultValueFromDomain; } + + public String getCollate() { + return collate; + } + + public void setCollate(String collate) { + this.collate = collate; + } } diff --git a/src/org/executequery/gui/procedure/CreateProcedureFunctionPanel.java b/src/org/executequery/gui/procedure/CreateProcedureFunctionPanel.java index a0d61b6ce..afaf03eec 100644 --- a/src/org/executequery/gui/procedure/CreateProcedureFunctionPanel.java +++ b/src/org/executequery/gui/procedure/CreateProcedureFunctionPanel.java @@ -444,6 +444,8 @@ public void enterDeclare_block_without_params(ProcedureParserParser.Declare_bloc if (var.default_statement() != null) variable.setDefaultValue(var.default_statement().getText()); + if (var.order_collate() != null) + variable.setCollate(var.order_collate().getText()); if (var.comment() != null) { diff --git a/src/org/underworldlabs/util/SQLUtils.java b/src/org/underworldlabs/util/SQLUtils.java index d9dd757ac..ec26d110f 100644 --- a/src/org/underworldlabs/util/SQLUtils.java +++ b/src/org/underworldlabs/util/SQLUtils.java @@ -819,6 +819,8 @@ public static String formattedParameter(ColumnData cd, boolean variable) { sb.append(cd.getFormattedDataType()); sb.append(cd.isNotNull() ? " NOT NULL" : CreateTableSQLSyntax.EMPTY); + if (!MiscUtils.isNull(cd.getCollate())) + sb.append(" COLLATE ").append(cd.getCollate()); if (cd.getTypeParameter() != ColumnData.OUTPUT_PARAMETER && !MiscUtils.isNull(cd.getDefaultValue().getValue()) && !cd.getDefaultValue().isDomain() @@ -870,6 +872,7 @@ public static ColumnData columnDataFromProcedureParameter(Parameter parameter, D cd.setDefaultValue(parameter.getDefaultValue(), true, parameter.isDefaultValueFromDomain()); cd.setRemarkAsSingleComment(parameter.isDescriptionAsSingleComment()); cd.setColumnPosition(parameter.getPosition()); + cd.setCollate(parameter.getCollate()); String[] dataTypes = dc.getDataTypesArray(); int[] intDataTypes = dc.getIntDataTypesArray(); for (int i = 0; i < dataTypes.length; i++) { From 2e6f42f4323bbef4e2790f8b093c9ab3443f0d85 Mon Sep 17 00:00:00 2001 From: "mikhail.kalyashin" Date: Thu, 28 Nov 2024 13:43:42 +0300 Subject: [PATCH 08/41] See RS-201665 add format int numbers for table statistic --- .../managment/tracemanager/net/AnaliseRow.java | 18 +++++------------- src/org/executequery/sql/QueryDispatcher.java | 2 +- src/org/underworldlabs/util/MiscUtils.java | 13 +++++++++++++ 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/org/executequery/gui/browser/managment/tracemanager/net/AnaliseRow.java b/src/org/executequery/gui/browser/managment/tracemanager/net/AnaliseRow.java index 950cd36fb..c919ac843 100644 --- a/src/org/executequery/gui/browser/managment/tracemanager/net/AnaliseRow.java +++ b/src/org/executequery/gui/browser/managment/tracemanager/net/AnaliseRow.java @@ -2,6 +2,7 @@ import org.executequery.localization.Bundles; import org.executequery.log.Log; +import org.underworldlabs.util.MiscUtils; import java.awt.*; import java.util.ArrayList; @@ -271,7 +272,7 @@ public String getDisplayValue(boolean isRound) { break; } - } else displayValue = delimitValue(longValue, ""); + } else displayValue = MiscUtils.delimitValue(longValue, " "); if (percent != -1) displayValue = displayValue + " [" + percent + "%" + "]"; return displayValue; @@ -301,15 +302,6 @@ public void setRoundValue(boolean roundValue) { isRoundValue = roundValue; } - private String delimitValue(long value, String result) { - if (value >= 1000) { - String div = String.valueOf(value % 1000); - while (div.length() < 3) - div = "0" + div; - return delimitValue(value / 1000, " " + div + result); - } else return value + result; - } - public String roundBytes(long value) { String suff = "b"; while (value > 10000 && !suff.contentEquals("pb")) { @@ -334,7 +326,7 @@ public String roundBytes(long value) { break; } } - String result = delimitValue(value, "") + + String result = MiscUtils.delimitValue(value, " ") + suff; return result; } @@ -363,7 +355,7 @@ public String roundTime(long value) { break; } } - String result = delimitValue(value, "") + + String result = MiscUtils.delimitValue(value, " ") + suff; return result; } @@ -392,7 +384,7 @@ public String roundEvents(long value) { break; } } - String result = delimitValue(value, "") + + String result = MiscUtils.delimitValue(value, " ") + suff; return result; } diff --git a/src/org/executequery/sql/QueryDispatcher.java b/src/org/executequery/sql/QueryDispatcher.java index 6cebccda2..598b56cb3 100644 --- a/src/org/executequery/sql/QueryDispatcher.java +++ b/src/org/executequery/sql/QueryDispatcher.java @@ -1503,7 +1503,7 @@ private void printTableStat(Map beforeMap, boolean a sb.append("\t").append(entry.getKey()).append(":\n"); for (KeyValuePair elem : list) - sb.append("\t\t").append(elem.getKey()).append(" = ").append(elem.getValue()).append("\n"); + sb.append("\t\t").append(elem.getKey()).append(" = ").append(MiscUtils.delimitValue((long) elem.getValue(), "'")).append("\n"); } setOutputMessage(dc, SqlMessages.PLAIN_MESSAGE, sb.toString(), anyConnections); diff --git a/src/org/underworldlabs/util/MiscUtils.java b/src/org/underworldlabs/util/MiscUtils.java index 3d58d31f5..bc5eccfe9 100644 --- a/src/org/underworldlabs/util/MiscUtils.java +++ b/src/org/underworldlabs/util/MiscUtils.java @@ -885,5 +885,18 @@ public static String getNulladbleString(String value) { return value != null ? value : ""; } + public static String delimitValue(long value, String delimiter) { + return delimitValue(value, "", delimiter); + } + + public static String delimitValue(long value, String result, String delimiter) { + if (value >= 1000) { + String div = String.valueOf(value % 1000); + while (div.length() < 3) + div = "0" + div; + return delimitValue(value / 1000, delimiter + div + result, delimiter); + } else return value + result; + } + } From cde4c6370dacd1f3270fbdc34846dc5733babf43 Mon Sep 17 00:00:00 2001 From: "mikhail.kalyashin" Date: Thu, 28 Nov 2024 15:10:24 +0300 Subject: [PATCH 09/41] See RS-206635 fix loss of characters while trace parsing --- src/org/underworldlabs/traceparser/RedTrace.g4 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/org/underworldlabs/traceparser/RedTrace.g4 b/src/org/underworldlabs/traceparser/RedTrace.g4 index 94e1f2b2b..251930d5e 100644 --- a/src/org/underworldlabs/traceparser/RedTrace.g4 +++ b/src/org/underworldlabs/traceparser/RedTrace.g4 @@ -820,3 +820,7 @@ SPACE:(' ')+; TAB: '\t' ; + +UNKNOWN_CHAR: +. +; From 60fcae12bbd052711ae91e29c3f2750bc3b102e6 Mon Sep 17 00:00:00 2001 From: "mikhail.kalyashin" Date: Fri, 29 Nov 2024 10:28:41 +0300 Subject: [PATCH 10/41] Revert "See RS-206635 fix loss of characters while trace parsing" This reverts commit cde4c6370dacd1f3270fbdc34846dc5733babf43. --- src/org/underworldlabs/traceparser/RedTrace.g4 | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/org/underworldlabs/traceparser/RedTrace.g4 b/src/org/underworldlabs/traceparser/RedTrace.g4 index 251930d5e..94e1f2b2b 100644 --- a/src/org/underworldlabs/traceparser/RedTrace.g4 +++ b/src/org/underworldlabs/traceparser/RedTrace.g4 @@ -820,7 +820,3 @@ SPACE:(' ')+; TAB: '\t' ; - -UNKNOWN_CHAR: -. -; From 708bc68cf09f2633c4bd3d054cc05427fb63a5ad Mon Sep 17 00:00:00 2001 From: "mikhail.kalyashin" Date: Fri, 29 Nov 2024 10:47:07 +0300 Subject: [PATCH 11/41] See RS-206635 fix loss of characters while trace parsing --- src/org/underworldlabs/traceparser/RedTrace.g4 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/org/underworldlabs/traceparser/RedTrace.g4 b/src/org/underworldlabs/traceparser/RedTrace.g4 index 94e1f2b2b..6e0568002 100644 --- a/src/org/underworldlabs/traceparser/RedTrace.g4 +++ b/src/org/underworldlabs/traceparser/RedTrace.g4 @@ -625,7 +625,7 @@ fragment TWO_DIGIT ; id -:(LETTER|DIGIT|IP_SEG)+ +:(LETTER|DIGIT|IP_SEG|'#')+ ; any_name @@ -820,3 +820,7 @@ SPACE:(' ')+; TAB: '\t' ; + +UNKNOWN_CHAR: +. +; \ No newline at end of file From 359e07fbfe353c132b93773f0a972393a63bc4b5 Mon Sep 17 00:00:00 2001 From: "mikhail.kalyashin" Date: Fri, 29 Nov 2024 18:51:09 +0300 Subject: [PATCH 12/41] store the audit text in a single instance to save memory --- .../browser/managment/tracemanager/net/AnaliseRow.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/org/executequery/gui/browser/managment/tracemanager/net/AnaliseRow.java b/src/org/executequery/gui/browser/managment/tracemanager/net/AnaliseRow.java index c919ac843..3cd448681 100644 --- a/src/org/executequery/gui/browser/managment/tracemanager/net/AnaliseRow.java +++ b/src/org/executequery/gui/browser/managment/tracemanager/net/AnaliseRow.java @@ -10,7 +10,6 @@ public class AnaliseRow { LogMessage logMessage; - StringBuilder logMessages; public final static int TIME = 0; public final static int READ = TIME + 1; public final static int FETCH = READ + 1; @@ -59,7 +58,10 @@ public LogMessage getLogMessage() { } public String getLogMessages() { - return logMessages.toString(); + StringBuilder sb = new StringBuilder(); + for (LogMessage msg : allRows) + sb.append(msg.getBody()); + return sb.toString(); } public void setLogMessage(LogMessage logMessage) { @@ -68,7 +70,6 @@ public void setLogMessage(LogMessage logMessage) { public AnaliseRow() { allRows = new ArrayList<>(); - logMessages = new StringBuilder(); rows = new List[TYPES.length]; for (int i = 0; i < TYPES.length; i++) { rows[i] = new ArrayList<>(); @@ -157,7 +158,6 @@ void calculateValues(int type) { public void addMessage(LogMessage msg) { allRows.add(msg); - logMessages.append(msg.getBody()).append("\n"); if (msg.getPlanText() != null) { if (plans.isEmpty()) plans.add(msg.getPlanText()); From 3be12981c1c203b90f84e08586b99bb14277b52e Mon Sep 17 00:00:00 2001 From: "mikhail.kalyashin" Date: Mon, 2 Dec 2024 10:44:30 +0300 Subject: [PATCH 13/41] See RS-206959 fix cursor parsing --- src/org/underworldlabs/procedureParser/ProcedureParser.g4 | 2 +- src/org/underworldlabs/util/SQLUtils.java | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/org/underworldlabs/procedureParser/ProcedureParser.g4 b/src/org/underworldlabs/procedureParser/ProcedureParser.g4 index f5f80a9a3..984d3774e 100644 --- a/src/org/underworldlabs/procedureParser/ProcedureParser.g4 +++ b/src/org/underworldlabs/procedureParser/ProcedureParser.g4 @@ -109,7 +109,7 @@ body: ; cursor: - K_CURSOR spases_or_comment K_FOR (spases_or_comment scroll)? spases_or_comment operator_select + (scroll spases_or_comment)?K_CURSOR spases_or_comment K_FOR spases_or_comment operator_select ; operator_select: diff --git a/src/org/underworldlabs/util/SQLUtils.java b/src/org/underworldlabs/util/SQLUtils.java index ec26d110f..560aa0fde 100644 --- a/src/org/underworldlabs/util/SQLUtils.java +++ b/src/org/underworldlabs/util/SQLUtils.java @@ -768,10 +768,9 @@ public static String formattedParameters(Vector tableVector, boolean sb.append("DECLARE "); if (cd.isCursor()) { - - sb.append(cd.getColumnName()).append(" CURSOR FOR "); if (cd.isScroll()) - sb.append("SCROLL "); + sb.append(" SCROLL"); + sb.append(cd.getColumnName()).append(" CURSOR FOR "); sb.append("(").append(cd.getSelectOperator()).append(")"); } else { From ae82cc33d4e56ea9217cfd87414a4905630dd62b Mon Sep 17 00:00:00 2001 From: "mikhail.kalyashin" Date: Tue, 3 Dec 2024 10:23:28 +0300 Subject: [PATCH 14/41] See RS-206959 fix sql generation for cursors --- src/org/underworldlabs/util/SQLUtils.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/org/underworldlabs/util/SQLUtils.java b/src/org/underworldlabs/util/SQLUtils.java index 560aa0fde..b333f0b7c 100644 --- a/src/org/underworldlabs/util/SQLUtils.java +++ b/src/org/underworldlabs/util/SQLUtils.java @@ -768,9 +768,10 @@ public static String formattedParameters(Vector tableVector, boolean sb.append("DECLARE "); if (cd.isCursor()) { + sb.append(cd.getColumnName()); if (cd.isScroll()) sb.append(" SCROLL"); - sb.append(cd.getColumnName()).append(" CURSOR FOR "); + sb.append(" CURSOR FOR "); sb.append("(").append(cd.getSelectOperator()).append(")"); } else { From 009c1ebae17599d9052ca65cd2f9611f9124cb3c Mon Sep 17 00:00:00 2001 From: "aleksey.kozlov" Date: Tue, 3 Dec 2024 10:49:39 +0300 Subject: [PATCH 15/41] Improve fbclient library unpacking 1. Remove repeatedly trying to unpack fbclient. 2. Remove repeatedly trying to set jna.library.path to the same value. 3. Improve logging when extracting fbclient. --- .../datasource/util/LibraryManager.java | 53 ++++++++++--------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/src/org/executequery/datasource/util/LibraryManager.java b/src/org/executequery/datasource/util/LibraryManager.java index 523d2736e..40c7e70bf 100644 --- a/src/org/executequery/datasource/util/LibraryManager.java +++ b/src/org/executequery/datasource/util/LibraryManager.java @@ -47,14 +47,22 @@ public static void updateJnaPath(DatabaseConnection connection, int driverVersio List jarPathsList = getJarPathsList(connection, driverVersion); Path fbClientJarPath = getFbClientJarPath(jarPathsList); - Path fbClientExtractedPath = checkExtractFbClient(fbClientJarPath, driverVersion); - String jnaLibraryPath = buildJnaLibraryPath(fbClientExtractedPath); - Log.info("Attempting to set jna.library.path to: " + jnaLibraryPath); + Path fbClientDirectory = getFbClientDirectory(fbClientJarPath); + if (fbClientDirectory == null || !Files.exists(fbClientDirectory)) { + Log.info("Extracting fbclient to: " + fbClientDirectory); + checkExtractFbClient(fbClientJarPath, fbClientDirectory, driverVersion); + } + + String jnaLibraryPath = buildJnaLibraryPath(fbClientDirectory); + String lastJnaLibraryPath = System.getProperty("jna.library.path"); - System.setProperty("jna.library.path", jnaLibraryPath != null ? jnaLibraryPath : ""); - System.setProperty("jna.platform.library.path", ""); - System.setProperty("jna.debug_load", "true"); + if (!Objects.equals(jnaLibraryPath, lastJnaLibraryPath)) { + Log.info("Attempting to set jna.library.path to: " + jnaLibraryPath); + System.setProperty("jna.library.path", jnaLibraryPath != null ? jnaLibraryPath : ""); + System.setProperty("jna.platform.library.path", ""); + System.setProperty("jna.debug_load", "true"); + } } /** @@ -136,37 +144,25 @@ private static Path getFbClientJarPath(List pathList) { * * @param fbClientJarPath path to the fbclient-n.jar file to extract * @param driverVersion driver version in use - * @return path to the extracted fbclient library or null */ - private static Path checkExtractFbClient(Path fbClientJarPath, int driverVersion) { + private static void checkExtractFbClient(Path fbClientJarPath, Path fbClientDirectory, int driverVersion) { if (fbClientJarPath == null) { Log.info("Couldn't extract fbclient, file not found"); - return null; + return; } Path tmpDirectory = ExecuteQuery.TMP_APP_DIR; if (checkCreateDirectory(tmpDirectory) == NOT_CREATED) - return null; - - String fbClientDirectoryName = FilenameUtils.removeExtension(fbClientJarPath.getFileName().toString()); - Path fbClientDirectory = Paths.get(tmpDirectory.toString(), fbClientDirectoryName); + return; - int createFbClientDirectoryResult = checkCreateDirectory(fbClientDirectory); - if (createFbClientDirectoryResult == EXISTS) - return fbClientDirectory; - - if (createFbClientDirectoryResult == CREATED) { + if (checkCreateDirectory(fbClientDirectory) == CREATED) { extractFbClient( fbClientJarPath, fbClientDirectory.toString(), getPlatformName(driverVersion) ); - - return fbClientDirectory; } - - return null; } /** @@ -192,7 +188,7 @@ private static void extractFbClient(Path fbClientJarPath, String fbClientDirecto createDirectory(outputFile); } else { - Log.info("Extracting: " + entryName); + Log.debug("Extracting: " + entryName); createFile(jarFile, jarEntry, outputFile); } } @@ -251,6 +247,15 @@ private static String getPlatformName(int driverVersion) { return LINUX_X84_64; } + private static Path getFbClientDirectory(Path fbClientJarPath) { + + if (fbClientJarPath == null) + return null; + + String directoryName = FilenameUtils.removeExtension(fbClientJarPath.getFileName().toString()); + return Paths.get(ExecuteQuery.TMP_APP_DIR.toString(), directoryName); + } + private static boolean isFbClient(Path path) { return path.getFileName().toString().startsWith("fbclient"); } @@ -271,7 +276,7 @@ private static String getEntryName(String platform, JarEntry jarEntry) { } private static void createDirectory(File file) throws IOException { - Log.info("Creating directory: " + file.getAbsolutePath()); + Log.debug("Creating directory: " + file.getAbsolutePath()); if (!file.mkdir()) throw new IOException("Couldn't create directory [" + file.getAbsolutePath() + "]"); } From 3bcfdb0c0054dcb5596a3092f78c942db60fe550 Mon Sep 17 00:00:00 2001 From: "aleksey.kozlov" Date: Tue, 3 Dec 2024 10:50:25 +0300 Subject: [PATCH 16/41] Set loading fbclient library for the embedded and native connections --- src/org/executequery/databasemediators/ConnectionType.java | 4 ++++ src/org/executequery/datasource/SimpleDataSource.java | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/org/executequery/databasemediators/ConnectionType.java b/src/org/executequery/databasemediators/ConnectionType.java index f784975e0..e9ae7e504 100644 --- a/src/org/executequery/databasemediators/ConnectionType.java +++ b/src/org/executequery/databasemediators/ConnectionType.java @@ -36,6 +36,10 @@ public static boolean isEmbedded(DatabaseConnection connection) { return connection != null && Objects.equals(connection.getConnType(), EMBEDDED.name()); } + public static boolean isPureJava(DatabaseConnection connection) { + return connection != null && Objects.equals(connection.getConnType(), PURE_JAVA.name()); + } + @Override public String toString() { return label(); diff --git a/src/org/executequery/datasource/SimpleDataSource.java b/src/org/executequery/datasource/SimpleDataSource.java index 86a7144a2..ab68f71c9 100644 --- a/src/org/executequery/datasource/SimpleDataSource.java +++ b/src/org/executequery/datasource/SimpleDataSource.java @@ -180,11 +180,14 @@ public Connection getConnection(String username, String password, ITPB tpb) thro if (driver == null) throw new DataSourceException("Error loading specified JDBC driver"); + // Unpack client library and update jna.library.path + if (!ConnectionType.isPureJava(databaseConnection)) + LibraryManager.updateJnaPath(databaseConnection, driver.getMajorVersion()); + // If embedded connection selected if (ConnectionType.isEmbedded(databaseConnection)) { if (connection == null) { - LibraryManager.updateJnaPath(databaseConnection, driver.getMajorVersion()); fbclient = LibraryManager.loadFbClientLibrary(driver); connection = driver.connect(url, advancedProperties); } From 30fa1f5711d9eb5983bc41e29ba6aa93d8a1a6b5 Mon Sep 17 00:00:00 2001 From: "aleksey.kozlov" Date: Tue, 3 Dec 2024 10:56:14 +0300 Subject: [PATCH 17/41] Temporary disable ability to use embedded connections --- .../datasource/SimpleDataSource.java | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/org/executequery/datasource/SimpleDataSource.java b/src/org/executequery/datasource/SimpleDataSource.java index ab68f71c9..71f03d0b2 100644 --- a/src/org/executequery/datasource/SimpleDataSource.java +++ b/src/org/executequery/datasource/SimpleDataSource.java @@ -185,15 +185,8 @@ public Connection getConnection(String username, String password, ITPB tpb) thro LibraryManager.updateJnaPath(databaseConnection, driver.getMajorVersion()); // If embedded connection selected - if (ConnectionType.isEmbedded(databaseConnection)) { - - if (connection == null) { - fbclient = LibraryManager.loadFbClientLibrary(driver); - connection = driver.connect(url, advancedProperties); - } - - return connection; - } + if (ConnectionType.isEmbedded(databaseConnection)) + throw new DataSourceException("Embedded connections doesn't supports yet"); if (dataSource != null) return dataSource.getConnection(tpb); @@ -509,10 +502,10 @@ public void close() throws ResourceException { } private void maybeShutdownNativeResources() { - if (ConnectionType.isEmbedded(databaseConnection)) { - LibraryManager.shutdownNativeResources(driver, fbclient); - fbclient = null; - } +// if (ConnectionType.isEmbedded(databaseConnection)) { +// LibraryManager.shutdownNativeResources(driver, fbclient); +// fbclient = null; +// } } } From 02cf4b3bb4a2acefe7aa83cad7b2faf967612683 Mon Sep 17 00:00:00 2001 From: "mikhail.kalyashin" Date: Wed, 4 Dec 2024 10:06:10 +0300 Subject: [PATCH 18/41] See RS-207516 fix subfunction parsing --- .../procedureParser/ProcedureParser.g4 | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/org/underworldlabs/procedureParser/ProcedureParser.g4 b/src/org/underworldlabs/procedureParser/ProcedureParser.g4 index 984d3774e..3ec9201fa 100644 --- a/src/org/underworldlabs/procedureParser/ProcedureParser.g4 +++ b/src/org/underworldlabs/procedureParser/ProcedureParser.g4 @@ -54,12 +54,13 @@ declare_function_block declare_function_block : ('('spases_or_comment? input_parameter (','spases_or_comment? input_parameter)*')')? - K_RETURNS spases_or_comment output_parameter + spases_or_comment K_RETURNS spases_or_comment return_parameter spases_or_comment? K_AS spases_or_comment declare_stmt* K_BEGIN body K_END + spases_or_comment? ; declare_block @@ -150,8 +151,18 @@ body: ; desciption_parameter - :parameter_name spases_or_comment datatype (spases_or_comment notnull)? (spases_or_comment K_COLLATE spases_or_comment order_collate)? + :parameter_name spases_or_comment description_datatype_parameter + ; + + description_datatype_parameter + :datatype (spases_or_comment notnull)? (spases_or_comment K_COLLATE spases_or_comment order_collate)? ; + + return_parameter + :description_datatype_parameter + ; + + parameter_name : any_name ; From 1662818e360d258f493a064b205057d976222706 Mon Sep 17 00:00:00 2001 From: "aleksey.kozlov" Date: Wed, 4 Dec 2024 12:43:27 +0300 Subject: [PATCH 19/41] Fix copying fbclient modules --- modules/plugins/fbclient-3/pom.xml | 33 +++++++++++++----------------- modules/plugins/fbclient-4/pom.xml | 33 +++++++++++++----------------- modules/plugins/fbclient-5/pom.xml | 33 +++++++++++++----------------- modules/redexpert/pom.xml | 21 ++++++------------- pom.xml | 3 +++ 5 files changed, 51 insertions(+), 72 deletions(-) diff --git a/modules/plugins/fbclient-3/pom.xml b/modules/plugins/fbclient-3/pom.xml index f56ccd99e..4a2a90512 100644 --- a/modules/plugins/fbclient-3/pom.xml +++ b/modules/plugins/fbclient-3/pom.xml @@ -12,26 +12,21 @@ fbclient-3 - 3.0.17 + ${fbclient3.version} jar - 2019 - - - mrotteveel - Mark Rotteveel - mark@lawinegevaar.nl - - Administrator - - - - - - Initial Developer's Public License Version 1.0 - https://firebirdsql.org/en/initial-developer-s-public-license-version-1-0/ - repo - - + + ${project.artifactId} + + + org.apache.maven.plugins + maven-jar-plugin + 2.3.2 + + ../../../lib + + + + \ No newline at end of file diff --git a/modules/plugins/fbclient-4/pom.xml b/modules/plugins/fbclient-4/pom.xml index 78bebdbf0..7666b0a15 100644 --- a/modules/plugins/fbclient-4/pom.xml +++ b/modules/plugins/fbclient-4/pom.xml @@ -12,26 +12,21 @@ fbclient-4 - 4.0.0 + ${fbclient4.version} jar - 2019 - - - mrotteveel - Mark Rotteveel - mark@lawinegevaar.nl - - Administrator - - - - - - Initial Developer's Public License Version 1.0 - https://firebirdsql.org/en/initial-developer-s-public-license-version-1-0/ - repo - - + + ${project.artifactId} + + + org.apache.maven.plugins + maven-jar-plugin + 2.3.2 + + ../../../lib + + + + \ No newline at end of file diff --git a/modules/plugins/fbclient-5/pom.xml b/modules/plugins/fbclient-5/pom.xml index eb50b296d..bbecba606 100644 --- a/modules/plugins/fbclient-5/pom.xml +++ b/modules/plugins/fbclient-5/pom.xml @@ -12,26 +12,21 @@ fbclient-5 - 5.0.0-rc.5 + ${fbclient5.version} jar - 2019 - - - mrotteveel - Mark Rotteveel - mark@lawinegevaar.nl - - Administrator - - - - - - Initial Developer's Public License Version 1.0 - https://firebirdsql.org/en/initial-developer-s-public-license-version-1-0/ - repo - - + + ${project.artifactId} + + + org.apache.maven.plugins + maven-jar-plugin + 2.3.2 + + ../../../lib + + + + \ No newline at end of file diff --git a/modules/redexpert/pom.xml b/modules/redexpert/pom.xml index b731cfdd5..77dc35186 100644 --- a/modules/redexpert/pom.xml +++ b/modules/redexpert/pom.xml @@ -28,19 +28,19 @@ org.executequery fbclient-3 - 3.0.17 + ${fbclient3.version} org.executequery fbclient-4 - 4.0.0 + ${fbclient4.version} org.executequery fbclient-5 - 5.0.0-rc.5 + ${fbclient5.version} @@ -312,6 +312,9 @@ ${pom.basedir}/../../lib + fbclient-3.jar + fbclient-4.jar + fbclient-5.jar fbplugin-impl.jar fbplugin-impl5.jar jdbc-logger.jar @@ -394,18 +397,6 @@ ${project.build.directory}/lib - - copy-fbclient-libs - package - - copy-dependencies - - - true - fbclient-3,fbclient-4,fbclient-5 - ${project.build.directory}/lib - - diff --git a/pom.xml b/pom.xml index c02b2169a..546d28c28 100644 --- a/pom.xml +++ b/pom.xml @@ -5,6 +5,9 @@ 4.0.0 4.7 + 3.0.17 + 4.0.0 + 5.0.0-rc.5 3.0.36 4.0.30 5.0.18 From 3e8fe8a75af2d6a90d20b301f717eee19071bdf0 Mon Sep 17 00:00:00 2001 From: "aleksey.kozlov" Date: Thu, 5 Dec 2024 10:16:00 +0300 Subject: [PATCH 20/41] Fix unpacking fbclient on the Windows OS --- .../datasource/util/LibraryManager.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/org/executequery/datasource/util/LibraryManager.java b/src/org/executequery/datasource/util/LibraryManager.java index 40c7e70bf..a0c2cf84d 100644 --- a/src/org/executequery/datasource/util/LibraryManager.java +++ b/src/org/executequery/datasource/util/LibraryManager.java @@ -9,7 +9,6 @@ import org.underworldlabs.util.DynamicLibraryLoader; import java.io.*; -import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -265,17 +264,17 @@ private static boolean isFbClient(Path path) { private static String getEntryName(String platform, JarEntry jarEntry) { String entryName = jarEntry.getName(); - if (!entryName.contains(platform)) - return null; - - entryName = entryName.replace(platform, "").trim(); - if (entryName.isEmpty() || Objects.equals(entryName, FileSystems.getDefault().getSeparator())) - return null; + if (entryName.contains(platform)) + return entryName.replace(platform, "").trim(); - return entryName; + return null; } private static void createDirectory(File file) throws IOException { + + if (Files.exists(file.toPath().toAbsolutePath())) + return; + Log.debug("Creating directory: " + file.getAbsolutePath()); if (!file.mkdir()) throw new IOException("Couldn't create directory [" + file.getAbsolutePath() + "]"); From 0e7699d69eab6c3055a803e21510c80e18ad6066 Mon Sep 17 00:00:00 2001 From: Elizaveta Rykova Date: Thu, 5 Dec 2024 17:33:15 +0300 Subject: [PATCH 21/41] Update screenshots of data import tool (RS-205725) --- guide_rst/source/img/import_date.png | Bin 24178 -> 22359 bytes guide_rst/source/img/import_example.png | Bin 58187 -> 42999 bytes guide_rst/source/sec-import.rst | 1 + 3 files changed, 1 insertion(+) diff --git a/guide_rst/source/img/import_date.png b/guide_rst/source/img/import_date.png index 46087156dc5086ad794beca12ab7a70484297e8e..8c395c1e8711ecb12ff4c5660b76401b6f879b64 100644 GIT binary patch literal 22359 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 literal 24178 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 I{q~c80Y+$=^#A|> literal 58187 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

SE5YGilu1;Vc4~=gY4})FZI%OX*Z}u%4 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 diff --git a/guide_rst/source/sec-import.rst b/guide_rst/source/sec-import.rst index b56d88bcd..510180abe 100644 --- a/guide_rst/source/sec-import.rst +++ b/guide_rst/source/sec-import.rst @@ -17,6 +17,7 @@ * ``Целевая БД`` - База данных, в которую будет производиться импорт. * ``Целевая таблица`` - Таблица, в которую будет производиться импорт. * ``Разделитель`` - Тип разделителя данных в CSV файлах. +* ``Количество потоков`` - Количество потоков, используемых для импортирования. Для каждого потока создаётся отдельное подключение. * ``Номер страницы`` - Для XLSX файлов можно выбрасть страницу excel-файла, из которой нужно импортировать данные. * ``Первая импортируемая строка`` - Строка, начиная с которой будут импортированы данные. * ``Последняя импортируемая строка`` - Строка, поcле которой импорт данных будет прекращён. Строки, непопадающие в диапазон между первой и последней импортируемой строкой, будут проигнорированы. From 3fa38093f4197bd3c3653b6718592b2dc951bd14 Mon Sep 17 00:00:00 2001 From: "mikhail.kalyashin" Date: Fri, 6 Dec 2024 09:57:21 +0300 Subject: [PATCH 22/41] sort localisation files --- .../CreateProcedureFunctionPanel.java | 2 +- .../localization/resources.properties | 254 +++++++++--------- .../localization/resources_pt_br.properties | 252 ++++++++--------- .../localization/resources_ru.properties | 254 +++++++++--------- 4 files changed, 383 insertions(+), 379 deletions(-) diff --git a/src/org/executequery/gui/procedure/CreateProcedureFunctionPanel.java b/src/org/executequery/gui/procedure/CreateProcedureFunctionPanel.java index afaf03eec..fa0523963 100644 --- a/src/org/executequery/gui/procedure/CreateProcedureFunctionPanel.java +++ b/src/org/executequery/gui/procedure/CreateProcedureFunctionPanel.java @@ -152,7 +152,7 @@ public void keyReleased(KeyEvent e) { tabbedPane.add(bundleString("OutputParameters"), outputParamsPanel); tabbedPane.add(bundleString("Variables"), variablesPanel); tabbedPane.add(bundleString("Cursors"), cursorsPanel); - tabbedPane.add(bundleString("Subprograms"), subProgramPanel); + tabbedPane.add(bundleStaticString("Subprograms"), subProgramPanel); addCommentTab(null); showHelpersCheck = WidgetFactory.createCheckBox("showHelpersCheck", bundleString("showHelpersCheck")); diff --git a/src/org/executequery/localization/resources.properties b/src/org/executequery/localization/resources.properties index 0c1688f4f..dd4a6dbb2 100644 --- a/src/org/executequery/localization/resources.properties +++ b/src/org/executequery/localization/resources.properties @@ -532,10 +532,85 @@ AboutPanel.discussionChatLabel=User community AboutPanel.discussionChatLink=https://t.me/redexpert_en AboutPanel.gitHubLabel=GitHub repository AboutPanel.reddatabaseNewsLabel=RedDatabase News +AbstractConnectionPanel.Advanced=Advanced +AbstractConnectionPanel.Basic=Basic +AbstractConnectionPanel.BasicAu=Basic +AbstractConnectionPanel.Create=Create +AbstractConnectionPanel.CreateDatabase=Create Database +AbstractConnectionPanel.DatabaseDefault=Database Default +AbstractConnectionPanel.EncryptPassword=Encrypt Password +AbstractConnectionPanel.MultiFactor=Multi-factor +AbstractConnectionPanel.NoCharacterSet=NONE +AbstractConnectionPanel.Store-container-password=Store container password +AbstractConnectionPanel.StorePassword=Store Password +AbstractConnectionPanel.Verify-server-certificate=Verify server certificate +AbstractConnectionPanel.addNewDriver=New Driver +AbstractConnectionPanel.authCombo=Authentication: +AbstractConnectionPanel.borderTitle=Connect Using an SSH Tunnel +AbstractConnectionPanel.certField=Certificate X.509: +AbstractConnectionPanel.certFile=Certificate files +AbstractConnectionPanel.charsetsCombo=Character Set: +AbstractConnectionPanel.connectionNotEstablished=The connection to the database could not be established.\nPlease ensure all required fields have been entered and try again. +AbstractConnectionPanel.containerPasswordField=Container password: +AbstractConnectionPanel.databaseFile=Database files +AbstractConnectionPanel.databaseNotCreated=Failed to create a database.{nThe system returned: {0} +AbstractConnectionPanel.delete.tool-tip=Clear this key/value pair +AbstractConnectionPanel.driverCombo=JDBC Driver: +AbstractConnectionPanel.driverNotSupported=Creating database for selected driver is not implemented. +AbstractConnectionPanel.driverVersionNotSupported=Cannot create database, Jaybird 2 has no implementation for creation database. +AbstractConnectionPanel.error.connect=Error occurred while connecting to the database.\nSystem returned: {0} +AbstractConnectionPanel.error.disconnect=Error occurred while disconnecting from the database.\nSystem returned: {0} +AbstractConnectionPanel.error.nameEmpty=The connection name cannot be empty +AbstractConnectionPanel.error.nameExist=The name entered for this connection ({0}) already exists +AbstractConnectionPanel.fbclientNotFound=Cannot create database, because fbclient library not found in environment path variable.\nPlease, add fbclient library to environment path variable. +AbstractConnectionPanel.fileField=Database File: +AbstractConnectionPanel.hostField.tool-tip=Server host name or IP address +AbstractConnectionPanel.hostField=Server (Host): +AbstractConnectionPanel.multiFactorPanel=Certificate +AbstractConnectionPanel.nameField.tool-tip=A friendly name for this connection +AbstractConnectionPanel.nameField=Connection Name: +AbstractConnectionPanel.namesToUpperCheck=Object names to upper case +AbstractConnectionPanel.pageSizeCombo=Page Size: +AbstractConnectionPanel.passwordField=Password: +AbstractConnectionPanel.portField.tool-tip=Database port number +AbstractConnectionPanel.portField=Port: +AbstractConnectionPanel.registration.message=Register a created database? +AbstractConnectionPanel.registration=Database Registration +AbstractConnectionPanel.roleField=Role: +AbstractConnectionPanel.selectDriver=Select... +AbstractConnectionPanel.serverCombo=Server: +AbstractConnectionPanel.somethingEmpty=Fill in all required fields. +AbstractConnectionPanel.sourceField.tool-tip=Data source name +AbstractConnectionPanel.ssh.hostField=SSH host: +AbstractConnectionPanel.ssh.note.bottom=Note: Storing the password here will encrypt it in the application configuration files only.
Encrypted and stored values may be compromised and should not be considered completely secure. +AbstractConnectionPanel.ssh.note.top=Enter the parameters for connecting to the remote server via SSH tunnel. +AbstractConnectionPanel.ssh.passwordField=Password: +AbstractConnectionPanel.ssh.portField=SSH port: +AbstractConnectionPanel.ssh.title=SSH Tunnel +AbstractConnectionPanel.ssh.userField=SSH user: +AbstractConnectionPanel.status.Connected.connection=connection open ] +AbstractConnectionPanel.status.Connected.connections=\ connections open ] +AbstractConnectionPanel.status.Connected=Connected +AbstractConnectionPanel.status.NotConnected=Not Connected +AbstractConnectionPanel.statusLabel.tool-tip=Current connection status +AbstractConnectionPanel.statusLabel=Status: +AbstractConnectionPanel.test.success=The connection test was successful! +AbstractConnectionPanel.urlField.tool-tip=The full JDBC URL for this connection (optional) +AbstractConnectionPanel.useEmbeddedCheck=Use embedded server (embedded connection) +AbstractConnectionPanel.useNativeCheck=Use client library to connect (native connection) +AbstractConnectionPanel.useNewApiCheck=Use Native OO API +AbstractConnectionPanel.useSshCheck=Use SSH tunnel +AbstractConnectionPanel.userField.tool-tip=Login username +AbstractConnectionPanel.userField=User Name: +AbstractConnectionPanel.warning.useNewAPI.connType=New API is available with NATIVE or EMBEDDED connection. +AbstractConnectionPanel.warning.useNewAPI.driver=New API is available with Jaybird 4 driver only and newer. AbstractCreateObjectPanel.Engine=Engine AbstractCreateObjectPanel.EntryPoint=Entry Point AbstractCreateObjectPanel.EntryPoint_alternative=Entry Point +AbstractCreateObjectPanel.FUNCTION=Function +AbstractCreateObjectPanel.PROCEDURE=Procedure AbstractCreateObjectPanel.SQL=SQL +AbstractCreateObjectPanel.Subprograms=Subprograms AbstractCreateObjectPanel.active=Active AbstractCreateObjectPanel.check=Check AbstractCreateObjectPanel.computed=Computed By @@ -589,7 +664,6 @@ AbstractServiceManagerPanel.Highlight=Highlight AbstractServiceManagerPanel.Host=Host AbstractServiceManagerPanel.ID=ID AbstractServiceManagerPanel.LogToFile=Log to file -DatabaseBackupRestorePanel.LogToFile=Log to file AbstractServiceManagerPanel.Logger=Grid View AbstractServiceManagerPanel.Name=Name AbstractServiceManagerPanel.OpenFileLog=Load from file @@ -640,6 +714,15 @@ AddQueryBookmarkPanel.saveError=Error storing bookmark for query AddQueryBookmarkPanel.validation.name=Please enter a name for this bookmark AddQueryBookmarkPanel.validation.query=Please enter the SQL query to be stored against this bookmark AddQueryBookmarkPanel.validation.uniqueName=The name for this bookmark already exists.\nWould you like to overwrite the existing bookmark value? +AdvancedPropertiesPanel.IsolationLevel=Isolation Level: +AdvancedPropertiesPanel.JDBCProperties=JDBC Properties +AdvancedPropertiesPanel.TransactionIsolation=Transaction Isolation +AdvancedPropertiesPanel.propertiesText=Enter any key-value pair properties for this connection

Refer to the relevant JDBC driver documentation for possible entries. +AdvancedPropertiesPanel.propertyLocked=The entered attribute is not available for editing as it's automatically generated according to the selected connection settings. +AdvancedPropertiesPanel.setLevel.exception=The selected isolation level could not be applied.\nThe JDBC driver returned: {0} +AdvancedPropertiesPanel.setLevel.success=The transaction isolation level {0} was applied successfully. +AdvancedPropertiesPanel.setLevel.warning=The specified driver for this connection does not support transactions.\nThis feature is unavailable. +AdvancedPropertiesPanel.transactionText=Default transaction isolation level for this connection

Note: the selected isolation level will apply to ALL open connections of this type. AnalisePanel.AvailableEvents=Available events AnalisePanel.HideEvents=Hide events AnalisePanel.HidePlan=Hide plan @@ -791,13 +874,13 @@ BrowserTreeDefaultPopupMenu.NewConnection=New Connection BrowserTreeDefaultPopupMenu.NewFolder=New Folder BrowserTreeDefaultPopupMenu.SearchNodes=Search for nodes BrowserTreeDefaultPopupMenu.SortConnections=Sort Connections +BrowserTreeHostPopupMenu.BackupRestore=Create database backup BrowserTreeHostPopupMenu.Connect=Connect BrowserTreeHostPopupMenu.CopyName=Copy Name BrowserTreeHostPopupMenu.Delete=Delete connection BrowserTreeHostPopupMenu.Disconnect=Disconnect BrowserTreeHostPopupMenu.Duplicate=Duplicate connection BrowserTreeHostPopupMenu.ExtractMetadata=Extract Metadata -BrowserTreeHostPopupMenu.BackupRestore=Create database backup BrowserTreeHostPopupMenu.MoveToFolder=Move to Folder BrowserTreeHostPopupMenu.NewConnection=New Connection BrowserTreeHostPopupMenu.NewFolder=New Folder @@ -969,6 +1052,7 @@ ComparerDBPanel.CreatingStubs=Creating stubs for %s ComparerDBPanel.DATABASE_TRIGGER=DB Triggers ComparerDBPanel.DatabaseChanges=Database Changes ComparerDBPanel.DropObjects=Objects To Drop +ComparerDBPanel.EmbeddedConnectionSelected=\nAt least one of the connection use embedded connection.\nJob will not be included in the comparison. ComparerDBPanel.ErrorOccurred=Error occurred while comparing DBs.\nThe comparison will be finished forcibly. ComparerDBPanel.ExecuteScriptButton=Execute Script ComparerDBPanel.Executing=Comparing, please wait @@ -1003,7 +1087,6 @@ ComparerDBPanel.OutputLabel=Output ComparerDBPanel.PropertiesLabel=Properties ComparerDBPanel.RDBVersionBelow3=\nAt least one of the connection use RDB version below 3.0.\nUser, Package, Function, Triggers for DDLs, Tablespace & Job will not be included in the comparison. ComparerDBPanel.RDBVersionBelow4=\nAt least one of the connection use RDB version below 4.0.\nTablespace & Job will not be included in the comparison. -ComparerDBPanel.EmbeddedConnectionSelected=\nAt least one of the connection use embedded connection.\nJob will not be included in the comparison. ComparerDBPanel.SafeTypeConversion=Safe Type Conversion ComparerDBPanel.SaveScriptButton=Save Script ComparerDBPanel.SavedTo=Saved to: @@ -1017,101 +1100,23 @@ ComparerDBPanel.TargetLabel=Target DB Script (old) ComparerDBPanel.TreeView=View ComparerDBPanel.UnableCompareBusyConnections=Unable to compare.\nAt least one of the connections is busy\nwith another comparing or metadata extracting process. ComparerDBPanel.UnableCompareNoAttributes=Unable to compare.\nNo attributes for comparing selected. -ComparerDBPanel.UnableCompareNoConnections=Unable to compare.\nAt least one of the connections is inactive. ComparerDBPanel.UnableCompareNoConnections.extract=Unable to compare.\nConnection is inactive. +ComparerDBPanel.UnableCompareNoConnections=Unable to compare.\nAt least one of the connections is inactive. ComparerDBPanel.UnableCompareNoProperties=Unable to compare.\nNo properties for comparing selected. ComparerDBPanel.UnableCompareSampleConnections=Unable to compare.\nThe same connections selected. ComparerDBPanel.UnableExtractBusyConnections=Unable to extract metadata.\nConnection is busy with comparing or another metadata extracting process. ComparerDBPanel.UnableExtractNoAttributes=Unable to extract metadata.\nNo attributes for comparing selected. ComparerDBPanel.title-export=DB Metadata Export ComparerDBPanel.title=Comparer DB -ConnectionsComboBox.embeddedNotAllowed=The tool does not support work with embedded connection.\nA network connection is required. -ConnectionsComboBox.connectionError=Couldn't connect to the selected database. ConnectionImporter.ImportingConnection=Importing connection [ {0} ] -AbstractConnectionPanel.Advanced=Advanced -AbstractConnectionPanel.authCombo=Authentication: -AbstractConnectionPanel.Basic=Basic -AbstractConnectionPanel.BasicAu=Basic -AbstractConnectionPanel.charsetsCombo=Character Set: -AbstractConnectionPanel.Create=Create -AbstractConnectionPanel.CreateDatabase=Create Database -AbstractConnectionPanel.DatabaseDefault=Database Default -AbstractConnectionPanel.registration.message=Register a created database? -AbstractConnectionPanel.registration=Database Registration -AbstractConnectionPanel.EncryptPassword=Encrypt Password -AbstractConnectionPanel.MultiFactor=Multi-factor -AbstractConnectionPanel.NoCharacterSet=NONE -AbstractConnectionPanel.pageSizeCombo=Page Size: -AbstractConnectionPanel.roleField=Role: -AbstractConnectionPanel.serverCombo=Server: -AbstractConnectionPanel.useSshCheck=Use SSH tunnel -AbstractConnectionPanel.ssh.title=SSH Tunnel -AbstractConnectionPanel.ssh.hostField=SSH host: -AbstractConnectionPanel.ssh.portField=SSH port: -AbstractConnectionPanel.ssh.userField=SSH user: -AbstractConnectionPanel.ssh.passwordField=Password: -AbstractConnectionPanel.ssh.note.top=Enter the parameters for connecting to the remote server via SSH tunnel. -AbstractConnectionPanel.ssh.note.bottom=Note: Storing the password here will encrypt it in the application configuration files only.
Encrypted and stored values may be compromised and should not be considered completely secure. -AbstractConnectionPanel.Store-container-password=Store container password -AbstractConnectionPanel.StorePassword=Store Password -AbstractConnectionPanel.useNewApiCheck=Use Native OO API -AbstractConnectionPanel.useNativeCheck=Use client library to connect (native connection) -AbstractConnectionPanel.useEmbeddedCheck=Use embedded server (embedded connection) -AbstractConnectionPanel.Verify-server-certificate=Verify server certificate -AbstractConnectionPanel.addNewDriver=New Driver -AbstractConnectionPanel.borderTitle=Connect Using an SSH Tunnel -AbstractConnectionPanel.certField=Certificate X.509: -AbstractConnectionPanel.certFile=Certificate files -AbstractConnectionPanel.databaseFile=Database files -AbstractConnectionPanel.containerPasswordField=Container password: -AbstractConnectionPanel.passwordField=Password: -AbstractConnectionPanel.delete.tool-tip=Clear this key/value pair -AbstractConnectionPanel.driverCombo=JDBC Driver: -AbstractConnectionPanel.error.disconnect=Error occurred while disconnecting from the database.\nSystem returned: {0} -AbstractConnectionPanel.error.connect=Error occurred while connecting to the database.\nSystem returned: {0} -AbstractConnectionPanel.error.nameExist=The name entered for this connection ({0}) already exists -AbstractConnectionPanel.error.nameEmpty=The connection name cannot be empty -AbstractConnectionPanel.hostField.tool-tip=Server host name or IP address -AbstractConnectionPanel.hostField=Server (Host): -AbstractConnectionPanel.nameField.tool-tip=A friendly name for this connection -AbstractConnectionPanel.nameField=Connection Name: -AbstractConnectionPanel.namesToUpperCheck=Object names to upper case -AbstractConnectionPanel.portField.tool-tip=Database port number -AbstractConnectionPanel.portField=Port: -AbstractConnectionPanel.selectDriver=Select... -AbstractConnectionPanel.sourceField.tool-tip=Data source name -AbstractConnectionPanel.fileField=Database File: -AbstractConnectionPanel.status.Connected.connection=connection open ] -AbstractConnectionPanel.status.Connected.connections=\ connections open ] -AbstractConnectionPanel.status.Connected=Connected -AbstractConnectionPanel.status.NotConnected=Not Connected -AbstractConnectionPanel.statusLabel.tool-tip=Current connection status -AbstractConnectionPanel.statusLabel=Status: -AbstractConnectionPanel.test.success=The connection test was successful! -AbstractConnectionPanel.urlField.tool-tip=The full JDBC URL for this connection (optional) -AbstractConnectionPanel.userField.tool-tip=Login username -AbstractConnectionPanel.userField=User Name: -AbstractConnectionPanel.warning.useNewAPI.driver=New API is available with Jaybird 4 driver only and newer. -AbstractConnectionPanel.warning.useNewAPI.connType=New API is available with NATIVE or EMBEDDED connection. -AbstractConnectionPanel.somethingEmpty=Fill in all required fields. -AbstractConnectionPanel.driverNotSupported=Creating database for selected driver is not implemented. -AbstractConnectionPanel.driverVersionNotSupported=Cannot create database, Jaybird 2 has no implementation for creation database. -AbstractConnectionPanel.fbclientNotFound=Cannot create database, because fbclient library not found in environment path variable.\nPlease, add fbclient library to environment path variable. -AbstractConnectionPanel.connectionNotEstablished=The connection to the database could not be established.\nPlease ensure all required fields have been entered and try again. -AbstractConnectionPanel.databaseNotCreated=Failed to create a database.{nThe system returned: {0} -AbstractConnectionPanel.multiFactorPanel=Certificate -AdvancedPropertiesPanel.JDBCProperties=JDBC Properties -AdvancedPropertiesPanel.IsolationLevel=Isolation Level: -AdvancedPropertiesPanel.TransactionIsolation=Transaction Isolation -AdvancedPropertiesPanel.setLevel.success=The transaction isolation level {0} was applied successfully. -AdvancedPropertiesPanel.setLevel.warning=The specified driver for this connection does not support transactions.\nThis feature is unavailable. -AdvancedPropertiesPanel.setLevel.exception=The selected isolation level could not be applied.\nThe JDBC driver returned: {0} -AdvancedPropertiesPanel.propertyLocked=The entered attribute is not available for editing as it's automatically generated according to the selected connection settings. -AdvancedPropertiesPanel.propertiesText=Enter any key-value pair properties for this connection

Refer to the relevant JDBC driver documentation for possible entries. -AdvancedPropertiesPanel.transactionText=Default transaction isolation level for this connection

Note: the selected isolation level will apply to ALL open connections of this type. ConnectionProgressDialog.connection-canceled=Connection cancelled ConnectionProgressDialog.connectionLabel=Establishing connection to {0} ConnectionTree.error.exportAsDrag=Node selection pending before drag +ConnectionType.EMBEDDED=Embedded +ConnectionType.NATIVE=Native +ConnectionType.PURE_JAVA=Pure Java +ConnectionsComboBox.connectionError=Couldn't connect to the selected database. +ConnectionsComboBox.embeddedNotAllowed=The tool does not support work with embedded connection.\nA network connection is required. ConnectionsListPanel.AvailableConnections=Available Connections ConnectionsListPanel.ConnectionName=Connection Name ConnectionsListPanel.DataSource=Data Source @@ -1175,12 +1180,12 @@ CreateProcedureFunctionPanel.FUNCTION=Function CreateProcedureFunctionPanel.InputParameters=Input Parameters CreateProcedureFunctionPanel.OutputParameters=Output Parameters CreateProcedureFunctionPanel.PROCEDURE=Procedure -CreateProcedureFunctionPanel.Subprograms=Subprograms CreateProcedureFunctionPanel.Variables=Variables CreateProcedureFunctionPanel.confirmTabChange=When you exit this tab, all changes you have made will be lost.\nAre you sure you want to switch tab? CreateProcedureFunctionPanel.executeFunction=Execute Function CreateProcedureFunctionPanel.executeProcedure=Execute Procedure CreateProcedureFunctionPanel.showHelpersCheck=Show helper tools +CreateRolePanel.title=Create role CreateTablePanel.Columns=Columns CreateTablePanel.Connection=Connection: CreateTablePanel.Constraints=Constraints @@ -1267,43 +1272,44 @@ CustomLafSelectionPanel.LookFeelLibraryIsRequired=A valid path to the look and f CustomLafSelectionPanel.NoValidClasses=No valid classes of type javax.swing.LookAndFeel\nwere found in the specified resource CustomLafSelectionPanel.SelectLookFeel=Select Look and Feel CustomLafSelectionPanel.SelectLookFeelFromList=You must select a look and feel from the list -DatabaseObjectMetaDataPanel.DatabaseObjectMetaData=Database Object Meta Data -DatabaseStatisticPanel.title=Database statistic -DatabaseBackupRestorePanel.title=Database backup/restore -DatabaseBackupRestorePanel.connections=Connection: +DatabaseBackupRestorePanel.Backup=Backup +DatabaseBackupRestorePanel.LogToFile=Log to file +DatabaseBackupRestorePanel.Restore=Restore DatabaseBackupRestorePanel.backupButton=Create Backup -DatabaseBackupRestorePanel.ignoreChecksumsCheckBox=Ignore Checksums -DatabaseBackupRestorePanel.noGarbageCollectCheckBox=No Garbage Collection -DatabaseBackupRestorePanel.metadataOnlyCheckBox=Metadata Only -DatabaseBackupRestorePanel.nonTransportableCheckBox=Non-Transportable Backup -DatabaseBackupRestorePanel.parallelWorkersAmount=Parallel workers amount: +DatabaseBackupRestorePanel.backupFailed=Backup failed\n{0} DatabaseBackupRestorePanel.backupFile=Backup file: -DatabaseBackupRestorePanel.restoreButton=Restore Database +DatabaseBackupRestorePanel.backupFileField=Backup file: +DatabaseBackupRestorePanel.backupFileSelection=Select Backup File +DatabaseBackupRestorePanel.backupSucceed=Backup completed successfully! +DatabaseBackupRestorePanel.charset=Charset: +DatabaseBackupRestorePanel.connections=Connection: +DatabaseBackupRestorePanel.database=Database: +DatabaseBackupRestorePanel.databaseFileSelection=Select Database File DatabaseBackupRestorePanel.deactivateIdxCheckBox=Deactivate Indices +DatabaseBackupRestorePanel.host=Server: +DatabaseBackupRestorePanel.ignoreChecksumsCheckBox=Ignore Checksums +DatabaseBackupRestorePanel.loggingOutput=Logging output +DatabaseBackupRestorePanel.metadataOnlyCheckBox=Metadata Only +DatabaseBackupRestorePanel.noGarbageCollectCheckBox=No Garbage Collection DatabaseBackupRestorePanel.noShadowCheckBox=No Shadow DatabaseBackupRestorePanel.noValidityCheckBox=No Validity Checks +DatabaseBackupRestorePanel.nonTransportableCheckBox=Non-Transportable Backup DatabaseBackupRestorePanel.oneAtATimeCheckBox=Restore One at a Time -DatabaseBackupRestorePanel.restoreOverrideCheck=Override database file DatabaseBackupRestorePanel.pageSizeField=Restore page size: +DatabaseBackupRestorePanel.parallelWorkersAmount=Parallel workers amount: DatabaseBackupRestorePanel.parallelWorkersField=Parallel workers amount: -DatabaseBackupRestorePanel.backupFileField=Backup file: -DatabaseBackupRestorePanel.backupFileSelection=Select Backup File -DatabaseBackupRestorePanel.databaseFileSelection=Select Database File -DatabaseBackupRestorePanel.loggingOutput=Logging output -DatabaseBackupRestorePanel.Backup=Backup -DatabaseBackupRestorePanel.Restore=Restore -DatabaseBackupRestorePanel.database=Database: -DatabaseBackupRestorePanel.host=Server: -DatabaseBackupRestorePanel.port=Port: -DatabaseBackupRestorePanel.username=User: DatabaseBackupRestorePanel.password=Password: -DatabaseBackupRestorePanel.charset=Charset: -DatabaseBackupRestorePanel.backupSucceed=Backup completed successfully! -DatabaseBackupRestorePanel.restoreSucceed=Restore completed successfully! -DatabaseBackupRestorePanel.restoreSucceed.register=Restore completed successfully!\nRegister restored database? -DatabaseBackupRestorePanel.backupFailed=Backup failed\n{0} -DatabaseBackupRestorePanel.restoreFailed=Restore failed\n{0} +DatabaseBackupRestorePanel.port=Port: DatabaseBackupRestorePanel.requiredFieldsCheckFailed=Fill in all required fields +DatabaseBackupRestorePanel.restoreButton=Restore Database +DatabaseBackupRestorePanel.restoreFailed=Restore failed\n{0} +DatabaseBackupRestorePanel.restoreOverrideCheck=Override database file +DatabaseBackupRestorePanel.restoreSucceed.register=Restore completed successfully!\nRegister restored database? +DatabaseBackupRestorePanel.restoreSucceed=Restore completed successfully! +DatabaseBackupRestorePanel.title=Database backup/restore +DatabaseBackupRestorePanel.username=User: +DatabaseObjectMetaDataPanel.DatabaseObjectMetaData=Database Object Meta Data +DatabaseStatisticPanel.title=Database statistic DatabaseTableNode.columns=Columns DatabaseTableNode.foreign-keys=Foreign Keys DatabaseTableNode.indexes=Indices @@ -1617,9 +1623,9 @@ FeedbackPanel.title=Feedback FeedbackPanel.userComments=User Comments FeedbackPanel.warningInternetConnection=This feature requires an active internet connection. FileChooserDialog.new-command.overwrite-file=Overwrite existing file? -FileValidator.nameEmpty=The file name must not be empty FileValidator.extensionEmpty=The file must have the {0} extension FileValidator.fileNotExists=The file {0} does not exist +FileValidator.nameEmpty=The file name must not be empty FindReplaceDialog.FindAndReplace=Find and Replace FindReplaceDialog.FindText=Find Text FindReplaceDialog.MatchCaseCheck=Match case @@ -2067,8 +2073,8 @@ PropertiesToolBar.RemoveSeparator=Remove PropertiesToolBar.Separator=Separator PropertyWrapperModel.property=Property PropertyWrapperModel.value=Value +QueryEditor.ExceptionOnClose=An error occurred when closing Query Editor.\nThe system returned:\n QueryEditor.FileSavedTo=File saved to {0} -QueryEditor.UnsavedChanges=There are unsaved changes QueryEditor.Filter=Filter: QueryEditor.FilterToolTip=Apply filter to current result set QueryEditor.LineWrapper.tool-tip=Enable/disable automatic line wrapping @@ -2076,14 +2082,14 @@ QueryEditor.LineWrapper=Wrap lines QueryEditor.MaxRowsToolTip=Set the maximum rows returned (-1 for all) QueryEditor.ShowTPP=Show TPP QueryEditor.TransactionIsolationLevel=Transaction isolation level: +QueryEditor.UnsavedChanges=There are unsaved changes QueryEditor.autocommitDisable=Auto-commit is disabled QueryEditor.autocommitEnable=Auto-commit is enabled +QueryEditor.isExecutionActive=Editor is currently executing.\nPlease wait until finished or attempt to cancel the running query. QueryEditor.requestTransactionMessage=Commit the active transaction before closing? QueryEditor.requestTransactionTitle=There is an active transaction QueryEditor.script=script QueryEditor.title=Query Editor -QueryEditor.isExecutionActive=Editor is currently executing.\nPlease wait until finished or attempt to cancel the running query. -QueryEditor.ExceptionOnClose=An error occurred when closing Query Editor.\nThe system returned:\n QueryEditorResultsPanel.DatabaseOutput=Database output QueryEditorResultsPanel.LIMIT_ON=Rows count limit enabled for {0} records QueryEditorResultsPanel.NO_ROWS=No rows selected @@ -2339,8 +2345,8 @@ TableTriggersTableModel.Description=Comment TableTriggersTableModel.Position=Position TableTriggersTableModel.TriggerName=Trigger Name TableTriggersTableModel.TriggerType=Trigger Type -TableValidationCommand.validationError=Unable run tables validation TableValidationCommand.initError=Unable to init IFBMaintenanceManager instance +TableValidationCommand.validationError=Unable run tables validation TableValidationPanel.AvailableIndexLabel=Available Indexes TableValidationPanel.AvailableTablesLabel=Available Tables TableValidationPanel.Connection=Connection: @@ -2389,6 +2395,8 @@ UserManagerPanel.message.confirm-delete-role=Are you sure that you want to delet UserManagerPanel.message.confirm-delete-user=Are you sure that you want to delete user? UserManagerPanel.message.create-role=Success UserManagerPanel.server=Server +ViewablePasswordField.buttonTooltip.hide=Hide password +ViewablePasswordField.buttonTooltip.show=Show password WindowAddUser.Administrator=Administrator WindowAddUser.Cancel=Cancel WindowAddUser.ConfirmPassword=Confirm Password @@ -2437,9 +2445,3 @@ WizardProcessPanel.Cancel=Cancel WizardProcessPanel.Help=Help WizardProcessPanel.Next=Next WizardProcessPanel.Steps=Steps -CreateRolePanel.title=Create role -ViewablePasswordField.buttonTooltip.show=Show password -ViewablePasswordField.buttonTooltip.hide=Hide password -ConnectionType.NATIVE=Native -ConnectionType.EMBEDDED=Embedded -ConnectionType.PURE_JAVA=Pure Java diff --git a/src/org/executequery/localization/resources_pt_br.properties b/src/org/executequery/localization/resources_pt_br.properties index 77f36d950..d07a5b73b 100644 --- a/src/org/executequery/localization/resources_pt_br.properties +++ b/src/org/executequery/localization/resources_pt_br.properties @@ -532,10 +532,85 @@ AboutPanel.discussionChatLabel=Comunidade de usuários AboutPanel.discussionChatLink=https://t.me/redexpert_en AboutPanel.gitHubLabel=Repositório do GitHub AboutPanel.reddatabaseNewsLabel=Notícias do RedDatabase +AbstractConnectionPanel.Advanced=Avançado +AbstractConnectionPanel.Basic=Basic +AbstractConnectionPanel.BasicAu=Básico +AbstractConnectionPanel.Create=Criar +AbstractConnectionPanel.CreateDatabase=Criar banco de dados +AbstractConnectionPanel.DatabaseDefault=Padrão +AbstractConnectionPanel.EncryptPassword=Criptografar senha +AbstractConnectionPanel.MultiFactor=Multifator +AbstractConnectionPanel.NoCharacterSet=Sem codificação +AbstractConnectionPanel.Store-container-password=Senha do contêiner de armazenamento +AbstractConnectionPanel.StorePassword=Salvar senha +AbstractConnectionPanel.Verify-server-certificate=Verifica o certificado do servidor +AbstractConnectionPanel.addNewDriver=Novo driver +AbstractConnectionPanel.authCombo=Autenticação: +AbstractConnectionPanel.borderTitle=Conectar usando túnel SSH +AbstractConnectionPanel.certField=Certificado X.509: +AbstractConnectionPanel.certFile=Arquivos de certificado +AbstractConnectionPanel.charsetsCombo=Codificação: +AbstractConnectionPanel.connectionNotEstablished=Não foi possível estabelecer a conexão com o banco de dados.\nPor favor, verifique se todos os campos obrigatórios foram inseridos e tente novamente. +AbstractConnectionPanel.containerPasswordField=Senha do contêiner: +AbstractConnectionPanel.databaseFile=Arquivos de banco de dados +AbstractConnectionPanel.databaseNotCreated=Falha ao criar um banco de dados.php.\nSistema retornou: {0} +AbstractConnectionPanel.delete.tool-tip=Remover este par: chave/valor +AbstractConnectionPanel.driverCombo=Driver JDBC: +AbstractConnectionPanel.driverNotSupported=Não há suporte para a criação de um banco de dados para o driver selecionado. +AbstractConnectionPanel.driverVersionNotSupported=Não é possível criar um banco de dados, o Jaybird 2 não possui uma implementação para criar um banco de dados. +AbstractConnectionPanel.error.connect=Ocorreu um erro ao se conectar ao banco de dados.\nSistema retornou: {0} +AbstractConnectionPanel.error.disconnect=Ocorreu um erro ao se desconectar do banco de dados.\nO sistema retornou: {0} +AbstractConnectionPanel.error.nameEmpty=O nome da conexão não pode estar vazio. +AbstractConnectionPanel.error.nameExist=O nome inserido para essa conexão ({0}) já existe +AbstractConnectionPanel.fbclientNotFound=Não é possível criar um banco de dados porque a biblioteca fbclient não foi encontrada na variável de caminho do ambiente. +AbstractConnectionPanel.fileField=Arquivo de banco de dados: +AbstractConnectionPanel.hostField.tool-tip=Nome do servidor ou endereço IP +AbstractConnectionPanel.hostField=Nome do servidor: +AbstractConnectionPanel.multiFactorPanel=Certificado. +AbstractConnectionPanel.nameField.tool-tip=Nome abreviado da conexão +AbstractConnectionPanel.nameField=Nome da conexão: +AbstractConnectionPanel.namesToUpperCheck=Tornar os nomes dos objetos em maiúsculas +AbstractConnectionPanel.pageSizeCombo=Tamanho da página: +AbstractConnectionPanel.passwordField=Senha: +AbstractConnectionPanel.portField.tool-tip=Número da porta do banco de dados +AbstractConnectionPanel.portField=Porta: +AbstractConnectionPanel.registration.message=Registrar o banco de dados criado? +AbstractConnectionPanel.registration=Registrar o banco de dados +AbstractConnectionPanel.roleField=Função: +AbstractConnectionPanel.selectDriver=Selecionar... +AbstractConnectionPanel.serverCombo=Servidor: +AbstractConnectionPanel.somethingEmpty=Preencha todos os campos obrigatórios. +AbstractConnectionPanel.sourceField.tool-tip=Caminho para o arquivo de banco de dados +AbstractConnectionPanel.ssh.hostField=Host SSH: +AbstractConnectionPanel.ssh.note.bottom=Nota:Ao salvar a senha aqui, ela será criptografada SOMENTE nos arquivos de configuração do aplicativo.
Os valores criptografados e armazenados podem ser comprometidos e não devem ser considerados completamente seguros. +AbstractConnectionPanel.ssh.note.top=Digite os parâmetros para conexão com o servidor remoto via túnel SSH. +AbstractConnectionPanel.ssh.passwordField=Senha: +AbstractConnectionPanel.ssh.portField=porta SSH: +AbstractConnectionPanel.ssh.title=Túnel SSH +AbstractConnectionPanel.ssh.userField=USUÁRIO: +AbstractConnectionPanel.status.Connected.connection=abrir conexão ] +AbstractConnectionPanel.status.Connected.connections=\ open connections ] +AbstractConnectionPanel.status.Connected=conectado +AbstractConnectionPanel.status.NotConnected=Não conectado +AbstractConnectionPanel.statusLabel.tool-tip=Situação atual da conexão +AbstractConnectionPanel.statusLabel=Status: +AbstractConnectionPanel.test.success=A conexão foi bem-sucedida! +AbstractConnectionPanel.urlField.tool-tip=URL completo do JDBC para esta conexão +AbstractConnectionPanel.useEmbeddedCheck=Usar servidor incorporado (conexão incorporada) +AbstractConnectionPanel.useNativeCheck=Usar a biblioteca do cliente (conexão nativa) +AbstractConnectionPanel.useNewApiCheck=Usar a nova API OO +AbstractConnectionPanel.useSshCheck=Usar túnel SSH +AbstractConnectionPanel.userField.tool-tip=Digite o nome do usuário +AbstractConnectionPanel.userField=Usuário: +AbstractConnectionPanel.warning.useNewAPI.connType=O uso da nova API OO é possível com uma conexão NATIVE ou EMBEDDED. +AbstractConnectionPanel.warning.useNewAPI.driver=A nova API OO pode ser utilizada com o driver Jaybird 4 ou mais recente. AbstractCreateObjectPanel.Engine=Motor AbstractCreateObjectPanel.EntryPoint=Ponto de entrada AbstractCreateObjectPanel.EntryPoint_alternative=Ponto de entrada +AbstractCreateObjectPanel.FUNCTION=Função +AbstractCreateObjectPanel.PROCEDURE=Procedimento AbstractCreateObjectPanel.SQL=SQL +AbstractCreateObjectPanel.Subprograms=Subprogramas AbstractCreateObjectPanel.active=Ativo AbstractCreateObjectPanel.check=Verificar AbstractCreateObjectPanel.computed=Computado por @@ -551,13 +626,9 @@ AbstractDriverPanel.addFindButton=Localizar AbstractDriverPanel.addLibraryButton=Adicionar biblioteca AbstractDriverPanel.addRemoveButton=Remover AbstractDriverPanel.classNameLabel=Nome da classe: -AbstractDriverPanel.classNameToolTip=O nome da classe do driver - pressione o botão "Localizar" para verificar os jars adicionados à lista de caminhos AbstractDriverPanel.databaseLabel=Banco de dados: -AbstractDriverPanel.databaseToolTip=O tipo de banco de dados para esse driver AbstractDriverPanel.descriptionLabel=Descrição: -AbstractDriverPanel.descriptionToolTip=Descrição opcional para esse driver AbstractDriverPanel.driverNameLabel=Nome do motorista: -AbstractDriverPanel.driverNameToolTip=Um nome amigável para esse driver AbstractDriverPanel.ioError=Ocorreu um erro ao acessar o arquivo especificado:\n{0} AbstractDriverPanel.javaArchiveFiles=Arquivos de arquivo Java AbstractDriverPanel.jdbcUrlLabel=URL DO JDBC: @@ -565,7 +636,6 @@ AbstractDriverPanel.jdbcUrlToolTip=O padrão de URL JDBC a ser usado para esse d AbstractDriverPanel.noDriverClassesError=Nenhuma classe válida que implementa o java.sql.Driver foi encontrada nos caminhos de recursos especificados AbstractDriverPanel.pathLabel=Caminho: AbstractDriverPanel.pathListEmptyError=É necessário um caminho válido para a biblioteca JDBC -AbstractDriverPanel.pathToolTip=Nomes e caminhos dos arquivos jar da biblioteca do driver JDBC AbstractDriverPanel.select=Selecione AbstractDriverPanel.selectJdbcDriverLabel=Selecionar driver JDBC AbstractDriverPanel.selectJdbcDriverNoSelection=Você deve selecionar um driver na lista @@ -594,7 +664,6 @@ AbstractServiceManagerPanel.Highlight=Destaque AbstractServiceManagerPanel.Host=Anfitrião AbstractServiceManagerPanel.ID=ID AbstractServiceManagerPanel.LogToFile=Registro em arquivo -DatabaseBackupRestorePanel.LogToFile=Registro em arquivo AbstractServiceManagerPanel.Logger=Visualização em grade AbstractServiceManagerPanel.Name=Nome AbstractServiceManagerPanel.OpenFileLog=Carregar do arquivo @@ -645,6 +714,15 @@ AddQueryBookmarkPanel.saveError=Erro ao armazenar marcador para consulta AddQueryBookmarkPanel.validation.name=Digite um nome para este marcador AddQueryBookmarkPanel.validation.query=Digite a consulta SQL a ser armazenada nesse marcador AddQueryBookmarkPanel.validation.uniqueName=O nome desse marcador já existe.\nVocê gostaria de substituir o valor do marcador existente? +AdvancedPropertiesPanel.IsolationLevel=Nível de isolamento: +AdvancedPropertiesPanel.JDBCProperties=Propriedades de JDBC +AdvancedPropertiesPanel.TransactionIsolation=Nível de isolamento de transação +AdvancedPropertiesPanel.propertiesText=Digite um par chave-valor nas propriedades dessa conexão

Verifique a documentação apropriada do driver JDBC para obter as entradas possíveis.. +AdvancedPropertiesPanel.propertyLocked=O atributo inserido não é editável porque é gerado automaticamente de acordo com as configurações de conexão selecionadas. +AdvancedPropertiesPanel.setLevel.exception=O nível de isolamento selecionado não pode ser aplicado.\nO driver JDBC retornou: {0} +AdvancedPropertiesPanel.setLevel.success=Transaction IsolationLevel {0} aplicado com sucesso +AdvancedPropertiesPanel.setLevel.warning=O driver especificado para essa conexão não oferece suporte a transações.\nEsse recurso não está disponível. +AdvancedPropertiesPanel.transactionText=Nível de isolamento de transação padrão para essa conexão

Nota: o nível de isolamento selecionado será aplicado a todas as conexões abertas desse tipo.. AnalisePanel.AvailableEvents=Eventos disponíveis AnalisePanel.HideEvents=Ocultar eventos AnalisePanel.HidePlan=Ocultar plano @@ -796,13 +874,13 @@ BrowserTreeDefaultPopupMenu.NewConnection=Nova conexão BrowserTreeDefaultPopupMenu.NewFolder=Nova pasta BrowserTreeDefaultPopupMenu.SearchNodes=Busca de nós BrowserTreeDefaultPopupMenu.SortConnections=Classificar conexões +BrowserTreeHostPopupMenu.BackupRestore=Backup de banco de dados BrowserTreeHostPopupMenu.Connect=Conectar BrowserTreeHostPopupMenu.CopyName=Nome da cópia BrowserTreeHostPopupMenu.Delete=Excluir conexão BrowserTreeHostPopupMenu.Disconnect=Desconectar BrowserTreeHostPopupMenu.Duplicate=Conexão duplicada BrowserTreeHostPopupMenu.ExtractMetadata=Extrair metadados -BrowserTreeHostPopupMenu.BackupRestore=Backup de banco de dados BrowserTreeHostPopupMenu.MoveToFolder=Mover para a pasta BrowserTreeHostPopupMenu.NewConnection=Nova conexão BrowserTreeHostPopupMenu.NewFolder=Nova pasta @@ -974,6 +1052,7 @@ ComparerDBPanel.CreatingStubs=Criando stubs para %s ComparerDBPanel.DATABASE_TRIGGER=Acionadores de BD ComparerDBPanel.DatabaseChanges=Alterações no banco de dados ComparerDBPanel.DropObjects=Objetos para soltar +ComparerDBPanel.EmbeddedConnectionSelected=\nPelo menos uma das conexões usa conexão incorporada.\nJob não serão incluídos na comparação. ComparerDBPanel.ErrorOccurred=Ocorreu um erro durante a comparação de BDs.\nA comparação será concluída à força. ComparerDBPanel.ExecuteScriptButton=Executar script ComparerDBPanel.Executing=Comparação, aguarde @@ -1008,7 +1087,6 @@ ComparerDBPanel.OutputLabel=Saída ComparerDBPanel.PropertiesLabel=Propriedades ComparerDBPanel.RDBVersionBelow3=\nPelo menos uma das conexões usa a versão do RDB abaixo de 3.0.\nUsuário, pacote, função, acionadores para DDLs, espaço de tabela e trabalho não serão incluídos na comparação. ComparerDBPanel.RDBVersionBelow4=\nPelo menos uma das conexões usa a versão do RDB abaixo de 4.0.\nTablespace e Job não serão incluídos na comparação. -ComparerDBPanel.EmbeddedConnectionSelected=\nPelo menos uma das conexões usa conexão incorporada.\nJob não serão incluídos na comparação. ComparerDBPanel.SafeTypeConversion=Conversão de tipo seguro ComparerDBPanel.SaveScriptButton=Salvar script ComparerDBPanel.SavedTo=Salvo em: @@ -1022,101 +1100,23 @@ ComparerDBPanel.TargetLabel=Script do banco de dados de destino (antigo) ComparerDBPanel.TreeView=Ver ComparerDBPanel.UnableCompareBusyConnections=Não é possível comparar.\nPelo menos uma das conexões está ocupada\ncom outro processo de comparação ou extração de metadados. ComparerDBPanel.UnableCompareNoAttributes=Não foi possível comparar.\nNenhum atributo para comparação selecionado. -ComparerDBPanel.UnableCompareNoConnections=Não é possível comparar.\nPelo menos uma das conexões está inativa. ComparerDBPanel.UnableCompareNoConnections.extract=Não é possível comparar.\nConexõ está inativa. +ComparerDBPanel.UnableCompareNoConnections=Não é possível comparar.\nPelo menos uma das conexões está inativa. ComparerDBPanel.UnableCompareNoProperties=Não foi possível comparar.\nNenhuma propriedade para comparação selecionada. ComparerDBPanel.UnableCompareSampleConnections=Não é possível comparar.\nAs mesmas conexões foram selecionadas. ComparerDBPanel.UnableExtractBusyConnections=Não foi possível extrair metadados.\nA conexão está ocupada com um processo de comparação ou outro processo de extração de metadados. ComparerDBPanel.UnableExtractNoAttributes=Não foi possível extrair metadados.\nNenhum atributo para comparação selecionado. ComparerDBPanel.title-export=Exportação de metadados de BD ComparerDBPanel.title=Comparador DB -ConnectionsComboBox.embeddedNotAllowed=A ferramenta não suporta o trabalho com conexão incorporada.\nÉ necessária uma conexão de rede. -ConnectionsComboBox.connectionError=Não foi possível conectar-se ao banco de dados selecionado. ConnectionImporter.ImportingConnection=Importando conexão [ {0} ] -AbstractConnectionPanel.Advanced=Avançado -AbstractConnectionPanel.authCombo=Autenticação: -AbstractConnectionPanel.Basic=Basic -AbstractConnectionPanel.BasicAu=Básico -AbstractConnectionPanel.charsetsCombo=Codificação: -AbstractConnectionPanel.Create=Criar -AbstractConnectionPanel.CreateDatabase=Criar banco de dados -AbstractConnectionPanel.DatabaseDefault=Padrão -AbstractConnectionPanel.registration.message=Registrar o banco de dados criado? -AbstractConnectionPanel.registration=Registrar o banco de dados -AbstractConnectionPanel.EncryptPassword=Criptografar senha -AbstractConnectionPanel.MultiFactor=Multifator -AbstractConnectionPanel.NoCharacterSet=Sem codificação -AbstractConnectionPanel.pageSizeCombo=Tamanho da página: -AbstractConnectionPanel.roleField=Função: -AbstractConnectionPanel.serverCombo=Servidor: -AbstractConnectionPanel.useSshCheck=Usar túnel SSH -AbstractConnectionPanel.ssh.title=Túnel SSH -AbstractConnectionPanel.ssh.hostField=Host SSH: -AbstractConnectionPanel.ssh.portField=porta SSH: -AbstractConnectionPanel.ssh.userField=USUÁRIO: -AbstractConnectionPanel.ssh.passwordField=Senha: -AbstractConnectionPanel.ssh.note.top=Digite os parâmetros para conexão com o servidor remoto via túnel SSH. -AbstractConnectionPanel.ssh.note.bottom=Nota:Ao salvar a senha aqui, ela será criptografada SOMENTE nos arquivos de configuração do aplicativo.
Os valores criptografados e armazenados podem ser comprometidos e não devem ser considerados completamente seguros. -AbstractConnectionPanel.Store-container-password=Senha do contêiner de armazenamento -AbstractConnectionPanel.StorePassword=Salvar senha -AbstractConnectionPanel.useNewApiCheck=Usar a nova API OO -AbstractConnectionPanel.useNativeCheck=Usar a biblioteca do cliente (conexão nativa) -AbstractConnectionPanel.useEmbeddedCheck=Usar servidor incorporado (conexão incorporada) -AbstractConnectionPanel.Verify-server-certificate=Verifica o certificado do servidor -AbstractConnectionPanel.addNewDriver=Novo driver -AbstractConnectionPanel.borderTitle=Conectar usando túnel SSH -AbstractConnectionPanel.certField=Certificado X.509: -AbstractConnectionPanel.certFile=Arquivos de certificado -AbstractConnectionPanel.databaseFile=Arquivos de banco de dados -AbstractConnectionPanel.containerPasswordField=Senha do contêiner: -AbstractConnectionPanel.passwordField=Senha: -AbstractConnectionPanel.delete.tool-tip=Remover este par: chave/valor -AbstractConnectionPanel.driverCombo=Driver JDBC: -AbstractConnectionPanel.error.disconnect=Ocorreu um erro ao se desconectar do banco de dados.\nO sistema retornou: {0} -AbstractConnectionPanel.error.connect=Ocorreu um erro ao se conectar ao banco de dados.\nSistema retornou: {0} -AbstractConnectionPanel.error.nameExist=O nome inserido para essa conexão ({0}) já existe -AbstractConnectionPanel.error.nameEmpty=O nome da conexão não pode estar vazio. -AbstractConnectionPanel.hostField.tool-tip=Nome do servidor ou endereço IP -AbstractConnectionPanel.hostField=Nome do servidor: -AbstractConnectionPanel.nameField.tool-tip=Nome abreviado da conexão -AbstractConnectionPanel.nameField=Nome da conexão: -AbstractConnectionPanel.namesToUpperCheck=Tornar os nomes dos objetos em maiúsculas -AbstractConnectionPanel.portField.tool-tip=Número da porta do banco de dados -AbstractConnectionPanel.portField=Porta: -AbstractConnectionPanel.selectDriver=Selecionar... -AbstractConnectionPanel.sourceField.tool-tip=Caminho para o arquivo de banco de dados -AbstractConnectionPanel.fileField=Arquivo de banco de dados: -AbstractConnectionPanel.status.Connected.connection=abrir conexão ] -AbstractConnectionPanel.status.Connected.connections=\ open connections ] -AbstractConnectionPanel.status.Connected=conectado -AbstractConnectionPanel.status.NotConnected=Não conectado -AbstractConnectionPanel.statusLabel.tool-tip=Situação atual da conexão -AbstractConnectionPanel.statusLabel=Status: -AbstractConnectionPanel.test.success=A conexão foi bem-sucedida! -AbstractConnectionPanel.urlField.tool-tip= URL completo do JDBC para esta conexão -AbstractConnectionPanel.userField.tool-tip=Digite o nome do usuário -AbstractConnectionPanel.userField=Usuário: -AbstractConnectionPanel.warning.useNewAPI.driver=A nova API OO pode ser utilizada com o driver Jaybird 4 ou mais recente. -AbstractConnectionPanel.warning.useNewAPI.connType=O uso da nova API OO é possível com uma conexão NATIVE ou EMBEDDED. -AbstractConnectionPanel.somethingEmpty=Preencha todos os campos obrigatórios. -AbstractConnectionPanel.driverNotSupported=Não há suporte para a criação de um banco de dados para o driver selecionado. -AbstractConnectionPanel.driverVersionNotSupported=Não é possível criar um banco de dados, o Jaybird 2 não possui uma implementação para criar um banco de dados. -AbstractConnectionPanel.fbclientNotFound=Não é possível criar um banco de dados porque a biblioteca fbclient não foi encontrada na variável de caminho do ambiente. -AbstractConnectionPanel.connectionNotEstablished=Não foi possível estabelecer a conexão com o banco de dados.\nPor favor, verifique se todos os campos obrigatórios foram inseridos e tente novamente. -AbstractConnectionPanel.databaseNotCreated=Falha ao criar um banco de dados.php.\nSistema retornou: {0} -AbstractConnectionPanel.multiFactorPanel=Certificado. -AdvancedPropertiesPanel.JDBCProperties=Propriedades de JDBC -AdvancedPropertiesPanel.IsolationLevel=Nível de isolamento: -AdvancedPropertiesPanel.TransactionIsolation=Nível de isolamento de transação -AdvancedPropertiesPanel.setLevel.success=Transaction IsolationLevel {0} aplicado com sucesso -AdvancedPropertiesPanel.setLevel.warning=O driver especificado para essa conexão não oferece suporte a transações.\nEsse recurso não está disponível. -AdvancedPropertiesPanel.setLevel.exception=O nível de isolamento selecionado não pode ser aplicado.\nO driver JDBC retornou: {0} -AdvancedPropertiesPanel.propertyLocked=O atributo inserido não é editável porque é gerado automaticamente de acordo com as configurações de conexão selecionadas. -AdvancedPropertiesPanel.propertiesText=Digite um par chave-valor nas propriedades dessa conexão

Verifique a documentação apropriada do driver JDBC para obter as entradas possíveis.. -AdvancedPropertiesPanel.transactionText=Nível de isolamento de transação padrão para essa conexão

Nota: o nível de isolamento selecionado será aplicado a todas as conexões abertas desse tipo.. ConnectionProgressDialog.connection-canceled=Conexão cancelada ConnectionProgressDialog.connectionLabel=Estabelecendo conexão com {0} ConnectionTree.error.exportAsDrag=Seleção de nó pendente antes de arrastar +ConnectionType.EMBEDDED=Incorporado +ConnectionType.NATIVE=Nativo +ConnectionType.PURE_JAVA=Java puro +ConnectionsComboBox.connectionError=Não foi possível conectar-se ao banco de dados selecionado. +ConnectionsComboBox.embeddedNotAllowed=A ferramenta não suporta o trabalho com conexão incorporada.\nÉ necessária uma conexão de rede. ConnectionsListPanel.AvailableConnections=Conexões disponíveis ConnectionsListPanel.ConnectionName=Nome da conexão ConnectionsListPanel.DataSource=Fonte de dados @@ -1180,12 +1180,12 @@ CreateProcedureFunctionPanel.FUNCTION=Função CreateProcedureFunctionPanel.InputParameters=Parâmetros de entrada CreateProcedureFunctionPanel.OutputParameters=Parâmetros de saída CreateProcedureFunctionPanel.PROCEDURE=Procedimento -CreateProcedureFunctionPanel.Subprograms=Subprogramas CreateProcedureFunctionPanel.Variables=Variáveis CreateProcedureFunctionPanel.confirmTabChange=Quando você sair dessa guia, todas as alterações feitas serão perdidas.\nTem certeza de que deseja mudar de guia? CreateProcedureFunctionPanel.executeFunction=Executar função CreateProcedureFunctionPanel.executeProcedure=Executar procedimento CreateProcedureFunctionPanel.showHelpersCheck=Mostrar ferramentas auxiliares +CreateRolePanel.title=Criar função CreateTablePanel.Columns=Colunas CreateTablePanel.Connection=Conexão: CreateTablePanel.Constraints=Restrições @@ -1272,43 +1272,44 @@ CustomLafSelectionPanel.LookFeelLibraryIsRequired=É necessário um caminho vál CustomLafSelectionPanel.NoValidClasses=Nenhuma classe válida do tipo javax.swing.LookAndFeel foi encontrada no recurso especificado. CustomLafSelectionPanel.SelectLookFeel=Selecione Look and Feel CustomLafSelectionPanel.SelectLookFeelFromList=Você deve selecionar uma aparência na lista -DatabaseObjectMetaDataPanel.DatabaseObjectMetaData=Meta dados do objeto de banco de dados -DatabaseStatisticPanel.title=Estatísticas do banco de dados -DatabaseBackupRestorePanel.title=Cópia de segurança/restauro da base de dados -DatabaseBackupRestorePanel.connections=Conexão: +DatabaseBackupRestorePanel.Backup=Backup +DatabaseBackupRestorePanel.LogToFile=Registro em arquivo +DatabaseBackupRestorePanel.Restore=Restauração DatabaseBackupRestorePanel.backupButton=Criar Backup -DatabaseBackupRestorePanel.ignoreChecksumsCheckBox=Ignorar checksums -DatabaseBackupRestorePanel.noGarbageCollectCheckBox=Sem coleta de lixo -DatabaseBackupRestorePanel.metadataOnlyCheckBox=Apenas Metadados -DatabaseBackupRestorePanel.nonTransportableCheckBox=Backup não transportável -DatabaseBackupRestorePanel.parallelWorkersAmount=Quantidade de trabalhadores paralelos: +DatabaseBackupRestorePanel.backupFailed=Falha no backup\n{0} DatabaseBackupRestorePanel.backupFile=Arquivo de backup: +DatabaseBackupRestorePanel.backupFileField=Arquivo de backup: DatabaseBackupRestorePanel.backupFileSelection=Selecionar arquivo de backup +DatabaseBackupRestorePanel.backupSucceed=Backup concluído com sucesso! +DatabaseBackupRestorePanel.charset=Caracteres: +DatabaseBackupRestorePanel.connections=Conexão: +DatabaseBackupRestorePanel.database=Banco de Dados: DatabaseBackupRestorePanel.databaseFileSelection=Selecionar arquivo de Banco de Dados -DatabaseBackupRestorePanel.restoreButton=Restaurar Banco de Dados DatabaseBackupRestorePanel.deactivateIdxCheckBox=Desativar Índices +DatabaseBackupRestorePanel.host=Servidor: +DatabaseBackupRestorePanel.ignoreChecksumsCheckBox=Ignorar checksums +DatabaseBackupRestorePanel.loggingOutput=Saída de log +DatabaseBackupRestorePanel.metadataOnlyCheckBox=Apenas Metadados +DatabaseBackupRestorePanel.noGarbageCollectCheckBox=Sem coleta de lixo DatabaseBackupRestorePanel.noShadowCheckBox=Sem sombra DatabaseBackupRestorePanel.noValidityCheckBox=Sem verificação de validade +DatabaseBackupRestorePanel.nonTransportableCheckBox=Backup não transportável DatabaseBackupRestorePanel.oneAtATimeCheckBox=Restaurar um de cada vez -DatabaseBackupRestorePanel.restoreOverrideCheck=Override o arquivo de banco de dados DatabaseBackupRestorePanel.pageSizeField=Tamanho da página de restauração: +DatabaseBackupRestorePanel.parallelWorkersAmount=Quantidade de trabalhadores paralelos: DatabaseBackupRestorePanel.parallelWorkersField=Quantidade de trabalhadores paralelos: -DatabaseBackupRestorePanel.backupFileField=Arquivo de backup: -DatabaseBackupRestorePanel.loggingOutput=Saída de log -DatabaseBackupRestorePanel.Backup=Backup -DatabaseBackupRestorePanel.Restore=Restauração -DatabaseBackupRestorePanel.database=Banco de Dados: -DatabaseBackupRestorePanel.host=Servidor: -DatabaseBackupRestorePanel.port=Porta: -DatabaseBackupRestorePanel.username=Usuário: DatabaseBackupRestorePanel.password=Senha: -DatabaseBackupRestorePanel.charset=Caracteres: -DatabaseBackupRestorePanel.backupSucceed=Backup concluído com sucesso! -DatabaseBackupRestorePanel.restoreSucceed=Restauração concluída com sucesso! -DatabaseBackupRestorePanel.restoreSucceed.register=Restauração concluída com sucesso!\nRegistrar o banco de dados restaurado? -DatabaseBackupRestorePanel.backupFailed=Falha no backup\n{0} -DatabaseBackupRestorePanel.restoreFailed=Falha na restauração\n{0} +DatabaseBackupRestorePanel.port=Porta: DatabaseBackupRestorePanel.requiredFieldsCheckFailed=Preencha todos os campos obrigatórios +DatabaseBackupRestorePanel.restoreButton=Restaurar Banco de Dados +DatabaseBackupRestorePanel.restoreFailed=Falha na restauração\n{0} +DatabaseBackupRestorePanel.restoreOverrideCheck=Override o arquivo de banco de dados +DatabaseBackupRestorePanel.restoreSucceed.register=Restauração concluída com sucesso!\nRegistrar o banco de dados restaurado? +DatabaseBackupRestorePanel.restoreSucceed=Restauração concluída com sucesso! +DatabaseBackupRestorePanel.title=Cópia de segurança/restauro da base de dados +DatabaseBackupRestorePanel.username=Usuário: +DatabaseObjectMetaDataPanel.DatabaseObjectMetaData=Meta dados do objeto de banco de dados +DatabaseStatisticPanel.title=Estatísticas do banco de dados DatabaseTableNode.columns=Colunas DatabaseTableNode.foreign-keys=Chaves estrangeiras DatabaseTableNode.indexes=Índices @@ -1622,9 +1623,9 @@ FeedbackPanel.title=Feedback FeedbackPanel.userComments=Comentários do usuário FeedbackPanel.warningInternetConnection=Esse recurso requer uma conexão ativa com a Internet. FileChooserDialog.new-command.overwrite-file=Substituir o arquivo existente? -FileValidator.nameEmpty=O nome do arquivo não pode estar vazio FileValidator.extensionEmpty=O arquivo deve ter a extensão {0} FileValidator.fileNotExists=O arquivo {0} não existe +FileValidator.nameEmpty=O nome do arquivo não pode estar vazio FindReplaceDialog.FindAndReplace=Localizar e substituir FindReplaceDialog.FindText=Localizar texto FindReplaceDialog.MatchCaseCheck=Caso de correspondência @@ -1812,8 +1813,6 @@ ImportDataPanel.ReadDatabaseErrorMessage=Obtendo erro no conjunto de resultados ImportDataPanel.ReadFileMessage=Primeiro, leia o arquivo de origem ImportDataPanel.RecordsAddedLabel=%s registros adicionados ImportDataPanel.RefreshButtonText=Atualizar -ImportDataPanel.SelectDB=Selecionar BD -ImportDataPanel.SelectDBMessage=Primeiro, selecione o banco de dados de destino ImportDataPanel.SelectTable=Selecionar tabela ImportDataPanel.SelectTableMessage=Primeiro, selecione a tabela de destino ImportDataPanel.SheetNumberLabel=Número da folha: @@ -2074,8 +2073,8 @@ PropertiesToolBar.RemoveSeparator=Remover PropertiesToolBar.Separator=Separador PropertyWrapperModel.property=Propriedade PropertyWrapperModel.value=Valor +QueryEditor.ExceptionOnClose=Ocorreu um erro ao fechar o editor de consultas.\nO sistema retornou:\n QueryEditor.FileSavedTo=Arquivo salvo em {0} -QueryEditor.UnsavedChanges=Há mudanças que não são salvas QueryEditor.Filter=Filtro: QueryEditor.FilterToolTip=Aplicar filtro ao conjunto de resultados atual QueryEditor.LineWrapper.tool-tip=Ativar/desativar a quebra automática de linha @@ -2083,14 +2082,14 @@ QueryEditor.LineWrapper=Linhas de enrolamento QueryEditor.MaxRowsToolTip=Definir o máximo de linhas retornadas (-1 para todas) QueryEditor.ShowTPP=Mostrar TPP QueryEditor.TransactionIsolationLevel=Nível de isolamento da transação: +QueryEditor.UnsavedChanges=Há mudanças que não são salvas QueryEditor.autocommitDisable=A confirmação automática está desativada QueryEditor.autocommitEnable=O autocommit está ativado +QueryEditor.isExecutionActive=O editor está a executar a consulta.\nPor favor, aguarde a conclusão ou tente interromper a execução. QueryEditor.requestTransactionMessage=Comprometer a transação ativa antes do fechamento? QueryEditor.requestTransactionTitle=Há uma transação ativa QueryEditor.script=script QueryEditor.title=Editor de consultas -QueryEditor.isExecutionActive=O editor está a executar a consulta.\nPor favor, aguarde a conclusão ou tente interromper a execução. -QueryEditor.ExceptionOnClose=Ocorreu um erro ao fechar o editor de consultas.\nO sistema retornou:\n QueryEditorResultsPanel.DatabaseOutput=Saída do banco de dados QueryEditorResultsPanel.LIMIT_ON=Limite de contagem de linhas ativado para {0} registros QueryEditorResultsPanel.NO_ROWS=Nenhuma linha selecionada @@ -2346,8 +2345,8 @@ TableTriggersTableModel.Description=Comentário TableTriggersTableModel.Position=Posição TableTriggersTableModel.TriggerName=Nome do acionador TableTriggersTableModel.TriggerType=Tipo de gatilho -TableValidationCommand.validationError=Não é possível executar a validação de tabelas TableValidationCommand.initError=Não foi possível iniciar a instância do IFBMaintenanceManager +TableValidationCommand.validationError=Não é possível executar a validação de tabelas TableValidationPanel.AvailableIndexLabel=Índices disponíveis TableValidationPanel.AvailableTablesLabel=Mesas disponíveis TableValidationPanel.Connection=Conexão: @@ -2396,7 +2395,8 @@ UserManagerPanel.message.confirm-delete-role=Tem certeza de que deseja excluir a UserManagerPanel.message.confirm-delete-user=Tem certeza de que deseja excluir o usuário? UserManagerPanel.message.create-role=Sucesso UserManagerPanel.server=Servidor -WindowAddRole.CreateRole=Criar função +ViewablePasswordField.buttonTooltip.hide=Ocultar senha +ViewablePasswordField.buttonTooltip.show=Show password WindowAddUser.Administrator=Administrador WindowAddUser.Cancel=Cancelar WindowAddUser.ConfirmPassword=Confirmar senha diff --git a/src/org/executequery/localization/resources_ru.properties b/src/org/executequery/localization/resources_ru.properties index 631890917..ce22732eb 100644 --- a/src/org/executequery/localization/resources_ru.properties +++ b/src/org/executequery/localization/resources_ru.properties @@ -532,10 +532,85 @@ AboutPanel.discussionChatLabel=Сообщество пользователей AboutPanel.discussionChatLink=https://t.me/firebird_reddatabase AboutPanel.gitHubLabel=Репозиторий на GitHub AboutPanel.reddatabaseNewsLabel=Новости Ред Базы Данных +AbstractConnectionPanel.Advanced=Расширенные +AbstractConnectionPanel.Basic=Базовые +AbstractConnectionPanel.BasicAu=Базовая +AbstractConnectionPanel.Create=Создать +AbstractConnectionPanel.CreateDatabase=Создать базу данных +AbstractConnectionPanel.DatabaseDefault=По умолчанию +AbstractConnectionPanel.EncryptPassword=Зашифровать пароль +AbstractConnectionPanel.MultiFactor=Многофакторная +AbstractConnectionPanel.NoCharacterSet=Без кодировки +AbstractConnectionPanel.Store-container-password=Сохранить пароль контейнера +AbstractConnectionPanel.StorePassword=Сохранить пароль +AbstractConnectionPanel.Verify-server-certificate=Проверить сертификат сервера +AbstractConnectionPanel.addNewDriver=Новый драйвер +AbstractConnectionPanel.authCombo=Аутентификация: +AbstractConnectionPanel.borderTitle=Подключиться используя SSH-туннель +AbstractConnectionPanel.certField=Сертификат X.509: +AbstractConnectionPanel.certFile=Файлы сертификата +AbstractConnectionPanel.charsetsCombo=Кодировка: +AbstractConnectionPanel.connectionNotEstablished=Не удалось установить соединение с базой данных.\nПожалуйста, убедитесь, что все необходимые поля введены, и повторите попытку. +AbstractConnectionPanel.containerPasswordField=Пароль контейнера: +AbstractConnectionPanel.databaseFile=Файлы базы данных +AbstractConnectionPanel.databaseNotCreated=Не удалось создать базу данных.\nСистема вернула: {0} +AbstractConnectionPanel.delete.tool-tip=Удалить эту пару:ключ/значение +AbstractConnectionPanel.driverCombo=JDBC Драйвер: +AbstractConnectionPanel.driverNotSupported=Создание базы данных для выбранного драйвера не поддерживается. +AbstractConnectionPanel.driverVersionNotSupported=Невозможно создать базу данных, Jaybird 2 не имеет реализации для создания базы данных. +AbstractConnectionPanel.error.connect=Произошла ошибка при подключении к базе данных.\nСистема вернула: {0} +AbstractConnectionPanel.error.disconnect=Произошла ошибка при отключении от базы данных.\nСистема вернула: {0} +AbstractConnectionPanel.error.nameEmpty=Имя подключения не может быть пустым +AbstractConnectionPanel.error.nameExist=Имя, введенное для этого подключения ({0}) уже существует +AbstractConnectionPanel.fbclientNotFound=Невозможно создать базу данных, так как библиотека fbclient не найдена в переменной пути окружения.\nПожалуйста, добавьте библиотеку fbclient в переменную пути окружения. +AbstractConnectionPanel.fileField=Файл БД: +AbstractConnectionPanel.hostField.tool-tip=Имя сервера или IP адрес +AbstractConnectionPanel.hostField=Имя сервера: +AbstractConnectionPanel.multiFactorPanel=Сертификат +AbstractConnectionPanel.nameField.tool-tip=Краткое имя подключения +AbstractConnectionPanel.nameField=Имя подключения: +AbstractConnectionPanel.namesToUpperCheck=Приводить имена объектов к верхнему регистру +AbstractConnectionPanel.pageSizeCombo=Размер страницы: +AbstractConnectionPanel.passwordField=Пароль: +AbstractConnectionPanel.portField.tool-tip=Номер порта базы данных +AbstractConnectionPanel.portField=Порт: +AbstractConnectionPanel.registration.message=Зарегистрировать созданную базу данных? +AbstractConnectionPanel.registration=Регистрация базы данных +AbstractConnectionPanel.roleField=Роль: +AbstractConnectionPanel.selectDriver=Выбрать... +AbstractConnectionPanel.serverCombo=Сервер: +AbstractConnectionPanel.somethingEmpty=Заполните все обязательные поля. +AbstractConnectionPanel.sourceField.tool-tip=Путь к файлу базы данных +AbstractConnectionPanel.ssh.hostField=SSH хост: +AbstractConnectionPanel.ssh.note.bottom=Примечание: Сохранение пароля здесь зашифрует его ТОЛЬКО в файлах конфигурации приложения.
Зашифрованные и сохраненные значения могут быть скомпрометированы и не должны считаться полностью безопасными. +AbstractConnectionPanel.ssh.note.top=Введите параметры подключения к удаленному серверу через SSH-туннель. +AbstractConnectionPanel.ssh.passwordField=Пароль: +AbstractConnectionPanel.ssh.portField=SSH порт: +AbstractConnectionPanel.ssh.title=SSH-туннель +AbstractConnectionPanel.ssh.userField=Пользователь: +AbstractConnectionPanel.status.Connected.connection=открытое подключение ] +AbstractConnectionPanel.status.Connected.connections=\ открытых подключений ] +AbstractConnectionPanel.status.Connected=Подключено +AbstractConnectionPanel.status.NotConnected=Не подключено +AbstractConnectionPanel.statusLabel.tool-tip=Текущее состояние подключения +AbstractConnectionPanel.statusLabel=Состояние: +AbstractConnectionPanel.test.success=Подключение состоялось! +AbstractConnectionPanel.urlField.tool-tip=Полный URL к JDBC для этого подключения +AbstractConnectionPanel.useEmbeddedCheck=Использовать встроенный сервер (embedded подключение) +AbstractConnectionPanel.useNativeCheck=Использовать клиентскую библиотеку (native подключение) +AbstractConnectionPanel.useNewApiCheck=Использовать новое OO API +AbstractConnectionPanel.useSshCheck=Использовать SSH-туннель +AbstractConnectionPanel.userField.tool-tip=Введите имя пользователя +AbstractConnectionPanel.userField=Пользователь: +AbstractConnectionPanel.warning.useNewAPI.connType=Использование нового OO API возможно с использованием NATIVE или EMBEDDED подключения. +AbstractConnectionPanel.warning.useNewAPI.driver=Использование нового OO API возможно с драйвером Jaybird 4 или новее. AbstractCreateObjectPanel.Engine=Движок AbstractCreateObjectPanel.EntryPoint=Внешний модуль AbstractCreateObjectPanel.EntryPoint_alternative=Модуль +AbstractCreateObjectPanel.FUNCTION=функции +AbstractCreateObjectPanel.PROCEDURE=процедуры AbstractCreateObjectPanel.SQL=SQL +AbstractCreateObjectPanel.Subprograms=Подпрограммы AbstractCreateObjectPanel.active=Активный AbstractCreateObjectPanel.check=Проверка AbstractCreateObjectPanel.computed=Вычисляемое как @@ -589,7 +664,6 @@ AbstractServiceManagerPanel.Highlight=Подсветка цветом AbstractServiceManagerPanel.Host=Сервер AbstractServiceManagerPanel.ID=ID AbstractServiceManagerPanel.LogToFile=Лог в файл -DatabaseBackupRestorePanel.LogToFile=Лог в файл AbstractServiceManagerPanel.Logger=Таблица событий AbstractServiceManagerPanel.Name=Имя AbstractServiceManagerPanel.OpenFileLog=Загрузить из файла @@ -640,6 +714,15 @@ AddQueryBookmarkPanel.saveError=Ошибка сохранения закладк AddQueryBookmarkPanel.validation.name=Пожалуйста, введите имя закладки AddQueryBookmarkPanel.validation.query=Пожалуйста, введите SQL-запрос, который будет храниться в этой закладке. AddQueryBookmarkPanel.validation.uniqueName=Имя этой закладки уже существует. \nВы хотите перезаписать существующее значение закладки? +AdvancedPropertiesPanel.IsolationLevel=Уровень изоляции: +AdvancedPropertiesPanel.JDBCProperties=Свойства JDBC +AdvancedPropertiesPanel.TransactionIsolation=Изоляция транзакции +AdvancedPropertiesPanel.propertiesText=Введите в свойствах для этого подключение пару: ключ-значение

Обратитесь к соответствующей документации драйвера JDBC, чтобы узнать возможные записи. +AdvancedPropertiesPanel.propertyLocked=Введенный атрибут не доступен для редактирования, так как автоматически генерируется в соответствии с выбранными настройками подключения. +AdvancedPropertiesPanel.setLevel.exception=Выбранный уровень изоляции не может быть применен.\nДрайвер JDBC вернул: {0} +AdvancedPropertiesPanel.setLevel.success=Уровень изоляции транзакций {0} успешно применен +AdvancedPropertiesPanel.setLevel.warning=Указанный драйвер для этого соединения не поддерживает транзакции.\nЭта функция недоступна. +AdvancedPropertiesPanel.transactionText=Стандартный уровень изоляции транзакции для этого подключения

Примечание: выбранный уровень изоляции будет применяться ко всем открытым соединениям этого типа. AnalisePanel.AvailableEvents=Доступные события AnalisePanel.HideEvents=Скрыть фильтр событий AnalisePanel.HidePlan=Скрыть план @@ -791,13 +874,13 @@ BrowserTreeDefaultPopupMenu.NewConnection=Новое подключение BrowserTreeDefaultPopupMenu.NewFolder=Новая папка BrowserTreeDefaultPopupMenu.SearchNodes=Поиск узлов BrowserTreeDefaultPopupMenu.SortConnections=Сортировка подключений +BrowserTreeHostPopupMenu.BackupRestore=Создать резервную копию БД BrowserTreeHostPopupMenu.Connect=Подключиться BrowserTreeHostPopupMenu.CopyName=Копировать имя BrowserTreeHostPopupMenu.Delete=Удалить подключение BrowserTreeHostPopupMenu.Disconnect=Отключиться -BrowserTreeHostPopupMenu.ExtractMetadata=Извлечь метаданные BrowserTreeHostPopupMenu.Duplicate=Дублировать подключение -BrowserTreeHostPopupMenu.BackupRestore=Создать резервную копию БД +BrowserTreeHostPopupMenu.ExtractMetadata=Извлечь метаданные BrowserTreeHostPopupMenu.MoveToFolder=Переместить в папку BrowserTreeHostPopupMenu.NewConnection=Новое подключение BrowserTreeHostPopupMenu.NewFolder=Новая папка @@ -969,6 +1052,7 @@ ComparerDBPanel.CreatingStubs=Создание скриптов-заглушек ComparerDBPanel.DATABASE_TRIGGER=Триггеры БД ComparerDBPanel.DatabaseChanges=Изменения БД ComparerDBPanel.DropObjects=Элементы для удаления +ComparerDBPanel.EmbeddedConnectionSelected=\nКак минимум одно из соединений использует встроенный сервер.\nЗадания не будут включены в процесс сравнения. ComparerDBPanel.ErrorOccurred=Произошла ошибка при сравнении БД.\nСравнение будет принудительно завершено. ComparerDBPanel.ExecuteScriptButton=Выполнить скрипт ComparerDBPanel.Executing=Идет сравнение, пожалуйста подождите @@ -1003,7 +1087,6 @@ ComparerDBPanel.OutputLabel=Вывод ComparerDBPanel.PropertiesLabel=Параметры ComparerDBPanel.RDBVersionBelow3=\nКак минимум одно из соединений использует версию РедБазыДанных ниже 3.0.\nПользователи, пакеты, функции, DDL триггеры, табличные пространства и задания не будут включены в процесс сравнения. ComparerDBPanel.RDBVersionBelow4=\nКак минимум одно из соединений использует версию РедБазыДанных ниже 4.0.\nТабличные пространства и задания не будут включены в процесс сравнения. -ComparerDBPanel.EmbeddedConnectionSelected=\nКак минимум одно из соединений использует встроенный сервер.\nЗадания не будут включены в процесс сравнения. ComparerDBPanel.SafeTypeConversion=Безопасное преобразование типов ComparerDBPanel.SaveScriptButton=Сохранить скрипт ComparerDBPanel.SavedTo=Путь к сохраненному файлу: @@ -1017,101 +1100,23 @@ ComparerDBPanel.TargetLabel=Скрипт целевой базы (старый) ComparerDBPanel.TreeView=Обзор ComparerDBPanel.UnableCompareBusyConnections=Невозможно начать процесс сравнения.\nКак минимум одно из соединений занято другим процессом сравнения или извлечением метаданных. ComparerDBPanel.UnableCompareNoAttributes=Невозможно начать процесс сравнения.\nНе выбраны аттрибуты для сравнения. -ComparerDBPanel.UnableCompareNoConnections=Невозможно начать процесс сравнения.\nКак минимум одно из соединений неактивно. ComparerDBPanel.UnableCompareNoConnections.extract=Невозможно начать процесс сравнения.\nСоединение неактивно. +ComparerDBPanel.UnableCompareNoConnections=Невозможно начать процесс сравнения.\nКак минимум одно из соединений неактивно. ComparerDBPanel.UnableCompareNoProperties=Невозможно начать процесс сравнения.\nНе выбраны параметры для сравнения. ComparerDBPanel.UnableCompareSampleConnections=Невозможно начать процесс сравнения.\nВыбраны эквивалентные соединения. ComparerDBPanel.UnableExtractBusyConnections=Невозможно начать процесс извлечения.\nВыбранное соединение занято процессом сравнения или другим процессом извлечения метаданных. ComparerDBPanel.UnableExtractNoAttributes=Невозможно начать процесс извлечения.\nНе выбраны аттрибуты для сравнения. ComparerDBPanel.title-export=Экспорт метаданных БД ComparerDBPanel.title=Сравнение баз данных -ConnectionsComboBox.embeddedNotAllowed=Инструмент не поддерживает работу со встроенным сервером.\nДля работы требуется сетевое подключение. -ConnectionsComboBox.connectionError=Не удалось подключиться к выбранной базе данных. ConnectionImporter.ImportingConnection=Импортирование соединения [ {0} ] -AbstractConnectionPanel.Advanced=Расширенные -AbstractConnectionPanel.authCombo=Аутентификация: -AbstractConnectionPanel.Basic=Базовые -AbstractConnectionPanel.BasicAu=Базовая -AbstractConnectionPanel.charsetsCombo=Кодировка: -AbstractConnectionPanel.Create=Создать -AbstractConnectionPanel.CreateDatabase=Создать базу данных -AbstractConnectionPanel.DatabaseDefault=По умолчанию -AbstractConnectionPanel.registration.message=Зарегистрировать созданную базу данных? -AbstractConnectionPanel.registration=Регистрация базы данных -AbstractConnectionPanel.EncryptPassword=Зашифровать пароль -AbstractConnectionPanel.MultiFactor=Многофакторная -AbstractConnectionPanel.NoCharacterSet=Без кодировки -AbstractConnectionPanel.pageSizeCombo=Размер страницы: -AbstractConnectionPanel.roleField=Роль: -AbstractConnectionPanel.serverCombo=Сервер: -AbstractConnectionPanel.useSshCheck=Использовать SSH-туннель -AbstractConnectionPanel.ssh.title=SSH-туннель -AbstractConnectionPanel.ssh.hostField=SSH хост: -AbstractConnectionPanel.ssh.portField=SSH порт: -AbstractConnectionPanel.ssh.userField=Пользователь: -AbstractConnectionPanel.ssh.passwordField=Пароль: -AbstractConnectionPanel.ssh.note.top=Введите параметры подключения к удаленному серверу через SSH-туннель. -AbstractConnectionPanel.ssh.note.bottom=Примечание: Сохранение пароля здесь зашифрует его ТОЛЬКО в файлах конфигурации приложения.
Зашифрованные и сохраненные значения могут быть скомпрометированы и не должны считаться полностью безопасными. -AbstractConnectionPanel.Store-container-password=Сохранить пароль контейнера -AbstractConnectionPanel.StorePassword=Сохранить пароль -AbstractConnectionPanel.useNewApiCheck=Использовать новое OO API -AbstractConnectionPanel.useNativeCheck=Использовать клиентскую библиотеку (native подключение) -AbstractConnectionPanel.useEmbeddedCheck=Использовать встроенный сервер (embedded подключение) -AbstractConnectionPanel.Verify-server-certificate=Проверить сертификат сервера -AbstractConnectionPanel.addNewDriver=Новый драйвер -AbstractConnectionPanel.borderTitle=Подключиться используя SSH-туннель -AbstractConnectionPanel.certField=Сертификат X.509: -AbstractConnectionPanel.certFile=Файлы сертификата -AbstractConnectionPanel.databaseFile=Файлы базы данных -AbstractConnectionPanel.containerPasswordField=Пароль контейнера: -AbstractConnectionPanel.passwordField=Пароль: -AbstractConnectionPanel.delete.tool-tip=Удалить эту пару:ключ/значение -AbstractConnectionPanel.driverCombo=JDBC Драйвер: -AbstractConnectionPanel.error.disconnect=Произошла ошибка при отключении от базы данных.\nСистема вернула: {0} -AbstractConnectionPanel.error.connect=Произошла ошибка при подключении к базе данных.\nСистема вернула: {0} -AbstractConnectionPanel.error.nameExist=Имя, введенное для этого подключения ({0}) уже существует -AbstractConnectionPanel.error.nameEmpty=Имя подключения не может быть пустым -AbstractConnectionPanel.hostField.tool-tip=Имя сервера или IP адрес -AbstractConnectionPanel.hostField=Имя сервера: -AbstractConnectionPanel.nameField.tool-tip=Краткое имя подключения -AbstractConnectionPanel.nameField=Имя подключения: -AbstractConnectionPanel.namesToUpperCheck=Приводить имена объектов к верхнему регистру -AbstractConnectionPanel.portField.tool-tip=Номер порта базы данных -AbstractConnectionPanel.portField=Порт: -AbstractConnectionPanel.selectDriver=Выбрать... -AbstractConnectionPanel.sourceField.tool-tip=Путь к файлу базы данных -AbstractConnectionPanel.fileField=Файл БД: -AbstractConnectionPanel.status.Connected.connection=открытое подключение ] -AbstractConnectionPanel.status.Connected.connections=\ открытых подключений ] -AbstractConnectionPanel.status.Connected=Подключено -AbstractConnectionPanel.status.NotConnected=Не подключено -AbstractConnectionPanel.statusLabel.tool-tip=Текущее состояние подключения -AbstractConnectionPanel.statusLabel=Состояние: -AbstractConnectionPanel.test.success=Подключение состоялось! -AbstractConnectionPanel.urlField.tool-tip=Полный URL к JDBC для этого подключения -AbstractConnectionPanel.userField.tool-tip=Введите имя пользователя -AbstractConnectionPanel.userField=Пользователь: -AbstractConnectionPanel.warning.useNewAPI.driver=Использование нового OO API возможно с драйвером Jaybird 4 или новее. -AbstractConnectionPanel.warning.useNewAPI.connType=Использование нового OO API возможно с использованием NATIVE или EMBEDDED подключения. -AbstractConnectionPanel.somethingEmpty=Заполните все обязательные поля. -AbstractConnectionPanel.driverNotSupported=Создание базы данных для выбранного драйвера не поддерживается. -AbstractConnectionPanel.driverVersionNotSupported=Невозможно создать базу данных, Jaybird 2 не имеет реализации для создания базы данных. -AbstractConnectionPanel.fbclientNotFound=Невозможно создать базу данных, так как библиотека fbclient не найдена в переменной пути окружения.\nПожалуйста, добавьте библиотеку fbclient в переменную пути окружения. -AbstractConnectionPanel.connectionNotEstablished=Не удалось установить соединение с базой данных.\nПожалуйста, убедитесь, что все необходимые поля введены, и повторите попытку. -AbstractConnectionPanel.databaseNotCreated=Не удалось создать базу данных.\nСистема вернула: {0} -AbstractConnectionPanel.multiFactorPanel=Сертификат -AdvancedPropertiesPanel.JDBCProperties=Свойства JDBC -AdvancedPropertiesPanel.IsolationLevel=Уровень изоляции: -AdvancedPropertiesPanel.TransactionIsolation=Изоляция транзакции -AdvancedPropertiesPanel.setLevel.success=Уровень изоляции транзакций {0} успешно применен -AdvancedPropertiesPanel.setLevel.warning=Указанный драйвер для этого соединения не поддерживает транзакции.\nЭта функция недоступна. -AdvancedPropertiesPanel.setLevel.exception=Выбранный уровень изоляции не может быть применен.\nДрайвер JDBC вернул: {0} -AdvancedPropertiesPanel.propertyLocked=Введенный атрибут не доступен для редактирования, так как автоматически генерируется в соответствии с выбранными настройками подключения. -AdvancedPropertiesPanel.propertiesText=Введите в свойствах для этого подключение пару: ключ-значение

Обратитесь к соответствующей документации драйвера JDBC, чтобы узнать возможные записи. -AdvancedPropertiesPanel.transactionText=Стандартный уровень изоляции транзакции для этого подключения

Примечание: выбранный уровень изоляции будет применяться ко всем открытым соединениям этого типа. ConnectionProgressDialog.connection-canceled=Соединение отменено ConnectionProgressDialog.connectionLabel=Устанавливается связь с {0} ConnectionTree.error.exportAsDrag=Выбор узла до перетаскивания +ConnectionType.EMBEDDED=Напрямую к файлу +ConnectionType.NATIVE=Нативное +ConnectionType.PURE_JAVA=Java реализация +ConnectionsComboBox.connectionError=Не удалось подключиться к выбранной базе данных. +ConnectionsComboBox.embeddedNotAllowed=Инструмент не поддерживает работу со встроенным сервером.\nДля работы требуется сетевое подключение. ConnectionsListPanel.AvailableConnections=Доступные подключения ConnectionsListPanel.ConnectionName=Имя подключения ConnectionsListPanel.DataSource=Путь к базе данных @@ -1175,12 +1180,12 @@ CreateProcedureFunctionPanel.FUNCTION=функции CreateProcedureFunctionPanel.InputParameters=Входные параметры CreateProcedureFunctionPanel.OutputParameters=Выходные параметры CreateProcedureFunctionPanel.PROCEDURE=процедуры -CreateProcedureFunctionPanel.Subprograms=Подпрограммы CreateProcedureFunctionPanel.Variables=Переменные CreateProcedureFunctionPanel.confirmTabChange=При выходе с этой вкладки все внесенные изменения будут потеряны.\nВы действительно хотите перейти на другую вкладку? CreateProcedureFunctionPanel.executeFunction=Выполнить функцию CreateProcedureFunctionPanel.executeProcedure=Выполнить процедуру CreateProcedureFunctionPanel.showHelpersCheck=Показать вспомогательные инструменты +CreateRolePanel.title=Создать роль CreateTablePanel.Columns=Столбцы CreateTablePanel.Connection=Подключение: CreateTablePanel.Constraints=Ограничения @@ -1267,43 +1272,44 @@ CustomLafSelectionPanel.LookFeelLibraryIsRequired=Требуется корре CustomLafSelectionPanel.NoValidClasses=В указанном ресурсе не найдено допустимых классов типа javax.swing.LookAndFeel CustomLafSelectionPanel.SelectLookFeel=Выберите плагин внешнего вида CustomLafSelectionPanel.SelectLookFeelFromList=Вы должны выбрать плагин внешнего вида из списка -DatabaseObjectMetaDataPanel.DatabaseObjectMetaData=Метаданные объекта базы данных -DatabaseStatisticPanel.title=Статистика БД -DatabaseBackupRestorePanel.title=Резервное копирование и восстановление -DatabaseBackupRestorePanel.connections=Подключение: +DatabaseBackupRestorePanel.Backup=Резервное копирование +DatabaseBackupRestorePanel.LogToFile=Лог в файл +DatabaseBackupRestorePanel.Restore=Восстановление DatabaseBackupRestorePanel.backupButton=Создать резервную копию -DatabaseBackupRestorePanel.ignoreChecksumsCheckBox=Игнорировать контрольные суммы -DatabaseBackupRestorePanel.noGarbageCollectCheckBox=Без сборки мусора -DatabaseBackupRestorePanel.metadataOnlyCheckBox=Только метаданные -DatabaseBackupRestorePanel.nonTransportableCheckBox=Непереносимое резервное копирование -DatabaseBackupRestorePanel.parallelWorkersAmount=Количество параллельных потоков: +DatabaseBackupRestorePanel.backupFailed=Ошибка резервного копирования\n{0} DatabaseBackupRestorePanel.backupFile=Файл резервной копии БД: +DatabaseBackupRestorePanel.backupFileField=Файл резервной копии БД: DatabaseBackupRestorePanel.backupFileSelection=Выбрать файл резервной копии +DatabaseBackupRestorePanel.backupSucceed=Резервное копирование успешно завершено! +DatabaseBackupRestorePanel.charset=Кодировка: +DatabaseBackupRestorePanel.connections=Подключение: +DatabaseBackupRestorePanel.database=База данных: DatabaseBackupRestorePanel.databaseFileSelection=Выбрать файл базы данных -DatabaseBackupRestorePanel.restoreButton=Восстановить базу данных DatabaseBackupRestorePanel.deactivateIdxCheckBox=Деактивировать индексы +DatabaseBackupRestorePanel.host=Сервер: +DatabaseBackupRestorePanel.ignoreChecksumsCheckBox=Игнорировать контрольные суммы +DatabaseBackupRestorePanel.loggingOutput=Вывод журнала +DatabaseBackupRestorePanel.metadataOnlyCheckBox=Только метаданные +DatabaseBackupRestorePanel.noGarbageCollectCheckBox=Без сборки мусора DatabaseBackupRestorePanel.noShadowCheckBox=Восстановление без теней DatabaseBackupRestorePanel.noValidityCheckBox=Без проверки валидности +DatabaseBackupRestorePanel.nonTransportableCheckBox=Непереносимое резервное копирование DatabaseBackupRestorePanel.oneAtATimeCheckBox=Восстанавливать по одному -DatabaseBackupRestorePanel.restoreOverrideCheck=Перезаписать файл базы данных DatabaseBackupRestorePanel.pageSizeField=Размер страницы БД: +DatabaseBackupRestorePanel.parallelWorkersAmount=Количество параллельных потоков: DatabaseBackupRestorePanel.parallelWorkersField=Количество параллельных потоков: -DatabaseBackupRestorePanel.backupFileField=Файл резервной копии БД: -DatabaseBackupRestorePanel.loggingOutput=Вывод журнала -DatabaseBackupRestorePanel.Backup=Резервное копирование -DatabaseBackupRestorePanel.Restore=Восстановление -DatabaseBackupRestorePanel.database=База данных: -DatabaseBackupRestorePanel.host=Сервер: -DatabaseBackupRestorePanel.port=Порт: -DatabaseBackupRestorePanel.username=Пользователь: DatabaseBackupRestorePanel.password=Пароль: -DatabaseBackupRestorePanel.charset=Кодировка: -DatabaseBackupRestorePanel.backupSucceed=Резервное копирование успешно завершено! -DatabaseBackupRestorePanel.restoreSucceed=Восстановление успешно завершено! -DatabaseBackupRestorePanel.restoreSucceed.register=Восстановление успешно завершено!\nЗарегистрировать восстановленную базу данных? -DatabaseBackupRestorePanel.backupFailed=Ошибка резервного копирования\n{0} -DatabaseBackupRestorePanel.restoreFailed=Ошибка восстановления\n{0} +DatabaseBackupRestorePanel.port=Порт: DatabaseBackupRestorePanel.requiredFieldsCheckFailed=Заполните все обязательные поля +DatabaseBackupRestorePanel.restoreButton=Восстановить базу данных +DatabaseBackupRestorePanel.restoreFailed=Ошибка восстановления\n{0} +DatabaseBackupRestorePanel.restoreOverrideCheck=Перезаписать файл базы данных +DatabaseBackupRestorePanel.restoreSucceed.register=Восстановление успешно завершено!\nЗарегистрировать восстановленную базу данных? +DatabaseBackupRestorePanel.restoreSucceed=Восстановление успешно завершено! +DatabaseBackupRestorePanel.title=Резервное копирование и восстановление +DatabaseBackupRestorePanel.username=Пользователь: +DatabaseObjectMetaDataPanel.DatabaseObjectMetaData=Метаданные объекта базы данных +DatabaseStatisticPanel.title=Статистика БД DatabaseTableNode.columns=Столбцы DatabaseTableNode.foreign-keys=Внешние ключи DatabaseTableNode.indexes=Индексы @@ -1617,9 +1623,9 @@ FeedbackPanel.title=Обратная связь FeedbackPanel.userComments=Комментарий пользователя FeedbackPanel.warningInternetConnection=Эта функция требует активного подключения к Интернету. FileChooserDialog.new-command.overwrite-file=Перезаписать существующий файл? -FileValidator.nameEmpty=Имя файла не должно быть пустым FileValidator.extensionEmpty=Файл должен иметь расширение {0} FileValidator.fileNotExists=Файл {0} не существует +FileValidator.nameEmpty=Имя файла не должно быть пустым FindReplaceDialog.FindAndReplace=Найти и Заменить FindReplaceDialog.FindText=Поиск текста FindReplaceDialog.MatchCaseCheck=Учитывать регистр @@ -2067,8 +2073,8 @@ PropertiesToolBar.RemoveSeparator=Удалить PropertiesToolBar.Separator=Разделитель PropertyWrapperModel.property=Свойство PropertyWrapperModel.value=Значение +QueryEditor.ExceptionOnClose=При закрытии редактора запросов произошла ошибка.\nСистема вернула:\n QueryEditor.FileSavedTo=Файл сохранен в {0} -QueryEditor.UnsavedChanges=Есть несохраненные изменения QueryEditor.Filter=Фильтр: QueryEditor.FilterToolTip=Применить фильтр к текущему набору результатов QueryEditor.LineWrapper.tool-tip=Включить/выключить автоматический перенос строк @@ -2076,14 +2082,14 @@ QueryEditor.LineWrapper=Перенос строк QueryEditor.MaxRowsToolTip=Установить максимальное количество возвращаемых строк (-1 для всех) QueryEditor.ShowTPP=Показать параметры транзакции QueryEditor.TransactionIsolationLevel=Уровень изоляции транзакций: +QueryEditor.UnsavedChanges=Есть несохраненные изменения QueryEditor.autocommitDisable=Автофиксация выключена QueryEditor.autocommitEnable=Автофиксация включена +QueryEditor.isExecutionActive=Редактор выполняет запрос.\nПожалуйста, дождитесь завершения или попытайтесь остановить выполнение. QueryEditor.requestTransactionMessage=Подтвердить активную транзакцию перед закрытием? QueryEditor.requestTransactionTitle=Есть неподтвежденная транзакция QueryEditor.script=скрипт QueryEditor.title=Редактор запросов -QueryEditor.isExecutionActive=Редактор выполняет запрос.\nПожалуйста, дождитесь завершения или попытайтесь остановить выполнение. -QueryEditor.ExceptionOnClose=При закрытии редактора запросов произошла ошибка.\nСистема вернула:\n QueryEditorResultsPanel.DatabaseOutput=Вывод БД QueryEditorResultsPanel.LIMIT_ON=Включено ограничение количества строк на {0} записей QueryEditorResultsPanel.NO_ROWS=Не выбрано ни одной строки @@ -2339,8 +2345,8 @@ TableTriggersTableModel.Description=Комментарий TableTriggersTableModel.Position=Позиция TableTriggersTableModel.TriggerName=Имя триггера TableTriggersTableModel.TriggerType=Тип триггера -TableValidationCommand.validationError=Невозможно выполнить валидацию таблиц TableValidationCommand.initError=Невозможно инициировать экземпляр IFBMaintenanceManager +TableValidationCommand.validationError=Невозможно выполнить валидацию таблиц TableValidationPanel.AvailableIndexLabel=Доступные индексы TableValidationPanel.AvailableTablesLabel=Доступные таблицы TableValidationPanel.Connection=Соединение: @@ -2389,6 +2395,8 @@ UserManagerPanel.message.confirm-delete-role=Вы уверены, что хот UserManagerPanel.message.confirm-delete-user=Вы уверены, что хотите удалить пользователя UserManagerPanel.message.create-role=Роль создана UserManagerPanel.server=Сервер +ViewablePasswordField.buttonTooltip.hide=Скрыть пароль +ViewablePasswordField.buttonTooltip.show=Показать пароль WindowAddUser.Administrator=Администратор WindowAddUser.Cancel=Отмена WindowAddUser.ConfirmPassword=Подтверждение пароля @@ -2436,10 +2444,4 @@ WizardProcessPanel.Back=Назад WizardProcessPanel.Cancel=Отменить WizardProcessPanel.Help=Помощь WizardProcessPanel.Next=Дальше -WizardProcessPanel.Steps=Шаги -CreateRolePanel.title=Создать роль -ViewablePasswordField.buttonTooltip.show=Показать пароль -ViewablePasswordField.buttonTooltip.hide=Скрыть пароль -ConnectionType.NATIVE=Нативное -ConnectionType.EMBEDDED=Напрямую к файлу -ConnectionType.PURE_JAVA=Java реализация \ No newline at end of file +WizardProcessPanel.Steps=Шаги \ No newline at end of file From 2649e6714fb952d4a5014cba9c4cbea5f3f94027 Mon Sep 17 00:00:00 2001 From: Nikita Kashin Date: Fri, 6 Dec 2024 11:08:30 +0300 Subject: [PATCH 23/41] Limit the number of test jobs to build regular commits. --- .gitlab-ci.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1ab41d092..2be0a3715 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -253,6 +253,9 @@ test:windows: dependencies: ["prepare", "sources", "build:windows"] needs: ["prepare", "sources", "build:windows"] timeout: 2 hours + only: + variables: + - ($CONTEXT == "weekly" || $CI_COMMIT_TAG) && $TEST_TYPE == "core" test:windows-robot: extends: .test_template @@ -286,6 +289,10 @@ test:windows-robot: dependencies: ["prepare", "sources", "build:windows"] needs: ["prepare", "sources", "build:windows"] timeout: 2 hours + only: + variables: + - ($CONTEXT == "weekly" || $CI_COMMIT_TAG) && $TEST_TYPE == "core" + - $CONTEXT == "commit" && $DBMS == "rdb50" test:linux-robot: extends: .test_template @@ -324,6 +331,10 @@ test:linux-robot: dependencies: ["prepare", "sources", "build:linux"] needs: ["prepare", "sources", "build:linux"] timeout: 2 hours + only: + variables: + - ($CONTEXT == "weekly" || $CI_COMMIT_TAG) && $TEST_TYPE == "core" + - $CONTEXT == "commit" && $DBMS == "rdb50" repackage: tags: From 4ec5c27b89d55b8ad5cc3c4a44348fcf039c9017 Mon Sep 17 00:00:00 2001 From: "mikhail.kalyashin" Date: Mon, 9 Dec 2024 15:56:33 +0300 Subject: [PATCH 24/41] See RS-207977 fix compute selectivity --- .../spi/DefaultStatementExecutor.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/org/executequery/databasemediators/spi/DefaultStatementExecutor.java b/src/org/executequery/databasemediators/spi/DefaultStatementExecutor.java index 450c63b61..72b0385f3 100644 --- a/src/org/executequery/databasemediators/spi/DefaultStatementExecutor.java +++ b/src/org/executequery/databasemediators/spi/DefaultStatementExecutor.java @@ -27,8 +27,10 @@ import org.executequery.databasemediators.DatabaseConnection; import org.executequery.databasemediators.ProcedureParameterSorter; import org.executequery.databasemediators.QueryTypes; +import org.executequery.databaseobjects.DatabaseExecutable; +import org.executequery.databaseobjects.DatabaseHost; +import org.executequery.databaseobjects.ProcedureParameter; import org.executequery.databaseobjects.Types; -import org.executequery.databaseobjects.*; import org.executequery.databaseobjects.impl.DatabaseObjectFactoryImpl; import org.executequery.datasource.ConnectionManager; import org.executequery.gui.editor.autocomplete.Parameter; @@ -493,11 +495,10 @@ public SqlStatementResult execute(DatabaseExecutable databaseExecutable) hasOut = !(outs.isEmpty()); procQuery = sb.toString(); } else { - StringBuilder sb = new StringBuilder(); - sb.append("{ call "); - sb.append(databaseExecutable.getName()).append("( ) }"); + String sb = "{ call " + + databaseExecutable.getName() + "( ) }"; - procQuery = sb.toString(); + procQuery = sb; } //Log.debug(procQuery); @@ -1039,6 +1040,7 @@ public SqlStatementResult execute(int type, String query, int fetchSize) throws case QueryTypes.CREATE_OR_ALTER: case QueryTypes.ALTER_OBJECT: case QueryTypes.DECLARE_OBJECT: + case QueryTypes.SET_STATISTICS: return executeDDL(query); case QueryTypes.UNKNOWN: @@ -1351,6 +1353,7 @@ public SqlStatementResult execute(int type, PreparedStatement statement, int fet case QueryTypes.CREATE_OR_ALTER: case QueryTypes.ALTER_OBJECT: case QueryTypes.DECLARE_OBJECT: + case QueryTypes.SET_STATISTICS: return executeDDL(statement); case QueryTypes.UNKNOWN: From b5e1a5f971ff616c1c2fc85c81722eb9a6e74206 Mon Sep 17 00:00:00 2001 From: Nikita Kashin Date: Tue, 10 Dec 2024 12:11:03 +0300 Subject: [PATCH 25/41] Increase the DBMS version. --- ci/download_dbms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/download_dbms.py b/ci/download_dbms.py index e25f0d319..722506d0d 100644 --- a/ci/download_dbms.py +++ b/ci/download_dbms.py @@ -20,7 +20,7 @@ last_stable_version = "3.0.18" if DBMS == "rdb50": - last_stable_version = "5.0.0" + last_stable_version = "5.0.1-rc.1" url = f"http://builds.red-soft.biz/release_hub/{DBMS}/{last_stable_version}/download/red-database:{os}-x86_64-enterprise:{last_stable_version}:{bin}" From e10c2687f391e7aa8fdf19b6e8c044c933aad64e Mon Sep 17 00:00:00 2001 From: "mikhail.kalyashin" Date: Tue, 10 Dec 2024 12:29:36 +0300 Subject: [PATCH 26/41] See RS-205460 fix procedure editing --- .../gui/databaseobjects/AbstractCreateObjectPanel.java | 2 +- .../gui/procedure/CreateProcedureFunctionPanel.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/org/executequery/gui/databaseobjects/AbstractCreateObjectPanel.java b/src/org/executequery/gui/databaseobjects/AbstractCreateObjectPanel.java index 93f0d609e..2250e86eb 100644 --- a/src/org/executequery/gui/databaseobjects/AbstractCreateObjectPanel.java +++ b/src/org/executequery/gui/databaseobjects/AbstractCreateObjectPanel.java @@ -349,8 +349,8 @@ protected void displayExecuteQueryDialog(String query, String delimiter) { if (executeDialog.getCommit()) { commit = true; reloadNodes(); - finish(); reset(); + finish(); } } else if (parent != null) diff --git a/src/org/executequery/gui/procedure/CreateProcedureFunctionPanel.java b/src/org/executequery/gui/procedure/CreateProcedureFunctionPanel.java index fa0523963..a1a4c6e09 100644 --- a/src/org/executequery/gui/procedure/CreateProcedureFunctionPanel.java +++ b/src/org/executequery/gui/procedure/CreateProcedureFunctionPanel.java @@ -780,6 +780,7 @@ protected void reset() { loadParameters(); fillSqlBody(); + generateDdlScript(false); } @Override From ac4ca170b0a1768db709b404868897b3583768b3 Mon Sep 17 00:00:00 2001 From: "mikhail.kalyashin" Date: Tue, 10 Dec 2024 13:07:57 +0300 Subject: [PATCH 27/41] =?UTF-8?q?See=20RS-207951=20fix=20thread=20terminat?= =?UTF-8?q?ion=20after=20=E2=80=9CCtrl+F=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/org/executequery/gui/text/SQLTextArea.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/executequery/gui/text/SQLTextArea.java b/src/org/executequery/gui/text/SQLTextArea.java index 63704c13e..b80bcd1d4 100644 --- a/src/org/executequery/gui/text/SQLTextArea.java +++ b/src/org/executequery/gui/text/SQLTextArea.java @@ -739,7 +739,7 @@ public Object construct() { }; worker.start(); - } + } else isCtrlPressed = false; } @Override From b03d8e0eaaee520f644b573ed37957593e157ca1 Mon Sep 17 00:00:00 2001 From: "aleksey.kozlov" Date: Tue, 10 Dec 2024 13:57:19 +0300 Subject: [PATCH 28/41] Rename package name comply with a naming convention --- .../executequery/actions/othercommands/ExportDataCommand.java | 2 +- .../gui/browser/managment/dbstatistic/StatisticTablePanel.java | 2 +- .../browser/managment/tracemanager/ServiceManagerPopupMenu.java | 2 +- src/org/executequery/gui/editor/QueryEditor.java | 2 +- src/org/executequery/gui/editor/ResultSetTablePopupMenu.java | 2 +- .../gui/{exportData => export}/AbstractExportHelper.java | 2 +- .../gui/{exportData => export}/ExportDataPanel.java | 2 +- .../executequery/gui/{exportData => export}/ExportHelper.java | 2 +- .../gui/{exportData => export}/ExportHelperCSV.java | 2 +- .../gui/{exportData => export}/ExportHelperSQL.java | 2 +- .../gui/{exportData => export}/ExportHelperXLSX.java | 2 +- .../gui/{exportData => export}/ExportHelperXML.java | 2 +- src/org/executequery/gui/importdata/ImportDataPanel.java | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) rename src/org/executequery/gui/{exportData => export}/AbstractExportHelper.java (99%) rename src/org/executequery/gui/{exportData => export}/ExportDataPanel.java (99%) rename src/org/executequery/gui/{exportData => export}/ExportHelper.java (59%) rename src/org/executequery/gui/{exportData => export}/ExportHelperCSV.java (99%) rename src/org/executequery/gui/{exportData => export}/ExportHelperSQL.java (99%) rename src/org/executequery/gui/{exportData => export}/ExportHelperXLSX.java (99%) rename src/org/executequery/gui/{exportData => export}/ExportHelperXML.java (99%) diff --git a/src/org/executequery/actions/othercommands/ExportDataCommand.java b/src/org/executequery/actions/othercommands/ExportDataCommand.java index 5e36559b8..4ac9eb223 100644 --- a/src/org/executequery/actions/othercommands/ExportDataCommand.java +++ b/src/org/executequery/actions/othercommands/ExportDataCommand.java @@ -22,7 +22,7 @@ import org.executequery.GUIUtilities; import org.executequery.gui.editor.QueryEditor; -import org.executequery.gui.exportData.ExportDataPanel; +import org.executequery.gui.export.ExportDataPanel; import javax.swing.*; import java.awt.event.ActionEvent; diff --git a/src/org/executequery/gui/browser/managment/dbstatistic/StatisticTablePanel.java b/src/org/executequery/gui/browser/managment/dbstatistic/StatisticTablePanel.java index 5f4c4b4fc..f8899fe97 100644 --- a/src/org/executequery/gui/browser/managment/dbstatistic/StatisticTablePanel.java +++ b/src/org/executequery/gui/browser/managment/dbstatistic/StatisticTablePanel.java @@ -6,7 +6,7 @@ import org.executequery.gui.WidgetFactory; import org.executequery.gui.browser.managment.tracemanager.AnalisePanel; import org.executequery.gui.browser.managment.tracemanager.ServiceManagerPopupMenu; -import org.executequery.gui.exportData.ExportDataPanel; +import org.executequery.gui.export.ExportDataPanel; import org.executequery.localization.Bundles; import org.underworldlabs.statParser.*; import org.underworldlabs.swing.AbstractPanel; diff --git a/src/org/executequery/gui/browser/managment/tracemanager/ServiceManagerPopupMenu.java b/src/org/executequery/gui/browser/managment/tracemanager/ServiceManagerPopupMenu.java index 65377646a..680e052e7 100644 --- a/src/org/executequery/gui/browser/managment/tracemanager/ServiceManagerPopupMenu.java +++ b/src/org/executequery/gui/browser/managment/tracemanager/ServiceManagerPopupMenu.java @@ -1,7 +1,7 @@ package org.executequery.gui.browser.managment.tracemanager; import org.executequery.gui.editor.ResultSetTablePopupMenu; -import org.executequery.gui.exportData.ExportDataPanel; +import org.executequery.gui.export.ExportDataPanel; import org.executequery.localization.Bundles; import org.underworldlabs.swing.actions.ReflectiveAction; import org.underworldlabs.swing.menu.MenuItemFactory; diff --git a/src/org/executequery/gui/editor/QueryEditor.java b/src/org/executequery/gui/editor/QueryEditor.java index aadfa1e9f..414c30a3e 100644 --- a/src/org/executequery/gui/editor/QueryEditor.java +++ b/src/org/executequery/gui/editor/QueryEditor.java @@ -33,7 +33,7 @@ import org.executequery.gui.editor.history.EditorData; import org.executequery.gui.editor.history.QueryEditorHistory; import org.executequery.gui.editor.history.QueryEditorsManager; -import org.executequery.gui.exportData.ExportDataPanel; +import org.executequery.gui.export.ExportDataPanel; import org.executequery.gui.resultset.ResultSetTable; import org.executequery.gui.resultset.ResultSetTableModel; import org.executequery.gui.text.TextEditor; diff --git a/src/org/executequery/gui/editor/ResultSetTablePopupMenu.java b/src/org/executequery/gui/editor/ResultSetTablePopupMenu.java index 915dc69a9..4b90a8376 100644 --- a/src/org/executequery/gui/editor/ResultSetTablePopupMenu.java +++ b/src/org/executequery/gui/editor/ResultSetTablePopupMenu.java @@ -24,7 +24,7 @@ import org.executequery.databaseobjects.DatabaseColumn; import org.executequery.databaseobjects.DatabaseTableObject; import org.executequery.gui.BaseDialog; -import org.executequery.gui.exportData.ExportDataPanel; +import org.executequery.gui.export.ExportDataPanel; import org.executequery.gui.resultset.*; import org.executequery.localization.Bundles; import org.executequery.print.PrintingSupport; diff --git a/src/org/executequery/gui/exportData/AbstractExportHelper.java b/src/org/executequery/gui/export/AbstractExportHelper.java similarity index 99% rename from src/org/executequery/gui/exportData/AbstractExportHelper.java rename to src/org/executequery/gui/export/AbstractExportHelper.java index 4640c596f..7627f1309 100644 --- a/src/org/executequery/gui/exportData/AbstractExportHelper.java +++ b/src/org/executequery/gui/export/AbstractExportHelper.java @@ -1,4 +1,4 @@ -package org.executequery.gui.exportData; +package org.executequery.gui.export; import org.executequery.GUIUtilities; import org.executequery.databaseobjects.Types; diff --git a/src/org/executequery/gui/exportData/ExportDataPanel.java b/src/org/executequery/gui/export/ExportDataPanel.java similarity index 99% rename from src/org/executequery/gui/exportData/ExportDataPanel.java rename to src/org/executequery/gui/export/ExportDataPanel.java index 0ce2f07a9..244365612 100644 --- a/src/org/executequery/gui/exportData/ExportDataPanel.java +++ b/src/org/executequery/gui/export/ExportDataPanel.java @@ -18,7 +18,7 @@ * */ -package org.executequery.gui.exportData; +package org.executequery.gui.export; import org.executequery.GUIUtilities; import org.executequery.components.FileChooserDialog; diff --git a/src/org/executequery/gui/exportData/ExportHelper.java b/src/org/executequery/gui/export/ExportHelper.java similarity index 59% rename from src/org/executequery/gui/exportData/ExportHelper.java rename to src/org/executequery/gui/export/ExportHelper.java index 952578140..8248aec8c 100644 --- a/src/org/executequery/gui/exportData/ExportHelper.java +++ b/src/org/executequery/gui/export/ExportHelper.java @@ -1,4 +1,4 @@ -package org.executequery.gui.exportData; +package org.executequery.gui.export; interface ExportHelper { diff --git a/src/org/executequery/gui/exportData/ExportHelperCSV.java b/src/org/executequery/gui/export/ExportHelperCSV.java similarity index 99% rename from src/org/executequery/gui/exportData/ExportHelperCSV.java rename to src/org/executequery/gui/export/ExportHelperCSV.java index 6ad681a00..d6900577b 100644 --- a/src/org/executequery/gui/exportData/ExportHelperCSV.java +++ b/src/org/executequery/gui/export/ExportHelperCSV.java @@ -1,4 +1,4 @@ -package org.executequery.gui.exportData; +package org.executequery.gui.export; import org.executequery.gui.browser.ColumnData; import org.executequery.gui.resultset.AbstractLobRecordDataItem; diff --git a/src/org/executequery/gui/exportData/ExportHelperSQL.java b/src/org/executequery/gui/export/ExportHelperSQL.java similarity index 99% rename from src/org/executequery/gui/exportData/ExportHelperSQL.java rename to src/org/executequery/gui/export/ExportHelperSQL.java index 5c5eca875..69ad2928d 100644 --- a/src/org/executequery/gui/exportData/ExportHelperSQL.java +++ b/src/org/executequery/gui/export/ExportHelperSQL.java @@ -1,4 +1,4 @@ -package org.executequery.gui.exportData; +package org.executequery.gui.export; import org.executequery.GUIUtilities; import org.executequery.databaseobjects.DatabaseColumn; diff --git a/src/org/executequery/gui/exportData/ExportHelperXLSX.java b/src/org/executequery/gui/export/ExportHelperXLSX.java similarity index 99% rename from src/org/executequery/gui/exportData/ExportHelperXLSX.java rename to src/org/executequery/gui/export/ExportHelperXLSX.java index 289141937..5193d3635 100644 --- a/src/org/executequery/gui/exportData/ExportHelperXLSX.java +++ b/src/org/executequery/gui/export/ExportHelperXLSX.java @@ -1,4 +1,4 @@ -package org.executequery.gui.exportData; +package org.executequery.gui.export; import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.usermodel.CellStyle; diff --git a/src/org/executequery/gui/exportData/ExportHelperXML.java b/src/org/executequery/gui/export/ExportHelperXML.java similarity index 99% rename from src/org/executequery/gui/exportData/ExportHelperXML.java rename to src/org/executequery/gui/export/ExportHelperXML.java index c21d0f77f..944462b41 100644 --- a/src/org/executequery/gui/exportData/ExportHelperXML.java +++ b/src/org/executequery/gui/export/ExportHelperXML.java @@ -1,4 +1,4 @@ -package org.executequery.gui.exportData; +package org.executequery.gui.export; import org.executequery.gui.browser.ColumnData; import org.executequery.gui.resultset.AbstractLobRecordDataItem; diff --git a/src/org/executequery/gui/importdata/ImportDataPanel.java b/src/org/executequery/gui/importdata/ImportDataPanel.java index 30a7cf14e..e19169006 100644 --- a/src/org/executequery/gui/importdata/ImportDataPanel.java +++ b/src/org/executequery/gui/importdata/ImportDataPanel.java @@ -13,7 +13,7 @@ import org.executequery.gui.NamedView; import org.executequery.gui.WidgetFactory; import org.executequery.gui.editor.ResultSetTablePopupMenu; -import org.executequery.gui.exportData.ExportDataPanel; +import org.executequery.gui.export.ExportDataPanel; import org.executequery.gui.resultset.ResultSetTable; import org.executequery.gui.resultset.ResultSetTableModel; import org.executequery.localization.Bundles; From 2ec56727f3a3d5f085665b76db609e2fe9e21969 Mon Sep 17 00:00:00 2001 From: "aleksey.kozlov" Date: Tue, 10 Dec 2024 13:57:35 +0300 Subject: [PATCH 29/41] Refactor ExportHelper classes to reduce the code cognitive complexity --- .../gui/export/AbstractExportHelper.java | 48 ++- .../gui/export/ExportHelperCSV.java | 224 +++++++------- .../gui/export/ExportHelperSQL.java | 282 +++++++++--------- .../gui/export/ExportHelperXLSX.java | 209 ++++++------- .../gui/export/ExportHelperXML.java | 184 +++++++----- 5 files changed, 512 insertions(+), 435 deletions(-) diff --git a/src/org/executequery/gui/export/AbstractExportHelper.java b/src/org/executequery/gui/export/AbstractExportHelper.java index 7627f1309..37eeac707 100644 --- a/src/org/executequery/gui/export/AbstractExportHelper.java +++ b/src/org/executequery/gui/export/AbstractExportHelper.java @@ -19,10 +19,7 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; -import java.sql.Blob; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.SQLException; +import java.sql.*; import java.util.LinkedList; import java.util.List; @@ -45,6 +42,7 @@ public final void export(Object data) { @Override public Object construct() { + extractExportParameters(); if (data instanceof ResultSet) exportResultSet((ResultSet) data); @@ -64,6 +62,8 @@ public void finished() { progressDialog.run(); } + abstract void extractExportParameters(); + abstract void exportResultSet(ResultSet resultSet); abstract void exportTableModel(TableModel tableModel); @@ -77,13 +77,13 @@ protected String getFormattedValue(Object value, String endlReplacement, String if (value instanceof RecordDataItem) { RecordDataItem recordDataItem = (RecordDataItem) value; if (!recordDataItem.isValueNull()) - formattedValue = recordDataItem.getDisplayValue().toString().replaceAll("'", "''"); + formattedValue = recordDataItem.getDisplayValue().toString().replace("'", "''"); } else if (value != null) - formattedValue = value.toString().replaceAll("'", "''"); + formattedValue = value.toString().replace("'", "''"); if (!formattedValue.isEmpty() && endlReplacement != null) - formattedValue = formattedValue.replaceAll("\n", endlReplacement); + formattedValue = formattedValue.replace("\n", endlReplacement); return formattedValue; } @@ -113,7 +113,9 @@ protected final boolean isCharType(Object value) { } else if (value instanceof ColumnData) { return ((ColumnData) value).isChar(); - } else return value instanceof String; + } + + return value instanceof String; } protected final boolean isDateType(Object value) { @@ -126,7 +128,7 @@ protected final boolean isDateType(Object value) { return ((ColumnData) value).isDate(); } - return false; + return value instanceof Timestamp; } protected final boolean isFieldSelected(int col) { @@ -205,6 +207,34 @@ private String saveBlobToFile(byte[] lobData, String lobType, String fileName, b return stringValue; } + // --- extract headers methods --- + + protected List getHeaders(Object columnData, int columnCount) { + + List columnNames = new LinkedList<>(); + for (int i = 0; i < columnCount; i++) + if (isFieldSelected(i)) + columnNames.add(getColumnName(columnData, i)); + + return columnNames; + } + + private static String getColumnName(Object columnData, int col) { + try { + + if (columnData instanceof ResultSetMetaData) + return ((ResultSetMetaData) columnData).getColumnName(col + 1); + + if (columnData instanceof TableModel) + return ((TableModel) columnData).getColumnName(col); + + } catch (SQLException e) { + Log.error(e.getMessage(), e); + } + + return null; + } + // --- protected final void displayErrorMessage(Throwable e) { diff --git a/src/org/executequery/gui/export/ExportHelperCSV.java b/src/org/executequery/gui/export/ExportHelperCSV.java index d6900577b..b7b867f96 100644 --- a/src/org/executequery/gui/export/ExportHelperCSV.java +++ b/src/org/executequery/gui/export/ExportHelperCSV.java @@ -6,179 +6,169 @@ import javax.swing.table.TableModel; import java.io.FileWriter; +import java.io.IOException; import java.io.PrintWriter; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; +import java.util.LinkedList; import java.util.List; public class ExportHelperCSV extends AbstractExportHelper { + private boolean addQuotes; + private boolean addHeaders; + private boolean saveBlobsIndividually; + + private String filePath; + private String columnDelimiter; + private String endlReplacement; + private String nullReplacement; + public ExportHelperCSV(ExportDataPanel parent) { super(parent); } @Override - protected void exportResultSet(ResultSet resultSet) { - - String filePath = parent.getFilePath(); - String columnDelimiter = parent.getColumnDelimiter(); - String endlReplacement = parent.getEndlReplacement(); - String nullReplacement = parent.getNullReplacement(); + protected void extractExportParameters() { + filePath = parent.getFilePath(); + addQuotes = parent.isAddQuotes(); + addHeaders = parent.isAddHeaders(); + columnDelimiter = parent.getColumnDelimiter(); + endlReplacement = parent.getEndlReplacement(); + nullReplacement = parent.getNullReplacement(); + saveBlobsIndividually = parent.isSaveBlobsIndividually(); + } - boolean addHeaders = parent.isAddHeaders(); - boolean addQuotes = parent.isAddQuotes(); - boolean saveBlobsIndividually = parent.isSaveBlobsIndividually(); + // --- - try { + @Override + protected void exportResultSet(ResultSet resultSet) { + try ( + FileWriter fileWriter = new FileWriter(filePath, false); + PrintWriter writer = new PrintWriter(fileWriter, true) + ) { ResultSetMetaData metaData = resultSet.getMetaData(); List columns = getCreateColumnData(metaData); int columnCount = metaData.getColumnCount(); - StringBuilder resultText = new StringBuilder(); - PrintWriter writer = new PrintWriter(new FileWriter(filePath, false), true); - if (addHeaders) - writer.println(getHeaders(columnCount, columnDelimiter, metaData)); + writer.println(String.join(columnDelimiter, getHeaders(metaData, columnCount))); int row = 0; - while (resultSet.next()) { - - if (isCancel()) - break; - - for (int col = 1; col < columnCount + 1; col++) { - - if (isCancel()) - break; - - if (!isFieldSelected(col - 1)) - continue; - - String stringValue = null; - Object value = resultSet.getObject(col); - ColumnData columnData = columns.get(col - 1); - - if (value != null) { - stringValue = getFormattedValue(value, endlReplacement, nullReplacement); - - if (isCharType(columnData) && addQuotes && !stringValue.isEmpty()) { - stringValue = "\"" + stringValue + "\""; - - } else if (isBlobType(columnData)) { - stringValue = writeBlob(resultSet.getBlob(col), saveBlobsIndividually, getCreateBlobFileName(columnData, col, row)); - } - } - - resultText.append(stringValue != null ? stringValue : nullReplacement); - resultText.append(columnDelimiter); - } - resultText.deleteCharAt(resultText.length() - 1); - - writer.println(resultText); - resultText.setLength(0); + while (resultSet.next() && !isCancel()) { + List values = getStringValues(resultSet, columns, columnCount + 1, row); + writer.println(String.join(columnDelimiter, values)); row++; } - writer.close(); } catch (Exception e) { displayErrorMessage(e); } } - @Override - protected void exportTableModel(TableModel tableModel) { - - String filePath = parent.getFilePath(); - String columnDelimiter = parent.getColumnDelimiter(); - String endlReplacement = parent.getEndlReplacement(); - String nullReplacement = parent.getNullReplacement(); - - boolean addHeaders = parent.isAddHeaders(); - boolean addQuotes = parent.isAddQuotes(); - boolean saveBlobsIndividually = parent.isSaveBlobsIndividually(); - - int rowCount = tableModel.getRowCount(); - int columnCount = tableModel.getColumnCount(); + private List getStringValues(ResultSet resultSet, List columns, int columnCount, int row) + throws SQLException, IOException { - try { - StringBuilder resultText = new StringBuilder(); - PrintWriter writer = new PrintWriter(new FileWriter(filePath, false), true); - - if (addHeaders) - writer.println(getHeaders(columnCount, columnDelimiter, tableModel)); - - for (int row = 0; row < rowCount; row++) { + List values = new LinkedList<>(); + for (int col = 1; col < columnCount && !isCancel(); col++) { + if (isFieldSelected(col - 1)) { + String stringValue = getStringValue(resultSet, columns.get(col - 1), row, col); + values.add(stringValue != null ? stringValue : nullReplacement); + } + } - if (isCancel()) - break; + return values; + } - for (int col = 0; col < columnCount; col++) { + private String getStringValue(ResultSet resultSet, ColumnData columnData, int row, int col) + throws SQLException, IOException { - if (isCancel()) - break; + Object value = resultSet.getObject(col); + if (value == null) + return null; - if (!isFieldSelected(col)) - continue; + if (isBlobType(columnData)) { + return writeBlob( + resultSet.getBlob(col), + saveBlobsIndividually, + getCreateBlobFileName(columnData, col, row) + ); + } - String stringValue = null; - Object value = tableModel.getValueAt(row, col); - if (value instanceof RecordDataItem) { - RecordDataItem rdi = (RecordDataItem) value; + return formatted(getFormattedValue(value, endlReplacement, nullReplacement), isCharType(columnData)); + } - if (!rdi.isValueNull()) { - stringValue = getFormattedValue(rdi, endlReplacement, nullReplacement); + // --- - if (isCharType(rdi) && addQuotes && !stringValue.isEmpty()) { - stringValue = "\"" + stringValue + "\""; + @Override + protected void exportTableModel(TableModel tableModel) { + try ( + FileWriter fileWriter = new FileWriter(filePath, false); + PrintWriter writer = new PrintWriter(fileWriter, true) + ) { - } else if (isBlobType(rdi)) { - stringValue = writeBlob((AbstractLobRecordDataItem) rdi, saveBlobsIndividually, getCreateBlobFileName(tableModel, col, row)); - } - } - } else { - if (value != null) { - stringValue = getFormattedValue(value, endlReplacement, nullReplacement); - if (isCharType(value) && addQuotes && !stringValue.isEmpty()) { - stringValue = "\"" + stringValue + "\""; - } - } - } + int rowCount = tableModel.getRowCount(); + int columnCount = tableModel.getColumnCount(); - resultText.append(stringValue != null ? stringValue : nullReplacement); - resultText.append(columnDelimiter); - } - resultText.deleteCharAt(resultText.length() - 1); + if (addHeaders) + writer.println(String.join(columnDelimiter, getHeaders(tableModel, columnCount))); - writer.println(resultText); - resultText.setLength(0); + for (int row = 0; row < rowCount && !isCancel(); row++) { + List values = getStringValues(tableModel, columnCount, row); + writer.println(String.join(columnDelimiter, values)); } - writer.close(); } catch (Exception e) { displayErrorMessage(e); } } - private String getHeaders(int columnCount, String columnDelimiter, Object columnData) throws SQLException { + private List getStringValues(TableModel tableModel, int columnCount, int row) throws IOException { - StringBuilder sb = new StringBuilder(); + List values = new LinkedList<>(); + for (int col = 0; col < columnCount && !isCancel(); col++) { + if (isFieldSelected(col)) { + String stringValue = getStringValue(tableModel, row, col); + values.add(stringValue != null ? stringValue : nullReplacement); + } + } + + return values; + } + + private String getStringValue(TableModel tableModel, int row, int col) throws IOException { + + Object value = tableModel.getValueAt(row, col); + if (value == null) + return null; - for (int i = 0; i < columnCount; i++) { - if (isFieldSelected(i)) { + if (value instanceof RecordDataItem) { - String columnName = null; - if (columnData instanceof ResultSetMetaData) - columnName = ((ResultSetMetaData) columnData).getColumnName(i + 1); - else if (columnData instanceof TableModel) - columnName = ((TableModel) columnData).getColumnName(i); + if (((RecordDataItem) value).isValueNull()) + return null; - sb.append(columnName).append(columnDelimiter); + if (isBlobType(value)) { + return writeBlob( + (AbstractLobRecordDataItem) value, + saveBlobsIndividually, + getCreateBlobFileName(tableModel, col, row) + ); } } - return sb.deleteCharAt(sb.length() - 1).toString().trim(); + return formatted(getFormattedValue(value, endlReplacement, nullReplacement), isCharType(value)); + } + + // --- helper methods --- + + private String formatted(String value, boolean isChar) { + + if (isChar && addQuotes && !value.isEmpty()) + value = "\"" + value + "\""; + + return value; } } diff --git a/src/org/executequery/gui/export/ExportHelperSQL.java b/src/org/executequery/gui/export/ExportHelperSQL.java index 69ad2928d..68e679726 100644 --- a/src/org/executequery/gui/export/ExportHelperSQL.java +++ b/src/org/executequery/gui/export/ExportHelperSQL.java @@ -1,10 +1,9 @@ package org.executequery.gui.export; -import org.executequery.GUIUtilities; +import org.executequery.actions.filecommands.OpenCommand; import org.executequery.databaseobjects.DatabaseColumn; import org.executequery.databaseobjects.impl.AbstractDatabaseObject; import org.executequery.gui.browser.ColumnData; -import org.executequery.gui.editor.QueryEditor; import org.executequery.gui.resultset.AbstractLobRecordDataItem; import org.executequery.gui.resultset.RecordDataItem; import org.executequery.log.Log; @@ -12,205 +11,189 @@ import org.underworldlabs.util.SQLUtils; import javax.swing.table.TableModel; +import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; -import java.sql.Timestamp; +import java.util.LinkedList; import java.util.List; public class ExportHelperSQL extends AbstractExportHelper { + private String filePath; + private String tableName; + private boolean containsBlob; + private boolean saveBlobsIndividually; + private boolean addCreateTableStatement; + private List databaseColumns; + public ExportHelperSQL(ExportDataPanel parent) { super(parent); } @Override - void exportResultSet(ResultSet resultSet) { + void extractExportParameters() { + filePath = parent.getFilePath(); + containsBlob = parent.isContainsBlob(); + tableName = parent.getExportTableName(); + databaseColumns = parent.getDatabaseColumns(); + saveBlobsIndividually = parent.isSaveBlobsIndividually(); + addCreateTableStatement = parent.isAddCreateTableStatement(); + } - String tableName = parent.getExportTableName(); - boolean addCreateTableStatement = parent.isAddCreateTableStatement(); - boolean saveBlobsIndividually = parent.isSaveBlobsIndividually(); + // --- - StringBuilder result = new StringBuilder(); - try { + @Override + void exportResultSet(ResultSet resultSet) { + try ( + FileWriter fileWriter = new FileWriter(filePath, false); + PrintWriter writer = new PrintWriter(fileWriter, true) + ) { ResultSetMetaData metaData = resultSet.getMetaData(); List columns = getCreateColumnData(metaData); int columnCount = metaData.getColumnCount(); - List databaseColumns = parent.getDatabaseColumns(); String insertTemplate = getInsertTemplate(tableName, columnCount, columns); if (addCreateTableStatement) - result.append(getCreateTableStatement(databaseColumns, tableName, metaData)); - if (!saveBlobsIndividually && parent.isContainsBlob()) - result.append(getSetBlobFileStatement()); + writer.println(getCreateTableStatement(databaseColumns, tableName, metaData)); + if (!saveBlobsIndividually && containsBlob) + writer.println(getSetBlobFileStatement()); // --- add values to script --- int row = 0; - StringBuilder values = new StringBuilder(); - while (resultSet.next()) { - - if (isCancel()) - break; - - for (int col = 1; col < columnCount + 1; col++) { - - if (isCancel()) - break; - - if (!isFieldSelected(col - 1)) - continue; - - values.append("\n\t"); - - Object value = resultSet.getObject(col); - ColumnData columnData = columns.get(col - 1); - String stringValue = getFormattedValue(value, null, ""); + while (resultSet.next() && !isCancel()) { + List stringValues = getStringValues(resultSet, columnCount + 1, columns, row); + writer.println(String.format(insertTemplate, String.join(",", stringValues))); + row++; + } - if (value == null) { - values.append("NULL"); + } catch (Exception e) { + displayErrorMessage(e); + } - } else if (isBlobType(columnData)) { + openQueryEditor(); + } - stringValue = writeBlob(resultSet.getBlob(col), saveBlobsIndividually, getCreateBlobFileName(columnData, col, row)); - if (saveBlobsIndividually) - values.append("?'").append(stringValue).append("'"); - else - values.append(stringValue); + private List getStringValues(ResultSet resultSet, int columnCount, List columns, int row) + throws SQLException, IOException { - } else if (!stringValue.isEmpty()) { + List values = new LinkedList<>(); + for (int col = 1; col < columnCount && !isCancel(); col++) { + if (isFieldSelected(col - 1)) { + String stringValue = getStringValue(resultSet, columns.get(col - 1), row, col); + values.add("\n\t" + stringValue); + } + } - if (isCharType(columnData)) - values.append("'").append(stringValue).append("'"); - else if (isDateType(columnData)) - values.append("'").append(stringValue.replace('T', ' ')).append("'"); - else - values.append(stringValue); + return values; + } - } + private String getStringValue(ResultSet resultSet, ColumnData columnData, int row, int col) + throws SQLException, IOException { - values.append(","); - } - values.deleteCharAt(values.lastIndexOf(",")); - result.append(String.format(insertTemplate, values)); - values.setLength(0); - row++; - } - write(result.toString().trim()); + Object value = resultSet.getObject(col); + if (value == null) + return "NULL"; - } catch (Exception e) { - displayErrorMessage(e); + if (isBlobType(columnData)) { + return formattedBlob(writeBlob( + resultSet.getBlob(col), + saveBlobsIndividually, + getCreateBlobFileName(columnData, col, row) + )); } + + return formatted( + getFormattedValue(value, null, ""), + isCharType(columnData), + isDateType(columnData) + ); } + // --- + @Override void exportTableModel(TableModel tableModel) { + try ( + FileWriter fileWriter = new FileWriter(filePath, false); + PrintWriter writer = new PrintWriter(fileWriter, true) + ) { - String tableName = parent.getExportTableName(); - boolean addCreateTableStatement = parent.isAddCreateTableStatement(); - boolean saveBlobsIndividually = parent.isSaveBlobsIndividually(); - - int rowCount = tableModel.getRowCount(); - int columnCount = tableModel.getColumnCount(); - List databaseColumns = parent.getDatabaseColumns(); - - StringBuilder result = new StringBuilder(); - try { + int rowCount = tableModel.getRowCount(); + int columnCount = tableModel.getColumnCount(); String insertTemplate = getInsertTemplate(tableName, columnCount, tableModel); if (addCreateTableStatement) - result.append(getCreateTableStatement(databaseColumns, tableName, tableModel)); - if (!saveBlobsIndividually && parent.isContainsBlob()) - result.append(getSetBlobFileStatement()); + writer.println(getCreateTableStatement(databaseColumns, tableName, tableModel)); + if (!saveBlobsIndividually && containsBlob) + writer.println(getSetBlobFileStatement()); // --- add values to script --- - StringBuilder values = new StringBuilder(); - for (int row = 0; row < rowCount; row++) { - - if (isCancel()) - break; - - for (int col = 0; col < columnCount; col++) { - - if (isCancel()) - break; - - if (!isFieldSelected(col)) - continue; + for (int row = 0; row < rowCount && !isCancel(); row++) { + List values = getStringValues(tableModel, columnCount, row); + writer.println(String.format(insertTemplate, String.join(",", values))); + } - values.append("\n\t"); + } catch (Exception e) { + displayErrorMessage(e); + } - Object value = tableModel.getValueAt(row, col); - String stringValue = getFormattedValue(value, null, ""); + openQueryEditor(); + } - if (isBlobType(value)) { + private List getStringValues(TableModel tableModel, int columnCount, int row) throws IOException { - stringValue = writeBlob((AbstractLobRecordDataItem) value, saveBlobsIndividually, getCreateBlobFileName(tableModel, col, row)); - if (saveBlobsIndividually) - values.append("?'").append(stringValue).append("'"); - else - values.append(stringValue); + List values = new LinkedList<>(); + for (int col = 0; col < columnCount && !isCancel(); col++) { + if (isFieldSelected(col)) { + String stringValue = getStringValue(tableModel, row, col); + values.add("\n\t" + stringValue); + } + } - } else if (!stringValue.isEmpty()) { + return values; + } - if (value instanceof RecordDataItem) { + private String getStringValue(TableModel tableModel, int row, int col) throws IOException { - if (isCharType(value)) - values.append("'").append(stringValue).append("'"); - else if (isDateType(value)) - values.append("'").append(stringValue.replace('T', ' ')).append("'"); - else - values.append(stringValue); + Object value = tableModel.getValueAt(row, col); + if (value == null) + return "NULL"; - } else { + if (value instanceof RecordDataItem) { - if (tableModel.getColumnClass(col) == String.class) - values.append("'").append(stringValue).append("'"); - else if (tableModel.getColumnClass(col) == Timestamp.class) - values.append("'").append(stringValue.replace('T', ' ')).append("'"); - else - values.append(stringValue); - } - } else - values.append("NULL"); + if (((RecordDataItem) value).isValueNull()) + return "NULL"; - values.append(","); - } - values.deleteCharAt(values.lastIndexOf(",")); - result.append(String.format(insertTemplate, values)); - values.setLength(0); + if (isBlobType(value)) { + return formattedBlob(writeBlob( + (AbstractLobRecordDataItem) value, + saveBlobsIndividually, + getCreateBlobFileName(tableModel, col, row) + )); } - write(result.toString().trim()); - - } catch (Exception e) { - displayErrorMessage(e); } - } - - private void write(String text) throws IOException { - - PrintWriter writer = new PrintWriter(new FileWriter(parent.getFilePath(), false), true); - writer.println(text); - writer.close(); - if (parent.isOpenQueryEditor()) { - GUIUtilities.addCentralPane( - QueryEditor.TITLE, QueryEditor.FRAME_ICON, - new QueryEditor(text), null, true - ); - } + return formatted( + getFormattedValue(value, null, ""), + isCharType(value), + isDateType(value) + ); } + // --- + @SuppressWarnings("unchecked") private String getInsertTemplate(String tableName, int columnCount, Object columnData) { StringBuilder sb = new StringBuilder(); - sb.append("\nINSERT INTO ").append(MiscUtils.getFormattedObject(tableName, null)).append(" ("); + sb.append("INSERT INTO ").append(MiscUtils.getFormattedObject(tableName, null)).append(" ("); for (int col = 0; col < columnCount; col++) { @@ -255,11 +238,40 @@ private String getCreateTableStatement(List databaseColumns, Str return null; } - return createTableTemplate + "\n-- inserting data --\n"; + return createTableTemplate + "\n\n-- inserting data --\n"; } private String getSetBlobFileStatement() { return "\nSET BLOBFILE '" + parent.getBlobPath() + "';\n"; } + // --- helper methods --- + + private String formatted(String stringValue, boolean isChar, boolean isDate) { + + if (stringValue.isEmpty()) + return "NULL"; + + if (isChar) + return "'" + stringValue + "'"; + + if (isDate) + return "'" + stringValue.replace('T', ' ') + "'"; + + return stringValue; + } + + private String formattedBlob(String value) { + + if (saveBlobsIndividually) + value = "?'" + value + "'"; + + return value; + } + + private void openQueryEditor() { + if (parent.isOpenQueryEditor()) + new OpenCommand().openFile(new File(filePath)); + } + } diff --git a/src/org/executequery/gui/export/ExportHelperXLSX.java b/src/org/executequery/gui/export/ExportHelperXLSX.java index 5193d3635..0124f7bdb 100644 --- a/src/org/executequery/gui/export/ExportHelperXLSX.java +++ b/src/org/executequery/gui/export/ExportHelperXLSX.java @@ -19,24 +19,35 @@ import java.io.OutputStream; import java.sql.ResultSet; import java.sql.ResultSetMetaData; +import java.sql.SQLException; import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; public class ExportHelperXLSX extends AbstractExportHelper { + private String filePath; + private String nullReplacement; + + private boolean addHeaders; + private boolean saveBlobsIndividually; + public ExportHelperXLSX(ExportDataPanel parent) { super(parent); } @Override - void exportResultSet(ResultSet resultSet) { - - String filePath = parent.getFilePath(); - String nullReplacement = parent.getNullReplacement(); + void extractExportParameters() { + filePath = parent.getFilePath(); + addHeaders = parent.isAddHeaders(); + nullReplacement = parent.getNullReplacement(); + saveBlobsIndividually = parent.isSaveBlobsIndividually(); + } - boolean addHeaders = parent.isAddHeaders(); - boolean saveBlobsIndividually = parent.isSaveBlobsIndividually(); + // --- + @Override + void exportResultSet(ResultSet resultSet) { try { ResultSetMetaData metaData = resultSet.getMetaData(); @@ -46,51 +57,12 @@ void exportResultSet(ResultSet resultSet) { ExcelBookBuilder builder = new ExcelBookBuilder(); builder.createSheet("Exported Data"); - if (addHeaders) { - - List headers = new ArrayList<>(); - for (int i = 1; i < columnCount + 1; i++) - if (isFieldSelected(i)) - headers.add(metaData.getColumnName(i)); - - builder.addRowHeader(headers); - } + if (addHeaders) + builder.addRowHeader(getHeaders(metaData, columnCount)); int row = 0; - while (resultSet.next()) { - - if (row >= SpreadsheetVersion.EXCEL2007.getLastRowIndex()) { - GUIUtilities.displayWarningMessage(String.format(bundleString("maxRowMessage"), SpreadsheetVersion.EXCEL2007.getLastRowIndex())); - break; - } - - if (isCancel()) - break; - - List values = new ArrayList<>(); - for (int col = 1; col < columnCount + 1; col++) { - - if (isCancel()) - break; - - if (!isFieldSelected(col - 1)) - continue; - - String stringValue = null; - Object value = resultSet.getObject(col); - ColumnData columnData = columns.get(col - 1); - - if (value != null) { - - if (isBlobType(columnData)) - stringValue = writeBlob(resultSet.getBlob(col), saveBlobsIndividually, getCreateBlobFileName(columnData, col, row)); - else - stringValue = getFormattedValue(value, null, nullReplacement); - } - - values.add(stringValue != null ? stringValue : nullReplacement); - } - + while (resultSet.next() && canAdd(row) && !isCancel()) { + List values = getStringValues(resultSet, columns, columnCount + 1, row); builder.addRow(values); row++; } @@ -104,84 +76,121 @@ void exportResultSet(ResultSet resultSet) { } } - @Override - void exportTableModel(TableModel tableModel) { + private List getStringValues(ResultSet resultSet, List columns, int columnCount, int row) + throws SQLException, IOException { - String filePath = parent.getFilePath(); - String nullReplacement = parent.getNullReplacement(); + List values = new LinkedList<>(); + for (int col = 1; col < columnCount && !isCancel(); col++) { + if (isFieldSelected(col - 1)) { + String stringValue = getStringValue(resultSet, columns.get(col - 1), row, col); + values.add(stringValue != null ? stringValue : nullReplacement); + } + } + + return values; + } - boolean addHeaders = parent.isAddHeaders(); - boolean saveBlobsIndividually = parent.isSaveBlobsIndividually(); + private String getStringValue(ResultSet resultSet, ColumnData columnData, int row, int col) + throws SQLException, IOException { - int rowCount = tableModel.getRowCount(); - int columnCount = tableModel.getColumnCount(); + Object value = resultSet.getObject(col); + if (value == null) + return null; + + if (isBlobType(columnData)) { + return writeBlob( + resultSet.getBlob(col), + saveBlobsIndividually, + getCreateBlobFileName(columnData, col, row) + ); + } + + return getFormattedValue(value, null, nullReplacement); + } + // --- + + @Override + void exportTableModel(TableModel tableModel) { try { - if (rowCount > SpreadsheetVersion.EXCEL2007.getLastRowIndex()) { - GUIUtilities.displayWarningMessage(String.format(bundleString("maxRowMessage"), SpreadsheetVersion.EXCEL2007.getLastRowIndex())); - rowCount = SpreadsheetVersion.EXCEL2007.getLastRowIndex(); - } + int rowCount = tableModel.getRowCount(); + int columnCount = tableModel.getColumnCount(); ExcelBookBuilder builder = new ExcelBookBuilder(); builder.createSheet("Exported Data"); - if (addHeaders) { + if (addHeaders) + builder.addRowHeader(getHeaders(tableModel, columnCount)); - List headers = new ArrayList<>(); - for (int i = 0; i < columnCount; i++) - if (isFieldSelected(i)) - headers.add(tableModel.getColumnName(i)); - - builder.addRowHeader(headers); + for (int row = 0; row < rowCount && canAdd(row) && !isCancel(); row++) { + List values = getStringValues(tableModel, columnCount, row); + builder.addRow(values); } - for (int row = 0; row < rowCount; row++) { + OutputStream outputStream = new FileOutputStream(filePath, false); + builder.writeTo(outputStream); + outputStream.close(); - if (isCancel()) - break; + } catch (IOException e) { + displayErrorMessage(e); + } + } - List values = new ArrayList<>(); - for (int col = 0; col < columnCount; col++) { + private List getStringValues(TableModel tableModel, int columnCount, int row) throws IOException { - if (isCancel()) - break; + List values = new ArrayList<>(); + for (int col = 0; col < columnCount && !isCancel(); col++) { + if (isFieldSelected(col)) { + String stringValue = getStringValue(tableModel, row, col); + values.add(stringValue != null ? stringValue : nullReplacement); + } + } - if (!isFieldSelected(col)) - continue; + return values; + } - String stringValue = null; - Object value = tableModel.getValueAt(row, col); - if (value instanceof RecordDataItem) { - RecordDataItem rdi = (RecordDataItem) value; + private String getStringValue(TableModel tableModel, int row, int col) throws IOException { - if (!rdi.isValueNull()) { + Object value = tableModel.getValueAt(row, col); + if (value == null) + return null; - if (isBlobType(rdi)) - stringValue = writeBlob((AbstractLobRecordDataItem) rdi, saveBlobsIndividually, getCreateBlobFileName(tableModel, col, row)); - else - stringValue = getFormattedValue(rdi, null, nullReplacement); - } - } else { - if (value != null) { - stringValue = getFormattedValue(value, null, nullReplacement); - } - } - values.add(stringValue != null ? stringValue : nullReplacement); - } + if (value instanceof RecordDataItem) { - builder.addRow(values); + if (((RecordDataItem) value).isValueNull()) + return null; + + if (isBlobType(value)) { + return writeBlob( + (AbstractLobRecordDataItem) value, + saveBlobsIndividually, + getCreateBlobFileName(tableModel, col, row) + ); } + } - OutputStream outputStream = new FileOutputStream(filePath, false); - builder.writeTo(outputStream); - outputStream.close(); + return getFormattedValue(value, null, nullReplacement); + } - } catch (IOException e) { - displayErrorMessage(e); + // --- helper methods --- + + private boolean canAdd(int row) { + + if (row >= SpreadsheetVersion.EXCEL2007.getLastRowIndex()) { + GUIUtilities.displayWarningMessage(String.format( + bundleString("maxRowMessage"), + SpreadsheetVersion.EXCEL2007.getLastRowIndex() + )); + + return false; } + + return true; } + // --- + private static class ExcelBookBuilder { private final SXSSFWorkbook workbook; diff --git a/src/org/executequery/gui/export/ExportHelperXML.java b/src/org/executequery/gui/export/ExportHelperXML.java index 944462b41..9658cf2a3 100644 --- a/src/org/executequery/gui/export/ExportHelperXML.java +++ b/src/org/executequery/gui/export/ExportHelperXML.java @@ -2,133 +2,161 @@ import org.executequery.gui.browser.ColumnData; import org.executequery.gui.resultset.AbstractLobRecordDataItem; +import org.executequery.gui.resultset.RecordDataItem; import javax.swing.table.TableModel; import java.io.FileWriter; +import java.io.IOException; import java.io.PrintWriter; import java.sql.ResultSet; import java.sql.ResultSetMetaData; +import java.sql.SQLException; import java.util.List; public class ExportHelperXML extends AbstractExportHelper { + public static final String DATA_INDENT = "\n\t\t\t<"; + + private String filePath; + private String nullReplacement; + private boolean saveBlobsIndividually; + public ExportHelperXML(ExportDataPanel parent) { super(parent); } @Override - void exportResultSet(ResultSet resultSet) { + void extractExportParameters() { + filePath = parent.getFilePath(); + nullReplacement = parent.getNullReplacement(); + saveBlobsIndividually = parent.isSaveBlobsIndividually(); + } - String filePath = parent.getFilePath(); - String nullReplacement = parent.getNullReplacement(); - boolean saveBlobsIndividually = parent.isSaveBlobsIndividually(); + // --- - try { + @Override + void exportResultSet(ResultSet resultSet) { + try ( + FileWriter fileWriter = new FileWriter(filePath, false); + PrintWriter writer = new PrintWriter(fileWriter, true) + ) { ResultSetMetaData metaData = resultSet.getMetaData(); List columns = getCreateColumnData(metaData); int columnCount = metaData.getColumnCount(); - StringBuilder rowData = new StringBuilder(); - PrintWriter writer = new PrintWriter(new FileWriter(filePath, false), true); writer.write(getHeader()); int row = 0; - while (resultSet.next()) { - - if (isCancel()) - break; - - for (int col = 1; col < columnCount + 1; col++) { - - if (isCancel()) - break; - - if (!isFieldSelected(col - 1)) - continue; - - Object value = resultSet.getObject(col); - ColumnData columnData = columns.get(col - 1); - - if (value != null) { - - if (isCharType(columnData)) - rowData.append(getCellData(metaData.getColumnName(col), "")); - else if (isBlobType(columnData)) - rowData.append(getCellData(metaData.getColumnName(col), writeBlob(resultSet.getBlob(col), saveBlobsIndividually, getCreateBlobFileName(columnData, col, row)))); - else - rowData.append(getCellData(metaData.getColumnName(col), value.toString())); - } else - rowData.append(getNullData(metaData.getColumnName(col), nullReplacement)); - } - + while (resultSet.next() && !isCancel()) { + String rowData = getRowData(resultSet, columns, metaData, columnCount + 1, row); writer.println(String.format(getRowDataTemplate(row), rowData)); - rowData.setLength(0); row++; } writer.write(getFooter()); - writer.close(); } catch (Exception e) { displayErrorMessage(e); } } - @Override - void exportTableModel(TableModel tableModel) { - - String filePath = parent.getFilePath(); - String nullReplacement = parent.getNullReplacement(); - boolean saveBlobsIndividually = parent.isSaveBlobsIndividually(); + private String getRowData(ResultSet resultSet, List columns, ResultSetMetaData metaData, int columnCount, int row) + throws SQLException, IOException { - int rowCount = tableModel.getRowCount(); - int columnCount = tableModel.getColumnCount(); + StringBuilder rowData = new StringBuilder(); + for (int col = 1; col < columnCount && !isCancel(); col++) { + if (isFieldSelected(col - 1)) { + String stringValue = getStringValue(resultSet, columns.get(col - 1), metaData.getColumnName(col), row, col); + rowData.append(stringValue); + } + } - try { + return rowData.toString(); + } - StringBuilder rowData = new StringBuilder(); - PrintWriter writer = new PrintWriter(new FileWriter(filePath, false), true); - writer.write(getHeader()); + private String getStringValue(ResultSet resultSet, ColumnData columnData, String columnName, int row, int col) + throws SQLException, IOException { - for (int row = 0; row < rowCount; row++) { + Object value = resultSet.getObject(col); + if (value == null || value.toString().isEmpty()) + return getNullData(columnName, nullReplacement); - if (isCancel()) - break; + if (isBlobType(columnData)) { + return getCellData(columnName, writeBlob( + resultSet.getBlob(col), + saveBlobsIndividually, + getCreateBlobFileName(columnData, col, row) + )); + } - for (int col = 0; col < columnCount; col++) { + return getCellData(columnName, formatted(value.toString(), isCharType(columnData))); + } - if (isCancel()) - break; + // --- - if (!isFieldSelected(col)) - continue; + @Override + void exportTableModel(TableModel tableModel) { + try ( + FileWriter fileWriter = new FileWriter(filePath, false); + PrintWriter writer = new PrintWriter(fileWriter, true) + ) { - Object value = tableModel.getValueAt(row, col); - if (value != null && value.toString() != null) { + int rowCount = tableModel.getRowCount(); + int columnCount = tableModel.getColumnCount(); - if (isCharType(value)) - rowData.append(getCellData(tableModel.getColumnName(col), "")); - else if (isBlobType(value)) - rowData.append(getCellData(tableModel.getColumnName(col), writeBlob((AbstractLobRecordDataItem) value, saveBlobsIndividually, getCreateBlobFileName(tableModel, col, row)))); - else - rowData.append(getCellData(tableModel.getColumnName(col), value.toString())); - } else - rowData.append(getNullData(tableModel.getColumnName(col), nullReplacement)); - } + writer.write(getHeader()); + for (int row = 0; row < rowCount && !isCancel(); row++) { + String rowData = getRowData(tableModel, columnCount, row); writer.println(String.format(getRowDataTemplate(row), rowData)); - rowData.setLength(0); } writer.write(getFooter()); - writer.close(); } catch (Exception e) { displayErrorMessage(e); } } + private String getRowData(TableModel tableModel, int columnCount, int row) throws IOException { + + StringBuilder rowData = new StringBuilder(); + for (int col = 0; col < columnCount && !isCancel(); col++) { + if (isFieldSelected(col)) { + String stringValue = getStringValue(tableModel, tableModel.getColumnName(col), row, col); + rowData.append(stringValue); + } + } + + return rowData.toString(); + } + + private String getStringValue(TableModel tableModel, String columnName, int row, int col) throws IOException { + + Object value = tableModel.getValueAt(row, col); + if (value == null || value.toString().isEmpty()) + return getNullData(columnName, nullReplacement); + + if (value instanceof RecordDataItem) { + + if (((RecordDataItem) value).isValueNull()) + return getNullData(columnName, nullReplacement); + + if (isBlobType(value)) { + return getCellData(columnName, writeBlob( + (AbstractLobRecordDataItem) value, + saveBlobsIndividually, + getCreateBlobFileName(tableModel, col, row) + )); + } + } + + return getCellData(columnName, formatted(value.toString(), isCharType(value))); + } + + // --- helper methods --- + private String getHeader() { return "" + "\n" + @@ -145,13 +173,21 @@ private String getRowDataTemplate(int rowNumber) { } private String getCellData(String columnName, String value) { - return "\n\t\t\t<" + columnName + ">" + value + ""; + return DATA_INDENT + columnName + ">" + value + ""; } private String getNullData(String columnName, String nullReplacement) { - return nullReplacement.isEmpty() ? - "\n\t\t\t<" + columnName + "/>" : - "\n\t\t\t<" + columnName + ">" + nullReplacement + ""; + if (nullReplacement.isEmpty()) + return DATA_INDENT + columnName + "/>"; + return getCellData(columnName, nullReplacement); + } + + private String formatted(String stringValue, boolean isChar) { + + if (isChar) + stringValue = ""; + + return stringValue; } } From 36fe5d8ee5aeafd454dff711a567784479cd71e0 Mon Sep 17 00:00:00 2001 From: "aleksey.kozlov" Date: Tue, 10 Dec 2024 14:16:21 +0300 Subject: [PATCH 30/41] Fix thread termination after "Ctrl+F" (RS-207951) This commits is a refinement of ac4ca170 --- .../executequery/gui/text/SQLTextArea.java | 48 +++++++++---------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/src/org/executequery/gui/text/SQLTextArea.java b/src/org/executequery/gui/text/SQLTextArea.java index b80bcd1d4..8eb645501 100644 --- a/src/org/executequery/gui/text/SQLTextArea.java +++ b/src/org/executequery/gui/text/SQLTextArea.java @@ -712,34 +712,11 @@ public void cleanup() { } } - @Override - public void keyTyped(KeyEvent e) { - } - @Override public void keyPressed(KeyEvent e) { - - if (e.isControlDown()) { - - isCtrlPressed = true; - SwingWorker worker = new SwingWorker("query editor cursor changer") { - @Override - public Object construct() { - - while (isCtrlPressed) { - if (isHyperlinkHovered()) - GUIUtilities.showHandCursor(getEditorTextComponent()); - else - GUIUtilities.showTextCursor(getEditorTextComponent()); - } - - GUIUtilities.showTextCursor(getEditorTextComponent()); - return null; - } - }; - worker.start(); - - } else isCtrlPressed = false; + if (e.isControlDown()) + SwingWorker.run("query editor cursor changer", this::doCursorChanging); + else isCtrlPressed = false; } @Override @@ -748,6 +725,25 @@ public void keyReleased(KeyEvent e) { isCtrlPressed = false; } + @Override + public void keyTyped(KeyEvent e) { + // do nothing + } + + private void doCursorChanging() { + + isCtrlPressed = true; + while (isCtrlPressed && isFocusOwner()) { + if (isHyperlinkHovered()) + GUIUtilities.showHandCursor(getEditorTextComponent()); + else + GUIUtilities.showTextCursor(getEditorTextComponent()); + } + + isCtrlPressed = false; + GUIUtilities.showTextCursor(getEditorTextComponent()); + } + class CommentAction extends RecordableTextAction { From 21f71eaf08ce702d6ebc976f98e82ab1bb93c536 Mon Sep 17 00:00:00 2001 From: "aleksey.kozlov" Date: Tue, 10 Dec 2024 15:41:13 +0300 Subject: [PATCH 31/41] Make blobPathField non-required for BLOB SUB_TYPE TEXT (RS-201653) --- .../gui/export/ExportDataPanel.java | 115 +++++++++++------- .../gui/export/ExportHelperCSV.java | 6 +- .../gui/export/ExportHelperSQL.java | 12 +- .../gui/export/ExportHelperXLSX.java | 6 +- .../gui/export/ExportHelperXML.java | 6 +- 5 files changed, 90 insertions(+), 55 deletions(-) diff --git a/src/org/executequery/gui/export/ExportDataPanel.java b/src/org/executequery/gui/export/ExportDataPanel.java index 244365612..2f2bcd447 100644 --- a/src/org/executequery/gui/export/ExportDataPanel.java +++ b/src/org/executequery/gui/export/ExportDataPanel.java @@ -144,9 +144,10 @@ public void mouseClicked(MouseEvent e) { String oldValue = columnTable.getValueAt(selectedRow, selectedColumn).toString().toLowerCase(); columnTable.setValueAt(!oldValue.contains("true"), selectedRow, selectedColumn); - blobPathField.setEnabled(isContainsBlob()); - browseBlobFileButton.setEnabled(isContainsBlob()); - saveBlobsIndividuallyCheck.setEnabled(isContainsBlob()); + boolean enableBlobFields = isContainsBlob(); + blobPathField.setEnabled(enableBlobFields); + browseBlobFileButton.setEnabled(enableBlobFields); + saveBlobsIndividuallyCheck.setEnabled(enableBlobFields); } columnTable.repaint(); @@ -170,9 +171,10 @@ public void mouseClicked(MouseEvent e) { browseFileButton = WidgetFactory.createButton("browseFileButton", Bundles.get("common.browse.button")); browseFileButton.addActionListener(e -> browseFile(filePathField)); + boolean enableBlobFields = isContainsBlob(); browseBlobFileButton = WidgetFactory.createButton("browseFolderButton", Bundles.get("common.browse.button")); browseBlobFileButton.addActionListener(e -> browseFile(blobPathField)); - browseBlobFileButton.setEnabled(isContainsBlob()); + browseBlobFileButton.setEnabled(enableBlobFields); exportButton = WidgetFactory.createButton("exportButton", Bundles.get("common.export.button")); exportButton.addActionListener(e -> export()); @@ -193,7 +195,7 @@ public void mouseClicked(MouseEvent e) { components.put(addCreateTableStatementCheck.getName(), addCreateTableStatementCheck); saveBlobsIndividuallyCheck = WidgetFactory.createCheckBox("saveBlobsIndividuallyCheck", bundleString("saveBlobsIndividually")); - saveBlobsIndividuallyCheck.setEnabled(isContainsBlob()); + saveBlobsIndividuallyCheck.setEnabled(enableBlobFields); components.put(saveBlobsIndividuallyCheck.getName(), saveBlobsIndividuallyCheck); replaceEndlCheck = WidgetFactory.createCheckBox("replaceEndlCheck", bundleString("replaceEndlLabel")); @@ -216,7 +218,7 @@ public void mouseClicked(MouseEvent e) { components.put(exportTableNameField.getName(), exportTableNameField); blobPathField = WidgetFactory.createTextField("folderPathField"); - blobPathField.setEnabled(isContainsBlob()); + blobPathField.setEnabled(enableBlobFields); components.put(blobPathField.getName(), blobPathField); filePathField = WidgetFactory.createTextField("filePathField"); @@ -490,14 +492,14 @@ private boolean exportAllow() { return false; } - // blob file defined - if (isContainsBlob() && MiscUtils.isNull(exportBlobPath)) { + // blob file defined (it is required for binary BLOBs) + if (isContainsBlob(true) && MiscUtils.isNull(exportBlobPath)) { GUIUtilities.displayErrorMessage(bundleString("YouMustSpecifyAFileToExportTo")); return false; } - // blob file writable - if (!new File(exportBlobPath).getAbsoluteFile().getParentFile().exists()) { + // if blob file defined check if it writable + if (isBlobFilePathSpecified() && !new File(exportBlobPath).getAbsoluteFile().getParentFile().exists()) { GUIUtilities.displayErrorMessage(bundleString("FileNotWritable", exportBlobPath)); return false; } @@ -534,33 +536,32 @@ private boolean exportAllow() { } } - // overwrite blob file check - if (isContainsBlob()) { + // if blob file defined check if it for overwrite + if (isBlobFilePathSpecified()) { - if (!saveBlobsIndividuallyCheck.isSelected()) { + if (saveBlobsIndividuallyCheck.isSelected()) + return new File(exportBlobPath).mkdirs(); - if (FileUtils.fileExists(exportBlobPath)) { + if (FileUtils.fileExists(exportBlobPath)) { - int result = GUIUtilities.displayYesNoDialog( - String.format(bundleString("OverwriteFile"), exportBlobPath), - Bundles.get("common.confirmation") - ); + int result = GUIUtilities.displayYesNoDialog( + String.format(bundleString("OverwriteFile"), exportBlobPath), + Bundles.get("common.confirmation") + ); - if (result == JOptionPane.NO_OPTION) { - blobPathField.selectAll(); - blobPathField.requestFocus(); - return false; - } + if (result == JOptionPane.NO_OPTION) { + blobPathField.selectAll(); + blobPathField.requestFocus(); + return false; } + } - try { - Files.write(Paths.get(exportBlobPath), "".getBytes(StandardCharsets.UTF_8)); - } catch (IOException ignored) { - } + try { + Files.write(Paths.get(exportBlobPath), "".getBytes(StandardCharsets.UTF_8)); - } else - //noinspection ResultOfMethodCallIgnored - new File(exportBlobPath).mkdirs(); + } catch (IOException e) { + Log.debug(e.getMessage(), e); + } } return true; @@ -575,26 +576,54 @@ protected boolean isFieldSelected(int fieldIndex) { return value.toString().toLowerCase().contains("true"); } + protected boolean isBlobFilePathSpecified() { + return !MiscUtils.isNull(getBlobPath()); + } + protected boolean isContainsBlob() { + return isContainsBlob(false); + } + + protected boolean isContainsBlob(boolean subTypeByn) { + String checkPattern = subTypeByn ? "blob sub_type 0" : "blob"; + return isContainsBlobAsTableModel(checkPattern) || isContainsBlobAsResultSet(checkPattern); + } - if (exportData instanceof TableModel) { + private boolean isContainsBlobAsTableModel(String checkPattern) { + try { TableModel tableModel = (TableModel) exportData; - for (int col = 0; col < tableModel.getColumnCount(); col++) - if (isFieldSelected(col) && tableModel.getValueAt(0, col) instanceof AbstractLobRecordDataItem) - return true; + for (int col = 0; col < tableModel.getColumnCount(); col++) { + if (isFieldSelected(col)) { + Object value = tableModel.getValueAt(0, col); + if (value instanceof AbstractLobRecordDataItem) { + AbstractLobRecordDataItem blob = (AbstractLobRecordDataItem) value; + if (blob.getDataTypeName().toLowerCase().contains(checkPattern)) + return true; + } + } + } - } else if (exportData instanceof ResultSet) { - try { + } catch (ClassCastException e) { + // do nothing + } - ResultSetMetaData metaData = ((ResultSet) exportData).getMetaData(); - for (int i = 1; i < metaData.getColumnCount() + 1; i++) - if (metaData.getColumnTypeName(i).toLowerCase().contains("blob")) - return true; + return false; + } - } catch (SQLException e) { - Log.error(e.getMessage(), e); - } + private boolean isContainsBlobAsResultSet(String checkPattern) { + try { + + ResultSetMetaData metaData = ((ResultSet) exportData).getMetaData(); + for (int col = 1; col < metaData.getColumnCount() + 1; col++) + if (metaData.getColumnTypeName(col).toLowerCase().contains(checkPattern)) + return true; + + } catch (SQLException e) { + Log.error(e.getMessage(), e); + + } catch (ClassCastException e) { + // do nothing } return false; diff --git a/src/org/executequery/gui/export/ExportHelperCSV.java b/src/org/executequery/gui/export/ExportHelperCSV.java index b7b867f96..675ad3286 100644 --- a/src/org/executequery/gui/export/ExportHelperCSV.java +++ b/src/org/executequery/gui/export/ExportHelperCSV.java @@ -18,6 +18,7 @@ public class ExportHelperCSV extends AbstractExportHelper { private boolean addQuotes; private boolean addHeaders; + private boolean blobFileSpecified; private boolean saveBlobsIndividually; private String filePath; @@ -37,6 +38,7 @@ protected void extractExportParameters() { columnDelimiter = parent.getColumnDelimiter(); endlReplacement = parent.getEndlReplacement(); nullReplacement = parent.getNullReplacement(); + blobFileSpecified = parent.isBlobFilePathSpecified(); saveBlobsIndividually = parent.isSaveBlobsIndividually(); } @@ -89,7 +91,7 @@ private String getStringValue(ResultSet resultSet, ColumnData columnData, int ro if (value == null) return null; - if (isBlobType(columnData)) { + if (isBlobType(columnData) && blobFileSpecified) { return writeBlob( resultSet.getBlob(col), saveBlobsIndividually, @@ -149,7 +151,7 @@ private String getStringValue(TableModel tableModel, int row, int col) throws IO if (((RecordDataItem) value).isValueNull()) return null; - if (isBlobType(value)) { + if (isBlobType(value) && blobFileSpecified) { return writeBlob( (AbstractLobRecordDataItem) value, saveBlobsIndividually, diff --git a/src/org/executequery/gui/export/ExportHelperSQL.java b/src/org/executequery/gui/export/ExportHelperSQL.java index 68e679726..55389b020 100644 --- a/src/org/executequery/gui/export/ExportHelperSQL.java +++ b/src/org/executequery/gui/export/ExportHelperSQL.java @@ -25,7 +25,7 @@ public class ExportHelperSQL extends AbstractExportHelper { private String filePath; private String tableName; - private boolean containsBlob; + private boolean blobFileSpecified; private boolean saveBlobsIndividually; private boolean addCreateTableStatement; private List databaseColumns; @@ -37,9 +37,9 @@ public ExportHelperSQL(ExportDataPanel parent) { @Override void extractExportParameters() { filePath = parent.getFilePath(); - containsBlob = parent.isContainsBlob(); tableName = parent.getExportTableName(); databaseColumns = parent.getDatabaseColumns(); + blobFileSpecified = parent.isBlobFilePathSpecified(); saveBlobsIndividually = parent.isSaveBlobsIndividually(); addCreateTableStatement = parent.isAddCreateTableStatement(); } @@ -60,7 +60,7 @@ void exportResultSet(ResultSet resultSet) { String insertTemplate = getInsertTemplate(tableName, columnCount, columns); if (addCreateTableStatement) writer.println(getCreateTableStatement(databaseColumns, tableName, metaData)); - if (!saveBlobsIndividually && containsBlob) + if (!saveBlobsIndividually && blobFileSpecified) writer.println(getSetBlobFileStatement()); // --- add values to script --- @@ -100,7 +100,7 @@ private String getStringValue(ResultSet resultSet, ColumnData columnData, int ro if (value == null) return "NULL"; - if (isBlobType(columnData)) { + if (isBlobType(columnData) && blobFileSpecified) { return formattedBlob(writeBlob( resultSet.getBlob(col), saveBlobsIndividually, @@ -130,7 +130,7 @@ void exportTableModel(TableModel tableModel) { String insertTemplate = getInsertTemplate(tableName, columnCount, tableModel); if (addCreateTableStatement) writer.println(getCreateTableStatement(databaseColumns, tableName, tableModel)); - if (!saveBlobsIndividually && containsBlob) + if (!saveBlobsIndividually && blobFileSpecified) writer.println(getSetBlobFileStatement()); // --- add values to script --- @@ -171,7 +171,7 @@ private String getStringValue(TableModel tableModel, int row, int col) throws IO if (((RecordDataItem) value).isValueNull()) return "NULL"; - if (isBlobType(value)) { + if (isBlobType(value) && blobFileSpecified) { return formattedBlob(writeBlob( (AbstractLobRecordDataItem) value, saveBlobsIndividually, diff --git a/src/org/executequery/gui/export/ExportHelperXLSX.java b/src/org/executequery/gui/export/ExportHelperXLSX.java index 0124f7bdb..ebf86e600 100644 --- a/src/org/executequery/gui/export/ExportHelperXLSX.java +++ b/src/org/executequery/gui/export/ExportHelperXLSX.java @@ -30,6 +30,7 @@ public class ExportHelperXLSX extends AbstractExportHelper { private String nullReplacement; private boolean addHeaders; + private boolean blobFileSpecified; private boolean saveBlobsIndividually; public ExportHelperXLSX(ExportDataPanel parent) { @@ -41,6 +42,7 @@ void extractExportParameters() { filePath = parent.getFilePath(); addHeaders = parent.isAddHeaders(); nullReplacement = parent.getNullReplacement(); + blobFileSpecified = parent.isBlobFilePathSpecified(); saveBlobsIndividually = parent.isSaveBlobsIndividually(); } @@ -97,7 +99,7 @@ private String getStringValue(ResultSet resultSet, ColumnData columnData, int ro if (value == null) return null; - if (isBlobType(columnData)) { + if (isBlobType(columnData) && blobFileSpecified) { return writeBlob( resultSet.getBlob(col), saveBlobsIndividually, @@ -161,7 +163,7 @@ private String getStringValue(TableModel tableModel, int row, int col) throws IO if (((RecordDataItem) value).isValueNull()) return null; - if (isBlobType(value)) { + if (isBlobType(value) && blobFileSpecified) { return writeBlob( (AbstractLobRecordDataItem) value, saveBlobsIndividually, diff --git a/src/org/executequery/gui/export/ExportHelperXML.java b/src/org/executequery/gui/export/ExportHelperXML.java index 9658cf2a3..cf9e684c3 100644 --- a/src/org/executequery/gui/export/ExportHelperXML.java +++ b/src/org/executequery/gui/export/ExportHelperXML.java @@ -19,6 +19,7 @@ public class ExportHelperXML extends AbstractExportHelper { private String filePath; private String nullReplacement; + private boolean blobFileSpecified; private boolean saveBlobsIndividually; public ExportHelperXML(ExportDataPanel parent) { @@ -29,6 +30,7 @@ public ExportHelperXML(ExportDataPanel parent) { void extractExportParameters() { filePath = parent.getFilePath(); nullReplacement = parent.getNullReplacement(); + blobFileSpecified = parent.isBlobFilePathSpecified(); saveBlobsIndividually = parent.isSaveBlobsIndividually(); } @@ -82,7 +84,7 @@ private String getStringValue(ResultSet resultSet, ColumnData columnData, String if (value == null || value.toString().isEmpty()) return getNullData(columnName, nullReplacement); - if (isBlobType(columnData)) { + if (isBlobType(columnData) && blobFileSpecified) { return getCellData(columnName, writeBlob( resultSet.getBlob(col), saveBlobsIndividually, @@ -143,7 +145,7 @@ private String getStringValue(TableModel tableModel, String columnName, int row, if (((RecordDataItem) value).isValueNull()) return getNullData(columnName, nullReplacement); - if (isBlobType(value)) { + if (isBlobType(value) && blobFileSpecified) { return getCellData(columnName, writeBlob( (AbstractLobRecordDataItem) value, saveBlobsIndividually, From 07e64436bcfc745890f904b38e397b929170a24a Mon Sep 17 00:00:00 2001 From: "aleksey.kozlov" Date: Tue, 10 Dec 2024 15:45:12 +0300 Subject: [PATCH 32/41] Code clean and fix sonar issues --- .../gui/export/ExportDataPanel.java | 66 ++++++++++--------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/src/org/executequery/gui/export/ExportDataPanel.java b/src/org/executequery/gui/export/ExportDataPanel.java index 2f2bcd447..beeec1c1e 100644 --- a/src/org/executequery/gui/export/ExportDataPanel.java +++ b/src/org/executequery/gui/export/ExportDataPanel.java @@ -95,10 +95,10 @@ public class ExportDataPanel extends AbstractBaseDialog { // --- - private final Object exportData; private final String tableNameForExport; - private final ParameterSaver parametersSaver; + private final transient Object exportData; private final List databaseColumns; + private final transient ParameterSaver parametersSaver; // --- @@ -135,22 +135,7 @@ private void init() { columnTable.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { - - int selectedRow = columnTable.getSelectedRow(); - int selectedColumn = columnTable.getSelectedColumn(); - - if (selectedColumn == 0) { - - String oldValue = columnTable.getValueAt(selectedRow, selectedColumn).toString().toLowerCase(); - columnTable.setValueAt(!oldValue.contains("true"), selectedRow, selectedColumn); - - boolean enableBlobFields = isContainsBlob(); - blobPathField.setEnabled(enableBlobFields); - browseBlobFileButton.setEnabled(enableBlobFields); - saveBlobsIndividuallyCheck.setEnabled(enableBlobFields); - } - - columnTable.repaint(); + columnTableTriggered(); } }); @@ -293,7 +278,7 @@ private void arrange() { setPreferredSize(new Dimension(500, 455)); setMinimumSize(getPreferredSize()); setSize(getPreferredSize()); - setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); + setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); setLocation(GUIUtilities.getLocationForDialog(this.getSize())); pack(); @@ -473,6 +458,25 @@ private void export() { } } + private void columnTableTriggered() { + + int selectedRow = columnTable.getSelectedRow(); + int selectedColumn = columnTable.getSelectedColumn(); + + if (selectedColumn == 0) { + + String oldValue = columnTable.getValueAt(selectedRow, selectedColumn).toString().toLowerCase(); + columnTable.setValueAt(!oldValue.contains("true"), selectedRow, selectedColumn); + + boolean enableBlobFields = isContainsBlob(); + blobPathField.setEnabled(enableBlobFields); + browseBlobFileButton.setEnabled(enableBlobFields); + saveBlobsIndividuallyCheck.setEnabled(enableBlobFields); + } + + columnTable.repaint(); + } + // --- helper method --- private boolean exportAllow() { @@ -758,19 +762,19 @@ public boolean isCellEditable(int rowIndex, int columnIndex) { @Override public Object getValueAt(int rowIndex, int columnIndex) { - if (rows.size() > rowIndex) { + if (rows.size() <= rowIndex) + return null; - switch (columnIndex) { - case 0: - return rows.get(rowIndex).isSelected(); - case 1: - return rows.get(rowIndex).getName(); - case 2: - return rows.get(rowIndex).getType(); - } + switch (columnIndex) { + case 0: + return rows.get(rowIndex).isSelected(); + case 1: + return rows.get(rowIndex).getName(); + case 2: + return rows.get(rowIndex).getType(); + default: + return null; } - - return null; } @Override @@ -781,10 +785,12 @@ public void setValueAt(Object aValue, int rowIndex, int columnIndex) { @Override public void addTableModelListener(TableModelListener l) { + // do nothing } @Override public void removeTableModelListener(TableModelListener l) { + // do nothing } } // class ColumnTableModel From 9efcd4d6157ca1e940e9916a825f9859e9a1ae84 Mon Sep 17 00:00:00 2001 From: "aleksey.kozlov" Date: Tue, 10 Dec 2024 15:53:05 +0300 Subject: [PATCH 33/41] Fix formating BLOB values when export to the SQL (RS-201653) --- src/org/executequery/gui/export/ExportHelperSQL.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/executequery/gui/export/ExportHelperSQL.java b/src/org/executequery/gui/export/ExportHelperSQL.java index 55389b020..eb070ccad 100644 --- a/src/org/executequery/gui/export/ExportHelperSQL.java +++ b/src/org/executequery/gui/export/ExportHelperSQL.java @@ -263,7 +263,7 @@ private String formatted(String stringValue, boolean isChar, boolean isDate) { private String formattedBlob(String value) { - if (saveBlobsIndividually) + if (saveBlobsIndividually && blobFileSpecified) value = "?'" + value + "'"; return value; From c6a2643e1903b3fb92251ae79b3097703119b6ec Mon Sep 17 00:00:00 2001 From: "aleksey.kozlov" Date: Tue, 10 Dec 2024 15:56:28 +0300 Subject: [PATCH 34/41] Add disabling saveBlobsIndividually check box if the export blob path not specified (RS-201653) --- .../executequery/gui/export/ExportDataPanel.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/org/executequery/gui/export/ExportDataPanel.java b/src/org/executequery/gui/export/ExportDataPanel.java index beeec1c1e..780ac15d6 100644 --- a/src/org/executequery/gui/export/ExportDataPanel.java +++ b/src/org/executequery/gui/export/ExportDataPanel.java @@ -25,6 +25,7 @@ import org.executequery.databaseobjects.DatabaseColumn; import org.executequery.gui.WidgetFactory; import org.executequery.gui.resultset.AbstractLobRecordDataItem; +import org.executequery.listeners.SimpleDocumentListener; import org.executequery.localization.Bundles; import org.executequery.log.Log; import org.underworldlabs.swing.AbstractBaseDialog; @@ -180,7 +181,7 @@ public void mouseClicked(MouseEvent e) { components.put(addCreateTableStatementCheck.getName(), addCreateTableStatementCheck); saveBlobsIndividuallyCheck = WidgetFactory.createCheckBox("saveBlobsIndividuallyCheck", bundleString("saveBlobsIndividually")); - saveBlobsIndividuallyCheck.setEnabled(enableBlobFields); + saveBlobsIndividuallyCheck.setEnabled(enableBlobFields && isBlobFilePathSpecified()); components.put(saveBlobsIndividuallyCheck.getName(), saveBlobsIndividuallyCheck); replaceEndlCheck = WidgetFactory.createCheckBox("replaceEndlCheck", bundleString("replaceEndlLabel")); @@ -203,6 +204,7 @@ public void mouseClicked(MouseEvent e) { components.put(exportTableNameField.getName(), exportTableNameField); blobPathField = WidgetFactory.createTextField("folderPathField"); + SimpleDocumentListener.initialize(blobPathField, this::blobPathFieldTriggered); blobPathField.setEnabled(enableBlobFields); components.put(blobPathField.getName(), blobPathField); @@ -471,12 +473,16 @@ private void columnTableTriggered() { boolean enableBlobFields = isContainsBlob(); blobPathField.setEnabled(enableBlobFields); browseBlobFileButton.setEnabled(enableBlobFields); - saveBlobsIndividuallyCheck.setEnabled(enableBlobFields); + saveBlobsIndividuallyCheck.setEnabled(enableBlobFields && isBlobFilePathSpecified()); } columnTable.repaint(); } + private void blobPathFieldTriggered() { + saveBlobsIndividuallyCheck.setEnabled(isContainsBlob() && isBlobFilePathSpecified()); + } + // --- helper method --- private boolean exportAllow() { @@ -687,11 +693,11 @@ protected String getExportTableName() { } protected String getFilePath() { - return filePathField.getText().trim(); + return filePathField != null ? filePathField.getText().trim() : ""; } protected String getBlobPath() { - return blobPathField.getText().trim(); + return blobPathField != null ? blobPathField.getText().trim() : ""; } protected boolean isAddHeaders() { From bf25a04240fa18b3ababb2e3337e06ded5068cc1 Mon Sep 17 00:00:00 2001 From: "aleksey.kozlov" Date: Tue, 10 Dec 2024 16:20:50 +0300 Subject: [PATCH 35/41] Add required fields painting (RS-201653) --- .../gui/export/ExportDataPanel.java | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/org/executequery/gui/export/ExportDataPanel.java b/src/org/executequery/gui/export/ExportDataPanel.java index 780ac15d6..74ae51740 100644 --- a/src/org/executequery/gui/export/ExportDataPanel.java +++ b/src/org/executequery/gui/export/ExportDataPanel.java @@ -30,6 +30,7 @@ import org.executequery.log.Log; import org.underworldlabs.swing.AbstractBaseDialog; import org.underworldlabs.swing.layouts.GridBagHelper; +import org.underworldlabs.swing.listener.RequiredFieldPainter; import org.underworldlabs.util.*; import javax.swing.*; @@ -94,6 +95,9 @@ public class ExportDataPanel extends AbstractBaseDialog { private JButton exportButton; private JButton cancelButton; + private List requirements; + private RequiredFieldPainter blobPathFieldRequiredPainter; + // --- private final String tableNameForExport; @@ -122,6 +126,7 @@ public ExportDataPanel(Object exportData, String tableNameForExport, List(); + requirements.add(blobPathFieldRequiredPainter); + requirements.add(RequiredFieldPainter.initialize(filePathField)); + } + // --- display handlers --- private void updateDialog() { @@ -474,6 +489,8 @@ private void columnTableTriggered() { blobPathField.setEnabled(enableBlobFields); browseBlobFileButton.setEnabled(enableBlobFields); saveBlobsIndividuallyCheck.setEnabled(enableBlobFields && isBlobFilePathSpecified()); + + blobPathFieldRequiredPainter.setEnable(isContainsBlob(true)); } columnTable.repaint(); @@ -490,10 +507,10 @@ private boolean exportAllow() { String exportFilePath = getFilePath(); String exportBlobPath = getBlobPath(); - // export file defined - if (MiscUtils.isNull(exportFilePath)) { - GUIUtilities.displayErrorMessage(bundleString("YouMustSpecifyAFileToExportTo")); - return false; + // export files defined + if (!requirements.stream().allMatch(RequiredFieldPainter::check)) { + GUIUtilities.displayWarningMessage(bundleString("YouMustSpecifyAFileToExportTo")); + return true; } // export file writable @@ -502,12 +519,6 @@ private boolean exportAllow() { return false; } - // blob file defined (it is required for binary BLOBs) - if (isContainsBlob(true) && MiscUtils.isNull(exportBlobPath)) { - GUIUtilities.displayErrorMessage(bundleString("YouMustSpecifyAFileToExportTo")); - return false; - } - // if blob file defined check if it writable if (isBlobFilePathSpecified() && !new File(exportBlobPath).getAbsoluteFile().getParentFile().exists()) { GUIUtilities.displayErrorMessage(bundleString("FileNotWritable", exportBlobPath)); From 21173b6f2979f7caa3208a79956a5306c8004f0e Mon Sep 17 00:00:00 2001 From: "mikhail.kalyashin" Date: Wed, 11 Dec 2024 11:27:40 +0300 Subject: [PATCH 36/41] fix database connection for first column data --- src/org/executequery/gui/table/CreateTablePanel.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/org/executequery/gui/table/CreateTablePanel.java b/src/org/executequery/gui/table/CreateTablePanel.java index 0f957c252..87c094d5d 100644 --- a/src/org/executequery/gui/table/CreateTablePanel.java +++ b/src/org/executequery/gui/table/CreateTablePanel.java @@ -186,6 +186,7 @@ public void changedUpdate(DocumentEvent e) { constraintsToolBar.enableButtons(true); columnsToolBar.enableButtons(true); centralPanel.setVisible(false); + columnChangeConnection(getSelectedConnection()); } @Override From 104633dc1c6f062aefd37371a448d88fbbabb401 Mon Sep 17 00:00:00 2001 From: "mikhail.kalyashin" Date: Wed, 11 Dec 2024 12:40:17 +0300 Subject: [PATCH 37/41] See RS-201657 add "copy formatted columns" --- .../datasource/PooledStatement.java | 12 +++-- .../gui/editor/ResultSetTablePopupMenu.java | 13 ++++- .../gui/resultset/ResultSetColumnHeader.java | 13 +++++ .../gui/resultset/ResultSetTable.java | 22 ++++++-- .../gui/resultset/ResultSetTableModel.java | 52 ++++++++++++------- .../localization/resources.properties | 2 + .../localization/resources_pt_br.properties | 2 + .../localization/resources_ru.properties | 2 + 8 files changed, 92 insertions(+), 26 deletions(-) diff --git a/src/org/executequery/datasource/PooledStatement.java b/src/org/executequery/datasource/PooledStatement.java index 388b625ff..fdfaeab20 100644 --- a/src/org/executequery/datasource/PooledStatement.java +++ b/src/org/executequery/datasource/PooledStatement.java @@ -1,8 +1,6 @@ package org.executequery.datasource; -import biz.redsoft.IFBSQLException; import org.executequery.log.Log; -import org.underworldlabs.util.DynamicLibraryLoader; import java.io.InputStream; import java.io.Reader; @@ -14,9 +12,9 @@ public class PooledStatement implements CallableStatement { - private PooledConnection connection; + private final PooledConnection connection; - private Statement statement; + private final Statement statement; private PreparedStatement preparedStatement; @@ -312,6 +310,10 @@ public Connection getConnection() throws SQLException { } } + public PooledConnection getPooledConnection() throws SQLException { + return connection; + } + @Override public boolean getMoreResults(int i) throws SQLException { try { @@ -2165,4 +2167,6 @@ public boolean isClosed() { public void setIndividual(boolean individual) { this.individual = individual; } + + } diff --git a/src/org/executequery/gui/editor/ResultSetTablePopupMenu.java b/src/org/executequery/gui/editor/ResultSetTablePopupMenu.java index 4b90a8376..fae4219fc 100644 --- a/src/org/executequery/gui/editor/ResultSetTablePopupMenu.java +++ b/src/org/executequery/gui/editor/ResultSetTablePopupMenu.java @@ -83,6 +83,8 @@ public ResultSetTablePopupMenu( // the copy sub-menu JMenu copyMenu = MenuItemFactory.createMenu(bundleString("CopyOtherOptions")); copyMenu.add(create(bundleString("CopySelectedColumnNames"), "copySelectedColumnNames")); + copyMenu.add(create(bundleString("CopySelectedColumnNamesFormated"), "copySelectedColumnNamesFormated")); + //copyMenu.add(create(bundleString("CopySelectedColumnNamesWithDataTypes"), "copySelectedColumnNamesWithDataTypes")); copyMenu.add(create(bundleString("CopySelectedCells-CommaSeparated"), "copySelectedCellsAsCSV")); copyMenu.add(create(bundleString("CopySelectedCells-CommaSeparatedWithNames"), "copySelectedCellsAsCSVWithNames")); copyMenu.add(create(bundleString("CopySelectedCells-CommaSeparatedAndQuoted"), "copySelectedCellsAsCSVQuoted")); @@ -186,9 +188,18 @@ public void exportTable(ActionEvent e) { @SuppressWarnings("unused") public void copySelectedColumnNames(ActionEvent e) { - table.copySelectedColumnNames(); + table.copySelectedColumnNames(false, false); } + public void copySelectedColumnNamesFormated(ActionEvent e) { + table.copySelectedColumnNames(true, false); + } + + public void copySelectedColumnNamesWithDataTypes(ActionEvent e) { + table.copySelectedColumnNames(true, true); + } + + @SuppressWarnings("unused") public void copySelectedCellsAsCSV(ActionEvent e) { table.copySelectedCellsAsCSV(); diff --git a/src/org/executequery/gui/resultset/ResultSetColumnHeader.java b/src/org/executequery/gui/resultset/ResultSetColumnHeader.java index b1a9076f6..c16b1ffc0 100644 --- a/src/org/executequery/gui/resultset/ResultSetColumnHeader.java +++ b/src/org/executequery/gui/resultset/ResultSetColumnHeader.java @@ -21,6 +21,7 @@ package org.executequery.gui.resultset; import org.apache.commons.lang.StringUtils; +import org.executequery.databaseobjects.T; import org.executequery.databaseobjects.Types; import javax.swing.*; @@ -129,7 +130,9 @@ public void setColWidth(int colWidth) { public int getDisplaySize() { if (displaySize == -1 && rsmd != null) { try { + if (isDisplaySize()) displaySize = rsmd.getColumnDisplaySize(getOriginalIndex() + 1); + else displaySize = 0; } catch (SQLException e) { e.printStackTrace(); } @@ -137,6 +140,16 @@ public int getDisplaySize() { return displaySize; } + protected boolean isDisplaySize() { + return getDataTypeName() != null && (getDataTypeName().equals(T.NUMERIC) + || getDataTypeName().equals(T.CHAR) + || getDataTypeName().equals(T.VARCHAR) + || getDataTypeName().equals(T.DECIMAL) + || getDataTypeName().equals(T.NCHAR) + || getDataTypeName().equalsIgnoreCase("CSTRING") + || getDataTypeName().equalsIgnoreCase(T.DECFLOAT)); + } + public void setDisplaySize(int displaySize) { this.displaySize = displaySize; } diff --git a/src/org/executequery/gui/resultset/ResultSetTable.java b/src/org/executequery/gui/resultset/ResultSetTable.java index c56442689..0763a628f 100644 --- a/src/org/executequery/gui/resultset/ResultSetTable.java +++ b/src/org/executequery/gui/resultset/ResultSetTable.java @@ -22,6 +22,7 @@ import org.apache.commons.lang.StringUtils; import org.executequery.GUIUtilities; +import org.executequery.databasemediators.DatabaseConnection; import org.executequery.databaseobjects.Types; import org.executequery.gui.StandardTable; import org.underworldlabs.swing.celleditor.*; @@ -211,7 +212,7 @@ public void copySelectedCellsAsCSVWithNames() { copySelectedCells(',', false, true); } - public void copySelectedColumnNames() { + public void copySelectedColumnNames(boolean formated, boolean datatypes) { StringBuilder sb = new StringBuilder(); int cols = getSelectedColumnCount(); @@ -220,8 +221,23 @@ public void copySelectedColumnNames() { int[] selectedCols = getSelectedColumns(); List list = new ArrayList<>(); - for (int j = 0; j < cols; j++) - list.add(getColumnName(selectedCols[j])); + DatabaseConnection dc = null; + ResultSetTableModel rstm = null; + if (getModel() instanceof TableSorter) { + + TableSorter model = (TableSorter) getModel(); + if (model.getTableModel() instanceof ResultSetTableModel) { + + rstm = (ResultSetTableModel) model.getTableModel(); + dc = rstm.getDatabaseConnection(); + } + } + for (int j = 0; j < cols; j++) { + String value = formated ? MiscUtils.getFormattedObject(getColumnName(selectedCols[j]), dc) : getColumnName(selectedCols[j]); + if (datatypes && rstm != null) + value += " " + rstm.getColumnType(selectedCols[j]); + list.add(value); + } sb.append(StringUtils.join(list, ", ")).append('\n'); GUIUtilities.copyToClipBoard(sb.toString()); } diff --git a/src/org/executequery/gui/resultset/ResultSetTableModel.java b/src/org/executequery/gui/resultset/ResultSetTableModel.java index 9fb9e63b1..e48ea9b68 100644 --- a/src/org/executequery/gui/resultset/ResultSetTableModel.java +++ b/src/org/executequery/gui/resultset/ResultSetTableModel.java @@ -121,23 +121,7 @@ public ResultSetTableModel(ResultSet resultSet, int maxRecords, boolean isTable) this(resultSet, maxRecords, null, isTable); } - public ResultSetTableModel(ResultSet resultSet, int maxRecords, String query, boolean isTable) throws SQLException { - - this.maxRecords = maxRecords; - this.query = query; - this.isTable = isTable; - - table = new ResultSetTable(); - tableData = new ArrayList<>(); - columnHeaders = new ArrayList<>(); - visibleColumnHeaders = new ArrayList<>(); - recordDataItemFactory = new RecordDataItemFactory(); - - holdMetaData = UserProperties.getInstance().getBooleanProperty("editor.results.metadata"); - - if (resultSet != null) - createTable(resultSet); - } + private DatabaseConnection databaseConnection; public ResultSetTableModel(List columnHeaders, List> tableData) { @@ -178,6 +162,24 @@ public synchronized void createTable(ResultSet resultSet) throws SQLException { ResultSet rs; int count; private int recordCount; + public ResultSetTableModel(ResultSet resultSet, int maxRecords, String query, boolean isTable) throws SQLException { + + this.maxRecords = maxRecords; + this.query = query; + this.isTable = isTable; + + table = new ResultSetTable(); + tableData = new ArrayList<>(); + columnHeaders = new ArrayList<>(); + visibleColumnHeaders = new ArrayList<>(); + recordDataItemFactory = new RecordDataItemFactory(); + + holdMetaData = UserProperties.getInstance().getBooleanProperty("editor.results.metadata"); + + if (resultSet != null) { + createTable(resultSet); + } + } public synchronized void createTable(ResultSet resultSet, List columnDataList) throws SQLException { @@ -190,6 +192,11 @@ public synchronized void createTable(ResultSet resultSet, List colum try { resetMetaData(); ResultSetMetaData rsmd = resultSet.getMetaData(); + try { + databaseConnection = ((PooledStatement) resultSet.getStatement()).getPooledConnection().getDatabaseConnection(); + } catch (Exception e) { + e.printStackTrace(); + } columnHeaders.clear(); visibleColumnHeaders.clear(); @@ -376,7 +383,7 @@ public synchronized void createTableFromMetaData(ResultSet resultSet, DatabaseCo if (executor != null) executor.releaseResources(); executor = new DefaultStatementExecutor(dc, true); - + databaseConnection = dc; try { resetMetaData(); @@ -1099,6 +1106,11 @@ public String getColumnNameHint(int column) { return visibleColumnHeaders.get(column).getNameHint() + " " + visibleColumnHeaders.get(column).getDataTypeName() + (visibleColumnHeaders.get(column).getDisplaySize() != 0 ? " (" + visibleColumnHeaders.get(column).getDisplaySize() + ")" : ""); } + public String getColumnType(int column) { + + return visibleColumnHeaders.get(column).getDataTypeName() + (visibleColumnHeaders.get(column).getDisplaySize() != 0 ? " (" + visibleColumnHeaders.get(column).getDisplaySize() + ")" : ""); + } + @Override public String getColumnName(int column) { @@ -1198,4 +1210,8 @@ else for (RecordDataItem recordDataItem : row) public SQLException getException() { return exception; } + + public DatabaseConnection getDatabaseConnection() { + return databaseConnection; + } } diff --git a/src/org/executequery/localization/resources.properties b/src/org/executequery/localization/resources.properties index dd4a6dbb2..5e7422be7 100644 --- a/src/org/executequery/localization/resources.properties +++ b/src/org/executequery/localization/resources.properties @@ -2150,6 +2150,8 @@ ResultSetTablePopupMenu.CopySelectedCells-CommaSeparatedAndQuotedWithNames=Copy ResultSetTablePopupMenu.CopySelectedCells-CommaSeparatedWithNames=Copy Selected Cells - comma-separated with names ResultSetTablePopupMenu.CopySelectedCells=Copy Selected Cells ResultSetTablePopupMenu.CopySelectedColumnNames=Copy Selected Columns - comma-separated +ResultSetTablePopupMenu.CopySelectedColumnNamesFormated=Copy Selected Formatted Columns - comma-separated +ResultSetTablePopupMenu.CopySelectedColumnNamesWithDataTypes=Copy Selected Columns With Datatypes - comma-separated ResultSetTablePopupMenu.Export=Export ResultSetTablePopupMenu.ExportTable=Export table ResultSetTablePopupMenu.LOBRecordDataItemViewer=BLOB Record Data Item Viewer diff --git a/src/org/executequery/localization/resources_pt_br.properties b/src/org/executequery/localization/resources_pt_br.properties index d07a5b73b..372de6943 100644 --- a/src/org/executequery/localization/resources_pt_br.properties +++ b/src/org/executequery/localization/resources_pt_br.properties @@ -2150,6 +2150,8 @@ ResultSetTablePopupMenu.CopySelectedCells-CommaSeparatedAndQuotedWithNames=Copia ResultSetTablePopupMenu.CopySelectedCells-CommaSeparatedWithNames=Copiar células selecionadas - separadas por vírgulas com nomes ResultSetTablePopupMenu.CopySelectedCells=Copiar células selecionadas ResultSetTablePopupMenu.CopySelectedColumnNames=Copiar colunas selecionadas - separadas por vírgula +ResultSetTablePopupMenu.CopySelectedColumnNamesFormated=Copiar colunas formatadas selecionadas - separadas por vírgula +ResultSetTablePopupMenu.CopySelectedColumnNamesWithDataTypes=Copiar colunas selecionadas com tipos de dados - separados por vírgula ResultSetTablePopupMenu.Export=Exportação ResultSetTablePopupMenu.ExportTable=Tabela de exportação ResultSetTablePopupMenu.LOBRecordDataItemViewer=Visualizador de itens de dados de registros BLOB diff --git a/src/org/executequery/localization/resources_ru.properties b/src/org/executequery/localization/resources_ru.properties index ce22732eb..a37b0d6af 100644 --- a/src/org/executequery/localization/resources_ru.properties +++ b/src/org/executequery/localization/resources_ru.properties @@ -2150,6 +2150,8 @@ ResultSetTablePopupMenu.CopySelectedCells-CommaSeparatedAndQuotedWithNames=Ко ResultSetTablePopupMenu.CopySelectedCells-CommaSeparatedWithNames=Копировать выделенные ячейки, разделенные запятыми с именами столбцов ResultSetTablePopupMenu.CopySelectedCells=Копировать выделенные ячейки ResultSetTablePopupMenu.CopySelectedColumnNames=Копировать имена столбцов выделенных ячеек, разделенные запятыми +ResultSetTablePopupMenu.CopySelectedColumnNamesFormated=Копировать форматированные имена столбцов выделенных ячеек, разделенные запятыми +ResultSetTablePopupMenu.CopySelectedColumnNamesWithDataTypes=Копировать имена столбцов выделенных ячеек с типами данных, разделенные запятыми ResultSetTablePopupMenu.Export=Экспортировать ResultSetTablePopupMenu.ExportTable=Экспортировать таблицу ResultSetTablePopupMenu.LOBRecordDataItemViewer=Средство просмотра элементов данных BLOB-записи From 46fc24592682c0ceda11177a4d89da5ba6d4576b Mon Sep 17 00:00:00 2001 From: Elizaveta Rykova Date: Wed, 11 Dec 2024 14:39:36 +0300 Subject: [PATCH 38/41] Revert "Update screenshots of data import tool (RS-205725)" This reverts commit 0e7699d69eab6c3055a803e21510c80e18ad6066. --- guide_rst/source/img/import_date.png | Bin 22359 -> 24178 bytes guide_rst/source/img/import_example.png | Bin 42999 -> 58187 bytes guide_rst/source/sec-import.rst | 1 - 3 files changed, 1 deletion(-) diff --git a/guide_rst/source/img/import_date.png b/guide_rst/source/img/import_date.png index 8c395c1e8711ecb12ff4c5660b76401b6f879b64..46087156dc5086ad794beca12ab7a70484297e8e 100644 GIT binary patch literal 24178 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 diff --git a/guide_rst/source/img/import_example.png b/guide_rst/source/img/import_example.png index 0ba2456cefbb76a366863815c8b347e4e6945de6..a0c2bbec38b8863c87c2c09420bf6995fdc58611 100644 GIT binary patch literal 58187 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

SE5YGilu1;Vc4~=gY4})FZI%OX*Z}u%4 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 literal 42999 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 I{q~c80Y+$=^#A|> diff --git a/guide_rst/source/sec-import.rst b/guide_rst/source/sec-import.rst index 510180abe..b56d88bcd 100644 --- a/guide_rst/source/sec-import.rst +++ b/guide_rst/source/sec-import.rst @@ -17,7 +17,6 @@ * ``Целевая БД`` - База данных, в которую будет производиться импорт. * ``Целевая таблица`` - Таблица, в которую будет производиться импорт. * ``Разделитель`` - Тип разделителя данных в CSV файлах. -* ``Количество потоков`` - Количество потоков, используемых для импортирования. Для каждого потока создаётся отдельное подключение. * ``Номер страницы`` - Для XLSX файлов можно выбрасть страницу excel-файла, из которой нужно импортировать данные. * ``Первая импортируемая строка`` - Строка, начиная с которой будут импортированы данные. * ``Последняя импортируемая строка`` - Строка, поcле которой импорт данных будет прекращён. Строки, непопадающие в диапазон между первой и последней импортируемой строкой, будут проигнорированы. From e63f9b3c50032d52b0cafe9221be6f88cbc5755a Mon Sep 17 00:00:00 2001 From: Elizaveta Rykova Date: Wed, 11 Dec 2024 14:50:47 +0300 Subject: [PATCH 39/41] Add version to title of documentation --- guide_rst/source/conf.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/guide_rst/source/conf.py b/guide_rst/source/conf.py index a9b150514..cc0a1b5be 100644 --- a/guide_rst/source/conf.py +++ b/guide_rst/source/conf.py @@ -6,12 +6,6 @@ # -- Project information ----------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information -latex_use_latex_multicolumn = True - -project = 'Red_Expert' -copyright = '2024, Red Soft' -author = 'Red Soft' - # General configuration import re @@ -19,7 +13,18 @@ import sys sys.path.append(os.path.abspath("./_ext")) import globalvar +from datetime import datetime + +year = datetime.now().year + +version = os.environ.get('VERSION', "VERSION") + +latex_use_latex_multicolumn = True + +project = 'Red_Expert' +copyright = f'{year}, Red Soft' +author = 'Red Soft' # функция подменяет один список слов на другой в rst файлах # эта функция вспомогательная, она работает, но выполнить ее достаточно один раз для замены необходимых слов @@ -103,7 +108,7 @@ def replace_words_in_files(words_to_replace, new_words): \begin{flushright} \Huge {\xhrulefill{red}{2mm}\color{red} Ред} Эксперт\\ -\LARGE Версия 2024.11\\ +\LARGE Версия """ + f"{version}" + r"""\\ \huge Руководство пользователя\\ \end{flushright} From b56431df39781ee868fa1d38d6e4a8ddc663f650 Mon Sep 17 00:00:00 2001 From: "aleksey.kozlov" Date: Fri, 13 Dec 2024 09:28:38 +0300 Subject: [PATCH 40/41] Add release notes for v2024.12 --- src/org/executequery/release_notes_en.html | 24 ++++++++++++++++++++++ src/org/executequery/release_notes_ru.html | 24 ++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/src/org/executequery/release_notes_en.html b/src/org/executequery/release_notes_en.html index 1fb1d6ea8..8192b6bc7 100644 --- a/src/org/executequery/release_notes_en.html +++ b/src/org/executequery/release_notes_en.html @@ -1,5 +1,29 @@

RedExpert Changelog

+

Major changes - v2024.12

+

Added:

+
    +
  1. Formatting numbers for table statistics
  2. +
  3. Copying formatted column names
  4. +
+

Improved:

+
    +
  1. The amount of memory required for audit analysis has been reduced
  2. +
  3. Exporting data with BLOB SUB_TYPE TEXT type now does not require mandatory file specification for exported + blobs +
  4. +
+

Fixed:

+
    +
  1. Recalculation of index selectivity
  2. +
  3. Parsing of the nested procedures
  4. +
  5. Parsing of the procedure cursors
  6. +
  7. Parsing of the procedure variables with NCHAR, REAL, INT, LONG FLOAT and other types
  8. +
  9. Generating SQL statements for variables with COLLATE
  10. +
  11. Display SQL queries containing special characters on the “Analyze” tab in the Trace Manager
  12. +
  13. Increased CPU load after repeated opening of the search window in the Query Editor
  14. +
  15. Mismatch between the versions of the client library and driver used for native connection
  16. +

Major changes - v2024.11

Added:

    diff --git a/src/org/executequery/release_notes_ru.html b/src/org/executequery/release_notes_ru.html index ea899e488..9aac5a466 100644 --- a/src/org/executequery/release_notes_ru.html +++ b/src/org/executequery/release_notes_ru.html @@ -1,5 +1,29 @@

    Лог изменений RedExpert

    +

    Основные изменения - v2024.12

    +

    Добавлено:

    +
      +
    1. Копирование форматированных имен столбцов
    2. +
    3. Форматирование чисел при выводе потабличной статистики
    4. +
    +

    Улучшено:

    +
      +
    1. Уменьшен объем необходимой памяти для анализа аудита
    2. +
    3. Экспорт данных с типом BLOB SUB_TYPE TEXT теперь не требует обязательного указания файла для экспортируемых + блобов +
    4. +
    +

    Исправлено:

    +
      +
    1. Пересчет селективности индексов
    2. +
    3. Парсинг вложенных процедур
    4. +
    5. Парсинг курсоров процедур
    6. +
    7. Парсинг переменных процедур с типами NCHAR, REAL, INT, LONG FLOAT и другими
    8. +
    9. Генерация SQL-выражений для переменных с COLLATE
    10. +
    11. Отображение SQL-запросов, которые содержат спецсимволы, на вкладке “Анализ” в Трейс Менеджере
    12. +
    13. Увеличение нагрузки на процессор после многократного открытия окна поиска в Редакторе Запросов
    14. +
    15. Несоответствие версий используемых клиентской библиотеки и драйвера для нативного подключения
    16. +

    Основные изменения - v2024.11

    Добавлено:

      From 7dec811818449565dd1d92630d0df4bba2d949ae Mon Sep 17 00:00:00 2001 From: "aleksey.kozlov" Date: Fri, 13 Dec 2024 09:30:08 +0300 Subject: [PATCH 41/41] RELEASE 2024.12 --- modules/plugins/fbclient-3/pom.xml | 2 +- modules/plugins/fbclient-4/pom.xml | 2 +- modules/plugins/fbclient-5/pom.xml | 2 +- modules/plugins/fbplugin-impl/pom.xml | 2 +- modules/plugins/fbplugin-impl5/pom.xml | 2 +- modules/plugins/fbplugin/pom.xml | 2 +- modules/plugins/procedure-parser/pom.xml | 2 +- modules/plugins/sql-parser/pom.xml | 2 +- modules/plugins/sqlLexer/pom.xml | 2 +- modules/plugins/trace-parser/pom.xml | 2 +- modules/redexpert/pom.xml | 2 +- pom.xml | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/modules/plugins/fbclient-3/pom.xml b/modules/plugins/fbclient-3/pom.xml index 4a2a90512..f22f841ed 100644 --- a/modules/plugins/fbclient-3/pom.xml +++ b/modules/plugins/fbclient-3/pom.xml @@ -7,7 +7,7 @@ org.executequery RedExpert-parent - 2024.11 + 2024.12 ../../../pom.xml diff --git a/modules/plugins/fbclient-4/pom.xml b/modules/plugins/fbclient-4/pom.xml index 7666b0a15..fa249b3f4 100644 --- a/modules/plugins/fbclient-4/pom.xml +++ b/modules/plugins/fbclient-4/pom.xml @@ -7,7 +7,7 @@ org.executequery RedExpert-parent - 2024.11 + 2024.12 ../../../pom.xml diff --git a/modules/plugins/fbclient-5/pom.xml b/modules/plugins/fbclient-5/pom.xml index bbecba606..943155f8c 100644 --- a/modules/plugins/fbclient-5/pom.xml +++ b/modules/plugins/fbclient-5/pom.xml @@ -7,7 +7,7 @@ org.executequery RedExpert-parent - 2024.11 + 2024.12 ../../../pom.xml diff --git a/modules/plugins/fbplugin-impl/pom.xml b/modules/plugins/fbplugin-impl/pom.xml index 2840df343..c3a82bea0 100644 --- a/modules/plugins/fbplugin-impl/pom.xml +++ b/modules/plugins/fbplugin-impl/pom.xml @@ -9,7 +9,7 @@ org.executequery RedExpert-parent - 2024.11 + 2024.12 ../../../pom.xml diff --git a/modules/plugins/fbplugin-impl5/pom.xml b/modules/plugins/fbplugin-impl5/pom.xml index 0db2adb7f..d1cb8ca34 100644 --- a/modules/plugins/fbplugin-impl5/pom.xml +++ b/modules/plugins/fbplugin-impl5/pom.xml @@ -9,7 +9,7 @@ org.executequery RedExpert-parent - 2024.11 + 2024.12 ../../../pom.xml diff --git a/modules/plugins/fbplugin/pom.xml b/modules/plugins/fbplugin/pom.xml index a60d15163..e1a215517 100644 --- a/modules/plugins/fbplugin/pom.xml +++ b/modules/plugins/fbplugin/pom.xml @@ -17,7 +17,7 @@ org.executequery RedExpert-parent - 2024.11 + 2024.12 ../../../pom.xml diff --git a/modules/plugins/procedure-parser/pom.xml b/modules/plugins/procedure-parser/pom.xml index ac9c07b88..e2887456b 100644 --- a/modules/plugins/procedure-parser/pom.xml +++ b/modules/plugins/procedure-parser/pom.xml @@ -15,7 +15,7 @@ org.executequery RedExpert-parent - 2024.11 + 2024.12 ../../../pom.xml diff --git a/modules/plugins/sql-parser/pom.xml b/modules/plugins/sql-parser/pom.xml index 7199967c2..f032cd502 100644 --- a/modules/plugins/sql-parser/pom.xml +++ b/modules/plugins/sql-parser/pom.xml @@ -6,7 +6,7 @@ org.executequery RedExpert-parent - 2024.11 + 2024.12 ../../../pom.xml 1.0 diff --git a/modules/plugins/sqlLexer/pom.xml b/modules/plugins/sqlLexer/pom.xml index 06def88f0..e127c1266 100644 --- a/modules/plugins/sqlLexer/pom.xml +++ b/modules/plugins/sqlLexer/pom.xml @@ -15,7 +15,7 @@ org.executequery RedExpert-parent - 2024.11 + 2024.12 ../../../pom.xml diff --git a/modules/plugins/trace-parser/pom.xml b/modules/plugins/trace-parser/pom.xml index 38d43c964..e9bf8e2be 100644 --- a/modules/plugins/trace-parser/pom.xml +++ b/modules/plugins/trace-parser/pom.xml @@ -15,7 +15,7 @@ org.executequery RedExpert-parent - 2024.11 + 2024.12 ../../../pom.xml diff --git a/modules/redexpert/pom.xml b/modules/redexpert/pom.xml index 77dc35186..e18d5fc82 100644 --- a/modules/redexpert/pom.xml +++ b/modules/redexpert/pom.xml @@ -14,7 +14,7 @@ org.executequery RedExpert-parent ../../pom.xml - 2024.11 + 2024.12 diff --git a/pom.xml b/pom.xml index 546d28c28..f5eecec63 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ org.executequery RedExpert-parent pom - 2024.11 + 2024.12 modules/plugins/fbplugin modules/plugins/fbclient-3