use of org.h2.util.ColumnNamer in project h2database by h2database.
the class Select method prepare.
@Override
public void prepare() {
if (isPrepared) {
// sometimes a subquery is prepared twice (CREATE TABLE AS SELECT)
return;
}
if (SysProperties.CHECK && !checkInit) {
DbException.throwInternalError("not initialized");
}
if (orderList != null) {
sort = prepareOrder(orderList, expressions.size());
orderList = null;
}
ColumnNamer columnNamer = new ColumnNamer(session);
for (int i = 0; i < expressions.size(); i++) {
Expression e = expressions.get(i);
String proposedColumnName = 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);
}
expressions.set(i, e.optimize(session));
}
if (condition != null) {
condition = condition.optimize(session);
for (TableFilter f : filters) {
// left outer join child on p = pc where c is null;
if (!f.isJoinOuter() && !f.isJoinOuterIndirect()) {
condition.createIndexConditions(session, f);
}
}
}
if (isGroupQuery && groupIndex == null && havingIndex < 0 && filters.size() == 1) {
if (condition == null) {
Table t = filters.get(0).getTable();
ExpressionVisitor optimizable = ExpressionVisitor.getOptimizableVisitor(t);
isQuickAggregateQuery = isEverything(optimizable);
}
}
cost = preparePlan(session.isParsingCreateView());
if (distinct && session.getDatabase().getSettings().optimizeDistinct && !isGroupQuery && filters.size() == 1 && expressions.size() == 1 && condition == null) {
Expression expr = expressions.get(0);
expr = expr.getNonAliasExpression();
if (expr instanceof ExpressionColumn) {
Column column = ((ExpressionColumn) expr).getColumn();
int selectivity = column.getSelectivity();
Index columnIndex = topTableFilter.getTable().getIndexForColumn(column, false, true);
if (columnIndex != null && selectivity != Constants.SELECTIVITY_DEFAULT && selectivity < 20) {
// the first column must be ascending
boolean ascending = columnIndex.getIndexColumns()[0].sortType == SortOrder.ASCENDING;
Index current = topTableFilter.getIndex();
// if another index is faster
if (columnIndex.canFindNext() && ascending && (current == null || current.getIndexType().isScan() || columnIndex == current)) {
IndexType type = columnIndex.getIndexType();
// indexes don't work
if (!type.isHash() && (!type.isUnique() || columnIndex.getColumns().length > 1)) {
topTableFilter.setIndex(columnIndex);
isDistinctQuery = true;
}
}
}
}
}
if (sort != null && !isQuickAggregateQuery && !isGroupQuery) {
Index index = getSortIndex();
Index current = topTableFilter.getIndex();
if (index != null && current != null) {
if (current.getIndexType().isScan() || current == index) {
topTableFilter.setIndex(index);
if (!topTableFilter.hasInComparisons()) {
// in(select ...) and in(1,2,3) may return the key in
// another order
sortUsingIndex = true;
}
} else if (index.getIndexColumns() != null && index.getIndexColumns().length >= current.getIndexColumns().length) {
IndexColumn[] sortColumns = index.getIndexColumns();
IndexColumn[] currentColumns = current.getIndexColumns();
boolean swapIndex = false;
for (int i = 0; i < currentColumns.length; i++) {
if (sortColumns[i].column != currentColumns[i].column) {
swapIndex = false;
break;
}
if (sortColumns[i].sortType != currentColumns[i].sortType) {
swapIndex = true;
}
}
if (swapIndex) {
topTableFilter.setIndex(index);
sortUsingIndex = true;
}
}
}
}
if (!isQuickAggregateQuery && isGroupQuery && getGroupByExpressionCount() > 0) {
Index index = getGroupSortedIndex();
Index current = topTableFilter.getIndex();
if (index != null && current != null && (current.getIndexType().isScan() || current == index)) {
topTableFilter.setIndex(index);
isGroupSortedQuery = true;
}
}
expressionArray = expressions.toArray(new Expression[0]);
isPrepared = true;
}
use of org.h2.util.ColumnNamer in project h2database by h2database.
the class TableView method createQueryColumnTemplateList.
/**
* Creates a list of column templates from a query (usually from WITH query,
* but could be any query)
*
* @param cols - an optional list of column names (can be specified by WITH
* clause overriding usual select names)
* @param theQuery - the query object we want the column list for
* @param querySQLOutput - array of length 1 to receive extra 'output' field
* in addition to return value - containing the SQL query of the
* Query object
* @return a list of column object returned by withQuery
*/
public static List<Column> createQueryColumnTemplateList(String[] cols, Query theQuery, String[] querySQLOutput) {
List<Column> columnTemplateList = new ArrayList<>();
theQuery.prepare();
// String array of length 1 is to receive extra 'output' field in addition to
// return value
querySQLOutput[0] = StringUtils.cache(theQuery.getPlanSQL());
ColumnNamer columnNamer = new ColumnNamer(theQuery.getSession());
ArrayList<Expression> withExpressions = theQuery.getExpressions();
for (int i = 0; i < withExpressions.size(); ++i) {
Expression columnExp = withExpressions.get(i);
// use the passed in column name if supplied, otherwise use alias
// (if found) otherwise use column name derived from column
// expression
String columnName = columnNamer.getColumnName(columnExp, i, cols);
columnTemplateList.add(new Column(columnName, columnExp.getType()));
}
return columnTemplateList;
}
use of org.h2.util.ColumnNamer in project h2database by h2database.
the class TableView method initColumnsAndTables.
private void initColumnsAndTables(Session session, boolean literalsChecked) {
Column[] cols;
removeCurrentViewFromOtherTables();
setTableExpression(isTableExpression);
try {
Query compiledQuery = compileViewQuery(session, querySQL, literalsChecked, getName());
this.querySQL = compiledQuery.getPlanSQL();
tables = new ArrayList<>(compiledQuery.getTables());
ArrayList<Expression> expressions = compiledQuery.getExpressions();
ArrayList<Column> list = New.arrayList();
ColumnNamer columnNamer = new ColumnNamer(session);
for (int i = 0, count = compiledQuery.getColumnCount(); i < count; i++) {
Expression expr = expressions.get(i);
String name = null;
int type = Value.UNKNOWN;
if (columnTemplates != null && columnTemplates.length > i) {
name = columnTemplates[i].getName();
type = columnTemplates[i].getType();
}
if (name == null) {
name = expr.getAlias();
}
name = columnNamer.getColumnName(expr, i, name);
if (type == Value.UNKNOWN) {
type = expr.getType();
}
long precision = expr.getPrecision();
int scale = expr.getScale();
int displaySize = expr.getDisplaySize();
String[] enumerators = null;
if (type == Value.ENUM) {
if (expr instanceof ExpressionColumn) {
enumerators = ((ExpressionColumn) expr).getColumn().getEnumerators();
}
}
Column col = new Column(name, type, precision, scale, displaySize, enumerators);
col.setTable(this, i);
// Fetch check constraint from view column source
ExpressionColumn fromColumn = null;
if (expr instanceof ExpressionColumn) {
fromColumn = (ExpressionColumn) expr;
} else if (expr instanceof Alias) {
Expression aliasExpr = expr.getNonAliasExpression();
if (aliasExpr instanceof ExpressionColumn) {
fromColumn = (ExpressionColumn) aliasExpr;
}
}
if (fromColumn != null) {
Expression checkExpression = fromColumn.getColumn().getCheckConstraint(session, name);
if (checkExpression != null) {
col.addCheckConstraint(session, checkExpression);
}
}
list.add(col);
}
cols = list.toArray(new Column[0]);
createException = null;
viewQuery = compiledQuery;
} catch (DbException e) {
e.addSQL(getCreateSQL());
createException = e;
// table expression query.
if (isRecursiveQueryExceptionDetected(createException)) {
this.isRecursiveQueryDetected = true;
}
tables = New.arrayList();
cols = new Column[0];
if (allowRecursive && columnTemplates != null) {
cols = new Column[columnTemplates.length];
for (int i = 0; i < columnTemplates.length; i++) {
cols[i] = columnTemplates[i].getClone();
}
index.setRecursive(true);
createException = null;
}
}
setColumns(cols);
if (getId() != 0) {
addDependentViewToTables();
}
}
use of org.h2.util.ColumnNamer in project h2database by h2database.
the class SelectUnion method prepare.
@Override
public void prepare() {
if (isPrepared) {
// sometimes a subquery is prepared twice (CREATE TABLE AS SELECT)
return;
}
if (SysProperties.CHECK && !checkInit) {
DbException.throwInternalError("not initialized");
}
isPrepared = true;
left.prepare();
right.prepare();
int len = left.getColumnCount();
// set the correct expressions now
expressions = New.arrayList();
ArrayList<Expression> le = left.getExpressions();
ArrayList<Expression> re = right.getExpressions();
ColumnNamer columnNamer = new ColumnNamer(session);
for (int i = 0; i < len; i++) {
Expression l = le.get(i);
Expression r = re.get(i);
int type = Value.getHigherOrder(l.getType(), r.getType());
long prec = Math.max(l.getPrecision(), r.getPrecision());
int scale = Math.max(l.getScale(), r.getScale());
int displaySize = Math.max(l.getDisplaySize(), r.getDisplaySize());
String columnName = columnNamer.getColumnName(l, i, l.getAlias());
Column col = new Column(columnName, type, prec, scale, displaySize);
Expression e = new ExpressionColumn(session.getDatabase(), col);
expressions.add(e);
}
if (orderList != null) {
initOrder(session, expressions, null, orderList, getColumnCount(), true, null);
sort = prepareOrder(orderList, expressions.size());
orderList = null;
}
expressionArray = expressions.toArray(new Expression[0]);
}
use of org.h2.util.ColumnNamer in project h2database by h2database.
the class CreateTable method generateColumnsFromQuery.
private void generateColumnsFromQuery() {
int columnCount = asQuery.getColumnCount();
ArrayList<Expression> expressions = asQuery.getExpressions();
ColumnNamer columnNamer = new ColumnNamer(session);
for (int i = 0; i < columnCount; i++) {
Expression expr = expressions.get(i);
int type = expr.getType();
String name = columnNamer.getColumnName(expr, i, expr.getAlias());
long precision = expr.getPrecision();
int displaySize = expr.getDisplaySize();
DataType dt = DataType.getDataType(type);
if (precision > 0 && (dt.defaultPrecision == 0 || (dt.defaultPrecision > precision && dt.defaultPrecision < Byte.MAX_VALUE))) {
// dont' set precision to MAX_VALUE if this is the default
precision = dt.defaultPrecision;
}
int scale = expr.getScale();
if (scale > 0 && (dt.defaultScale == 0 || (dt.defaultScale > scale && dt.defaultScale < precision))) {
scale = dt.defaultScale;
}
if (scale > precision) {
precision = scale;
}
String[] enumerators = null;
if (dt.type == Value.ENUM) {
/**
* Only columns of tables may be enumerated.
*/
if (!(expr instanceof ExpressionColumn)) {
throw DbException.get(ErrorCode.GENERAL_ERROR_1, "Unable to resolve enumerators of expression");
}
enumerators = ((ExpressionColumn) expr).getColumn().getEnumerators();
}
Column col = new Column(name, type, precision, scale, displaySize, enumerators);
addColumn(col);
}
}
Aggregations