Merge lp:~nwilliams/akiban-server/alter-generated into lp:~akiban-technologies/akiban-server/trunk

Proposed by Nathan Williams
Status: Merged
Approved by: Mike McMahon
Approved revision: 2628
Merged at revision: 2624
Proposed branch: lp:~nwilliams/akiban-server/alter-generated
Merge into: lp:~akiban-technologies/akiban-server/trunk
Diff against target: 1014 lines (+399/-106)
20 files modified
src/main/java/com/akiban/ais/model/AISBuilder.java (+3/-3)
src/main/java/com/akiban/ais/model/AISMerge.java (+61/-22)
src/main/java/com/akiban/ais/model/AkibanInformationSchema.java (+1/-1)
src/main/java/com/akiban/ais/model/DefaultNameGenerator.java (+3/-1)
src/main/java/com/akiban/ais/model/aisb2/AISBBasedBuilder.java (+13/-7)
src/main/java/com/akiban/ais/model/aisb2/NewUserTableBuilder.java (+11/-1)
src/main/java/com/akiban/ais/util/ChangedTableDescription.java (+8/-1)
src/main/java/com/akiban/ais/util/TableChangeValidator.java (+14/-10)
src/main/java/com/akiban/server/error/ColumnAlreadyGeneratedException.java (+31/-0)
src/main/java/com/akiban/server/error/ColumnNotGeneratedException.java (+29/-0)
src/main/java/com/akiban/server/error/ErrorCode.java (+2/-0)
src/main/java/com/akiban/server/service/dxl/BasicDDLFunctions.java (+2/-1)
src/main/java/com/akiban/sql/aisddl/AlterTableDDL.java (+77/-36)
src/main/java/com/akiban/sql/aisddl/TableDDL.java (+16/-15)
src/main/java/com/akiban/sql/aisddl/ViewDDL.java (+1/-1)
src/main/resources/com/akiban/server/error/error_code.properties (+2/-0)
src/test/java/com/akiban/server/test/it/dxl/AlterTableBasicIT.java (+8/-4)
src/test/java/com/akiban/sql/aisddl/AlterTableDDLTest.java (+103/-2)
src/test/java/com/akiban/sql/aisddl/TableDDLIT.java (+1/-1)
src/test/resources/com/akiban/sql/pg/yaml/functional/test-identity.yaml (+13/-0)
To merge this branch: bzr merge lp:~nwilliams/akiban-server/alter-generated
Reviewer Review Type Date Requested Status
Mike McMahon Approve
Review via email: mp+158990@code.launchpad.net

Description of the change

Support SET INCREMENT and GENERATED ALTER actions.

A little tweaking in handling DEFAULT nodes in AlterTableDDL and a little propagation of new sequences through the validator and merger.

Minor tweaks and helper methods elsewhere.

To post a comment you must log in.
Revision history for this message
Mike McMahon (mmcm) wrote :

Looks right and passes new tests. Is line 87 leftover from an earlier stage of tracking the change? newSequences doesn't seem to get used.

review: Needs Information
2626. By Nathan Williams

Remove dead variable

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

Indeed it was. Removed.

Revision history for this message
Mike McMahon (mmcm) wrote :

Uncovered trying to update the client-tools test for this: DumpClient assumes that identity sequences are named _sequence-XXX, whereas one added by ALTER is still called temp-sequence-1. I assume that name will cause other kinds of trouble, but it is possible to alter the dumper, of course.

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

Wasn't using as much of the helper as I thought I was. Fixed.

Good catch. Why does DumpClient assume that? Is there no other indication that it is an identity column?

2627. By Nathan Williams

Use helper for sequence name.

2628. By Nathan Williams

Cleanup

Revision history for this message
Mike McMahon (mmcm) wrote :

Looks good.

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/AISBuilder.java'
--- src/main/java/com/akiban/ais/model/AISBuilder.java 2013-03-22 20:05:57 +0000
+++ src/main/java/com/akiban/ais/model/AISBuilder.java 2013-04-15 20:33:27 +0000
@@ -75,12 +75,12 @@
75 return nameGenerator;75 return nameGenerator;
76 }76 }
7777
78 public void sequence (String schemaName, String sequenceName,78 public Sequence sequence(String schemaName, String sequenceName,
79 long start, long increment,79 long start, long increment, long minValue, long maxValue, boolean cycle) {
80 long minValue, long maxValue, boolean cycle) {
81 LOG.trace("sequence: {}.{} ", schemaName,sequenceName);80 LOG.trace("sequence: {}.{} ", schemaName,sequenceName);
82 Sequence identityGenerator = Sequence.create(ais, schemaName, sequenceName, start, increment, minValue, maxValue, cycle);81 Sequence identityGenerator = Sequence.create(ais, schemaName, sequenceName, start, increment, minValue, maxValue, cycle);
83 identityGenerator.setTreeName(nameGenerator.generateSequenceTreeName(identityGenerator));82 identityGenerator.setTreeName(nameGenerator.generateSequenceTreeName(identityGenerator));
83 return identityGenerator;
84 }84 }
85 85
86 public UserTable userTable(String schemaName, String tableName) {86 public UserTable userTable(String schemaName, String tableName) {
8787
=== modified file 'src/main/java/com/akiban/ais/model/AISMerge.java'
--- src/main/java/com/akiban/ais/model/AISMerge.java 2013-04-11 03:40:21 +0000
+++ src/main/java/com/akiban/ais/model/AISMerge.java 2013-04-15 20:33:27 +0000
@@ -86,6 +86,20 @@
86 }86 }
87 }87 }
8888
89 private static class IdentityInfo {
90 public final TableName tableName;
91 public final String columnName;
92 public final boolean defaultIdentity;
93 public final Sequence sequence;
94
95 public IdentityInfo(TableName tableName, String columnName, boolean defaultIdentity, Sequence sequence) {
96 this.tableName = tableName;
97 this.columnName = columnName;
98 this.defaultIdentity = defaultIdentity;
99 this.sequence = sequence;
100 }
101 }
102
89 private static final Logger LOG = LoggerFactory.getLogger(AISMerge.class);103 private static final Logger LOG = LoggerFactory.getLogger(AISMerge.class);
90104
91 /* state */105 /* state */
@@ -95,16 +109,17 @@
95 private final MergeType mergeType;109 private final MergeType mergeType;
96 private final List<JoinChange> changedJoins;110 private final List<JoinChange> changedJoins;
97 private final Map<IndexName,IndexInfo> indexesToFix;111 private final Map<IndexName,IndexInfo> indexesToFix;
112 private final List<IdentityInfo> identityToFix;
98113
99114
100 /** Legacy test constructor. Creates an AISMerge for adding a table with a new {@link DefaultNameGenerator}. */115 /** Legacy test constructor. Creates an AISMerge for adding a table with a new {@link DefaultNameGenerator}. */
101 AISMerge(AkibanInformationSchema sourceAIS, UserTable newTable) {116 AISMerge(AkibanInformationSchema sourceAIS, UserTable newTable) {
102 this(new DefaultNameGenerator(sourceAIS), copyAISForAdd(sourceAIS), newTable, MergeType.ADD_TABLE, null, null);117 this(new DefaultNameGenerator(sourceAIS), copyAISForAdd(sourceAIS), newTable, MergeType.ADD_TABLE, null, null, null);
103 }118 }
104119
105 /** Create a new AISMerge to be used for adding a new table. */120 /** Create a new AISMerge to be used for adding a new table. */
106 public static AISMerge newForAddTable(NameGenerator generator, AkibanInformationSchema sourceAIS, UserTable newTable) {121 public static AISMerge newForAddTable(NameGenerator generator, AkibanInformationSchema sourceAIS, UserTable newTable) {
107 return new AISMerge(generator, copyAISForAdd(sourceAIS), newTable, MergeType.ADD_TABLE, null, null);122 return new AISMerge(generator, copyAISForAdd(sourceAIS), newTable, MergeType.ADD_TABLE, null, null, null);
108 }123 }
109124
110 /** Create a new AISMerge to be used for modifying a table. */125 /** Create a new AISMerge to be used for modifying a table. */
@@ -112,27 +127,30 @@
112 Collection<ChangedTableDescription> alteredTables) {127 Collection<ChangedTableDescription> alteredTables) {
113 List<JoinChange> changedJoins = new ArrayList<>();128 List<JoinChange> changedJoins = new ArrayList<>();
114 Map<IndexName,IndexInfo> indexesToFix = new HashMap<>();129 Map<IndexName,IndexInfo> indexesToFix = new HashMap<>();
115 AkibanInformationSchema targetAIS = copyAISForModify(sourceAIS, indexesToFix, changedJoins, alteredTables);130 List<IdentityInfo> identityToFix = new ArrayList<>();
116 return new AISMerge(generator, targetAIS, null, MergeType.MODIFY_TABLE, changedJoins, indexesToFix);131 AkibanInformationSchema targetAIS = copyAISForModify(sourceAIS, indexesToFix, changedJoins, identityToFix, alteredTables);
132 return new AISMerge(generator, targetAIS, null, MergeType.MODIFY_TABLE, changedJoins, indexesToFix, identityToFix);
117 }133 }
118134
119 /** Create a new AISMerge to be used for adding one, or more, index to a table. Also see {@link #mergeIndex(Index)}. */135 /** Create a new AISMerge to be used for adding one, or more, index to a table. Also see {@link #mergeIndex(Index)}. */
120 public static AISMerge newForAddIndex(NameGenerator generator, AkibanInformationSchema sourceAIS) {136 public static AISMerge newForAddIndex(NameGenerator generator, AkibanInformationSchema sourceAIS) {
121 return new AISMerge(generator, copyAISForAdd(sourceAIS), null, MergeType.ADD_INDEX, null, null);137 return new AISMerge(generator, copyAISForAdd(sourceAIS), null, MergeType.ADD_INDEX, null, null, null);
122 }138 }
123139
124 public static AISMerge newForOther(NameGenerator generator, AkibanInformationSchema sourceAIS) {140 public static AISMerge newForOther(NameGenerator generator, AkibanInformationSchema sourceAIS) {
125 return new AISMerge(generator, copyAISForAdd(sourceAIS), null, MergeType.OTHER, null, null);141 return new AISMerge(generator, copyAISForAdd(sourceAIS), null, MergeType.OTHER, null, null, null);
126 }142 }
127143
128 private AISMerge(NameGenerator nameGenerator, AkibanInformationSchema targetAIS, UserTable sourceTable,144 private AISMerge(NameGenerator nameGenerator, AkibanInformationSchema targetAIS, UserTable sourceTable,
129 MergeType mergeType, List<JoinChange> changedJoins, Map<IndexName,IndexInfo> indexesToFix) {145 MergeType mergeType, List<JoinChange> changedJoins, Map<IndexName,IndexInfo> indexesToFix,
146 List<IdentityInfo> identityToFix) {
130 this.nameGenerator = nameGenerator;147 this.nameGenerator = nameGenerator;
131 this.targetAIS = targetAIS;148 this.targetAIS = targetAIS;
132 this.sourceTable = sourceTable;149 this.sourceTable = sourceTable;
133 this.mergeType = mergeType;150 this.mergeType = mergeType;
134 this.changedJoins = changedJoins;151 this.changedJoins = changedJoins;
135 this.indexesToFix = indexesToFix;152 this.indexesToFix = indexesToFix;
153 this.identityToFix = identityToFix;
136 }154 }
137155
138156
@@ -143,6 +161,7 @@
143 private static AkibanInformationSchema copyAISForModify(AkibanInformationSchema oldAIS,161 private static AkibanInformationSchema copyAISForModify(AkibanInformationSchema oldAIS,
144 Map<IndexName,IndexInfo> indexesToFix,162 Map<IndexName,IndexInfo> indexesToFix,
145 final List<JoinChange> joinsToFix,163 final List<JoinChange> joinsToFix,
164 List<IdentityInfo> identityToFix,
146 Collection<ChangedTableDescription> changedTables)165 Collection<ChangedTableDescription> changedTables)
147 {166 {
148 final Set<Sequence> excludedSequences = new HashSet<>();167 final Set<Sequence> excludedSequences = new HashSet<>();
@@ -218,6 +237,11 @@
218 for(TableName name : desc.getDroppedSequences()) {237 for(TableName name : desc.getDroppedSequences()) {
219 excludedSequences.add(oldAIS.getSequence(name));238 excludedSequences.add(oldAIS.getSequence(name));
220 }239 }
240
241 for(String name : desc.getIdentityAdded()) {
242 Column col = newTable.getColumn(name);
243 identityToFix.add(new IdentityInfo(desc.getNewName(), name, col.getDefaultIdentity(), col.getIdentityGenerator()));
244 }
221 }245 }
222246
223 return AISCloner.clone(247 return AISCloner.clone(
@@ -481,6 +505,11 @@
481 index.setTreeName((info.tree != null) ? info.tree : nameGenerator.generateIndexTreeName(index));505 index.setTreeName((info.tree != null) ? info.tree : nameGenerator.generateIndexTreeName(index));
482 }506 }
483507
508 for(IdentityInfo info : identityToFix) {
509 addIdentitySequence(builder, info.tableName.getSchemaName(), info.tableName.getTableName(), info.columnName,
510 info.defaultIdentity, info.sequence);
511 }
512
484 builder.akibanInformationSchema().validate(AISValidations.LIVE_AIS_VALIDATIONS).throwIfNecessary();513 builder.akibanInformationSchema().validate(AISValidations.LIVE_AIS_VALIDATIONS).throwIfNecessary();
485 builder.akibanInformationSchema().freeze();514 builder.akibanInformationSchema().freeze();
486 }515 }
@@ -529,16 +558,8 @@
529 newColumn.setInitialAutoIncrementValue(column.getInitialAutoIncrementValue());558 newColumn.setInitialAutoIncrementValue(column.getInitialAutoIncrementValue());
530 }559 }
531 if (column.getDefaultIdentity() != null) {560 if (column.getDefaultIdentity() != null) {
532 TableName sequenceName = nameGenerator.generateIdentitySequenceName(new TableName(schemaName, tableName));561 addIdentitySequence(builder, schemaName, tableName, column.getName(),
533 Sequence sequence = column.getIdentityGenerator();562 column.getDefaultIdentity(), column.getIdentityGenerator());
534 builder.sequence(sequenceName.getSchemaName(), sequenceName.getTableName(),
535 sequence.getStartsWith(),
536 sequence.getIncrement(),
537 sequence.getMinValue(),
538 sequence.getMaxValue(),
539 sequence.isCycle());
540 builder.columnAsIdentity(schemaName, tableName, column.getName(), sequenceName.getTableName(), column.getDefaultIdentity());
541 LOG.debug("Generated sequence: {}, with tree name; {}", sequenceName, sequence.getTreeName());
542 }563 }
543 // Proactively cache, can go away if Column ever cleans itself up564 // Proactively cache, can go away if Column ever cleans itself up
544 newColumn.getMaxStorageSize();565 newColumn.getMaxStorageSize();
@@ -546,6 +567,19 @@
546 }567 }
547 }568 }
548569
570 private void addIdentitySequence(AISBuilder builder, String schemaName, String tableName, String column,
571 boolean defaultIdentity, Sequence sequence) {
572 TableName sequenceName = nameGenerator.generateIdentitySequenceName(new TableName(schemaName, tableName));
573 Sequence newSeq = builder.sequence(sequenceName.getSchemaName(), sequenceName.getTableName(),
574 sequence.getStartsWith(),
575 sequence.getIncrement(),
576 sequence.getMinValue(),
577 sequence.getMaxValue(),
578 sequence.isCycle());
579 builder.columnAsIdentity(schemaName, tableName, column, sequenceName.getTableName(), defaultIdentity);
580 LOG.debug("Generated sequence: {}, with tree name; {}", sequenceName, newSeq.getTreeName());
581 }
582
549 private void addNewGroup (AISBuilder builder, UserTable rootTable) {583 private void addNewGroup (AISBuilder builder, UserTable rootTable) {
550 TableName groupName = rootTable.getName();584 TableName groupName = rootTable.getName();
551 builder.createGroup(groupName.getTableName(), groupName.getSchemaName());585 builder.createGroup(groupName.getTableName(), groupName.getSchemaName());
@@ -650,13 +684,18 @@
650 684
651 public AkibanInformationSchema mergeSequence(Sequence sequence)685 public AkibanInformationSchema mergeSequence(Sequence sequence)
652 {686 {
687 mergeSequenceInternal(sequence);
688 targetAIS.validate(AISValidations.LIVE_AIS_VALIDATIONS).throwIfNecessary();
689 targetAIS.freeze();
690 return targetAIS;
691 }
692
693 private Sequence mergeSequenceInternal(Sequence sequence)
694 {
653 Sequence newSeq = Sequence.create(targetAIS, sequence);695 Sequence newSeq = Sequence.create(targetAIS, sequence);
654 newSeq.setTreeName(nameGenerator.generateSequenceTreeName(newSeq));696 newSeq.setTreeName(nameGenerator.generateSequenceTreeName(newSeq));
655 targetAIS.addSequence(newSeq);697 return newSeq;
656 targetAIS.validate(AISValidations.LIVE_AIS_VALIDATIONS).throwIfNecessary();698 }
657 targetAIS.freeze();
658 return targetAIS;
659 }
660699
661 public static AkibanInformationSchema mergeRoutine(AkibanInformationSchema oldAIS,700 public static AkibanInformationSchema mergeRoutine(AkibanInformationSchema oldAIS,
662 Routine routine) {701 Routine routine) {
663702
=== modified file 'src/main/java/com/akiban/ais/model/AkibanInformationSchema.java'
--- src/main/java/com/akiban/ais/model/AkibanInformationSchema.java 2013-03-22 20:05:57 +0000
+++ src/main/java/com/akiban/ais/model/AkibanInformationSchema.java 2013-04-15 20:33:27 +0000
@@ -642,7 +642,7 @@
642 invalidateTableIdMap();642 invalidateTableIdMap();
643 }643 }
644 644
645 void removeSequence (TableName name) {645 public void removeSequence (TableName name) {
646 sequences.remove(name);646 sequences.remove(name);
647 Schema schema = getSchema(name.getSchemaName());647 Schema schema = getSchema(name.getSchemaName());
648 if (schema != null) {648 if (schema != null) {
649649
=== modified file 'src/main/java/com/akiban/ais/model/DefaultNameGenerator.java'
--- src/main/java/com/akiban/ais/model/DefaultNameGenerator.java 2013-03-22 20:05:57 +0000
+++ src/main/java/com/akiban/ais/model/DefaultNameGenerator.java 2013-04-15 20:33:27 +0000
@@ -34,6 +34,8 @@
34public class DefaultNameGenerator implements NameGenerator {34public class DefaultNameGenerator implements NameGenerator {
35 private static final Logger LOG = LoggerFactory.getLogger(DefaultNameGenerator.class);35 private static final Logger LOG = LoggerFactory.getLogger(DefaultNameGenerator.class);
3636
37 public static final String IDENTITY_SEQUENCE_PREFIX = "_sequence-";
38
37 // Use 1 as default offset because the AAM uses tableID 0 as a marker value.39 // Use 1 as default offset because the AAM uses tableID 0 as a marker value.
38 static final int USER_TABLE_ID_OFFSET = 1;40 static final int USER_TABLE_ID_OFFSET = 1;
39 static final int IS_TABLE_ID_OFFSET = 1000000000;41 static final int IS_TABLE_ID_OFFSET = 1000000000;
@@ -99,7 +101,7 @@
99101
100 @Override102 @Override
101 public TableName generateIdentitySequenceName(TableName tableName) {103 public TableName generateIdentitySequenceName(TableName tableName) {
102 TableName seqName = new TableName(tableName.getSchemaName(), "_sequence-" + tableName.hashCode());104 TableName seqName = new TableName(tableName.getSchemaName(), IDENTITY_SEQUENCE_PREFIX + tableName.hashCode());
103 return makeUnique(sequenceNames, seqName);105 return makeUnique(sequenceNames, seqName);
104 }106 }
105107
106108
=== modified file 'src/main/java/com/akiban/ais/model/aisb2/AISBBasedBuilder.java'
--- src/main/java/com/akiban/ais/model/aisb2/AISBBasedBuilder.java 2013-04-10 23:46:56 +0000
+++ src/main/java/com/akiban/ais/model/aisb2/AISBBasedBuilder.java 2013-04-15 20:33:27 +0000
@@ -214,29 +214,35 @@
214214
215 @Override215 @Override
216 public NewUserTableBuilder colLong(String name) {216 public NewUserTableBuilder colLong(String name) {
217 return colLong(name, NULLABLE_DEFAULT, null);217 return colLong(name, NULLABLE_DEFAULT, null, null);
218 }218 }
219219
220 @Override220 @Override
221 public NewUserTableBuilder colLong(String name, boolean nullable) {221 public NewUserTableBuilder colLong(String name, boolean nullable) {
222 return colLong(name, nullable, null);222 return colLong(name, nullable, null, null);
223 }223 }
224224
225 @Override225 @Override
226 public NewUserTableBuilder autoIncLong(String name, int initialValue) {226 public NewUserTableBuilder autoIncLong(String name, int initialValue) {
227 return colLong(name, false, initialValue);227 return colLong(name, false, initialValue, true);
228 }228 }
229229
230 private NewUserTableBuilder colLong(String name, boolean nullable, Integer initialAutoInc) {230 @Override
231 public NewUserTableBuilder autoIncLong(String name, int initialValue, boolean always) {
232 return colLong(name, false, initialValue, !always);
233 }
234
235 private NewUserTableBuilder colLong(String name, boolean nullable, Integer initialAutoInc, Boolean defaultIdentity) {
231 checkUsable();236 checkUsable();
232 aisb.column(schema, userTable, name, uTableColumnPos++, "INT", 10L, null, nullable, false, null, null);237 aisb.column(schema, userTable, name, uTableColumnPos++, "INT", 10L, null, nullable, false, null, null);
233 if (initialAutoInc != null) {238 if (initialAutoInc != null) {
239 assert defaultIdentity != null;
234 String sequenceName = "temp-seq-" + userTable + "-" + name;240 String sequenceName = "temp-seq-" + userTable + "-" + name;
235 long initValue = initialAutoInc.longValue();241 long initValue = initialAutoInc.longValue();
236 aisb.sequence(schema, sequenceName, 242 aisb.sequence(schema, sequenceName,
237 initValue, 1L, initValue, Long.MAX_VALUE,243 initValue, 1L, initValue, Long.MAX_VALUE,
238 false);244 false);
239 aisb.columnAsIdentity(schema, userTable, name, sequenceName, true);245 aisb.columnAsIdentity(schema, userTable, name, sequenceName, defaultIdentity);
240 aisb.akibanInformationSchema().246 aisb.akibanInformationSchema().
241 getUserTable(schema, userTable).247 getUserTable(schema, userTable).
242 getColumn(name).248 getColumn(name).
243249
=== modified file 'src/main/java/com/akiban/ais/model/aisb2/NewUserTableBuilder.java'
--- src/main/java/com/akiban/ais/model/aisb2/NewUserTableBuilder.java 2013-04-01 18:36:36 +0000
+++ src/main/java/com/akiban/ais/model/aisb2/NewUserTableBuilder.java 2013-04-15 20:33:27 +0000
@@ -67,13 +67,23 @@
67 NewUserTableBuilder colLong(String name, boolean nullable);67 NewUserTableBuilder colLong(String name, boolean nullable);
6868
69 /**69 /**
70 * Adds a non-nullable, sequence backed, auto-incrementing column70 * Adds a non-nullable, sequence backed, auto-incrementing BY DEFAULT identity column
71 * @param name the column's name71 * @param name the column's name
72 * @param initialValue the START WITH value
72 * @return this73 * @return this
73 */74 */
74 NewUserTableBuilder autoIncLong(String name, int initialValue);75 NewUserTableBuilder autoIncLong(String name, int initialValue);
7576
76 /**77 /**
78 * Adds a non-nullable, sequence backed, auto-incrementing identity column
79 * @param name the column's name
80 * @param initialValue the START WITH value
81 * @param always ALWAYS if <code>true</code>, otherwise DEFAULT
82 * @return this
83 */
84 NewUserTableBuilder autoIncLong(String name, int initialValue, boolean always);
85
86 /**
77 * Adds an optionally nullable boolean column87 * Adds an optionally nullable boolean column
78 * @param name the column's name88 * @param name the column's name
79 * @param nullable whether the column is nullable89 * @param nullable whether the column is nullable
8090
=== modified file 'src/main/java/com/akiban/ais/util/ChangedTableDescription.java'
--- src/main/java/com/akiban/ais/util/ChangedTableDescription.java 2013-03-22 20:05:57 +0000
+++ src/main/java/com/akiban/ais/util/ChangedTableDescription.java 2013-04-15 20:33:27 +0000
@@ -38,6 +38,7 @@
38 private final Map<String,String> parentColNames;38 private final Map<String,String> parentColNames;
39 private final Map<String,String> preserveIndexes;39 private final Map<String,String> preserveIndexes;
40 private final Collection<TableName> droppedSequences;40 private final Collection<TableName> droppedSequences;
41 private final Collection<String> identityAdded;
4142
42 /**43 /**
43 * @param tableName Current name of the table being changed.44 * @param tableName Current name of the table being changed.
@@ -46,7 +47,8 @@
46 */47 */
47 public ChangedTableDescription(TableName tableName, UserTable newDefinition, Map<String,String> colNames,48 public ChangedTableDescription(TableName tableName, UserTable newDefinition, Map<String,String> colNames,
48 ParentChange parentChange, TableName parentName, Map<String,String> parentColNames,49 ParentChange parentChange, TableName parentName, Map<String,String> parentColNames,
49 Map<String, String> preserveIndexes, Collection<TableName> droppedSequences) {50 Map<String, String> preserveIndexes, Collection<TableName> droppedSequences,
51 Collection<String> identityAdded) {
50 ArgumentValidation.notNull("tableName", tableName);52 ArgumentValidation.notNull("tableName", tableName);
51 ArgumentValidation.notNull("preserveIndexes", preserveIndexes);53 ArgumentValidation.notNull("preserveIndexes", preserveIndexes);
52 this.tableName = tableName;54 this.tableName = tableName;
@@ -57,6 +59,7 @@
57 this.parentColNames = parentColNames;59 this.parentColNames = parentColNames;
58 this.preserveIndexes = preserveIndexes;60 this.preserveIndexes = preserveIndexes;
59 this.droppedSequences = droppedSequences;61 this.droppedSequences = droppedSequences;
62 this.identityAdded = identityAdded;
60 }63 }
6164
62 public TableName getOldName() {65 public TableName getOldName() {
@@ -95,6 +98,10 @@
95 return droppedSequences;98 return droppedSequences;
96 }99 }
97100
101 public Collection<String> getIdentityAdded() {
102 return identityAdded;
103 }
104
98 public boolean isNewGroup() {105 public boolean isNewGroup() {
99 return (parentChange != ParentChange.NONE);106 return (parentChange != ParentChange.NONE);
100 }107 }
101108
=== modified file 'src/main/java/com/akiban/ais/util/TableChangeValidator.java'
--- src/main/java/com/akiban/ais/util/TableChangeValidator.java 2013-04-11 04:48:29 +0000
+++ src/main/java/com/akiban/ais/util/TableChangeValidator.java 2013-04-15 20:33:27 +0000
@@ -393,9 +393,9 @@
393 primaryKeyChanged = containsOldOrNew(indexChanges, Index.PRIMARY_KEY_CONSTRAINT);393 primaryKeyChanged = containsOldOrNew(indexChanges, Index.PRIMARY_KEY_CONSTRAINT);
394394
395 List<TableName> droppedSequences = new ArrayList<>();395 List<TableName> droppedSequences = new ArrayList<>();
396 List<String> addedIdentity = new ArrayList<>();
396 Map<String,String> renamedColumns = new HashMap<>();397 Map<String,String> renamedColumns = new HashMap<>();
397 for(TableChange change : columnChanges) {398 for(TableChange change : columnChanges) {
398 Sequence seqToDrop = null;
399 switch(change.getChangeType()) {399 switch(change.getChangeType()) {
400 case MODIFY: {400 case MODIFY: {
401 if(!change.getOldName().equals(change.getNewName())) {401 if(!change.getOldName().equals(change.getNewName())) {
@@ -403,20 +403,24 @@
403 }403 }
404 Column oldColumn = oldTable.getColumn(change.getOldName());404 Column oldColumn = oldTable.getColumn(change.getOldName());
405 Column newColumn = newTable.getColumn(change.getNewName());405 Column newColumn = newTable.getColumn(change.getNewName());
406 if((oldColumn != null) && (oldColumn.getIdentityGenerator() != null) && (newColumn.getIdentityGenerator() == null)) {406 if((oldColumn != null)) {
407 seqToDrop = oldColumn.getIdentityGenerator();407 Sequence oldSeq = oldColumn.getIdentityGenerator();
408 Sequence newSeq = newColumn.getIdentityGenerator();
409 if((oldSeq == null) && (newSeq != null)) {
410 addedIdentity.add(newColumn.getName());
411 } else if((oldSeq != null) && (newSeq == null)) {
412 droppedSequences.add(oldSeq.getSequenceName());
413 }
414 // else both not null and not equal, not yet supported
408 }415 }
409 } break;416 } break;
410 case DROP: {417 case DROP: {
411 Column oldColumn = oldTable.getColumn(change.getOldName());418 Column oldColumn = oldTable.getColumn(change.getOldName());
412 if(oldColumn != null) {419 if((oldColumn != null) && (oldColumn.getIdentityGenerator() != null)) {
413 seqToDrop = oldColumn.getIdentityGenerator();420 droppedSequences.add(oldColumn.getIdentityGenerator().getSequenceName());
414 }421 }
415 } break;422 } break;
416 }423 }
417 if(seqToDrop != null) {
418 droppedSequences.add(seqToDrop.getSequenceName());
419 }
420 }424 }
421425
422 boolean renamed = !oldTable.getName().equals(newTable.getName()) || !renamedColumns.isEmpty();426 boolean renamed = !oldTable.getName().equals(newTable.getName()) || !renamedColumns.isEmpty();
@@ -425,7 +429,7 @@
425 TableName parentName = (newTable.getParentJoin() != null) ? newTable.getParentJoin().getParent().getName() : null;429 TableName parentName = (newTable.getParentJoin() != null) ? newTable.getParentJoin().getParent().getName() : null;
426 changedTables.add(new ChangedTableDescription(oldTable.getName(), newTable, renamedColumns,430 changedTables.add(new ChangedTableDescription(oldTable.getName(), newTable, renamedColumns,
427 parentChange, parentName, EMPTY_STRING_MAP, preserveIndexes,431 parentChange, parentName, EMPTY_STRING_MAP, preserveIndexes,
428 droppedSequences));432 droppedSequences, addedIdentity));
429433
430 if(!isParentChanged() && !primaryKeyChanged) {434 if(!isParentChanged() && !primaryKeyChanged) {
431 for(Index index : newTable.getIndexesIncludingInternal()) {435 for(Index index : newTable.getIndexesIncludingInternal()) {
@@ -507,7 +511,7 @@
507 parentRenames = (parentRenames != null) ? parentRenames : EMPTY_STRING_MAP;511 parentRenames = (parentRenames != null) ? parentRenames : EMPTY_STRING_MAP;
508 changedTables.add(new ChangedTableDescription(table.getName(), null, EMPTY_STRING_MAP,512 changedTables.add(new ChangedTableDescription(table.getName(), null, EMPTY_STRING_MAP,
509 parentChange, parentName, parentRenames, preserved,513 parentChange, parentName, parentRenames, preserved,
510 EMPTY_TABLE_NAME_LIST));514 EMPTY_TABLE_NAME_LIST, Collections.<String>emptyList()));
511 }515 }
512516
513 private static boolean containsOldOrNew(List<TableChange> changes, String name) {517 private static boolean containsOldOrNew(List<TableChange> changes, String name) {
514518
=== added file 'src/main/java/com/akiban/server/error/ColumnAlreadyGeneratedException.java'
--- src/main/java/com/akiban/server/error/ColumnAlreadyGeneratedException.java 1970-01-01 00:00:00 +0000
+++ src/main/java/com/akiban/server/error/ColumnAlreadyGeneratedException.java 2013-04-15 20:33:27 +0000
@@ -0,0 +1,31 @@
1/**
2 * Copyright (C) 2009-2013 Akiban Technologies, Inc.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Affero General Public License for more details.
13 *
14 * You should have received a copy of the GNU Affero General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18package com.akiban.server.error;
19
20import com.akiban.ais.model.Column;
21
22public class ColumnAlreadyGeneratedException extends InvalidOperationException {
23 public ColumnAlreadyGeneratedException(Column column) {
24 super(ErrorCode.COLUMN_ALREADY_GENERATED,
25 column.getColumnar().getName().getSchemaName(),
26 column.getColumnar().getName().getTableName(),
27 column.getName(),
28 column.getIdentityGenerator().getSchemaName(),
29 column.getIdentityGenerator().getSequenceName().getTableName());
30 }
31}
032
=== added file 'src/main/java/com/akiban/server/error/ColumnNotGeneratedException.java'
--- src/main/java/com/akiban/server/error/ColumnNotGeneratedException.java 1970-01-01 00:00:00 +0000
+++ src/main/java/com/akiban/server/error/ColumnNotGeneratedException.java 2013-04-15 20:33:27 +0000
@@ -0,0 +1,29 @@
1/**
2 * Copyright (C) 2009-2013 Akiban Technologies, Inc.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Affero General Public License for more details.
13 *
14 * You should have received a copy of the GNU Affero General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18package com.akiban.server.error;
19
20import com.akiban.ais.model.Column;
21
22public class ColumnNotGeneratedException extends InvalidOperationException {
23 public ColumnNotGeneratedException(Column column) {
24 super(ErrorCode.COLUMN_NOT_GENERATED,
25 column.getColumnar().getName().getSchemaName(),
26 column.getColumnar().getName().getTableName(),
27 column.getName());
28 }
29}
030
=== modified file 'src/main/java/com/akiban/server/error/ErrorCode.java'
--- src/main/java/com/akiban/server/error/ErrorCode.java 2013-04-15 14:38:06 +0000
+++ src/main/java/com/akiban/server/error/ErrorCode.java 2013-04-15 20:33:27 +0000
@@ -373,6 +373,8 @@
373 INVALID_ROUTINE ("50", "024", Importance.DEBUG, InvalidRoutineException.class),373 INVALID_ROUTINE ("50", "024", Importance.DEBUG, InvalidRoutineException.class),
374 INVALID_INDEX_ID ("50", "025", Importance.DEBUG, InvalidIndexIDException.class),374 INVALID_INDEX_ID ("50", "025", Importance.DEBUG, InvalidIndexIDException.class),
375 MODEL_BUILDER_ERROR ("50", "026", Importance.DEBUG, ModelBuilderException.class),375 MODEL_BUILDER_ERROR ("50", "026", Importance.DEBUG, ModelBuilderException.class),
376 COLUMN_NOT_GENERATED ("50", "027", Importance.DEBUG, ColumnNotGeneratedException.class),
377 COLUMN_ALREADY_GENERATED ("50", "028", Importance.DEBUG, ColumnAlreadyGeneratedException.class),
376378
377 // Class 51 - Internal problems created by user configuration379 // Class 51 - Internal problems created by user configuration
378 STALE_AIS ("51", "001", Importance.TRACE, OldAISException.class),380 STALE_AIS ("51", "001", Importance.TRACE, OldAISException.class),
379381
=== modified file 'src/main/java/com/akiban/server/service/dxl/BasicDDLFunctions.java'
--- src/main/java/com/akiban/server/service/dxl/BasicDDLFunctions.java 2013-04-11 18:35:20 +0000
+++ src/main/java/com/akiban/server/service/dxl/BasicDDLFunctions.java 2013-04-15 20:33:27 +0000
@@ -31,6 +31,7 @@
3131
32import com.akiban.ais.model.AkibanInformationSchema;32import com.akiban.ais.model.AkibanInformationSchema;
33import com.akiban.ais.model.Column;33import com.akiban.ais.model.Column;
34import com.akiban.ais.model.DefaultNameGenerator;
34import com.akiban.ais.model.Group;35import com.akiban.ais.model.Group;
35import com.akiban.ais.model.GroupIndex;36import com.akiban.ais.model.GroupIndex;
36import com.akiban.ais.model.Index;37import com.akiban.ais.model.Index;
@@ -752,7 +753,7 @@
752 for (Sequence sequence : schema.getSequences().values()) {753 for (Sequence sequence : schema.getSequences().values()) {
753 // Drop the sequences in this schema, but not the 754 // Drop the sequences in this schema, but not the
754 // generator sequences, which will be dropped with the table. 755 // generator sequences, which will be dropped with the table.
755 if (!(sequence.getSequenceName().getTableName().startsWith("_sequence-"))) {756 if (!(sequence.getSequenceName().getTableName().startsWith(DefaultNameGenerator.IDENTITY_SEQUENCE_PREFIX))) {
756 sequencesToDrop.add(sequence);757 sequencesToDrop.add(sequence);
757 }758 }
758 }759 }
759760
=== modified file 'src/main/java/com/akiban/sql/aisddl/AlterTableDDL.java'
--- src/main/java/com/akiban/sql/aisddl/AlterTableDDL.java 2013-03-22 20:05:57 +0000
+++ src/main/java/com/akiban/sql/aisddl/AlterTableDDL.java 2013-04-15 20:33:27 +0000
@@ -17,7 +17,10 @@
1717
18package com.akiban.sql.aisddl;18package com.akiban.sql.aisddl;
1919
20import com.akiban.ais.model.Sequence;
20import com.akiban.server.error.AkibanInternalException;21import com.akiban.server.error.AkibanInternalException;
22import com.akiban.server.error.ColumnAlreadyGeneratedException;
23import com.akiban.server.error.ColumnNotGeneratedException;
21import com.akiban.sql.parser.AlterTableRenameColumnNode;24import com.akiban.sql.parser.AlterTableRenameColumnNode;
22import com.akiban.sql.parser.AlterTableRenameNode;25import com.akiban.sql.parser.AlterTableRenameNode;
23import com.akiban.ais.AISCloner;26import com.akiban.ais.AISCloner;
@@ -122,8 +125,7 @@
122 List<ColumnDefinitionNode> columnDefNodes = new ArrayList<>();125 List<ColumnDefinitionNode> columnDefNodes = new ArrayList<>();
123 List<FKConstraintDefinitionNode> fkDefNodes= new ArrayList<>();126 List<FKConstraintDefinitionNode> fkDefNodes= new ArrayList<>();
124 List<ConstraintDefinitionNode> conDefNodes = new ArrayList<>();127 List<ConstraintDefinitionNode> conDefNodes = new ArrayList<>();
125 List<String> newCols = null;128
126
127 for(TableElementNode node : elements) {129 for(TableElementNode node : elements) {
128 switch(node.getNodeType()) {130 switch(node.getNodeType()) {
129 case NodeTypes.COLUMN_DEFINITION_NODE: {131 case NodeTypes.COLUMN_DEFINITION_NODE: {
@@ -181,7 +183,6 @@
181 } break;183 } break;
182184
183 case NodeTypes.AT_RENAME_NODE:185 case NodeTypes.AT_RENAME_NODE:
184
185 TableName newName = DDLHelper.convertName(defaultSchema,186 TableName newName = DDLHelper.convertName(defaultSchema,
186 ((AlterTableRenameNode)node).newName());187 ((AlterTableRenameNode)node).newName());
187 TableName oldName = table.getName();188 TableName oldName = table.getName();
@@ -189,18 +190,14 @@
189 return ChangeLevel.METADATA;190 return ChangeLevel.METADATA;
190 191
191 case NodeTypes.AT_RENAME_COLUMN_NODE:192 case NodeTypes.AT_RENAME_COLUMN_NODE:
192
193 AlterTableRenameColumnNode alterRenameCol = (AlterTableRenameColumnNode) node;193 AlterTableRenameColumnNode alterRenameCol = (AlterTableRenameColumnNode) node;
194 String oldColName = alterRenameCol.getName();194 String oldColName = alterRenameCol.getName();
195 String newColName = alterRenameCol.newName();195 String newColName = alterRenameCol.newName();
196 final Column oldCol = table.getColumn(oldColName);196 final Column oldCol = table.getColumn(oldColName);
197 if (oldCol == null)197 if (oldCol == null)
198 throw new NoSuchColumnException(oldColName);198 throw new NoSuchColumnException(oldColName);
199 if (newCols == null)
200 newCols = new ArrayList<>();
201 newCols.add(newColName);
202 columnChanges.add(TableChange.createModify(oldColName, newColName));199 columnChanges.add(TableChange.createModify(oldColName, newColName));
203 break;200 break;
204201
205 default:202 default:
206 return null; // Something unsupported203 return null; // Something unsupported
@@ -216,38 +213,11 @@
216 for(ColumnDefinitionNode cdn : columnDefNodes) {213 for(ColumnDefinitionNode cdn : columnDefNodes) {
217 if(cdn instanceof ModifyColumnNode) {214 if(cdn instanceof ModifyColumnNode) {
218 ModifyColumnNode modNode = (ModifyColumnNode) cdn;215 ModifyColumnNode modNode = (ModifyColumnNode) cdn;
219 Column column = tableCopy.getColumn(modNode.getColumnName());216 handleModifyColumnNode(modNode, builder, tableCopy);
220 if(column == null) {
221 throw new NoSuchColumnException(modNode.getColumnName());
222 }
223 switch(modNode.getNodeType()) {
224 case NodeTypes.MODIFY_COLUMN_DEFAULT_NODE:
225 column.setDefaultValue(TableDDL.getColumnDefault(modNode));
226 break;
227 case NodeTypes.MODIFY_COLUMN_CONSTRAINT_NODE: // Type only comes from NULL
228 column.setNullable(true);
229 break;
230 case NodeTypes.MODIFY_COLUMN_CONSTRAINT_NOT_NULL_NODE: // Type only comes from NOT NULL
231 column.setNullable(false);
232 break;
233 case NodeTypes.MODIFY_COLUMN_TYPE_NODE:
234 tableCopy.dropColumn(modNode.getColumnName());
235 TableDDL.addColumn(builder, table.getName().getSchemaName(), table.getName().getTableName(),
236 column.getName(), column.getPosition(), cdn.getType(), column.getNullable(),
237 column.getInitialAutoIncrementValue() != null,
238 column.getDefaultValue());
239 break;
240 default:
241 throw new IllegalStateException("Unexpected node type: " + modNode);
242 }
243 } else {217 } else {
244 TableDDL.addColumn(builder, cdn, table.getName().getSchemaName(), table.getName().getTableName(), pos++);218 TableDDL.addColumn(builder, cdn, table.getName().getSchemaName(), table.getName().getTableName(), pos++);
245 }219 }
246 }220 }
247 if (newCols != null)
248 for (String name : newCols)
249 if (tableCopy.getColumn(name) == null)
250 throw new AkibanInternalException("New Columns " + newCols + " not created successfully");
251 copyTableIndexes(table, tableCopy, columnChanges, indexChanges);221 copyTableIndexes(table, tableCopy, columnChanges, indexChanges);
252222
253 IndexNameGenerator indexNamer = DefaultIndexNameGenerator.forTable(tableCopy);223 IndexNameGenerator indexNamer = DefaultIndexNameGenerator.forTable(tableCopy);
@@ -283,6 +253,77 @@
283 return ddl.alterTable(session, table.getName(), tableCopy, columnChanges, indexChanges, context);253 return ddl.alterTable(session, table.getName(), tableCopy, columnChanges, indexChanges, context);
284 }254 }
285255
256 private static void handleModifyColumnNode(ModifyColumnNode modNode, AISBuilder builder, UserTable tableCopy) {
257 AkibanInformationSchema aisCopy = tableCopy.getAIS();
258 Column column = tableCopy.getColumn(modNode.getColumnName());
259 if(column == null) {
260 throw new NoSuchColumnException(modNode.getColumnName());
261 }
262 switch(modNode.getNodeType()) {
263 case NodeTypes.MODIFY_COLUMN_DEFAULT_NODE:
264 if(modNode.isAutoincrementColumn()) {
265 int autoIncType = (int)modNode.getAutoinc_create_or_modify_Start_Increment();
266 switch(autoIncType) {
267 case ColumnDefinitionNode.CREATE_AUTOINCREMENT: {
268 if(column.getIdentityGenerator() != null) {
269 throw new ColumnAlreadyGeneratedException(column);
270 }
271 TableName name = tableCopy.getName();
272 TableDDL.setAutoIncrement(builder, name.getSchemaName(), name.getTableName(), modNode);
273 }
274 break;
275 case ColumnDefinitionNode.MODIFY_AUTOINCREMENT_INC_VALUE: {
276 Sequence curSeq = column.getIdentityGenerator();
277 if(curSeq == null) {
278 throw new ColumnNotGeneratedException(column);
279 }
280 aisCopy.removeSequence(curSeq.getSequenceName());
281 Sequence newSeq = Sequence.create(aisCopy,
282 curSeq.getSchemaName(),
283 curSeq.getSequenceName().getTableName(),
284 curSeq.getStartsWith(),
285 modNode.getAutoincrementIncrement(),
286 curSeq.getMinValue(),
287 curSeq.getMaxValue(),
288 curSeq.isCycle());
289 aisCopy.addSequence(newSeq);
290 column.setIdentityGenerator(newSeq);
291 }
292 break;
293 case ColumnDefinitionNode.MODIFY_AUTOINCREMENT_RESTART_VALUE:
294 // Requires Accumulator reset
295 throw new UnsupportedSQLException("Not yet implemented", modNode);
296 default:
297 throw new IllegalStateException("Unknown autoIncType: " + autoIncType);
298 }
299 } else {
300 // DROP DEFAULT will come though as a NULL default, clears both GENERATED and DEFAULT
301 Sequence seq = column.getIdentityGenerator();
302 if(seq != null) {
303 column.setDefaultIdentity(null);
304 column.setIdentityGenerator(null);
305 aisCopy.removeSequence(seq.getSequenceName());
306 }
307 column.setDefaultValue(TableDDL.getColumnDefault(modNode));
308 }
309 break;
310 case NodeTypes.MODIFY_COLUMN_CONSTRAINT_NODE: // Type only comes from NULL
311 column.setNullable(true);
312 break;
313 case NodeTypes.MODIFY_COLUMN_CONSTRAINT_NOT_NULL_NODE: // Type only comes from NOT NULL
314 column.setNullable(false);
315 break;
316 case NodeTypes.MODIFY_COLUMN_TYPE_NODE:
317 tableCopy.dropColumn(modNode.getColumnName());
318 TableDDL.addColumn(builder, tableCopy.getName().getSchemaName(), tableCopy.getName().getTableName(),
319 column.getName(), column.getPosition(), modNode.getType(), column.getNullable(),
320 column.getDefaultValue());
321 break;
322 default:
323 throw new IllegalStateException("Unexpected node type: " + modNode);
324 }
325 }
326
286 private static void checkColumnChange(UserTable table, String columnName) {327 private static void checkColumnChange(UserTable table, String columnName) {
287 Column column = table.getColumn(columnName);328 Column column = table.getColumn(columnName);
288 if(column == null) {329 if(column == null) {
289330
=== modified file 'src/main/java/com/akiban/sql/aisddl/TableDDL.java'
--- src/main/java/com/akiban/sql/aisddl/TableDDL.java 2013-04-11 05:21:42 +0000
+++ src/main/java/com/akiban/sql/aisddl/TableDDL.java 2013-04-15 20:33:27 +0000
@@ -213,7 +213,7 @@
213 // BIGINT NOT NULL 213 // BIGINT NOT NULL
214 DataTypeDescriptor bigint = new DataTypeDescriptor (TypeId.BIGINT_ID, false);214 DataTypeDescriptor bigint = new DataTypeDescriptor (TypeId.BIGINT_ID, false);
215 addColumn (builder, schemaName, tableName, cdn.getColumnName(), colpos,215 addColumn (builder, schemaName, tableName, cdn.getColumnName(), colpos,
216 bigint, false, true, getColumnDefault(cdn));216 bigint, false, getColumnDefault(cdn));
217 // GENERATED ALWAYS AS IDENTITY217 // GENERATED ALWAYS AS IDENTITY
218 setAutoIncrement (builder, schemaName, tableName, cdn.getColumnName(), false, 1, 1);218 setAutoIncrement (builder, schemaName, tableName, cdn.getColumnName(), false, 1, 1);
219 // UNIQUE (KEY)219 // UNIQUE (KEY)
@@ -221,24 +221,25 @@
221 builder.index(schemaName, tableName, cdn.getColumnName(), true, constraint);221 builder.index(schemaName, tableName, cdn.getColumnName(), true, constraint);
222 builder.indexColumn(schemaName, tableName, cdn.getColumnName(), cdn.getColumnName(), 0, true, null);222 builder.indexColumn(schemaName, tableName, cdn.getColumnName(), cdn.getColumnName(), 0, true, null);
223 } else {223 } else {
224 boolean autoIncrement = cdn.isAutoincrementColumn();
225
226 addColumn(builder, schemaName, tableName, cdn.getColumnName(), colpos,224 addColumn(builder, schemaName, tableName, cdn.getColumnName(), colpos,
227 cdn.getType(), cdn.getType().isNullable(), autoIncrement, getColumnDefault(cdn));225 cdn.getType(), cdn.getType().isNullable(), getColumnDefault(cdn));
228 226
229 if (autoIncrement) {227 if (cdn.isAutoincrementColumn()) {
230 // if the cdn has a default node-> GENERATE BY DEFAULT228 setAutoIncrement(builder, schemaName, tableName, cdn);
231 // if no default node -> GENERATE ALWAYS
232 Boolean defaultIdentity = cdn.getDefaultNode() != null;
233 setAutoIncrement (builder, schemaName, tableName, cdn.getColumnName(),
234 defaultIdentity, cdn.getAutoincrementStart(), cdn.getAutoincrementIncrement());
235 }229 }
236 }230 }
237 }231 }
238232
239 static void setAutoIncrement (final AISBuilder builder, 233 public static void setAutoIncrement(AISBuilder builder, String schema, String table, ColumnDefinitionNode cdn) {
240 String schemaName, String tableName, String columnName, boolean defaultIdentity, 234 // if the cdn has a default node-> GENERATE BY DEFAULT
241 long start, long increment) {235 // if no default node -> GENERATE ALWAYS
236 Boolean defaultIdentity = cdn.getDefaultNode() != null;
237 setAutoIncrement(builder, schema, table, cdn.getColumnName(),
238 defaultIdentity, cdn.getAutoincrementStart(), cdn.getAutoincrementIncrement());
239 }
240
241 public static void setAutoIncrement(AISBuilder builder, String schemaName, String tableName, String columnName,
242 boolean defaultIdentity, long start, long increment) {
242 // The merge process will generate a real sequence name243 // The merge process will generate a real sequence name
243 final String sequenceName = "temp-sequence-1"; 244 final String sequenceName = "temp-sequence-1";
244 builder.sequence(schemaName, sequenceName, 245 builder.sequence(schemaName, sequenceName,
@@ -267,7 +268,7 @@
267268
268 static void addColumn(final AISBuilder builder,269 static void addColumn(final AISBuilder builder,
269 final String schemaName, final String tableName, final String columnName,270 final String schemaName, final String tableName, final String columnName,
270 int colpos, DataTypeDescriptor type, boolean nullable, boolean autoIncrement,271 int colpos, DataTypeDescriptor type, boolean nullable,
271 final String defaultValue) {272 final String defaultValue) {
272 Long[] typeParameters = new Long[2];273 Long[] typeParameters = new Long[2];
273 Type builderType = columnType(type, typeParameters, schemaName, tableName, columnName);274 Type builderType = columnType(type, typeParameters, schemaName, tableName, columnName);
@@ -280,7 +281,7 @@
280 colpos,281 colpos,
281 builderType.name(), typeParameters[0], typeParameters[1],282 builderType.name(), typeParameters[0], typeParameters[1],
282 nullable,283 nullable,
283 autoIncrement,284 false,
284 charset, collation,285 charset, collation,
285 defaultValue);286 defaultValue);
286 }287 }
287288
=== modified file 'src/main/java/com/akiban/sql/aisddl/ViewDDL.java'
--- src/main/java/com/akiban/sql/aisddl/ViewDDL.java 2013-03-22 20:05:57 +0000
+++ src/main/java/com/akiban/sql/aisddl/ViewDDL.java 2013-04-15 20:33:27 +0000
@@ -86,7 +86,7 @@
86 type = new DataTypeDescriptor(TypeId.CHAR_ID, true, 0);86 type = new DataTypeDescriptor(TypeId.CHAR_ID, true, 0);
87 }87 }
88 TableDDL.addColumn(builder, schemaName, viewName, rc.getName(), colpos++,88 TableDDL.addColumn(builder, schemaName, viewName, rc.getName(), colpos++,
89 type, type.isNullable(), false, null);89 type, type.isNullable(), null);
90 }90 }
91 View view = builder.akibanInformationSchema().getView(schemaName, viewName);91 View view = builder.akibanInformationSchema().getView(schemaName, viewName);
92 ddlFunctions.createView(session, view);92 ddlFunctions.createView(session, view);
9393
=== modified file 'src/main/resources/com/akiban/server/error/error_code.properties'
--- src/main/resources/com/akiban/server/error/error_code.properties 2013-04-15 14:38:06 +0000
+++ src/main/resources/com/akiban/server/error/error_code.properties 2013-04-15 20:33:27 +0000
@@ -249,6 +249,8 @@
249INVALID_ROUTINE = Invalid procedure `{0}.`{1}`: {2}249INVALID_ROUTINE = Invalid procedure `{0}.`{1}`: {2}
250INVALID_INDEX_ID = Index `{0}.`{1}`.`{2}` has an invalid ID: {3}250INVALID_INDEX_ID = Index `{0}.`{1}`.`{2}` has an invalid ID: {3}
251MODEL_BUILDER_ERROR = Error building model for `{0}`.`{1}`: {2}251MODEL_BUILDER_ERROR = Error building model for `{0}`.`{1}`: {2}
252COLUMN_NOT_GENERATED = Column `{0}`.`{1}`.`{2}` is not generated
253COLUMN_ALREADY_GENERATED = Column `{0}`.`{1}`.`{2}` already generated by sequence `{3}`.`{4}`
252#254#
253# Class 51 - Internal problems created by user configuration255# Class 51 - Internal problems created by user configuration
254#256#
255257
=== modified file 'src/test/java/com/akiban/server/test/it/dxl/AlterTableBasicIT.java'
--- src/test/java/com/akiban/server/test/it/dxl/AlterTableBasicIT.java 2013-04-11 04:48:29 +0000
+++ src/test/java/com/akiban/server/test/it/dxl/AlterTableBasicIT.java 2013-04-15 20:33:27 +0000
@@ -21,6 +21,7 @@
21import com.akiban.ais.model.AISBuilder;21import com.akiban.ais.model.AISBuilder;
22import com.akiban.ais.model.AkibanInformationSchema;22import com.akiban.ais.model.AkibanInformationSchema;
23import com.akiban.ais.model.Column;23import com.akiban.ais.model.Column;
24import com.akiban.ais.model.DefaultNameGenerator;
24import com.akiban.ais.model.Index;25import com.akiban.ais.model.Index;
25import com.akiban.ais.model.Sequence;26import com.akiban.ais.model.Sequence;
26import com.akiban.ais.model.TableName;27import com.akiban.ais.model.TableName;
@@ -1180,12 +1181,15 @@
1180 Sequence seq = column.getIdentityGenerator();1181 Sequence seq = column.getIdentityGenerator();
1181 assertNotNull("id column has sequence", seq);1182 assertNotNull("id column has sequence", seq);
11821183
1183 AkibanInformationSchema copy = AISCloner.clone(ais());1184 runAlter(ChangeLevel.METADATA, "ALTER TABLE c ALTER COLUMN id DROP DEFAULT");
1184 copy.getUserTable(id).getColumn("id").setDefaultIdentity(false);1185 assertNull("Old seq was dropped", ais().getSequence(seq.getSequenceName()));
1185 runAlter(ChangeLevel.METADATA, C_NAME, copy.getUserTable(id),
1186 Arrays.asList(TableChange.createModify("id", "id")), Arrays.<TableChange>asList());
11871186
1187 runAlter(ChangeLevel.METADATA, "ALTER TABLE c ALTER COLUMN id SET GENERATED ALWAYS AS IDENTITY");
1188 Column newColumn = getUserTable(id).getColumn("id");1188 Column newColumn = getUserTable(id).getColumn("id");
1189 assertEquals("altered is always", false, newColumn.getDefaultIdentity());1189 assertEquals("altered is always", false, newColumn.getDefaultIdentity());
1190 seq = newColumn.getIdentityGenerator();
1191 assertEquals("Sequence name prefix",
1192 true,
1193 seq.getSequenceName().getTableName().startsWith(DefaultNameGenerator.IDENTITY_SEQUENCE_PREFIX));
1190 }1194 }
1191}1195}
11921196
=== modified file 'src/test/java/com/akiban/sql/aisddl/AlterTableDDLTest.java'
--- src/test/java/com/akiban/sql/aisddl/AlterTableDDLTest.java 2013-03-22 20:05:57 +0000
+++ src/test/java/com/akiban/sql/aisddl/AlterTableDDLTest.java 2013-04-15 20:33:27 +0000
@@ -24,6 +24,7 @@
24import com.akiban.ais.model.IndexColumn;24import com.akiban.ais.model.IndexColumn;
25import com.akiban.ais.model.Join;25import com.akiban.ais.model.Join;
26import com.akiban.ais.model.JoinColumn;26import com.akiban.ais.model.JoinColumn;
27import com.akiban.ais.model.Sequence;
27import com.akiban.ais.model.TableName;28import com.akiban.ais.model.TableName;
28import com.akiban.ais.model.UserTable;29import com.akiban.ais.model.UserTable;
29import com.akiban.ais.model.aisb2.AISBBasedBuilder;30import com.akiban.ais.model.aisb2.AISBBasedBuilder;
@@ -31,6 +32,8 @@
31import com.akiban.ais.util.TableChange;32import com.akiban.ais.util.TableChange;
32import com.akiban.qp.operator.QueryContext;33import com.akiban.qp.operator.QueryContext;
33import com.akiban.server.api.ddl.DDLFunctionsMockBase;34import com.akiban.server.api.ddl.DDLFunctionsMockBase;
35import com.akiban.server.error.ColumnAlreadyGeneratedException;
36import com.akiban.server.error.ColumnNotGeneratedException;
34import com.akiban.server.error.DuplicateColumnNameException;37import com.akiban.server.error.DuplicateColumnNameException;
35import com.akiban.server.error.DuplicateIndexException;38import com.akiban.server.error.DuplicateIndexException;
36import com.akiban.server.error.JoinColumnMismatchException;39import com.akiban.server.error.JoinColumnMismatchException;
@@ -42,6 +45,7 @@
42import com.akiban.server.error.NoSuchTableException;45import com.akiban.server.error.NoSuchTableException;
43import com.akiban.server.error.NoSuchUniqueException;46import com.akiban.server.error.NoSuchUniqueException;
44import com.akiban.server.error.UnsupportedCheckConstraintException;47import com.akiban.server.error.UnsupportedCheckConstraintException;
48import com.akiban.server.error.UnsupportedSQLException;
45import com.akiban.server.service.session.Session;49import com.akiban.server.service.session.Session;
46import com.akiban.server.types3.Types3Switch;50import com.akiban.server.types3.Types3Switch;
47import com.akiban.sql.StandardException;51import com.akiban.sql.StandardException;
@@ -208,7 +212,7 @@
208 expectColumnChanges("ADD:new");212 expectColumnChanges("ADD:new");
209 expectIndexChanges();213 expectIndexChanges();
210 if (Types3Switch.ON) {214 if (Types3Switch.ON) {
211 expectFinalTable(A_NAME, "aid MCOMPAT_ BIGINT(21) NOT NULL", "new MCOMPAT_ BIGINT(21) NOT NULL", "UNIQUE new(new)");215 expectFinalTable(A_NAME, "aid MCOMPAT_ BIGINT(21) NOT NULL", "new MCOMPAT_ BIGINT(21) NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1)", "UNIQUE new(new)");
212 } else {216 } else {
213 expectFinalTable(A_NAME, "aid bigint NOT NULL", "new bigint NOT NULL", "UNIQUE new(new)");217 expectFinalTable(A_NAME, "aid bigint NOT NULL", "new bigint NOT NULL", "UNIQUE new(new)");
214 }218 }
@@ -221,7 +225,7 @@
221 expectColumnChanges("ADD:new");225 expectColumnChanges("ADD:new");
222 expectIndexChanges("ADD:PRIMARY");226 expectIndexChanges("ADD:PRIMARY");
223 if (Types3Switch.ON) {227 if (Types3Switch.ON) {
224 expectFinalTable(A_NAME, "aid MCOMPAT_ BIGINT(21) NOT NULL", "new MCOMPAT_ BIGINT(21) NOT NULL", "UNIQUE new(new)", "PRIMARY(new)");228 expectFinalTable(A_NAME, "aid MCOMPAT_ BIGINT(21) NOT NULL", "new MCOMPAT_ BIGINT(21) NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1)", "UNIQUE new(new)", "PRIMARY(new)");
225 } else {229 } else {
226 expectFinalTable(A_NAME, "aid bigint NOT NULL", "new bigint NOT NULL", "UNIQUE new(new)", "PRIMARY(new)");230 expectFinalTable(A_NAME, "aid bigint NOT NULL", "new bigint NOT NULL", "UNIQUE new(new)", "PRIMARY(new)");
227 }231 }
@@ -540,6 +544,84 @@
540 }544 }
541545
542 //546 //
547 // ALTER COLUMN DROP DEFAULT (where default is generated)
548 //
549 @Test
550 public void alterColumnDropDefaultGenerated() throws StandardException {
551 buildCWithGeneratedID(1, true);
552 parseAndRun("ALTER TABLE c ALTER COLUMN id DROP DEFAULT");
553 expectColumnChanges("MODIFY:id->id");
554 expectIndexChanges();
555 expectFinalTable(C_NAME, "id MCOMPAT_ INTEGER(11) NOT NULL", "PRIMARY(id)");
556 }
557
558 //
559 // ALTER COLUMN SET INCREMENT BY <number>
560 //
561
562 @Test
563 public void alterColumnSetIncrementByLess() throws StandardException {
564 buildCWithGeneratedID(1, true);
565 parseAndRun("ALTER TABLE c ALTER COLUMN id SET INCREMENT BY -1");
566 expectColumnChanges("MODIFY:id->id");
567 expectIndexChanges();
568 expectFinalTable(C_NAME, "id MCOMPAT_ INTEGER(11) NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY -1)", "PRIMARY(id)");
569 }
570
571 @Test
572 public void alterColumnSetIncrementByMore() throws StandardException {
573 buildCWithGeneratedID(1, true);
574 parseAndRun("ALTER TABLE c ALTER COLUMN id SET INCREMENT BY 5");
575 expectColumnChanges("MODIFY:id->id");
576 expectIndexChanges();
577 expectFinalTable(C_NAME, "id MCOMPAT_ INTEGER(11) NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 5)", "PRIMARY(id)");
578 }
579
580 @Test(expected=ColumnNotGeneratedException.class)
581 public void alterColumnSetIncrementInvalid() throws StandardException {
582 buildCWithID();
583 parseAndRun("ALTER TABLE c ALTER COLUMN id SET INCREMENT BY 5");
584 }
585
586 //
587 // ALTER COLUMN RESTART WITH <number>
588 //
589
590 @Test(expected=UnsupportedSQLException.class)
591 public void alterColumnRestartWith() throws StandardException {
592 buildCWithGeneratedID(1, true);
593 parseAndRun("ALTER TABLE c ALTER COLUMN id RESTART WITH 10");
594 }
595
596 //
597 // ALTER COLUMN [SET] GENERATED <BY DEFAULT | ALWAYS>
598 //
599
600 @Test
601 public void alterColumnSetGeneratedByDefault() throws StandardException {
602 buildCWithID();
603 parseAndRun("ALTER TABLE c ALTER COLUMN id SET GENERATED BY DEFAULT AS IDENTITY (START WITH 10, INCREMENT BY 50)");
604 expectColumnChanges("MODIFY:id->id");
605 expectIndexChanges();
606 expectFinalTable(C_NAME, "id MCOMPAT_ INTEGER(11) NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 10, INCREMENT BY 50)", "PRIMARY(id)");
607 }
608
609 @Test
610 public void alterColumnSetGeneratedAlways() throws StandardException {
611 buildCWithID();
612 parseAndRun("ALTER TABLE c ALTER COLUMN id SET GENERATED ALWAYS AS IDENTITY (START WITH 42, INCREMENT BY 100)");
613 expectColumnChanges("MODIFY:id->id");
614 expectIndexChanges();
615 expectFinalTable(C_NAME, "id MCOMPAT_ INTEGER(11) NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 42, INCREMENT BY 100)", "PRIMARY(id)");
616 }
617
618 @Test(expected=ColumnAlreadyGeneratedException.class)
619 public void alterColumnSetGeneratedAlreadyGenerated() throws StandardException {
620 buildCWithGeneratedID(1, true);
621 parseAndRun("ALTER TABLE c ALTER COLUMN id SET GENERATED ALWAYS AS IDENTITY (START WITH 42, INCREMENT BY 100)");
622 }
623
624 //
543 // ADD [CONSTRAINT] UNIQUE625 // ADD [CONSTRAINT] UNIQUE
544 //626 //
545627
@@ -1155,6 +1237,14 @@
1155 builder.userTable(A_NAME).colBigInt("id", false).colBigInt("other_id", true).pk("id");1237 builder.userTable(A_NAME).colBigInt("id", false).colBigInt("other_id", true).pk("id");
1156 }1238 }
11571239
1240 private void buildCWithGeneratedID(int startWith, boolean always) {
1241 builder.userTable(C_NAME).autoIncLong("id", startWith, always).pk("id");
1242 }
1243
1244 private void buildCWithID() {
1245 builder.userTable(C_NAME).colLong("id", false).pk("id");
1246 }
1247
1158 private static class DDLFunctionsMock extends DDLFunctionsMockBase {1248 private static class DDLFunctionsMock extends DDLFunctionsMockBase {
1159 final AkibanInformationSchema ais;1249 final AkibanInformationSchema ais;
1160 final List<String> columnChangeDesc = new ArrayList<>();1250 final List<String> columnChangeDesc = new ArrayList<>();
@@ -1212,6 +1302,17 @@
1212 sb.append(" DEFAULT ");1302 sb.append(" DEFAULT ");
1213 sb.append(defaultVal);1303 sb.append(defaultVal);
1214 }1304 }
1305 Boolean identity = col.getDefaultIdentity();
1306 if(identity != null) {
1307 Sequence seq = col.getIdentityGenerator();
1308 sb.append(" GENERATED ");
1309 sb.append(identity ? "BY DEFAULT" : "ALWAYS");
1310 sb.append(" AS IDENTITY (START WITH ");
1311 sb.append(seq.getStartsWith());
1312 sb.append(", INCREMENT BY ");
1313 sb.append(seq.getIncrement());
1314 sb.append(')');
1315 }
1215 }1316 }
1216 for(Index index : table.getIndexes()) {1317 for(Index index : table.getIndexes()) {
1217 sb.append(", ");1318 sb.append(", ");
12181319
=== modified file 'src/test/java/com/akiban/sql/aisddl/TableDDLIT.java'
--- src/test/java/com/akiban/sql/aisddl/TableDDLIT.java 2013-04-11 05:21:42 +0000
+++ src/test/java/com/akiban/sql/aisddl/TableDDLIT.java 2013-04-15 20:33:27 +0000
@@ -106,7 +106,7 @@
106 assertNotNull(table);106 assertNotNull(table);
107 assertEquals(table.getColumn(0).getType(), Types.INT);107 assertEquals(table.getColumn(0).getType(), Types.INT);
108 assertEquals(table.getPrimaryKey().getColumns().get(0), table.getColumn(0));108 assertEquals(table.getPrimaryKey().getColumns().get(0), table.getColumn(0));
109 assertEquals(1000L, table.getColumn(0).getInitialAutoIncrementValue().longValue());109 assertEquals(1000L, table.getColumn(0).getIdentityGenerator().getStartsWith());
110 }110 }
111111
112 @Test112 @Test
113113
=== modified file 'src/test/resources/com/akiban/sql/pg/yaml/functional/test-identity.yaml'
--- src/test/resources/com/akiban/sql/pg/yaml/functional/test-identity.yaml 2012-09-26 03:50:12 +0000
+++ src/test/resources/com/akiban/sql/pg/yaml/functional/test-identity.yaml 2013-04-15 20:33:27 +0000
@@ -146,4 +146,17 @@
146---146---
147- Statement: select * from t147- Statement: select * from t
148- output: [[1, 1, null]]148- output: [[1, 1, null]]
149---
150- DropTable: t
151
152---
153- CreateTable: t (id int not null primary key)
154---
155- Statement: ALTER TABLE t ALTER COLUMN id SET GENERATED BY DEFAULT AS IDENTITY (START WITH 42, INCREMENT BY 5)
156---
157- Statement: INSERT INTO t VALUES (NULL),(NULL),(NULL)
158---
159- Statement: SELECT * FROM t
160- output: [[42],[47],[52]]
161
149...162...

Subscribers

People subscribed via source and target branches