提交 2f403af6 authored 作者: Owner's avatar Owner

Created instance class for configuration preventing static Tomcat test case failures

上级 3a056e47
...@@ -1181,7 +1181,7 @@ Emulation settings can be appended to the database URL: ...@@ -1181,7 +1181,7 @@ Emulation settings can be appended to the database URL:
It is not recommended to use overly restrictive settings as system It is not recommended to use overly restrictive settings as system
columns can accidentally get their identifiers truncated leading to columns can accidentally get their identifiers truncated leading to
undefined behavior. undefined behavior. A minimum value of 30 is enforced.
"," ","
-- Emulate popular database settings -- Emulate popular database settings
SET COLUMN_NAME_RULES=EMULATE=ORACLE128 -- Emulate Oracle 128 character column identifiers SET COLUMN_NAME_RULES=EMULATE=ORACLE128 -- Emulate Oracle 128 character column identifiers
...@@ -1189,10 +1189,11 @@ SET COLUMN_NAME_RULES=EMULATE=ORACLE30; -- Emulate Oracle 30 character column id ...@@ -1189,10 +1189,11 @@ SET COLUMN_NAME_RULES=EMULATE=ORACLE30; -- Emulate Oracle 30 character column id
SET COLUMN_NAME_RULES=EMULATE=POSTGRES; -- Emulate Postgres SET COLUMN_NAME_RULES=EMULATE=POSTGRES; -- Emulate Postgres
SET COLUMN_NAME_RULES=DEFAULT; -- Reset back to default H2 allow-anything rules SET COLUMN_NAME_RULES=DEFAULT; -- Reset back to default H2 allow-anything rules
-- Custom settings -- Custom settings
SET COLUMN_NAME_RULES=MAX_IDENTIFIER_LENGTH = 10; -- Custom configure max identifier length SET COLUMN_NAME_RULES=MAX_IDENTIFIER_LENGTH = 30; -- Custom configure max identifier length (minimum value is 30)
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_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=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=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"," "Commands (Other)","SET CLUSTER","
......
...@@ -5269,12 +5269,13 @@ public class Parser { ...@@ -5269,12 +5269,13 @@ public class Parser {
// array of length 1 to receive extra 'output' field in addition to // array of length 1 to receive extra 'output' field in addition to
// return value // return value
querySQLOutput[0] = StringUtils.cache(theQuery.getPlanSQL()); querySQLOutput[0] = StringUtils.cache(theQuery.getPlanSQL());
ColumnNamer columnNamer = new ColumnNamer(theQuery.getSession());
ArrayList<Expression> withExpressions = theQuery.getExpressions(); ArrayList<Expression> withExpressions = theQuery.getExpressions();
for (int i = 0; i < withExpressions.size(); ++i) { for (int i = 0; i < withExpressions.size(); ++i) {
Expression columnExp = withExpressions.get(i); Expression columnExp = withExpressions.get(i);
// use the passed in column name if supplied, otherwise use alias (if found) otherwise use column name // use the passed in column name if supplied, otherwise use alias (if found) otherwise use column name
// derived from column expression // derived from column expression
String columnName = ColumnNamer.getColumnName(columnExp,i,cols).replace("\n", " ").replace("\r", " "); String columnName = columnNamer.getColumnName(columnExp,i,cols);
columnTemplateList.add(new Column(columnName, columnTemplateList.add(new Column(columnName,
columnExp.getType())); columnExp.getType()));
......
...@@ -231,10 +231,11 @@ public class CreateTable extends SchemaCommand { ...@@ -231,10 +231,11 @@ public class CreateTable extends SchemaCommand {
private void generateColumnsFromQuery() { private void generateColumnsFromQuery() {
int columnCount = asQuery.getColumnCount(); int columnCount = asQuery.getColumnCount();
ArrayList<Expression> expressions = asQuery.getExpressions(); ArrayList<Expression> expressions = asQuery.getExpressions();
ColumnNamer columnNamer= new ColumnNamer(session);
for (int i = 0; i < columnCount; i++) { for (int i = 0; i < columnCount; i++) {
Expression expr = expressions.get(i); Expression expr = expressions.get(i);
int type = expr.getType(); int type = expr.getType();
String name = ColumnNamer.getColumnName(expr,i,expr.getAlias()); String name = columnNamer.getColumnName(expr,i,expr.getAlias());
long precision = expr.getPrecision(); long precision = expr.getPrecision();
int displaySize = expr.getDisplaySize(); int displaySize = expr.getDisplaySize();
DataType dt = DataType.getDataType(type); DataType dt = DataType.getDataType(type);
......
...@@ -840,10 +840,13 @@ public class Select extends Query { ...@@ -840,10 +840,13 @@ public class Select extends Query {
sort = prepareOrder(orderList, expressions.size()); sort = prepareOrder(orderList, expressions.size());
orderList = null; orderList = null;
} }
ColumnNamer columnNamer= new ColumnNamer(session);
for (int i = 0; i < expressions.size(); i++) { for (int i = 0; i < expressions.size(); i++) {
Expression e = expressions.get(i); Expression e = expressions.get(i);
if(!ColumnNamer.isAllowableColumnName(e.getAlias())){ String proposedColumnName = e.getAlias();
String columnName = ColumnNamer.getColumnName(e,i,e.getAlias()); String columnName = columnNamer.getColumnName(e,i,proposedColumnName);
// if the name changed, create an alias
if(!columnName.equals(proposedColumnName)){
e = new Alias(e,columnName,true); e = new Alias(e,columnName,true);
} }
expressions.set(i, e.optimize(session)); expressions.set(i, e.optimize(session));
......
...@@ -36,9 +36,10 @@ public class SelectListColumnResolver implements ColumnResolver { ...@@ -36,9 +36,10 @@ public class SelectListColumnResolver implements ColumnResolver {
columns = new Column[columnCount]; columns = new Column[columnCount];
expressions = new Expression[columnCount]; expressions = new Expression[columnCount];
ArrayList<Expression> columnList = select.getExpressions(); ArrayList<Expression> columnList = select.getExpressions();
ColumnNamer columnNamer= new ColumnNamer(select.getSession());
for (int i = 0; i < columnCount; i++) { for (int i = 0; i < columnCount; i++) {
Expression expr = columnList.get(i); Expression expr = columnList.get(i);
String columnName = ColumnNamer.getColumnName(expr, i, expr.getAlias()); String columnName = columnNamer.getColumnName(expr, i, expr.getAlias());
Column column = new Column(columnName, Value.NULL); Column column = new Column(columnName, Value.NULL);
column.setTable(null, i); column.setTable(null, i);
columns[i] = column; columns[i] = column;
......
...@@ -330,6 +330,7 @@ public class SelectUnion extends Query { ...@@ -330,6 +330,7 @@ public class SelectUnion extends Query {
expressions = New.arrayList(); expressions = New.arrayList();
ArrayList<Expression> le = left.getExpressions(); ArrayList<Expression> le = left.getExpressions();
ArrayList<Expression> re = right.getExpressions(); ArrayList<Expression> re = right.getExpressions();
ColumnNamer columnNamer= new ColumnNamer(session);
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
Expression l = le.get(i); Expression l = le.get(i);
Expression r = re.get(i); Expression r = re.get(i);
...@@ -337,7 +338,7 @@ public class SelectUnion extends Query { ...@@ -337,7 +338,7 @@ public class SelectUnion extends Query {
long prec = Math.max(l.getPrecision(), r.getPrecision()); long prec = Math.max(l.getPrecision(), r.getPrecision());
int scale = Math.max(l.getScale(), r.getScale()); int scale = Math.max(l.getScale(), r.getScale());
int displaySize = Math.max(l.getDisplaySize(), r.getDisplaySize()); int displaySize = Math.max(l.getDisplaySize(), r.getDisplaySize());
String columnName = ColumnNamer.getColumnName(l,i,l.getAlias()); String columnName = columnNamer.getColumnName(l,i,l.getAlias());
Column col = new Column(columnName, type, prec, scale, displaySize); Column col = new Column(columnName, type, prec, scale, displaySize);
Expression e = new ExpressionColumn(session.getDatabase(), col); Expression e = new ExpressionColumn(session.getDatabase(), col);
expressions.add(e); expressions.add(e);
......
...@@ -23,7 +23,7 @@ import org.h2.result.RowFactory; ...@@ -23,7 +23,7 @@ import org.h2.result.RowFactory;
import org.h2.schema.Schema; import org.h2.schema.Schema;
import org.h2.table.Table; import org.h2.table.Table;
import org.h2.tools.CompressTool; import org.h2.tools.CompressTool;
import org.h2.util.ColumnNamer; import org.h2.util.ColumnNamerConfiguration;
import org.h2.util.JdbcUtils; import org.h2.util.JdbcUtils;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
import org.h2.value.CompareMode; import org.h2.value.CompareMode;
...@@ -538,7 +538,10 @@ public class Set extends Prepared { ...@@ -538,7 +538,10 @@ public class Set extends Prepared {
case SetTypes.COLUMN_NAME_RULES: { case SetTypes.COLUMN_NAME_RULES: {
session.getUser().checkAdmin(); session.getUser().checkAdmin();
ColumnNamer.configure(expression.getColumnName()); if(session.getColumnNamerConfiguration()==null){
session.setColumnNamerConfiguration(ColumnNamerConfiguration.getDefault());
}
session.getColumnNamerConfiguration().configure(expression.getColumnName());
break; break;
} }
......
...@@ -42,6 +42,7 @@ import org.h2.table.SubQueryInfo; ...@@ -42,6 +42,7 @@ import org.h2.table.SubQueryInfo;
import org.h2.table.Table; import org.h2.table.Table;
import org.h2.table.TableFilter; import org.h2.table.TableFilter;
import org.h2.table.TableType; import org.h2.table.TableType;
import org.h2.util.ColumnNamerConfiguration;
import org.h2.util.New; import org.h2.util.New;
import org.h2.util.SmallLRUCache; import org.h2.util.SmallLRUCache;
import org.h2.value.Value; import org.h2.value.Value;
...@@ -126,6 +127,7 @@ public class Session extends SessionWithState { ...@@ -126,6 +127,7 @@ public class Session extends SessionWithState {
private boolean joinBatchEnabled; private boolean joinBatchEnabled;
private boolean forceJoinOrder; private boolean forceJoinOrder;
private boolean lazyQueryExecution; private boolean lazyQueryExecution;
private ColumnNamerConfiguration columnNamerConfiguration;
/** /**
* Tables marked for ANALYZE after the current transaction is committed. * Tables marked for ANALYZE after the current transaction is committed.
* Prevents us calling ANALYZE repeatedly in large transactions. * Prevents us calling ANALYZE repeatedly in large transactions.
...@@ -162,6 +164,7 @@ public class Session extends SessionWithState { ...@@ -162,6 +164,7 @@ public class Session extends SessionWithState {
this.lockTimeout = setting == null ? this.lockTimeout = setting == null ?
Constants.INITIAL_LOCK_TIMEOUT : setting.getIntValue(); Constants.INITIAL_LOCK_TIMEOUT : setting.getIntValue();
this.currentSchemaName = Constants.SCHEMA_MAIN; this.currentSchemaName = Constants.SCHEMA_MAIN;
this.columnNamerConfiguration = ColumnNamerConfiguration.getDefault();
} }
public void setLazyQueryExecution(boolean lazyQueryExecution) { public void setLazyQueryExecution(boolean lazyQueryExecution) {
...@@ -1751,4 +1754,12 @@ public class Session extends SessionWithState { ...@@ -1751,4 +1754,12 @@ public class Session extends SessionWithState {
} }
} }
public ColumnNamerConfiguration getColumnNamerConfiguration() {
return columnNamerConfiguration;
}
public void setColumnNamerConfiguration(ColumnNamerConfiguration columnNamerConfiguration) {
this.columnNamerConfiguration = columnNamerConfiguration;
}
} }
...@@ -163,6 +163,7 @@ public class TableView extends Table { ...@@ -163,6 +163,7 @@ public class TableView extends Table {
tables = New.arrayList(query.getTables()); tables = New.arrayList(query.getTables());
ArrayList<Expression> expressions = query.getExpressions(); ArrayList<Expression> expressions = query.getExpressions();
ArrayList<Column> list = New.arrayList(); ArrayList<Column> list = New.arrayList();
ColumnNamer columnNamer= new ColumnNamer(session);
for (int i = 0, count = query.getColumnCount(); i < count; i++) { for (int i = 0, count = query.getColumnCount(); i < count; i++) {
Expression expr = expressions.get(i); Expression expr = expressions.get(i);
String name = null; String name = null;
...@@ -174,7 +175,7 @@ public class TableView extends Table { ...@@ -174,7 +175,7 @@ public class TableView extends Table {
if (name == null) { if (name == null) {
name = expr.getAlias(); name = expr.getAlias();
} }
name = ColumnNamer.getColumnName(expr,i,name); name = columnNamer.getColumnName(expr,i,name);
if (type == Value.UNKNOWN) { if (type == Value.UNKNOWN) {
type = expr.getType(); type = expr.getType();
} }
......
package org.h2.util; package org.h2.util;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import org.h2.engine.Session;
import org.h2.expression.Expression; import org.h2.expression.Expression;
import org.h2.message.DbException;
public class ColumnNamer { public class ColumnNamer {
private static final String DEFAULT_COLUMN_NAME = "DEFAULT"; private static final String DEFAULT_COLUMN_NAME = "DEFAULT";
private static final String DEFAULT_COMMAND = "DEFAULT";
private static final String REGULAR_EXPRESSION_MATCH_DISALLOWED = "REGULAR_EXPRESSION_MATCH_DISALLOWED = ";
private static final String REGULAR_EXPRESSION_MATCH_ALLOWED = "REGULAR_EXPRESSION_MATCH_ALLOWED = ";
private static final String DEFAULT_COLUMN_NAME_PATTERN = "DEFAULT_COLUMN_NAME_PATTERN = ";
private static final String MAX_IDENTIFIER_LENGTH = "MAX_IDENTIFIER_LENGTH = ";
private static final String EMULATE_COMMAND = "EMULATE = ";
private ColumnNamerConfiguration configuration;
private Session session;
private Set<String> existingColumnNames = new HashSet<String>();
public ColumnNamer(Session session) {
this.session = session;
if(this.session!=null && this.session.getColumnNamerConfiguration()!=null){
// use original from session
this.configuration = this.session.getColumnNamerConfiguration();
}
else{
// detached namer, create new
this.configuration = ColumnNamerConfiguration.getDefault();
if(session!=null){
session.setColumnNamerConfiguration(this.configuration);
}
}
}
/** /**
* Create a standardized column name that isn't null and doesn't have a CR/LF in it. * Create a standardized column name that isn't null and doesn't have a CR/LF in it.
* @param columnExp the column expression * @param columnExp the column expression
* @param indexOfColumn index of column in below array * @param indexOfColumn index of column in below array
* @return * @return
*/ */
public static String getColumnName(Expression expr, int indexOfColumn) { public String getColumnName(Expression expr, int indexOfColumn) {
return getColumnName(expr,indexOfColumn,(String) null); return getColumnName(expr,indexOfColumn,(String) null);
} }
/** /**
...@@ -31,7 +45,7 @@ public class ColumnNamer { ...@@ -31,7 +45,7 @@ public class ColumnNamer {
* @param columnNameOverides array of overriding column names * @param columnNameOverides array of overriding column names
* @return the new column name * @return the new column name
*/ */
public static String getColumnName(Expression columnExp, int indexOfColumn, String[] columnNameOverides){ public String getColumnName(Expression columnExp, int indexOfColumn, String[] columnNameOverides){
String columnNameOverride = null; String columnNameOverride = null;
if (columnNameOverides != null && columnNameOverides.length > indexOfColumn){ if (columnNameOverides != null && columnNameOverides.length > indexOfColumn){
columnNameOverride = columnNameOverides[indexOfColumn]; columnNameOverride = columnNameOverides[indexOfColumn];
...@@ -46,7 +60,7 @@ public class ColumnNamer { ...@@ -46,7 +60,7 @@ public class ColumnNamer {
* @param columnNameOverride single overriding column name * @param columnNameOverride single overriding column name
* @return the new column name * @return the new column name
*/ */
public static String getColumnName(Expression columnExp, int indexOfColumn, String columnNameOverride) { public String getColumnName(Expression columnExp, int indexOfColumn, String columnNameOverride) {
// try a name from the column name override // try a name from the column name override
String columnName = null; String columnName = null;
if (columnNameOverride != null){ if (columnNameOverride != null){
...@@ -90,106 +104,59 @@ public class ColumnNamer { ...@@ -90,106 +104,59 @@ public class ColumnNamer {
} }
// go with a innocuous default name pattern // go with a innocuous default name pattern
if (columnName==null){ if (columnName==null){
columnName = defaultColumnNamePattern.replace("$$", ""+(indexOfColumn+1)); columnName = configuration.getDefaultColumnNamePattern().replace("$$", ""+(indexOfColumn+1));
} }
if(existingColumnNames.contains(columnName) && configuration.isGenerateUniqueColumnNames()){
columnName = generateUniqueName(columnName);
}
existingColumnNames.add(columnName);
return columnName; return columnName;
} }
public static boolean isAllowableColumnName(String proposedName){ private String generateUniqueName(String columnName) {
String newColumnName = columnName;
int loopCount = 2;
while(existingColumnNames.contains(newColumnName)){
String loopCountString = "_"+loopCount;
newColumnName = columnName.substring(0,Math.min(columnName.length(), configuration.getMaxIdentiferLength()-loopCountString.length()))+loopCountString;
loopCount++;
}
return newColumnName;
}
public boolean isAllowableColumnName(String proposedName){
// check null // check null
if (proposedName == null){ if (proposedName == null){
return false; return false;
} }
// check size limits // check size limits
if (proposedName.length() > maxIdentiferLength || proposedName.length()==0){ if (proposedName.length() > configuration.getMaxIdentiferLength() || proposedName.length()==0){
return false; return false;
} }
Matcher match = compiledRegularExpressionMatchAllowed.matcher(proposedName); Matcher match = configuration.getCompiledRegularExpressionMatchAllowed().matcher(proposedName);
if(!match.matches()){ if(!match.matches()){
return false; return false;
} }
return true; return true;
} }
private static String fixColumnName(String proposedName) { private String fixColumnName(String proposedName) {
Matcher match = compiledRegularExpressionMatchDisallowed.matcher(proposedName); Matcher match = configuration.getCompiledRegularExpressionMatchDisallowed().matcher(proposedName);
proposedName = match.replaceAll(""); proposedName = match.replaceAll("");
// check size limits - then truncate // check size limits - then truncate
if (proposedName.length() > maxIdentiferLength){ if (proposedName.length() > configuration.getMaxIdentiferLength()){
proposedName=proposedName.substring(0, maxIdentiferLength); proposedName=proposedName.substring(0, configuration.getMaxIdentiferLength());
} }
return proposedName; return proposedName;
} }
private static String unquoteString(String s){ public ColumnNamerConfiguration getConfiguration() {
if(s.startsWith("'") && s.endsWith("'")){ return configuration;
s = s.substring(1, s.length()-1);
return s;
}
return s;
} }
static int maxIdentiferLength = Integer.MAX_VALUE;
static String regularExpressionMatchAllowed = "(?m)(?s).+";
static String regularExpressionMatchDisallowed = "(?m)(?s)[\\x00]";
static String defaultColumnNamePattern = "_unnamed_column_$$_";
static Pattern compiledRegularExpressionMatchAllowed = Pattern.compile(regularExpressionMatchAllowed);
static Pattern compiledRegularExpressionMatchDisallowed = Pattern.compile(regularExpressionMatchDisallowed);
public static void configure(String stringValue) {
try{
if(stringValue.equalsIgnoreCase(DEFAULT_COMMAND)){
maxIdentiferLength = Integer.MAX_VALUE;
regularExpressionMatchAllowed = "(?m)(?s).+";
regularExpressionMatchDisallowed = "(?m)(?s)[\\x00]";
defaultColumnNamePattern = "_UNNAMED_$$";
} else if(stringValue.equalsIgnoreCase(EMULATE_COMMAND+"ORACLE128")){
maxIdentiferLength = 128;
regularExpressionMatchAllowed = "(?m)(?s)\"?[A-Za-z0-9_]+\"?";
regularExpressionMatchDisallowed = "(?m)(?s)[^A-Za-z0-9_\"]";
defaultColumnNamePattern = "_UNNAMED_$$";
} else if(stringValue.equalsIgnoreCase(EMULATE_COMMAND+"ORACLE30")){
maxIdentiferLength = 30;
regularExpressionMatchAllowed = "(?m)(?s)\"?[A-Za-z0-9_]+\"?";
regularExpressionMatchDisallowed = "(?m)(?s)[^A-Za-z0-9_\"]";
defaultColumnNamePattern = "_UNNAMED_$$";
}else if(stringValue.equalsIgnoreCase(EMULATE_COMMAND+"POSTGRES")){
maxIdentiferLength = 31;
regularExpressionMatchAllowed = "(?m)(?s)\"?[A-Za-z0-9_\"]+\"?";
regularExpressionMatchDisallowed = "(?m)(?s)[^A-Za-z0-9_\"]";
defaultColumnNamePattern = "_UNNAMED_$$";
} else if(stringValue.startsWith(MAX_IDENTIFIER_LENGTH)){
maxIdentiferLength = Math.max(0,Integer.parseInt(stringValue.substring(MAX_IDENTIFIER_LENGTH.length())));
} else if(stringValue.startsWith(DEFAULT_COLUMN_NAME_PATTERN)){
defaultColumnNamePattern =unquoteString(stringValue.substring(DEFAULT_COLUMN_NAME_PATTERN.length()));
} else if(stringValue.startsWith(REGULAR_EXPRESSION_MATCH_ALLOWED)){
regularExpressionMatchAllowed=unquoteString(stringValue.substring(REGULAR_EXPRESSION_MATCH_ALLOWED.length()));
} else if(stringValue.startsWith(REGULAR_EXPRESSION_MATCH_DISALLOWED)){
regularExpressionMatchDisallowed =unquoteString(stringValue.substring(REGULAR_EXPRESSION_MATCH_DISALLOWED.length()));
}
else
{
throw DbException.getInvalidValueException("SET COLUMN_NAME_RULES: unknown id:"+stringValue,
stringValue);
}
// recompile RE patterns
compiledRegularExpressionMatchAllowed = Pattern.compile(regularExpressionMatchAllowed);
compiledRegularExpressionMatchDisallowed = Pattern.compile(regularExpressionMatchDisallowed);
}
//Including NumberFormatException|PatternSyntaxException
catch(RuntimeException e){
throw DbException.getInvalidValueException("SET COLUMN_NAME_RULES:"+e.getMessage(),
stringValue);
}
}
} }
package org.h2.util;
import java.util.regex.Pattern;
import org.h2.message.DbException;
public class ColumnNamerConfiguration {
private static final String DEFAULT_COMMAND = "DEFAULT";
private static final String REGULAR_EXPRESSION_MATCH_DISALLOWED = "REGULAR_EXPRESSION_MATCH_DISALLOWED = ";
private static final String REGULAR_EXPRESSION_MATCH_ALLOWED = "REGULAR_EXPRESSION_MATCH_ALLOWED = ";
private static final String DEFAULT_COLUMN_NAME_PATTERN = "DEFAULT_COLUMN_NAME_PATTERN = ";
private static final String MAX_IDENTIFIER_LENGTH = "MAX_IDENTIFIER_LENGTH = ";
private static final String EMULATE_COMMAND = "EMULATE = ";
private static final String GENERATE_UNIQUE_COLUMN_NAMES = "GENERATE_UNIQUE_COLUMN_NAMES = ";
private int maxIdentiferLength;
private String regularExpressionMatchAllowed;
private String regularExpressionMatchDisallowed;
private String defaultColumnNamePattern;
private boolean generateUniqueColumnNames;
private Pattern compiledRegularExpressionMatchAllowed;
private Pattern compiledRegularExpressionMatchDisallowed;
public ColumnNamerConfiguration(int maxIdentiferLength, String regularExpressionMatchAllowed,
String regularExpressionMatchDisallowed, String defaultColumnNamePattern, boolean generateUniqueColumnNames) {
this.maxIdentiferLength = maxIdentiferLength;
this.regularExpressionMatchAllowed = regularExpressionMatchAllowed;
this.regularExpressionMatchDisallowed = regularExpressionMatchDisallowed;
this.defaultColumnNamePattern = defaultColumnNamePattern;
this.generateUniqueColumnNames = generateUniqueColumnNames;
compiledRegularExpressionMatchAllowed = Pattern.compile(regularExpressionMatchAllowed);
compiledRegularExpressionMatchDisallowed = Pattern.compile(regularExpressionMatchDisallowed);
}
public int getMaxIdentiferLength() {
return maxIdentiferLength;
}
public void setMaxIdentiferLength(int maxIdentiferLength) {
this.maxIdentiferLength = maxIdentiferLength;
}
public String getRegularExpressionMatchAllowed() {
return regularExpressionMatchAllowed;
}
public void setRegularExpressionMatchAllowed(String regularExpressionMatchAllowed) {
this.regularExpressionMatchAllowed = regularExpressionMatchAllowed;
}
public String getRegularExpressionMatchDisallowed() {
return regularExpressionMatchDisallowed;
}
public void setRegularExpressionMatchDisallowed(String regularExpressionMatchDisallowed) {
this.regularExpressionMatchDisallowed = regularExpressionMatchDisallowed;
}
public String getDefaultColumnNamePattern() {
return defaultColumnNamePattern;
}
public void setDefaultColumnNamePattern(String defaultColumnNamePattern) {
this.defaultColumnNamePattern = defaultColumnNamePattern;
}
public Pattern getCompiledRegularExpressionMatchAllowed() {
return compiledRegularExpressionMatchAllowed;
}
public void setCompiledRegularExpressionMatchAllowed(Pattern compiledRegularExpressionMatchAllowed) {
this.compiledRegularExpressionMatchAllowed = compiledRegularExpressionMatchAllowed;
}
public Pattern getCompiledRegularExpressionMatchDisallowed() {
return compiledRegularExpressionMatchDisallowed;
}
public void setCompiledRegularExpressionMatchDisallowed(Pattern compiledRegularExpressionMatchDisallowed) {
this.compiledRegularExpressionMatchDisallowed = compiledRegularExpressionMatchDisallowed;
}
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_$$");
} 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);
}
} 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)){
setDefaultColumnNamePattern(unquoteString(stringValue.substring(DEFAULT_COLUMN_NAME_PATTERN.length())));
} else if(stringValue.startsWith(REGULAR_EXPRESSION_MATCH_ALLOWED)){
setRegularExpressionMatchAllowed(unquoteString(stringValue.substring(REGULAR_EXPRESSION_MATCH_ALLOWED.length())));
} else if(stringValue.startsWith(REGULAR_EXPRESSION_MATCH_DISALLOWED)){
setRegularExpressionMatchDisallowed(unquoteString(stringValue.substring(REGULAR_EXPRESSION_MATCH_DISALLOWED.length())));
}
else
{
throw DbException.getInvalidValueException("SET COLUMN_NAME_RULES: unknown id:"+stringValue,
stringValue);
}
// recompile RE patterns
setCompiledRegularExpressionMatchAllowed(Pattern.compile(getRegularExpressionMatchAllowed()));
setCompiledRegularExpressionMatchDisallowed(Pattern.compile(getRegularExpressionMatchDisallowed()));
}
//Including NumberFormatException|PatternSyntaxException
catch(RuntimeException e){
throw DbException.getInvalidValueException("SET COLUMN_NAME_RULES:"+e.getMessage(),
stringValue);
}
}
public static ColumnNamerConfiguration getDefault(){
return new ColumnNamerConfiguration(Integer.MAX_VALUE, "(?m)(?s).+", "(?m)(?s)[\\x00]", "_unnamed_column_$$_",false);
}
private static String unquoteString(String s){
if(s.startsWith("'") && s.endsWith("'")){
s = s.substring(1, s.length()-1);
return s;
}
return s;
}
public boolean isGenerateUniqueColumnNames() {
return generateUniqueColumnNames;
}
public void setGenerateUniqueColumnNames(boolean generateUniqueColumnNames) {
this.generateUniqueColumnNames = generateUniqueColumnNames;
}
}
\ No newline at end of file
...@@ -230,6 +230,7 @@ import org.h2.test.utils.SelfDestructor; ...@@ -230,6 +230,7 @@ import org.h2.test.utils.SelfDestructor;
import org.h2.tools.DeleteDbFiles; import org.h2.tools.DeleteDbFiles;
import org.h2.tools.Server; import org.h2.tools.Server;
import org.h2.util.AbbaLockingDetector; import org.h2.util.AbbaLockingDetector;
import org.h2.util.TestColumnNamer;
import org.h2.util.New; import org.h2.util.New;
import org.h2.util.Profiler; import org.h2.util.Profiler;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
...@@ -782,6 +783,8 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1` ...@@ -782,6 +783,8 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
addTest(new TestViewDropView()); addTest(new TestViewDropView());
addTest(new TestReplace()); addTest(new TestReplace());
addTest(new TestSynonymForTable()); addTest(new TestSynonymForTable());
addTest(new TestColumnNamer());
// jaqu // jaqu
addTest(new AliasMapTest()); addTest(new AliasMapTest());
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
-- --
-- Try a custom column naming rules setup -- Try a custom column naming rules setup
SET COLUMN_NAME_RULES=MAX_IDENTIFIER_LENGTH = 10; SET COLUMN_NAME_RULES=MAX_IDENTIFIER_LENGTH = 30;
> ok > ok
SET COLUMN_NAME_RULES=REGULAR_EXPRESSION_MATCH_ALLOWED = '[A-Za-z0-9_]+'; SET COLUMN_NAME_RULES=REGULAR_EXPRESSION_MATCH_ALLOWED = '[A-Za-z0-9_]+';
...@@ -16,11 +16,14 @@ SET COLUMN_NAME_RULES=REGULAR_EXPRESSION_MATCH_DISALLOWED = '[^A-Za-z0-9_]+'; ...@@ -16,11 +16,14 @@ SET COLUMN_NAME_RULES=REGULAR_EXPRESSION_MATCH_DISALLOWED = '[^A-Za-z0-9_]+';
SET COLUMN_NAME_RULES=DEFAULT_COLUMN_NAME_PATTERN = 'noName$$'; SET COLUMN_NAME_RULES=DEFAULT_COLUMN_NAME_PATTERN = 'noName$$';
> ok > ok
SELECT 1 AS VERY_VERY_VERY_LONG_ID, SUM(X)+1 AS _123456789012345, SUM(X)+1 , SUM(X)+1 SET COLUMN_NAME_RULES=GENERATE_UNIQUE_COLUMN_NAMES = 1;
> ok
SELECT 1 AS VERY_VERY_VERY_LONG_ID_VERY_VERY_VERY_LONG_ID, SUM(X)+1 AS _123456789012345, SUM(X)+1 , SUM(X)+1
+47, 'x' , '!!!' , '!!!!' FROM SYSTEM_RANGE(1,2); +47, 'x' , '!!!' , '!!!!' FROM SYSTEM_RANGE(1,2);
> VERY_VERY_ _123456789 SUMX1 SUMX147 x noName6 noName7 > VERY_VERY_VERY_LONG_ID_VERY_VE _123456789012345 SUMX1 SUMX147 x noName6 noName7
> ---------- ---------- ----- ------- - ------- ------- > ------------------------------ ---------------- ----- ------- - ------- -------
> 1 4 4 51 x !!! !!!! > 1 4 4 51 x !!! !!!!
SET COLUMN_NAME_RULES=EMULATE=ORACLE128; SET COLUMN_NAME_RULES=EMULATE=ORACLE128;
> ok > ok
......
package org.h2.util;
import org.h2.expression.Expression;
import org.h2.expression.ValueExpression;
import org.h2.test.TestBase;
public class TestColumnNamer extends TestBase {
private String[] ids = new String[]{
"ABC"
,"123"
,"a\n2"
,"a$c%d#e@f!."
,null
,"VERYVERYVERYVERYVERYVERYLONGVERYVERYVERYVERYVERYVERYLONGVERYVERYVERYVERYVERYVERYLONG"
,"'!!!'"
,"'!!!!'"
,"3.1415"
,"\r"
,"col1"
,"col1"
,"col1"
,"col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2"
,"col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2col2"
};
private String[] expectedColumnName= {"ABC"
,"123"
,"a2"
,"acdef"
,"colName6"
,"VERYVERYVERYVERYVERYVERYLONGVE"
,"colName8"
,"colName9"
,"31415"
,"colName11"
,"col1"
,"col1_2"
,"col1_3"
,"col2col2col2col2col2col2col2co"
,"col2col2col2col2col2col2col2_2"};
public static void main(String[] args){
new TestColumnNamer().test();
}
public void test() {
ColumnNamer columnNamer = new ColumnNamer(null);
columnNamer.getConfiguration().configure("MAX_IDENTIFIER_LENGTH = 30");
columnNamer.getConfiguration().configure("REGULAR_EXPRESSION_MATCH_ALLOWED = '[A-Za-z0-9_]+'");
columnNamer.getConfiguration().configure("REGULAR_EXPRESSION_MATCH_DISALLOWED = '[^A-Za-z0-9_]+'");
columnNamer.getConfiguration().configure("DEFAULT_COLUMN_NAME_PATTERN = 'colName$$'");
columnNamer.getConfiguration().configure("GENERATE_UNIQUE_COLUMN_NAMES = 1");
int index =0;
for(String id : ids){
Expression columnExp = ValueExpression.getDefault();
String newColumnName = columnNamer.getColumnName(columnExp , index+1, id);
assertTrue(newColumnName!=null);
assertTrue(newColumnName.length()<=30);
assertTrue(newColumnName.length()>=1);
assertEquals(newColumnName,expectedColumnName[index]);
index++;
}
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论