提交 56e947ef authored 作者: Thomas Mueller's avatar Thomas Mueller

Linked tables now support default values.

上级 218b14f3
......@@ -96,15 +96,7 @@ public class Update extends Prepared {
newValue = oldRow.getValue(i);
} else if (newExpr == ValueExpression.getDefault()) {
Column column = table.getColumn(i);
Expression defaultExpr = column.getDefaultExpression();
Value v;
if (defaultExpr == null) {
v = column.validateConvertUpdateSequence(session, null);
} else {
v = defaultExpr.getValue(session);
}
int type = column.getType();
newValue = v.convertTo(type);
newValue = table.getDefaultValue(session, column);
} else {
Column column = table.getColumn(i);
newValue = newExpr.getValue(session).convertTo(column.getType());
......
......@@ -55,8 +55,10 @@ public class LinkedIndex extends BaseIndex {
buff.append(targetTableName).append(" VALUES(");
for (int i = 0; i < row.getColumnCount(); i++) {
Value v = row.getValue(i);
buff.appendExceptFirst(",");
if (isNull(v)) {
buff.appendExceptFirst(", ");
if (v == null) {
buff.append("DEFAULT");
} else if (isNull(v)) {
buff.append("NULL");
} else {
buff.append('?');
......@@ -221,7 +223,13 @@ public class LinkedIndex extends BaseIndex {
buff.append(targetTableName).append(" SET ");
for (int i = 0; i < newRow.getColumnCount(); i++) {
buff.appendExceptFirst(", ");
buff.append(table.getColumn(i).getSQL()).append("=?");
buff.append(table.getColumn(i).getSQL()).append('=');
Value v = newRow.getValue(i);
if (v == null) {
buff.append("DEFAULT");
} else {
buff.append('?');
}
}
buff.append(" WHERE ");
buff.resetCount();
......@@ -243,9 +251,12 @@ public class LinkedIndex extends BaseIndex {
int j = 1;
PreparedStatement prep = link.getPreparedStatement(sql, false);
for (int i = 0; i < newRow.getColumnCount(); i++) {
newRow.getValue(i).set(prep, j);
Value v = newRow.getValue(i);
if (v != null) {
v.set(prep, j);
j++;
}
}
for (int i = 0; i < oldRow.getColumnCount(); i++) {
Value v = oldRow.getValue(i);
if (!isNull(v)) {
......
......@@ -62,6 +62,10 @@ public class RowList {
buff.writeInt(r.getStorageId());
for (int i = 0; i < r.getColumnCount(); i++) {
Value v = r.getValue(i);
if (v == null) {
buff.writeByte((byte) 0);
} else {
buff.writeByte((byte) 1);
if (v.getType() == Value.CLOB || v.getType() == Value.BLOB) {
// need to keep a reference to temporary lobs,
// otherwise the temp file is deleted
......@@ -82,6 +86,7 @@ public class RowList {
buff.writeValue(v);
}
}
}
private void writeAllRows() throws SQLException {
if (file == null) {
......@@ -180,7 +185,11 @@ public class RowList {
int storageId = buff.readInt();
Value[] values = new Value[columnCount];
for (int i = 0; i < columnCount; i++) {
Value v = buff.readValue();
Value v;
if (buff.readByte() == 0) {
v = null;
} else {
v = buff.readValue();
if (v.isLinked()) {
ValueLob lob = (ValueLob) v;
// the table id is 0 if it was linked when writing
......@@ -189,6 +198,7 @@ public class RowList {
session.unlinkAtCommit(lob);
}
}
}
values[i] = v;
}
if (key != 0 && cache != null) {
......
......@@ -18,6 +18,7 @@ import org.h2.engine.Constants;
import org.h2.engine.DbObject;
import org.h2.engine.Right;
import org.h2.engine.Session;
import org.h2.expression.Expression;
import org.h2.expression.ExpressionVisitor;
import org.h2.index.Index;
import org.h2.index.IndexType;
......@@ -936,4 +937,23 @@ public abstract class Table extends SchemaObjectBase {
return compareMode;
}
/**
* Get or generate a default value for the given column.
*
* @param session the session
* @param column the column
* @return the value
*/
public Value getDefaultValue(Session session, Column column) throws SQLException {
Expression defaultExpr = column.getDefaultExpression();
Value v;
if (defaultExpr == null) {
v = column.validateConvertUpdateSequence(session, null);
} else {
v = defaultExpr.getValue(session);
}
int type = column.getType();
return v.convertTo(type);
}
}
......@@ -33,6 +33,7 @@ import org.h2.util.New;
import org.h2.util.ObjectArray;
import org.h2.util.StringUtils;
import org.h2.value.DataType;
import org.h2.value.Value;
import org.h2.value.ValueDate;
import org.h2.value.ValueTime;
import org.h2.value.ValueTimestamp;
......@@ -542,4 +543,37 @@ public class TableLink extends Table {
return false;
}
/**
* Convert the values if required. Default values are not set (kept as
* null).
*
* @param session the session
* @param row the row
*/
public void validateConvertUpdateSequence(Session session, Row row) throws SQLException {
for (int i = 0; i < columns.length; i++) {
Value value = row.getValue(i);
if (value != null) {
// null means use the default value
Column column = columns[i];
Value v2 = column.validateConvertUpdateSequence(session, value);
if (v2 != value) {
row.setValue(i, v2);
}
}
}
}
/**
* Get or generate a default value for the given column. Default values are
* not set (kept as null).
*
* @param session the session
* @param column the column
* @return the value
*/
public Value getDefaultValue(Session session, Column column) {
return null;
}
}
......@@ -33,6 +33,7 @@ public class TestLinkedTable extends TestBase {
}
public void test() throws SQLException {
testDefaultValues();
testHiddenSQL();
// testLinkAutoAdd();
testNestedQueriesToSameTable();
......@@ -50,6 +51,47 @@ public class TestLinkedTable extends TestBase {
deleteDb("linkedTable");
}
private void testDefaultValues() throws SQLException {
if (config.memory) {
return;
}
deleteDb("linkedTable");
Connection connMain = DriverManager.getConnection("jdbc:h2:mem:linkedTable");
Statement statMain = connMain.createStatement();
statMain.execute("create table test(id identity, name varchar default 'test')");
Connection conn = getConnection("linkedTable");
Statement stat = conn.createStatement();
stat.execute("create linked table test1('', 'jdbc:h2:mem:linkedTable', '', '', 'TEST') emit updates");
stat.execute("create linked table test2('', 'jdbc:h2:mem:linkedTable', '', '', 'TEST')");
stat.execute("insert into test1 values(default, default)");
stat.execute("insert into test2 values(default, default)");
stat.execute("merge into test2 values(3, default)");
stat.execute("update test1 set name=default where id=1");
stat.execute("update test2 set name=default where id=2");
ResultSet rs = statMain.executeQuery("select * from test order by id");
rs.next();
assertEquals(1, rs.getInt(1));
assertEquals("test", rs.getString(2));
rs.next();
assertEquals(2, rs.getInt(1));
assertEquals("test", rs.getString(2));
rs.next();
assertEquals(3, rs.getInt(1));
assertEquals("test", rs.getString(2));
assertFalse(rs.next());
stat.execute("delete from test1 where id=1");
stat.execute("delete from test2 where id=2");
stat.execute("delete from test2 where id=3");
conn.close();
rs = statMain.executeQuery("select * from test order by id");
assertFalse(rs.next());
connMain.close();
}
private void testHiddenSQL() throws SQLException {
if (config.memory || !SysProperties.SHARE_LINKED_CONNECTIONS) {
return;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论