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

fix recursive queries: infer column data types

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