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
=== modified file 'src/main/java/com/akiban/ais/model/AISMerge.java'
--- src/main/java/com/akiban/ais/model/AISMerge.java 2013-03-22 20:05:57 +0000
+++ src/main/java/com/akiban/ais/model/AISMerge.java 2013-04-03 15:22:24 +0000
@@ -483,6 +483,7 @@
483483
484 private void doAddIndexMerge() {484 private void doAddIndexMerge() {
485 AISBuilder builder = new AISBuilder(targetAIS, nameGenerator);485 AISBuilder builder = new AISBuilder(targetAIS, nameGenerator);
486 builder.groupingIsComplete();
486 builder.akibanInformationSchema().validate(AISValidations.LIVE_AIS_VALIDATIONS).throwIfNecessary();487 builder.akibanInformationSchema().validate(AISValidations.LIVE_AIS_VALIDATIONS).throwIfNecessary();
487 builder.akibanInformationSchema().freeze();488 builder.akibanInformationSchema().freeze();
488 }489 }
489490
=== modified file 'src/main/java/com/akiban/ais/model/UserTable.java'
--- src/main/java/com/akiban/ais/model/UserTable.java 2013-03-22 20:05:57 +0000
+++ src/main/java/com/akiban/ais/model/UserTable.java 2013-04-03 15:22:24 +0000
@@ -354,6 +354,44 @@
354 assert primaryKeyIndex != null : this;354 assert primaryKeyIndex != null : this;
355 primaryKey = new PrimaryKey(primaryKeyIndex);355 primaryKey = new PrimaryKey(primaryKeyIndex);
356 }356 }
357
358 // Put the columns into our list
359 TreeSet<String> entities = new TreeSet<String>();
360 for (Column column : getColumns()) {
361 entities.add(column.getName());
362 }
363
364 // put the child tables into their ordered list.
365 TreeMap<String, UserTable> childTables = new TreeMap<String, UserTable>();
366 for (Join childJoin : candidateChildJoins ) {
367 String childName;
368 if (childJoin.getChild().getName().getSchemaName().equals(getName().getSchemaName())) {
369 childName = childJoin.getChild().getName().getTableName();
370 } else {
371 childName = childJoin.getChild().getName().toString();
372 }
373 childTables.put(childName, childJoin.getChild());
374 }
375
376 // Mangle the child table names to be unique with the "_"
377 for (String child : childTables.keySet()) {
378 String tryName = child;
379 while (entities.contains(tryName)) {
380 tryName = "_" + tryName;
381 }
382 childTables.get(child).nameForOutput = tryName;
383 entities.add(tryName);
384 }
385
386 if (nameForOutput == null) {
387 Join parentJoin = getParentJoin();
388 if ((parentJoin != null) &&
389 parentJoin.getParent().getName().getSchemaName().equals(getName().getSchemaName())) {
390 nameForOutput = getName().getTableName();
391 } else {
392 nameForOutput = getName().toString();
393 }
394 }
357 }395 }
358396
359 public Integer getDepth()397 public Integer getDepth()
@@ -483,14 +521,8 @@
483 this.version = version;521 this.version = version;
484 }522 }
485523
486 public boolean isSchemaNameSameAsParent() {
487 Join parentJoin = getParentJoin();
488 return (parentJoin != null) &&
489 parentJoin.getParent().getName().getSchemaName().equals(getName().getSchemaName());
490 }
491
492 public String getNameForOutput() {524 public String getNameForOutput() {
493 return isSchemaNameSameAsParent() ? getName().getTableName() : getName().toString();525 return nameForOutput;
494 }526 }
495 527
496 private void addTableAndDescendents(UserTable table, List<UserTable> accumulator)528 private void addTableAndDescendents(UserTable table, List<UserTable> accumulator)
@@ -619,17 +651,16 @@
619 private PrimaryKey primaryKey;651 private PrimaryKey primaryKey;
620 private HKey hKey;652 private HKey hKey;
621 private boolean containsOwnHKey;653 private boolean containsOwnHKey;
622 private HKey branchHKey;
623 private List<Column> allHKeyColumns;654 private List<Column> allHKeyColumns;
624 private Integer depth = null;655 private Integer depth = null;
625 private volatile List<UserTable> hKeyDependentTables;656 private volatile List<UserTable> hKeyDependentTables;
626 private volatile List<UserTable> ancestors;
627 private MemoryTableFactory tableFactory;657 private MemoryTableFactory tableFactory;
628 private Integer version;658 private Integer version;
629 private PendingOSC pendingOSC;659 private PendingOSC pendingOSC;
630 private final Collection<FullTextIndex> fullTextIndexes;660 private final Collection<FullTextIndex> fullTextIndexes;
631 private final Collection<FullTextIndex> unmodifiableFullTextIndexes;661 private final Collection<FullTextIndex> unmodifiableFullTextIndexes;
632662 private String nameForOutput;
663
633 // consts664 // consts
634665
635 private static final Comparator<Column> COLUMNS_BY_TABLE_DEPTH = new Comparator<Column>() {666 private static final Comparator<Column> COLUMNS_BY_TABLE_DEPTH = new Comparator<Column>() {
636667
=== modified file 'src/main/java/com/akiban/server/service/externaldata/TableRowTracker.java'
--- src/main/java/com/akiban/server/service/externaldata/TableRowTracker.java 2013-03-25 23:55:33 +0000
+++ src/main/java/com/akiban/server/service/externaldata/TableRowTracker.java 2013-04-03 15:22:24 +0000
@@ -22,9 +22,6 @@
22import com.akiban.qp.row.Row;22import com.akiban.qp.row.Row;
23import com.akiban.qp.rowtype.RowType;23import com.akiban.qp.rowtype.RowType;
2424
25import java.util.HashSet;
26import java.util.Set;
27
28public class TableRowTracker implements RowTracker {25public class TableRowTracker implements RowTracker {
29 private final int minDepth;26 private final int minDepth;
30 private final int maxDepth;27 private final int maxDepth;
@@ -34,13 +31,8 @@
34 // rows, discarding any that are not.31 // rows, discarding any that are not.
35 private final RowType[] openTypes;32 private final RowType[] openTypes;
3633
37 // Tracks child tables where the schema name does not match the parent.
38 // Will almost always be empty, so use null as empty.
39 private Set<UserTable> tablesNeedingFullName = null;
40
41 private RowType curRowType;34 private RowType curRowType;
42 private UserTable curTable;35 private UserTable curTable;
43 private boolean curNeedsFullName;
4436
45 public TableRowTracker(UserTable table, int addlDepth) {37 public TableRowTracker(UserTable table, int addlDepth) {
46 minDepth = table.getDepth();38 minDepth = table.getDepth();
@@ -50,12 +42,6 @@
50 @Override42 @Override
51 public void visitUserTable(UserTable userTable) {43 public void visitUserTable(UserTable userTable) {
52 max[0] = Math.max(max[0], userTable.getDepth());44 max[0] = Math.max(max[0], userTable.getDepth());
53 if(!userTable.isSchemaNameSameAsParent()) {
54 if(tablesNeedingFullName == null) {
55 tablesNeedingFullName = new HashSet<>();
56 }
57 tablesNeedingFullName.add(userTable);
58 }
59 }45 }
60 });46 });
61 }47 }
@@ -87,7 +73,6 @@
87 assert row.rowType().hasUserTable() : "Invalid row type for TableRowTracker";73 assert row.rowType().hasUserTable() : "Invalid row type for TableRowTracker";
88 curRowType = row.rowType();74 curRowType = row.rowType();
89 curTable = curRowType.userTable();75 curTable = curRowType.userTable();
90 curNeedsFullName = (tablesNeedingFullName != null) && tablesNeedingFullName.contains(curTable);
91 }76 }
9277
93 @Override78 @Override
@@ -97,7 +82,7 @@
9782
98 @Override83 @Override
99 public String getRowName() {84 public String getRowName() {
100 return curNeedsFullName ? curTable.getName().toString() : curTable.getName().getTableName();85 return curTable.getNameForOutput();
101 }86 }
10287
103 @Override88 @Override
10489
=== modified file 'src/test/java/com/akiban/ais/model/AISBuilderTest.java'
--- src/test/java/com/akiban/ais/model/AISBuilderTest.java 2013-03-22 20:05:57 +0000
+++ src/test/java/com/akiban/ais/model/AISBuilderTest.java 2013-04-03 15:22:24 +0000
@@ -1235,4 +1235,96 @@
1235 AISValidationFailure fail = vResults.failures().iterator().next();1235 AISValidationFailure fail = vResults.failures().iterator().next();
1236 Assert.assertEquals(ErrorCode.SEQUENCE_MIN_GE_MAX, fail.errorCode());1236 Assert.assertEquals(ErrorCode.SEQUENCE_MIN_GE_MAX, fail.errorCode());
1237 }1237 }
1238
1239 private AISBuilder twoChildGroup () {
1240 final AISBuilder builder = new AISBuilder();
1241 builder.userTable("test", "c");
1242 builder.column("test", "c", "id", 0, "int", 0L, 0L, false, false, null, null);
1243 builder.column("test", "c", "name", 1, "varchar", 64L, 0L, false, false, null, null);
1244 builder.index("test", "c", Index.PRIMARY_KEY_CONSTRAINT, true, Index.PRIMARY_KEY_CONSTRAINT);
1245 builder.indexColumn("test", "c", Index.PRIMARY_KEY_CONSTRAINT, "id", 0, true, null);
1246 builder.userTable("test", "o");
1247 builder.column("test", "o", "oid", 0, "int", 0L, 0L, false, false, null, null);
1248 builder.column("test", "o", "cid", 1, "int", 0L, 0L, false, false, null, null);
1249 builder.column("test", "o", "date", 2, "int", 0L, 0L, false, false, null, null);
1250 builder.joinTables("c/id/o/cid", "test", "c", "test", "o");
1251 builder.joinColumns("c/id/o/cid", "test", "c", "id", "test", "o", "cid");
1252 builder.basicSchemaIsComplete();
1253 TableName groupName = TableName.create("test", "coi");
1254 builder.createGroup(groupName.getTableName(), groupName.getSchemaName());
1255 builder.addJoinToGroup(groupName, "c/id/o/cid", 1);
1256 builder.addTableToGroup(groupName, "test", "c");
1257 builder.addTableToGroup(groupName, "test", "o");
1258
1259 return builder;
1260
1261 }
1262
1263 @Test
1264 public void validateNameForOutputSimple() {
1265 AISBuilder builder = twoChildGroup();
1266
1267 builder.groupingIsComplete();
1268 UserTable c = builder.akibanInformationSchema().getUserTable("test", "c");
1269 UserTable o = builder.akibanInformationSchema().getUserTable("test", "o");
1270
1271 Assert.assertEquals("test.c", c.getNameForOutput());
1272 Assert.assertEquals("o", o.getNameForOutput());
1273 }
1274
1275 @Test
1276 public void validateNameForOutputCase1() {
1277 AISBuilder builder = twoChildGroup();
1278 builder.column("test", "c", "o", 2, "int", 0L, 0L, false, false, null, null);
1279 builder.groupingIsComplete();
1280 UserTable c = builder.akibanInformationSchema().getUserTable("test", "c");
1281 UserTable o = builder.akibanInformationSchema().getUserTable("test", "o");
1282
1283 Assert.assertEquals("test.c", c.getNameForOutput());
1284 Assert.assertEquals("_o", o.getNameForOutput());
1285 }
1286
1287 @Test
1288 public void validateNameForOutputCase2() {
1289 AISBuilder builder = twoChildGroup();
1290 builder.userTable("test", "_o");
1291 builder.column("test", "_o", "oid", 0, "int", 0L, 0L, false, false, null, null);
1292 builder.column("test", "_o", "cid", 1, "int", 0L, 0L, false, false, null, null);
1293 builder.column("test", "_o", "date", 2, "int", 0L, 0L, false, false, null, null);
1294 builder.joinTables("c/id/_o/cid", "test", "c", "test", "_o");
1295 builder.joinColumns("c/id/_o/cid", "test", "c", "id", "test", "_o", "cid");
1296 TableName groupName = TableName.create("test", "coi");
1297 builder.addJoinToGroup(groupName, "c/id/_o/cid", 1);
1298 builder.addTableToGroup(groupName, "test", "_o");
1299
1300 builder.groupingIsComplete();
1301 UserTable o = builder.akibanInformationSchema().getUserTable("test", "o");
1302 UserTable _o = builder.akibanInformationSchema().getUserTable("test", "_o");
1303
1304 Assert.assertEquals("o", o.getNameForOutput());
1305 Assert.assertEquals("_o", _o.getNameForOutput());
1306 }
1307
1308 @Test
1309 public void validateNameForOutputCase3() {
1310 AISBuilder builder = twoChildGroup();
1311 builder.column("test", "c", "o", 2, "int", 0L, 0L, false, false, null, null);
1312 builder.userTable("test", "_o");
1313 builder.column("test", "_o", "oid", 0, "int", 0L, 0L, false, false, null, null);
1314 builder.column("test", "_o", "cid", 1, "int", 0L, 0L, false, false, null, null);
1315 builder.column("test", "_o", "date", 2, "int", 0L, 0L, false, false, null, null);
1316 builder.joinTables("c/id/_o/cid", "test", "c", "test", "_o");
1317 builder.joinColumns("c/id/_o/cid", "test", "c", "id", "test", "_o", "cid");
1318 TableName groupName = TableName.create("test", "coi");
1319 builder.addJoinToGroup(groupName, "c/id/_o/cid", 1);
1320 builder.addTableToGroup(groupName, "test", "_o");
1321
1322 builder.groupingIsComplete();
1323 UserTable o = builder.akibanInformationSchema().getUserTable("test", "o");
1324 UserTable _o = builder.akibanInformationSchema().getUserTable("test", "_o");
1325
1326 Assert.assertEquals("__o", o.getNameForOutput());
1327 Assert.assertEquals("_o", _o.getNameForOutput());
1328 }
1329
1238}1330}

Subscribers

People subscribed via source and target branches