Merge lp:~tjoneslo/akiban-server/json-entity-name-collision-resolution into lp:~akiban-technologies/akiban-server/trunk

Proposed by Thomas Jones-Low
Status: Merged
Approved by: Nathan Williams
Approved revision: 2610
Merged at revision: 2608
Proposed branch: lp:~tjoneslo/akiban-server/json-entity-name-collision-resolution
Merge into: lp:~akiban-technologies/akiban-server/trunk
Diff against target: 255 lines (+135/-26)
4 files modified
src/main/java/com/akiban/ais/model/AISMerge.java (+1/-0)
src/main/java/com/akiban/ais/model/UserTable.java (+41/-10)
src/main/java/com/akiban/server/service/externaldata/TableRowTracker.java (+1/-16)
src/test/java/com/akiban/ais/model/AISBuilderTest.java (+92/-0)
To merge this branch: bzr merge lp:~tjoneslo/akiban-server/json-entity-name-collision-resolution
Reviewer Review Type Date Requested Status
Thomas Jones-Low Approve
Nathan Williams Needs Fixing
Review via email: mp+156724@code.launchpad.net

Description of the change

Address potential name collision between fields and collections (Tables) in the JSON output. When the AISBuilder completes the process of building an AIS, the UserTable@endTable() is called. This in turn builds a unique name for the table in the group wrt the fields.

AISMerge#doAddIndexMerge() - Add call to builder#groupingIsComplete() to get the tables to generate their cached unique name.

UserTable@endTable() - generate the group unique name for the table (and child tables).

TableRowTracker - Update the tracker to use the UserTable unique name, rather than generating it on the fly.

AISBuilderTest - add tests for the UserTable name generate.

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

Looks pretty good.

I think we can skip the "is same schema" logic. That was really working around the collapsed namespace issue, which this branch does explicitly.

Since they must be unused, can you delete the commented out members on UserTable?

review: Needs Fixing
Revision history for this message
Thomas Jones-Low (tjoneslo) wrote :

Remove dead code from UserTable.

review: Needs Resubmitting
Revision history for this message
Nathan Williams (nwilliams) wrote :

Thanks for the tweak!

Looks like the isSameSchema helper is commented out. Delete that and then feel free to big-A.

review: Needs Fixing
Revision history for this message
Thomas Jones-Low (tjoneslo) wrote :

Remove the newly dead code, before it becomes zombie code.

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/ais/model/AISMerge.java'
2--- src/main/java/com/akiban/ais/model/AISMerge.java 2013-03-22 20:05:57 +0000
3+++ src/main/java/com/akiban/ais/model/AISMerge.java 2013-04-03 15:22:24 +0000
4@@ -483,6 +483,7 @@
5
6 private void doAddIndexMerge() {
7 AISBuilder builder = new AISBuilder(targetAIS, nameGenerator);
8+ builder.groupingIsComplete();
9 builder.akibanInformationSchema().validate(AISValidations.LIVE_AIS_VALIDATIONS).throwIfNecessary();
10 builder.akibanInformationSchema().freeze();
11 }
12
13=== modified file 'src/main/java/com/akiban/ais/model/UserTable.java'
14--- src/main/java/com/akiban/ais/model/UserTable.java 2013-03-22 20:05:57 +0000
15+++ src/main/java/com/akiban/ais/model/UserTable.java 2013-04-03 15:22:24 +0000
16@@ -354,6 +354,44 @@
17 assert primaryKeyIndex != null : this;
18 primaryKey = new PrimaryKey(primaryKeyIndex);
19 }
20+
21+ // Put the columns into our list
22+ TreeSet<String> entities = new TreeSet<String>();
23+ for (Column column : getColumns()) {
24+ entities.add(column.getName());
25+ }
26+
27+ // put the child tables into their ordered list.
28+ TreeMap<String, UserTable> childTables = new TreeMap<String, UserTable>();
29+ for (Join childJoin : candidateChildJoins ) {
30+ String childName;
31+ if (childJoin.getChild().getName().getSchemaName().equals(getName().getSchemaName())) {
32+ childName = childJoin.getChild().getName().getTableName();
33+ } else {
34+ childName = childJoin.getChild().getName().toString();
35+ }
36+ childTables.put(childName, childJoin.getChild());
37+ }
38+
39+ // Mangle the child table names to be unique with the "_"
40+ for (String child : childTables.keySet()) {
41+ String tryName = child;
42+ while (entities.contains(tryName)) {
43+ tryName = "_" + tryName;
44+ }
45+ childTables.get(child).nameForOutput = tryName;
46+ entities.add(tryName);
47+ }
48+
49+ if (nameForOutput == null) {
50+ Join parentJoin = getParentJoin();
51+ if ((parentJoin != null) &&
52+ parentJoin.getParent().getName().getSchemaName().equals(getName().getSchemaName())) {
53+ nameForOutput = getName().getTableName();
54+ } else {
55+ nameForOutput = getName().toString();
56+ }
57+ }
58 }
59
60 public Integer getDepth()
61@@ -483,14 +521,8 @@
62 this.version = version;
63 }
64
65- public boolean isSchemaNameSameAsParent() {
66- Join parentJoin = getParentJoin();
67- return (parentJoin != null) &&
68- parentJoin.getParent().getName().getSchemaName().equals(getName().getSchemaName());
69- }
70-
71 public String getNameForOutput() {
72- return isSchemaNameSameAsParent() ? getName().getTableName() : getName().toString();
73+ return nameForOutput;
74 }
75
76 private void addTableAndDescendents(UserTable table, List<UserTable> accumulator)
77@@ -619,17 +651,16 @@
78 private PrimaryKey primaryKey;
79 private HKey hKey;
80 private boolean containsOwnHKey;
81- private HKey branchHKey;
82 private List<Column> allHKeyColumns;
83 private Integer depth = null;
84 private volatile List<UserTable> hKeyDependentTables;
85- private volatile List<UserTable> ancestors;
86 private MemoryTableFactory tableFactory;
87 private Integer version;
88 private PendingOSC pendingOSC;
89 private final Collection<FullTextIndex> fullTextIndexes;
90 private final Collection<FullTextIndex> unmodifiableFullTextIndexes;
91-
92+ private String nameForOutput;
93+
94 // consts
95
96 private static final Comparator<Column> COLUMNS_BY_TABLE_DEPTH = new Comparator<Column>() {
97
98=== modified file 'src/main/java/com/akiban/server/service/externaldata/TableRowTracker.java'
99--- src/main/java/com/akiban/server/service/externaldata/TableRowTracker.java 2013-03-25 23:55:33 +0000
100+++ src/main/java/com/akiban/server/service/externaldata/TableRowTracker.java 2013-04-03 15:22:24 +0000
101@@ -22,9 +22,6 @@
102 import com.akiban.qp.row.Row;
103 import com.akiban.qp.rowtype.RowType;
104
105-import java.util.HashSet;
106-import java.util.Set;
107-
108 public class TableRowTracker implements RowTracker {
109 private final int minDepth;
110 private final int maxDepth;
111@@ -34,13 +31,8 @@
112 // rows, discarding any that are not.
113 private final RowType[] openTypes;
114
115- // Tracks child tables where the schema name does not match the parent.
116- // Will almost always be empty, so use null as empty.
117- private Set<UserTable> tablesNeedingFullName = null;
118-
119 private RowType curRowType;
120 private UserTable curTable;
121- private boolean curNeedsFullName;
122
123 public TableRowTracker(UserTable table, int addlDepth) {
124 minDepth = table.getDepth();
125@@ -50,12 +42,6 @@
126 @Override
127 public void visitUserTable(UserTable userTable) {
128 max[0] = Math.max(max[0], userTable.getDepth());
129- if(!userTable.isSchemaNameSameAsParent()) {
130- if(tablesNeedingFullName == null) {
131- tablesNeedingFullName = new HashSet<>();
132- }
133- tablesNeedingFullName.add(userTable);
134- }
135 }
136 });
137 }
138@@ -87,7 +73,6 @@
139 assert row.rowType().hasUserTable() : "Invalid row type for TableRowTracker";
140 curRowType = row.rowType();
141 curTable = curRowType.userTable();
142- curNeedsFullName = (tablesNeedingFullName != null) && tablesNeedingFullName.contains(curTable);
143 }
144
145 @Override
146@@ -97,7 +82,7 @@
147
148 @Override
149 public String getRowName() {
150- return curNeedsFullName ? curTable.getName().toString() : curTable.getName().getTableName();
151+ return curTable.getNameForOutput();
152 }
153
154 @Override
155
156=== modified file 'src/test/java/com/akiban/ais/model/AISBuilderTest.java'
157--- src/test/java/com/akiban/ais/model/AISBuilderTest.java 2013-03-22 20:05:57 +0000
158+++ src/test/java/com/akiban/ais/model/AISBuilderTest.java 2013-04-03 15:22:24 +0000
159@@ -1235,4 +1235,96 @@
160 AISValidationFailure fail = vResults.failures().iterator().next();
161 Assert.assertEquals(ErrorCode.SEQUENCE_MIN_GE_MAX, fail.errorCode());
162 }
163+
164+ private AISBuilder twoChildGroup () {
165+ final AISBuilder builder = new AISBuilder();
166+ builder.userTable("test", "c");
167+ builder.column("test", "c", "id", 0, "int", 0L, 0L, false, false, null, null);
168+ builder.column("test", "c", "name", 1, "varchar", 64L, 0L, false, false, null, null);
169+ builder.index("test", "c", Index.PRIMARY_KEY_CONSTRAINT, true, Index.PRIMARY_KEY_CONSTRAINT);
170+ builder.indexColumn("test", "c", Index.PRIMARY_KEY_CONSTRAINT, "id", 0, true, null);
171+ builder.userTable("test", "o");
172+ builder.column("test", "o", "oid", 0, "int", 0L, 0L, false, false, null, null);
173+ builder.column("test", "o", "cid", 1, "int", 0L, 0L, false, false, null, null);
174+ builder.column("test", "o", "date", 2, "int", 0L, 0L, false, false, null, null);
175+ builder.joinTables("c/id/o/cid", "test", "c", "test", "o");
176+ builder.joinColumns("c/id/o/cid", "test", "c", "id", "test", "o", "cid");
177+ builder.basicSchemaIsComplete();
178+ TableName groupName = TableName.create("test", "coi");
179+ builder.createGroup(groupName.getTableName(), groupName.getSchemaName());
180+ builder.addJoinToGroup(groupName, "c/id/o/cid", 1);
181+ builder.addTableToGroup(groupName, "test", "c");
182+ builder.addTableToGroup(groupName, "test", "o");
183+
184+ return builder;
185+
186+ }
187+
188+ @Test
189+ public void validateNameForOutputSimple() {
190+ AISBuilder builder = twoChildGroup();
191+
192+ builder.groupingIsComplete();
193+ UserTable c = builder.akibanInformationSchema().getUserTable("test", "c");
194+ UserTable o = builder.akibanInformationSchema().getUserTable("test", "o");
195+
196+ Assert.assertEquals("test.c", c.getNameForOutput());
197+ Assert.assertEquals("o", o.getNameForOutput());
198+ }
199+
200+ @Test
201+ public void validateNameForOutputCase1() {
202+ AISBuilder builder = twoChildGroup();
203+ builder.column("test", "c", "o", 2, "int", 0L, 0L, false, false, null, null);
204+ builder.groupingIsComplete();
205+ UserTable c = builder.akibanInformationSchema().getUserTable("test", "c");
206+ UserTable o = builder.akibanInformationSchema().getUserTable("test", "o");
207+
208+ Assert.assertEquals("test.c", c.getNameForOutput());
209+ Assert.assertEquals("_o", o.getNameForOutput());
210+ }
211+
212+ @Test
213+ public void validateNameForOutputCase2() {
214+ AISBuilder builder = twoChildGroup();
215+ builder.userTable("test", "_o");
216+ builder.column("test", "_o", "oid", 0, "int", 0L, 0L, false, false, null, null);
217+ builder.column("test", "_o", "cid", 1, "int", 0L, 0L, false, false, null, null);
218+ builder.column("test", "_o", "date", 2, "int", 0L, 0L, false, false, null, null);
219+ builder.joinTables("c/id/_o/cid", "test", "c", "test", "_o");
220+ builder.joinColumns("c/id/_o/cid", "test", "c", "id", "test", "_o", "cid");
221+ TableName groupName = TableName.create("test", "coi");
222+ builder.addJoinToGroup(groupName, "c/id/_o/cid", 1);
223+ builder.addTableToGroup(groupName, "test", "_o");
224+
225+ builder.groupingIsComplete();
226+ UserTable o = builder.akibanInformationSchema().getUserTable("test", "o");
227+ UserTable _o = builder.akibanInformationSchema().getUserTable("test", "_o");
228+
229+ Assert.assertEquals("o", o.getNameForOutput());
230+ Assert.assertEquals("_o", _o.getNameForOutput());
231+ }
232+
233+ @Test
234+ public void validateNameForOutputCase3() {
235+ AISBuilder builder = twoChildGroup();
236+ builder.column("test", "c", "o", 2, "int", 0L, 0L, false, false, null, null);
237+ builder.userTable("test", "_o");
238+ builder.column("test", "_o", "oid", 0, "int", 0L, 0L, false, false, null, null);
239+ builder.column("test", "_o", "cid", 1, "int", 0L, 0L, false, false, null, null);
240+ builder.column("test", "_o", "date", 2, "int", 0L, 0L, false, false, null, null);
241+ builder.joinTables("c/id/_o/cid", "test", "c", "test", "_o");
242+ builder.joinColumns("c/id/_o/cid", "test", "c", "id", "test", "_o", "cid");
243+ TableName groupName = TableName.create("test", "coi");
244+ builder.addJoinToGroup(groupName, "c/id/_o/cid", 1);
245+ builder.addTableToGroup(groupName, "test", "_o");
246+
247+ builder.groupingIsComplete();
248+ UserTable o = builder.akibanInformationSchema().getUserTable("test", "o");
249+ UserTable _o = builder.akibanInformationSchema().getUserTable("test", "_o");
250+
251+ Assert.assertEquals("__o", o.getNameForOutput());
252+ Assert.assertEquals("_o", _o.getNameForOutput());
253+ }
254+
255 }

Subscribers

People subscribed via source and target branches