提交 b6fe3f7f authored 作者: Owner's avatar Owner

Final round of changes from review

上级 5bdb1b14
......@@ -1168,34 +1168,6 @@ This setting can be appended to the database URL: ""jdbc:h2:test;CACHE_SIZE=8192
SET CACHE_SIZE 8192
"
"Commands (Other)","SET COLUMN_NAMING_RULES","
SET COLUMN_NAMING_RULES = { DEFAULT | EMULATE=... | MAX_IDENTIFIER_LENGTH=... | REGULAR_EXPRESSION_MATCH_ALLOWED=... | REGULAR_EXPRESSION_MATCH_DISALLOWED=... | DEFAULT_COLUMN_NAME_PATTERN=... | GENERATE_UNIQUE_COLUMN_NAMES=...}
","
This setting controls the rules dealing with how column names are generated
in select statements.
Administrator rights are required to execute this command, as it affects all
connections. This setting is not persistent.
Emulation settings can be appended to the database URL:
""jdbc:h2:test;COLUMN_NAME_RULES=EMULATE=ORACLE30""
It is not recommended to use overly restrictive settings as system
columns can accidentally get their identifiers truncated leading to
undefined behavior. A minimum value of 30 is enforced.
","
-- Emulate popular database settings
SET COLUMN_NAME_RULES=EMULATE=ORACLE128 -- Emulate Oracle 128 character column identifiers
SET COLUMN_NAME_RULES=EMULATE=ORACLE30; -- Emulate Oracle 30 character column identifiers
SET COLUMN_NAME_RULES=EMULATE=POSTGRES; -- Emulate Postgres
SET COLUMN_NAME_RULES=DEFAULT; -- Reset back to default H2 allow-anything rules
-- Custom settings
SET COLUMN_NAME_RULES=MAX_IDENTIFIER_LENGTH = 30; -- Custom configure max identifier length (minimum value is 30). Default is 2147483647.
SET COLUMN_NAME_RULES=REGULAR_EXPRESSION_MATCH_ALLOWED = '[A-Za-z0-9_]+'; -- Custom configure Java RegEx for allowed characters
SET COLUMN_NAME_RULES=REGULAR_EXPRESSION_MATCH_DISALLOWED = '[^A-Za-z0-9_]+'; -- Custom configure Java RegEx for disallowed characters
SET COLUMN_NAME_RULES=DEFAULT_COLUMN_NAME_PATTERN = '_unnamed$$'; -- Custom configure default column name, $$ is replaced by column Nth ordinal
SET COLUMN_NAME_RULES=GENERATE_UNIQUE_COLUMN_NAMES = 1; -- Generate unique column names (default is 0, meaning false)
"
"Commands (Other)","SET CLUSTER","
SET CLUSTER serverListString
","
......
......@@ -23,7 +23,6 @@ import org.h2.result.RowFactory;
import org.h2.schema.Schema;
import org.h2.table.Table;
import org.h2.tools.CompressTool;
import org.h2.util.ColumnNamerConfiguration;
import org.h2.util.JdbcUtils;
import org.h2.util.StringUtils;
import org.h2.value.CompareMode;
......@@ -342,6 +341,7 @@ public class Set extends Prepared {
if (database.getMode() != mode) {
session.getUser().checkAdmin();
database.setMode(mode);
session.getColumnNamerConfiguration().configure(mode.getEnum());
}
break;
case SetTypes.MULTI_THREADED: {
......@@ -538,9 +538,6 @@ public class Set extends Prepared {
case SetTypes.COLUMN_NAME_RULES: {
session.getUser().checkAdmin();
if(session.getColumnNamerConfiguration()==null){
session.setColumnNamerConfiguration(ColumnNamerConfiguration.getDefault());
}
session.getColumnNamerConfiguration().configure(expression.getColumnName());
break;
}
......
......@@ -17,11 +17,15 @@ import org.h2.util.StringUtils;
* PostgreSQL, MySQL). Each mode has different settings.
*/
public class Mode {
public enum ModeEnum {
REGULAR, DB2, Derby, MSSQLServer, HSQLDB, MySQL, Oracle, PostgreSQL, Ignite,
}
/**
* The name of the default mode.
*/
static final String REGULAR = "REGULAR";
static final String REGULAR = ModeEnum.REGULAR.name();
private static final HashMap<String, Mode> MODES = New.hashMap();
......@@ -180,12 +184,14 @@ public class Mode {
private final String name;
private ModeEnum modeEnum;
static {
Mode mode = new Mode(REGULAR);
Mode mode = new Mode(ModeEnum.REGULAR.name());
mode.nullConcatIsNull = true;
add(mode);
mode = new Mode("DB2");
mode = new Mode(ModeEnum.DB2.name());
mode.aliasColumnName = true;
mode.supportOffsetFetch = true;
mode.sysDummy1 = true;
......@@ -200,7 +206,7 @@ public class Mode {
mode.allowDB2TimestampFormat = true;
add(mode);
mode = new Mode("Derby");
mode = new Mode(ModeEnum.Derby.name());
mode.aliasColumnName = true;
mode.uniqueIndexSingleNull = true;
mode.supportOffsetFetch = true;
......@@ -210,7 +216,7 @@ public class Mode {
mode.supportedClientInfoPropertiesRegEx = null;
add(mode);
mode = new Mode("HSQLDB");
mode = new Mode(ModeEnum.HSQLDB.name());
mode.aliasColumnName = true;
mode.convertOnlyToSmallerScale = true;
mode.nullConcatIsNull = true;
......@@ -223,7 +229,7 @@ public class Mode {
mode.supportedClientInfoPropertiesRegEx = null;
add(mode);
mode = new Mode("MSSQLServer");
mode = new Mode(ModeEnum.MSSQLServer.name());
mode.aliasColumnName = true;
mode.squareBracketQuotedNames = true;
mode.uniqueIndexSingleNull = true;
......@@ -235,7 +241,7 @@ public class Mode {
mode.supportedClientInfoPropertiesRegEx = null;
add(mode);
mode = new Mode("MySQL");
mode = new Mode(ModeEnum.MySQL.name());
mode.convertInsertNullToZero = true;
mode.indexDefinitionInCreateTable = true;
mode.lowerCaseIdentifiers = true;
......@@ -249,7 +255,7 @@ public class Mode {
mode.prohibitEmptyInPredicate = true;
add(mode);
mode = new Mode("Oracle");
mode = new Mode(ModeEnum.Oracle.name());
mode.aliasColumnName = true;
mode.convertOnlyToSmallerScale = true;
mode.uniqueIndexSingleNullExceptAllColumnsAreNull = true;
......@@ -262,7 +268,7 @@ public class Mode {
mode.prohibitEmptyInPredicate = true;
add(mode);
mode = new Mode("PostgreSQL");
mode = new Mode(ModeEnum.PostgreSQL.name());
mode.aliasColumnName = true;
mode.nullConcatIsNull = true;
mode.supportOffsetFetch = true;
......@@ -285,7 +291,7 @@ public class Mode {
mode.disallowedTypes = disallowedTypes;
add(mode);
mode = new Mode("Ignite");
mode = new Mode(ModeEnum.Ignite.name());
mode.nullConcatIsNull = true;
mode.allowAffinityKey = true;
mode.indexDefinitionInCreateTable = true;
......@@ -294,6 +300,7 @@ public class Mode {
private Mode(String name) {
this.name = name;
this.modeEnum = ModeEnum.valueOf(name);
}
private static void add(Mode mode) {
......@@ -311,15 +318,19 @@ public class Mode {
}
public static Mode getMySQL() {
return getInstance("MySQL");
return getInstance(ModeEnum.MySQL.name());
}
public static Mode getOracle() {
return getInstance("Oracle");
return getInstance(ModeEnum.Oracle.name());
}
public String getName() {
return name;
}
public ModeEnum getEnum() {
return this.modeEnum;
}
}
package org.h2.util;
import java.util.regex.Pattern;
import org.h2.engine.Mode.ModeEnum;
import static org.h2.engine.Mode.ModeEnum.*;
import org.h2.message.DbException;
public class ColumnNamerConfiguration {
......@@ -38,7 +40,10 @@ public class ColumnNamerConfiguration {
}
public void setMaxIdentiferLength(int maxIdentiferLength) {
this.maxIdentiferLength = maxIdentiferLength;
this.maxIdentiferLength = Math.max(30,maxIdentiferLength);
if(maxIdentiferLength!=getMaxIdentiferLength()){
throw DbException.getInvalidValueException("Illegal value (<30) in SET COLUMN_NAME_RULES","MAX_IDENTIFIER_LENGTH="+maxIdentiferLength);
}
}
public String getRegularExpressionMatchAllowed() {
......@@ -84,31 +89,12 @@ public class ColumnNamerConfiguration {
public void configure(String stringValue) {
try{
if(stringValue.equalsIgnoreCase(DEFAULT_COMMAND)){
setMaxIdentiferLength(Integer.MAX_VALUE);
setRegularExpressionMatchAllowed("(?m)(?s).+");
setRegularExpressionMatchDisallowed("(?m)(?s)[\\x00]");
setDefaultColumnNamePattern("_UNNAMED_$$");
} else if(stringValue.equalsIgnoreCase(EMULATE_COMMAND+"ORACLE128")){
setMaxIdentiferLength(128);
setRegularExpressionMatchAllowed("(?m)(?s)\"?[A-Za-z0-9_]+\"?");
setRegularExpressionMatchDisallowed("(?m)(?s)[^A-Za-z0-9_\"]");
setDefaultColumnNamePattern("_UNNAMED_$$");
} else if(stringValue.equalsIgnoreCase(EMULATE_COMMAND+"ORACLE30")){
setMaxIdentiferLength(30);
setRegularExpressionMatchAllowed("(?m)(?s)\"?[A-Za-z0-9_]+\"?");
setRegularExpressionMatchDisallowed("(?m)(?s)[^A-Za-z0-9_\"]");
setDefaultColumnNamePattern("_UNNAMED_$$");
}else if(stringValue.equalsIgnoreCase(EMULATE_COMMAND+"POSTGRES")){
setMaxIdentiferLength(31);
setRegularExpressionMatchAllowed("(?m)(?s)\"?[A-Za-z0-9_\"]+\"?");
setRegularExpressionMatchDisallowed("(?m)(?s)[^A-Za-z0-9_\"]");
setDefaultColumnNamePattern("_UNNAMED_$$");
configure(REGULAR);
} else if(stringValue.startsWith(EMULATE_COMMAND)){
configure(ModeEnum.valueOf(unquoteString(stringValue.substring(EMULATE_COMMAND.length()))));
} else if(stringValue.startsWith(MAX_IDENTIFIER_LENGTH)){
int maxLength = Integer.parseInt(stringValue.substring(MAX_IDENTIFIER_LENGTH.length()));
setMaxIdentiferLength(Math.max(30,maxLength));
if(maxLength!=getMaxIdentiferLength()){
throw DbException.getInvalidValueException("Illegal value (<30) in SET COLUMN_NAME_RULES="+stringValue,stringValue);
}
setMaxIdentiferLength(maxLength);
} else if(stringValue.startsWith(GENERATE_UNIQUE_COLUMN_NAMES)){
setGenerateUniqueColumnNames(Integer.parseInt(stringValue.substring(GENERATE_UNIQUE_COLUMN_NAMES.length()))==1);
} else if(stringValue.startsWith(DEFAULT_COLUMN_NAME_PATTERN)){
......@@ -125,9 +111,7 @@ public class ColumnNamerConfiguration {
}
// recompile RE patterns
setCompiledRegularExpressionMatchAllowed(Pattern.compile(getRegularExpressionMatchAllowed()));
setCompiledRegularExpressionMatchDisallowed(Pattern.compile(getRegularExpressionMatchDisallowed()));
recompilePatterns();
}
//Including NumberFormatException|PatternSyntaxException
catch(RuntimeException e){
......@@ -135,10 +119,22 @@ public class ColumnNamerConfiguration {
stringValue);
}
}
private void recompilePatterns() {
try{
// recompile RE patterns
setCompiledRegularExpressionMatchAllowed(Pattern.compile(getRegularExpressionMatchAllowed()));
setCompiledRegularExpressionMatchDisallowed(Pattern.compile(getRegularExpressionMatchDisallowed()));
}
catch(Exception e){
configure(REGULAR);
throw e;
}
}
public static ColumnNamerConfiguration getDefault(){
return new ColumnNamerConfiguration(Integer.MAX_VALUE, "(?m)(?s).+", "(?m)(?s)[\\x00]", "_unnamed_column_$$_",false);
return new ColumnNamerConfiguration(Integer.MAX_VALUE, "(?m)(?s).+", "(?m)(?s)[\\x00]", "_UNNAMED_$$",false);
}
private static String unquoteString(String s){
......@@ -156,5 +152,59 @@ public class ColumnNamerConfiguration {
public void setGenerateUniqueColumnNames(boolean generateUniqueColumnNames) {
this.generateUniqueColumnNames = generateUniqueColumnNames;
}
public void configure(ModeEnum modeEnum) {
switch(modeEnum){
case Oracle:
// Nonquoted identifiers can contain only alphanumeric characters
// from your database character set and the underscore (_), dollar sign ($), and pound sign (#).
setMaxIdentiferLength(128);
setRegularExpressionMatchAllowed("(?m)(?s)\"?[A-Za-z0-9_\\$#]+\"?");
setRegularExpressionMatchDisallowed("(?m)(?s)[^A-Za-z0-9_\"\\$#]");
setDefaultColumnNamePattern("_UNNAMED_$$");
setGenerateUniqueColumnNames(false);
break;
case MSSQLServer:
// https://docs.microsoft.com/en-us/sql/sql-server/maximum-capacity-specifications-for-sql-server
setMaxIdentiferLength(128);
setRegularExpressionMatchAllowed("(?m)(?s)[A-Za-z0-9_\\[\\]]+");// allows [] around names
setRegularExpressionMatchDisallowed("(?m)(?s)[^A-Za-z0-9_\\[\\]]");
setDefaultColumnNamePattern("_UNNAMED_$$");
setGenerateUniqueColumnNames(false);
break;
case PostgreSQL:
setMaxIdentiferLength(63);// this default can be changed to 128 by postgres config
setRegularExpressionMatchAllowed("(?m)(?s)[A-Za-z0-9_\\$]+");
setRegularExpressionMatchDisallowed("(?m)(?s)[^A-Za-z0-9_\\$]");
setDefaultColumnNamePattern("_UNNAMED_$$");
setGenerateUniqueColumnNames(false);
break;
case MySQL:
//https://dev.mysql.com/doc/refman/5.7/en/identifiers.html
setMaxIdentiferLength(64);
setRegularExpressionMatchAllowed("(?m)(?s)`?[A-Za-z0-9_`\\$]+`?");
setRegularExpressionMatchDisallowed("(?m)(?s)[^A-Za-z0-9_`\\$]");
setDefaultColumnNamePattern("_UNNAMED_$$");
setGenerateUniqueColumnNames(false);
break;
default:
case REGULAR:
case DB2:
case Derby:
case HSQLDB:
case Ignite:
setMaxIdentiferLength(Integer.MAX_VALUE);
setRegularExpressionMatchAllowed("(?m)(?s).+");
setRegularExpressionMatchDisallowed("(?m)(?s)[\\x00]");
setDefaultColumnNamePattern("_UNNAMED_$$");
setGenerateUniqueColumnNames(false);
break;
}
recompilePatterns();
}
}
\ No newline at end of file
......@@ -25,7 +25,7 @@ SELECT 1 AS VERY_VERY_VERY_LONG_ID_VERY_VERY_VERY_LONG_ID, SUM(X)+1 AS _12345678
> ------------------------------ ---------------- ----- ------- - ------- -------
> 1 4 4 51 x !!! !!!!
SET COLUMN_NAME_RULES=EMULATE=ORACLE128;
SET COLUMN_NAME_RULES=EMULATE='Oracle';
> ok
SELECT 1 AS VERY_VERY_VERY_LONG_ID, SUM(X)+1 AS _123456789012345, SUM(X)+1 , SUM(X)+1
......@@ -34,16 +34,16 @@ SELECT 1 AS VERY_VERY_VERY_LONG_ID, SUM(X)+1 AS _123456789012345, SUM(X)+1 , SUM
> ---------------------- ---------------- ----- ------- - ---------- ----------
> 1 4 4 51 x !!! !!!!
SET COLUMN_NAME_RULES=EMULATE=ORACLE30;
SET COLUMN_NAME_RULES=EMULATE='Oracle';
> ok
SELECT 1 AS VERY_VERY_VERY_LONG_ID, SUM(X)+1 AS _123456789012345, SUM(X)+1 , SUM(X)+1
+47, 'x' , '!!!' , '!!!!', 'Very Long' AS _23456789012345678901234567890XXX FROM SYSTEM_RANGE(1,2);
> VERY_VERY_VERY_LONG_ID _123456789012345 SUMX1 SUMX147 x _UNNAMED_6 _UNNAMED_7 _23456789012345678901234567890
> ---------------------- ---------------- ----- ------- - ---------- ---------- ------------------------------
> VERY_VERY_VERY_LONG_ID _123456789012345 SUMX1 SUMX147 x _UNNAMED_6 _UNNAMED_7 _23456789012345678901234567890XXX
> ---------------------- ---------------- ----- ------- - ---------- ---------- ---------------------------------
> 1 4 4 51 x !!! !!!! Very Long
SET COLUMN_NAME_RULES=EMULATE=POSTGRES;
SET COLUMN_NAME_RULES=EMULATE='PostgreSQL';
> ok
SELECT 1 AS VERY_VERY_VERY_LONG_ID, SUM(X)+1 AS _123456789012345, SUM(X)+1 , SUM(X)+1
......@@ -54,3 +54,29 @@ SELECT 1 AS VERY_VERY_VERY_LONG_ID, SUM(X)+1 AS _123456789012345, SUM(X)+1 , SUM
SET COLUMN_NAME_RULES=DEFAULT;
> ok
-- Test all MODES of database:
-- DB2, Derby, MSSQLServer, HSQLDB, MySQL, Oracle, PostgreSQL, Ignite
SET COLUMN_NAME_RULES=EMULATE='DB2';
> ok
SET COLUMN_NAME_RULES=EMULATE='Derby';
> ok
SET COLUMN_NAME_RULES=EMULATE='MSSQLServer';
> ok
SET COLUMN_NAME_RULES=EMULATE='MySQL';
> ok
SET COLUMN_NAME_RULES=EMULATE='Oracle';
> ok
SET COLUMN_NAME_RULES=EMULATE='PostgreSQL';
> ok
SET COLUMN_NAME_RULES=EMULATE='Ignite';
> ok
SET COLUMN_NAME_RULES=EMULATE='REGULAR';
> ok
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论