![JAR search and dependency download from the Maven repository](/logo.png)
org.h2.table.TableView Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of h2 Show documentation
Show all versions of h2 Show documentation
魔改版h2,主要针对sql的自定义重写。 原h2项目地址https://github.com/h2database/h2database
The newest version!
/*
* Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.table;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import org.h2.api.ErrorCode;
import org.h2.command.Prepared;
import org.h2.command.dml.Query;
import org.h2.engine.Constants;
import org.h2.engine.Database;
import org.h2.engine.DbObject;
import org.h2.engine.Session;
import org.h2.engine.User;
import org.h2.expression.Alias;
import org.h2.expression.Expression;
import org.h2.expression.ExpressionColumn;
import org.h2.expression.ExpressionVisitor;
import org.h2.expression.Parameter;
import org.h2.index.Index;
import org.h2.index.IndexType;
import org.h2.index.ViewIndex;
import org.h2.message.DbException;
import org.h2.result.LocalResult;
import org.h2.result.Row;
import org.h2.result.SortOrder;
import org.h2.schema.Schema;
import org.h2.util.New;
import org.h2.util.StatementBuilder;
import org.h2.util.StringUtils;
import org.h2.value.Value;
/**
* A view is a virtual table that is defined by a query.
* @author Thomas Mueller
* @author Nicolas Fortin, Atelier SIG, IRSTV FR CNRS 24888
*/
public class TableView extends Table {
private static final long ROW_COUNT_APPROXIMATION = 100;
private String querySQL;
private ArrayList tables;
private Column[] columnTemplates;
private Query viewQuery;
private ViewIndex index;
private boolean recursive;
private DbException createException;
private long lastModificationCheck;
private long maxDataModificationId;
private User owner;
private Query topQuery;
private LocalResult recursiveResult;
private boolean tableExpression;
public TableView(Schema schema, int id, String name, String querySQL,
ArrayList params, Column[] columnTemplates, Session session,
boolean recursive) {
super(schema, id, name, false, true);
init(querySQL, params, columnTemplates, session, recursive);
}
/**
* Try to replace the SQL statement of the view and re-compile this and all
* dependent views.
*
* @param querySQL the SQL statement
* @param columnNames the column names
* @param session the session
* @param recursive whether this is a recursive view
* @param force if errors should be ignored
*/
public void replace(String querySQL, String[] columnNames, Session session,
boolean recursive, boolean force) {
String oldQuerySQL = this.querySQL;
Column[] oldColumnTemplates = this.columnTemplates;
boolean oldRecursive = this.recursive;
init(querySQL, null, columnTemplates, session, recursive);
DbException e = recompile(session, force, true);
if (e != null) {
init(oldQuerySQL, null, oldColumnTemplates, session, oldRecursive);
recompile(session, true, false);
throw e;
}
}
private synchronized void init(String querySQL, ArrayList params,
Column[] columnTemplates, Session session, boolean recursive) {
this.querySQL = querySQL;
this.columnTemplates = columnTemplates;
this.recursive = recursive;
index = new ViewIndex(this, querySQL, params, recursive);
initColumnsAndTables(session);
}
private static Query compileViewQuery(Session session, String sql) {
Prepared p;
session.setParsingView(true);
try {
p = session.prepare(sql);
} finally {
session.setParsingView(false);
}
if (!(p instanceof Query)) {
throw DbException.getSyntaxError(sql, 0);
}
return (Query) p;
}
/**
* Re-compile the view query and all views that depend on this object.
*
* @param session the session
* @param force if exceptions should be ignored
* @param clearIndexCache if we need to clear view index cache
* @return the exception if re-compiling this or any dependent view failed
* (only when force is disabled)
*/
public synchronized DbException recompile(Session session, boolean force,
boolean clearIndexCache) {
try {
compileViewQuery(session, querySQL);
} catch (DbException e) {
if (!force) {
return e;
}
}
ArrayList views = getViews();
if (views != null) {
views = New.arrayList(views);
}
initColumnsAndTables(session);
if (views != null) {
for (TableView v : views) {
DbException e = v.recompile(session, force, false);
if (e != null && !force) {
return e;
}
}
}
if (clearIndexCache) {
clearIndexCaches(database);
}
return force ? null : createException;
}
private void initColumnsAndTables(Session session) {
Column[] cols;
removeViewFromTables();
try {
Query query = compileViewQuery(session, querySQL);
this.querySQL = query.getPlanSQL();
tables = New.arrayList(query.getTables());
ArrayList expressions = query.getExpressions();
ArrayList list = New.arrayList();
for (int i = 0, count = query.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();
}
if (type == Value.UNKNOWN) {
type = expr.getType();
}
long precision = expr.getPrecision();
int scale = expr.getScale();
int displaySize = expr.getDisplaySize();
Column col = new Column(name, type, precision, scale, displaySize);
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 = new Column[list.size()];
list.toArray(cols);
createException = null;
viewQuery = query;
} catch (DbException e) {
e.addSQL(getCreateSQL());
createException = e;
// if it can't be compiled, then it's a 'zero column table'
// this avoids problems when creating the view when opening the
// database
tables = New.arrayList();
cols = new Column[0];
if (recursive && 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) {
addViewToTables();
}
}
@Override
public boolean isView() {
return true;
}
/**
* Check if this view is currently invalid.
*
* @return true if it is
*/
public boolean isInvalid() {
return createException != null;
}
@Override
public PlanItem getBestPlanItem(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet allColumnsSet) {
final CacheKey cacheKey = new CacheKey(masks, this);
Map