提交 7844e2b0 authored 作者: Vakhurin Sergey's avatar Vakhurin Sergey

fix recursive queries: infer column data types

上级 076e7531
......@@ -4746,6 +4746,7 @@ public class Parser {
recursiveTable = schema.createTable(data);
session.addLocalTempTable(recursiveTable);
String querySQL;
Column[] columnTemplates = new Column[cols.length];
try {
read("AS");
read("(");
......@@ -4753,12 +4754,16 @@ public class Parser {
read(")");
withQuery.prepare();
querySQL = StringUtils.fromCacheOrNew(withQuery.getPlanSQL());
ArrayList<Expression> withExpressions = withQuery.getExpressions();
for (int i = 0; i < cols.length; ++i) {
columnTemplates[i] = new Column(cols[i], withExpressions.get(i).getType());
}
} finally {
session.removeLocalTempTable(recursiveTable);
}
int id = database.allocateObjectId();
TableView view = new TableView(schema, id, tempViewName, querySQL,
parameters, cols, session, true);
parameters, columnTemplates, session, true);
view.setTableExpression(true);
view.setTemporary(true);
session.addLocalTempTable(view);
......
......@@ -16,8 +16,10 @@ import org.h2.engine.Session;
import org.h2.expression.Parameter;
import org.h2.message.DbException;
import org.h2.schema.Schema;
import org.h2.table.Column;
import org.h2.table.Table;
import org.h2.table.TableView;
import org.h2.value.Value;
/**
* This class represents the statement
......@@ -104,8 +106,15 @@ public class CreateView extends SchemaCommand {
if (view == null) {
Schema schema = session.getDatabase().getSchema(session.getCurrentSchemaName());
sysSession.setCurrentSchema(schema);
Column[] columnTemplates = null;
if (columnNames != null) {
columnTemplates = new Column[columnNames.length];
for (int i = 0; i < columnNames.length; ++i) {
columnTemplates[i] = new Column(columnNames[i], Value.UNKNOWN);
}
}
view = new TableView(getSchema(), id, viewName, querySQL, null,
columnNames, sysSession, false);
columnTemplates, sysSession, false);
} else {
view.replace(querySQL, columnNames, sysSession, false, force);
view.setModified();
......
......@@ -95,7 +95,7 @@ public class Column {
int displaySize) {
this.name = name;
this.type = type;
if (precision == -1 && scale == -1 && displaySize == -1) {
if (precision == -1 && scale == -1 && displaySize == -1 && type != Value.UNKNOWN) {
DataType dt = DataType.getDataType(type);
precision = dt.defaultPrecision;
scale = dt.defaultScale;
......
......@@ -46,7 +46,7 @@ public class TableView extends Table {
private String querySQL;
private ArrayList<Table> tables;
private String[] columnNames;
private Column[] columnTemplates;
private Query viewQuery;
private ViewIndex index;
private boolean recursive;
......@@ -59,10 +59,10 @@ public class TableView extends Table {
private boolean tableExpression;
public TableView(Schema schema, int id, String name, String querySQL,
ArrayList<Parameter> params, String[] columnNames, Session session,
ArrayList<Parameter> params, Column[] columnTemplates, Session session,
boolean recursive) {
super(schema, id, name, false, true);
init(querySQL, params, columnNames, session, recursive);
init(querySQL, params, columnTemplates, session, recursive);
}
/**
......@@ -78,21 +78,21 @@ public class TableView extends Table {
public void replace(String querySQL, String[] columnNames, Session session,
boolean recursive, boolean force) {
String oldQuerySQL = this.querySQL;
String[] oldColumnNames = this.columnNames;
Column[] oldColumnTemplates = this.columnTemplates;
boolean oldRecursive = this.recursive;
init(querySQL, null, columnNames, session, recursive);
init(querySQL, null, columnTemplates, session, recursive);
DbException e = recompile(session, force, true);
if (e != null) {
init(oldQuerySQL, null, oldColumnNames, session, oldRecursive);
init(oldQuerySQL, null, oldColumnTemplates, session, oldRecursive);
recompile(session, true, false);
throw e;
}
}
private synchronized void init(String querySQL, ArrayList<Parameter> params,
String[] columnNames, Session session, boolean recursive) {
Column[] columnTemplates, Session session, boolean recursive) {
this.querySQL = querySQL;
this.columnNames = columnNames;
this.columnTemplates = columnTemplates;
this.recursive = recursive;
index = new ViewIndex(this, querySQL, params, recursive);
initColumnsAndTables(session);
......@@ -161,13 +161,17 @@ public class TableView extends Table {
for (int i = 0, count = query.getColumnCount(); i < count; i++) {
Expression expr = expressions.get(i);
String name = null;
if (columnNames != null && columnNames.length > i) {
name = columnNames[i];
int type = Value.UNKNOWN;
if (columnTemplates != null && columnTemplates.length > i) {
name = columnTemplates[i].getName();
type = columnTemplates[i].getType();
}
if (name == null) {
name = expr.getAlias();
}
int type = expr.getType();
if (type == Value.UNKNOWN) {
type = expr.getType();
}
long precision = expr.getPrecision();
int scale = expr.getScale();
int displaySize = expr.getDisplaySize();
......@@ -204,10 +208,10 @@ public class TableView extends Table {
// database
tables = New.arrayList();
cols = new Column[0];
if (recursive && columnNames != null) {
cols = new Column[columnNames.length];
for (int i = 0; i < columnNames.length; i++) {
cols[i] = new Column(columnNames[i], Value.STRING);
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;
......@@ -319,11 +323,11 @@ public class TableView extends Table {
buff.append(c.getSQL());
}
buff.append(')');
} else if (columnNames != null) {
} else if (columnTemplates != null) {
buff.append('(');
for (String n : columnNames) {
for (Column c : columnTemplates) {
buff.appendExceptFirst(", ");
buff.append(n);
buff.append(c.getName());
}
buff.append(')');
}
......
......@@ -9,6 +9,7 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.Types;
import org.h2.test.TestBase;
/**
......@@ -138,6 +139,14 @@ public class TestRecursiveQueries extends TestBase {
rs = prep.executeQuery();
assertResultSetOrdered(rs, new String[][]{{"100"}, {"103"}});
rs = stat.executeQuery("with recursive t(i, s, d) as "
+ "(select 1, '.', now() union all"
+ " select i+1, s||'.', d from t where i<3)"
+ " select * from t");
assertResultSetMeta(rs, 3, new String[]{ "I", "S", "D" },
new int[]{ Types.INTEGER, Types.VARCHAR, Types.TIMESTAMP },
null, null);
conn.close();
deleteDb("recursiveQueries");
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论