Merge lp:~tjoneslo/akiban-server/fix-bug-1168503 into lp:~akiban-technologies/akiban-server/trunk

Proposed by Thomas Jones-Low
Status: Merged
Approved by: Nathan Williams
Approved revision: 2627
Merged at revision: 2627
Proposed branch: lp:~tjoneslo/akiban-server/fix-bug-1168503
Merge into: lp:~akiban-technologies/akiban-server/trunk
Diff against target: 173 lines (+128/-8)
3 files modified
src/main/java/com/akiban/qp/rowtype/UserTableRowChecker.java (+0/-8)
src/test/java/com/akiban/qp/rowtype/UserTableRowCheckerTest.java (+120/-0)
src/test/resources/com/akiban/sql/pg/yaml/bugs/test-bug-1168503.yaml (+8/-0)
To merge this branch: bzr merge lp:~tjoneslo/akiban-server/fix-bug-1168503
Reviewer Review Type Date Requested Status
Nathan Williams Approve
Review via email: mp+159272@code.launchpad.net

Description of the change

Fix bug 1168503 - The code that tests the NULL constraint (UserTableRowChecker) was excluding the identity columns from the null check. This was an old assumption that the identity sequence processing would be performed below the insert_returning and update_returning (e.g. in the PerstititStore#writeRow). In the current processing the identity column is done above the insert/update operators. So by the time the identity column gets to the insert/update operator, the value has already been populated from the sequence.

Add two levels of testing to verify the bug is fixed.

To post a comment you must log in.
Revision history for this message
Nathan Williams (nwilliams) wrote :

Allowing NULL on INSERT but not on UPDATE is a little funny but not horrible. That can be rectified if/when we support DEFAULT.

So good by me.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/main/java/com/akiban/qp/rowtype/UserTableRowChecker.java'
2--- src/main/java/com/akiban/qp/rowtype/UserTableRowChecker.java 2013-03-22 20:05:57 +0000
3+++ src/main/java/com/akiban/qp/rowtype/UserTableRowChecker.java 2013-04-17 01:13:34 +0000
4@@ -32,11 +32,6 @@
5 {
6 for (int f = 0; f < fields; f++) {
7 if (notNull.get(f) && isNull(row, f, usePValues)) {
8- // if this column is an identity column, null is allowed
9- //
10- if (f == identityColumn) {
11- continue;
12- }
13 TableName tableName = table.getName();
14 throw new NotNullViolationException(tableName.getSchemaName(),
15 tableName.getTableName(),
16@@ -57,7 +52,6 @@
17 fields = rowType.nFields();
18 table = rowType.userTable();
19 notNull = table.notNull();
20- identityColumn = table.getIdentityColumn() != null ? table.getIdentityColumn().getPosition().intValue() : -1;
21 }
22
23 public UserTableRowChecker(UserTable userTable)
24@@ -65,10 +59,8 @@
25 fields = userTable.getColumnsIncludingInternal().size();
26 table = userTable;
27 notNull = table.notNull();
28- identityColumn = table.getIdentityColumn() != null ? table.getIdentityColumn().getPosition().intValue() : -1;
29 }
30
31- private final int identityColumn;
32 private final int fields;
33 private final UserTable table;
34 private final BitSet notNull;
35
36=== added file 'src/test/java/com/akiban/qp/rowtype/UserTableRowCheckerTest.java'
37--- src/test/java/com/akiban/qp/rowtype/UserTableRowCheckerTest.java 1970-01-01 00:00:00 +0000
38+++ src/test/java/com/akiban/qp/rowtype/UserTableRowCheckerTest.java 2013-04-17 01:13:34 +0000
39@@ -0,0 +1,120 @@
40+/**
41+ * Copyright (C) 2009-2013 Akiban Technologies, Inc.
42+ *
43+ * This program is free software: you can redistribute it and/or modify
44+ * it under the terms of the GNU Affero General Public License as published by
45+ * the Free Software Foundation, either version 3 of the License, or
46+ * (at your option) any later version.
47+ *
48+ * This program is distributed in the hope that it will be useful,
49+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
50+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51+ * GNU Affero General Public License for more details.
52+ *
53+ * You should have received a copy of the GNU Affero General Public License
54+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
55+ */
56+
57+package com.akiban.qp.rowtype;
58+
59+import org.junit.Test;
60+
61+import com.akiban.ais.model.AISBuilder;
62+import com.akiban.ais.model.Index;
63+import com.akiban.ais.model.UserTable;
64+import com.akiban.qp.row.PValuesRow;
65+import com.akiban.server.rowdata.SchemaFactory;
66+import com.akiban.server.types3.pvalue.PValue;
67+import com.akiban.server.error.NotNullViolationException;
68+
69+public class UserTableRowCheckerTest {
70+
71+ @Test (expected = NotNullViolationException.class)
72+ public void idCheckNull () {
73+ Schema schema = caoiSchema();
74+ UserTable customer = schema.ais().getUserTable("schema", "customer");
75+ PValue col1 = new PValue(customer.getColumn(0).tInstance());
76+ col1.putNull();
77+
78+ PValue col2 = new PValue(customer.getColumn(1).tInstance());
79+ col2.putString("Test Value", null);
80+
81+ PValuesRow row = new PValuesRow (schema.userTableRowType(customer), col1, col2);
82+
83+ UserTableRowChecker checker = new UserTableRowChecker (customer);
84+ checker.checkConstraints(row, true);
85+ }
86+
87+ @Test (expected = NotNullViolationException.class)
88+ public void nameCheckNull () {
89+ Schema schema = caoiSchema();
90+ UserTable customer = schema.ais().getUserTable("schema", "customer");
91+ PValue col1 = new PValue(customer.getColumn(0).tInstance());
92+ col1.putInt32(1);
93+
94+ PValue col2 = new PValue(customer.getColumn(1).tInstance());
95+ col2.putNull();
96+
97+ PValuesRow row = new PValuesRow (schema.userTableRowType(customer), col1, col2);
98+
99+ UserTableRowChecker checker = new UserTableRowChecker (customer);
100+ checker.checkConstraints(row, true);
101+ }
102+
103+
104+ private Schema caoiSchema() {
105+ AISBuilder builder = new AISBuilder();
106+ builder.userTable("schema", "customer");
107+
108+ builder.sequence("schema", "customer_id", 0, 1, 0, 1000, true);
109+ builder.column("schema", "customer", "customer_id", 0, "int", 0L, 0L, false, false, null, null);
110+ builder.columnAsIdentity("schema", "customer", "customer_id", "customer_id", true);
111+
112+
113+ builder.column("schema", "customer", "customer_name", 1, "varchar", 64L, 0L, false, false, null, null);
114+ builder.index("schema", "customer", Index.PRIMARY_KEY_CONSTRAINT, true, Index.PRIMARY_KEY_CONSTRAINT);
115+ builder.indexColumn("schema", "customer", Index.PRIMARY_KEY_CONSTRAINT, "customer_id", 0, true, null);
116+ builder.userTable("schema", "order");
117+ builder.column("schema", "order", "order_id", 0, "int", 0L, 0L, false, false, null, null);
118+ builder.sequence("schema", "order_id", 0, 1, 0, 1000, false);
119+ builder.columnAsIdentity("schema", "order", "order_id", "order_id", true);
120+
121+ builder.column("schema", "order", "customer_id", 1, "int", 0L, 0L, false, false, null, null);
122+ builder.column("schema", "order", "order_date", 2, "int", 0L, 0L, false, false, null, null);
123+ builder.index("schema", "order", Index.PRIMARY_KEY_CONSTRAINT, true, Index.PRIMARY_KEY_CONSTRAINT);
124+ builder.indexColumn("schema", "order", Index.PRIMARY_KEY_CONSTRAINT, "order_id", 0, true, null);
125+ builder.userTable("schema", "item");
126+ builder.column("schema", "item", "item_id", 0, "int", 0L, 0L, false, false, null, null);
127+ builder.column("schema", "item", "order_id", 1, "int", 0L, 0L, false, false, null, null);
128+ builder.column("schema", "item", "quantity", 2, "int", 0L, 0L, false, false, null, null);
129+ builder.index("schema", "item", Index.PRIMARY_KEY_CONSTRAINT, true, Index.PRIMARY_KEY_CONSTRAINT);
130+ builder.indexColumn("schema", "item", Index.PRIMARY_KEY_CONSTRAINT, "item_id", 0, true, null);
131+ builder.joinTables("co", "schema", "customer", "schema", "order");
132+ builder.joinColumns("co", "schema", "customer", "customer_id", "schema", "order", "customer_id");
133+ builder.joinTables("oi", "schema", "order", "schema", "item");
134+ builder.joinColumns("oi", "schema", "order", "order_id", "schema", "item", "item_id");
135+ builder.userTable("schema", "state");
136+ builder.column("schema", "state", "code", 0, "varchar", 2L, 0L, false, false, null, null);
137+ builder.column("schema", "state", "name", 1, "varchar", 50L, 0L, false, false, null, null);
138+ builder.userTable("schema", "address");
139+ builder.column("schema", "address", "customer_id", 0, "int", 0L, 0L, false, false, null, null);
140+ builder.column("schema", "address", "location", 1, "varchar", 50L, 0L, false, false, null, null);
141+ builder.column("schema", "address", "zipcode", 2, "int", 0L, 0L, false, false, null, null);
142+ builder.joinTables("ca", "schema", "customer", "schema", "address");
143+ builder.joinColumns("ca", "schema", "customer", "customer_id", "schema", "address", "customer_id");
144+
145+ builder.basicSchemaIsComplete();
146+ builder.createGroup("group", "groupschema");
147+ builder.addJoinToGroup("group", "co", 0);
148+ builder.addJoinToGroup("group", "oi", 0);
149+ builder.addJoinToGroup("group", "ca", 0);
150+ builder.createGroup("state", "schema");
151+ builder.addTableToGroup("state", "schema", "state");
152+ builder.groupingIsComplete();
153+
154+ SchemaFactory factory = new SchemaFactory ("schema");
155+ factory.buildRowDefs(builder.akibanInformationSchema());
156+ return new Schema(builder.akibanInformationSchema());
157+ }
158+
159+}
160
161=== added file 'src/test/resources/com/akiban/sql/pg/yaml/bugs/test-bug-1168503.yaml'
162--- src/test/resources/com/akiban/sql/pg/yaml/bugs/test-bug-1168503.yaml 1970-01-01 00:00:00 +0000
163+++ src/test/resources/com/akiban/sql/pg/yaml/bugs/test-bug-1168503.yaml 2013-04-17 01:13:34 +0000
164@@ -0,0 +1,8 @@
165+---
166+- CreateTable: t (id INT NOT NULL PRIMARY KEY, x INT NOT NULL GENERATED BY DEFAULT AS IDENTITY);
167+---
168+- Statement: INSERT INTO t VALUES (1,NULL),(2,NULL);
169+---
170+- Statement: UPDATE t SET x=NULL WHERE id=2;
171+- error: [23502]
172+...
173\ No newline at end of file

Subscribers

People subscribed via source and target branches