Merge lp:~nwilliams/akiban-server/alter-generated into lp:~akiban-technologies/akiban-server/trunk
- alter-generated
- Merge into trunk
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mike McMahon | Approve | ||
Review via email: mp+158990@code.launchpad.net |
Commit message
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.
- 2626. By Nathan Williams
-
Remove dead variable
Nathan Williams (nwilliams) wrote : | # |
Indeed it was. Removed.
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.
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
Preview Diff
1 | === modified file 'src/main/java/com/akiban/ais/model/AISBuilder.java' | |||
2 | --- src/main/java/com/akiban/ais/model/AISBuilder.java 2013-03-22 20:05:57 +0000 | |||
3 | +++ src/main/java/com/akiban/ais/model/AISBuilder.java 2013-04-15 20:33:27 +0000 | |||
4 | @@ -75,12 +75,12 @@ | |||
5 | 75 | return nameGenerator; | 75 | return nameGenerator; |
6 | 76 | } | 76 | } |
7 | 77 | 77 | ||
11 | 78 | public void sequence (String schemaName, String sequenceName, | 78 | public Sequence sequence(String schemaName, String sequenceName, |
12 | 79 | long start, long increment, | 79 | long start, long increment, long minValue, long maxValue, boolean cycle) { |
10 | 80 | long minValue, long maxValue, boolean cycle) { | ||
13 | 81 | LOG.trace("sequence: {}.{} ", schemaName,sequenceName); | 80 | LOG.trace("sequence: {}.{} ", schemaName,sequenceName); |
14 | 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); |
15 | 83 | identityGenerator.setTreeName(nameGenerator.generateSequenceTreeName(identityGenerator)); | 82 | identityGenerator.setTreeName(nameGenerator.generateSequenceTreeName(identityGenerator)); |
16 | 83 | return identityGenerator; | ||
17 | 84 | } | 84 | } |
18 | 85 | 85 | ||
19 | 86 | public UserTable userTable(String schemaName, String tableName) { | 86 | public UserTable userTable(String schemaName, String tableName) { |
20 | 87 | 87 | ||
21 | === modified file 'src/main/java/com/akiban/ais/model/AISMerge.java' | |||
22 | --- src/main/java/com/akiban/ais/model/AISMerge.java 2013-04-11 03:40:21 +0000 | |||
23 | +++ src/main/java/com/akiban/ais/model/AISMerge.java 2013-04-15 20:33:27 +0000 | |||
24 | @@ -86,6 +86,20 @@ | |||
25 | 86 | } | 86 | } |
26 | 87 | } | 87 | } |
27 | 88 | 88 | ||
28 | 89 | private static class IdentityInfo { | ||
29 | 90 | public final TableName tableName; | ||
30 | 91 | public final String columnName; | ||
31 | 92 | public final boolean defaultIdentity; | ||
32 | 93 | public final Sequence sequence; | ||
33 | 94 | |||
34 | 95 | public IdentityInfo(TableName tableName, String columnName, boolean defaultIdentity, Sequence sequence) { | ||
35 | 96 | this.tableName = tableName; | ||
36 | 97 | this.columnName = columnName; | ||
37 | 98 | this.defaultIdentity = defaultIdentity; | ||
38 | 99 | this.sequence = sequence; | ||
39 | 100 | } | ||
40 | 101 | } | ||
41 | 102 | |||
42 | 89 | private static final Logger LOG = LoggerFactory.getLogger(AISMerge.class); | 103 | private static final Logger LOG = LoggerFactory.getLogger(AISMerge.class); |
43 | 90 | 104 | ||
44 | 91 | /* state */ | 105 | /* state */ |
45 | @@ -95,16 +109,17 @@ | |||
46 | 95 | private final MergeType mergeType; | 109 | private final MergeType mergeType; |
47 | 96 | private final List<JoinChange> changedJoins; | 110 | private final List<JoinChange> changedJoins; |
48 | 97 | private final Map<IndexName,IndexInfo> indexesToFix; | 111 | private final Map<IndexName,IndexInfo> indexesToFix; |
49 | 112 | private final List<IdentityInfo> identityToFix; | ||
50 | 98 | 113 | ||
51 | 99 | 114 | ||
52 | 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}. */ |
53 | 101 | AISMerge(AkibanInformationSchema sourceAIS, UserTable newTable) { | 116 | AISMerge(AkibanInformationSchema sourceAIS, UserTable newTable) { |
55 | 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); |
56 | 103 | } | 118 | } |
57 | 104 | 119 | ||
58 | 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. */ |
59 | 106 | public static AISMerge newForAddTable(NameGenerator generator, AkibanInformationSchema sourceAIS, UserTable newTable) { | 121 | public static AISMerge newForAddTable(NameGenerator generator, AkibanInformationSchema sourceAIS, UserTable newTable) { |
61 | 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); |
62 | 108 | } | 123 | } |
63 | 109 | 124 | ||
64 | 110 | /** Create a new AISMerge to be used for modifying a table. */ | 125 | /** Create a new AISMerge to be used for modifying a table. */ |
65 | @@ -112,27 +127,30 @@ | |||
66 | 112 | Collection<ChangedTableDescription> alteredTables) { | 127 | Collection<ChangedTableDescription> alteredTables) { |
67 | 113 | List<JoinChange> changedJoins = new ArrayList<>(); | 128 | List<JoinChange> changedJoins = new ArrayList<>(); |
68 | 114 | Map<IndexName,IndexInfo> indexesToFix = new HashMap<>(); | 129 | Map<IndexName,IndexInfo> indexesToFix = new HashMap<>(); |
71 | 115 | AkibanInformationSchema targetAIS = copyAISForModify(sourceAIS, indexesToFix, changedJoins, alteredTables); | 130 | List<IdentityInfo> identityToFix = new ArrayList<>(); |
72 | 116 | return new AISMerge(generator, targetAIS, null, MergeType.MODIFY_TABLE, changedJoins, indexesToFix); | 131 | AkibanInformationSchema targetAIS = copyAISForModify(sourceAIS, indexesToFix, changedJoins, identityToFix, alteredTables); |
73 | 132 | return new AISMerge(generator, targetAIS, null, MergeType.MODIFY_TABLE, changedJoins, indexesToFix, identityToFix); | ||
74 | 117 | } | 133 | } |
75 | 118 | 134 | ||
76 | 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)}. */ |
77 | 120 | public static AISMerge newForAddIndex(NameGenerator generator, AkibanInformationSchema sourceAIS) { | 136 | public static AISMerge newForAddIndex(NameGenerator generator, AkibanInformationSchema sourceAIS) { |
79 | 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); |
80 | 122 | } | 138 | } |
81 | 123 | 139 | ||
82 | 124 | public static AISMerge newForOther(NameGenerator generator, AkibanInformationSchema sourceAIS) { | 140 | public static AISMerge newForOther(NameGenerator generator, AkibanInformationSchema sourceAIS) { |
84 | 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); |
85 | 126 | } | 142 | } |
86 | 127 | 143 | ||
87 | 128 | private AISMerge(NameGenerator nameGenerator, AkibanInformationSchema targetAIS, UserTable sourceTable, | 144 | private AISMerge(NameGenerator nameGenerator, AkibanInformationSchema targetAIS, UserTable sourceTable, |
89 | 129 | MergeType mergeType, List<JoinChange> changedJoins, Map<IndexName,IndexInfo> indexesToFix) { | 145 | MergeType mergeType, List<JoinChange> changedJoins, Map<IndexName,IndexInfo> indexesToFix, |
90 | 146 | List<IdentityInfo> identityToFix) { | ||
91 | 130 | this.nameGenerator = nameGenerator; | 147 | this.nameGenerator = nameGenerator; |
92 | 131 | this.targetAIS = targetAIS; | 148 | this.targetAIS = targetAIS; |
93 | 132 | this.sourceTable = sourceTable; | 149 | this.sourceTable = sourceTable; |
94 | 133 | this.mergeType = mergeType; | 150 | this.mergeType = mergeType; |
95 | 134 | this.changedJoins = changedJoins; | 151 | this.changedJoins = changedJoins; |
96 | 135 | this.indexesToFix = indexesToFix; | 152 | this.indexesToFix = indexesToFix; |
97 | 153 | this.identityToFix = identityToFix; | ||
98 | 136 | } | 154 | } |
99 | 137 | 155 | ||
100 | 138 | 156 | ||
101 | @@ -143,6 +161,7 @@ | |||
102 | 143 | private static AkibanInformationSchema copyAISForModify(AkibanInformationSchema oldAIS, | 161 | private static AkibanInformationSchema copyAISForModify(AkibanInformationSchema oldAIS, |
103 | 144 | Map<IndexName,IndexInfo> indexesToFix, | 162 | Map<IndexName,IndexInfo> indexesToFix, |
104 | 145 | final List<JoinChange> joinsToFix, | 163 | final List<JoinChange> joinsToFix, |
105 | 164 | List<IdentityInfo> identityToFix, | ||
106 | 146 | Collection<ChangedTableDescription> changedTables) | 165 | Collection<ChangedTableDescription> changedTables) |
107 | 147 | { | 166 | { |
108 | 148 | final Set<Sequence> excludedSequences = new HashSet<>(); | 167 | final Set<Sequence> excludedSequences = new HashSet<>(); |
109 | @@ -218,6 +237,11 @@ | |||
110 | 218 | for(TableName name : desc.getDroppedSequences()) { | 237 | for(TableName name : desc.getDroppedSequences()) { |
111 | 219 | excludedSequences.add(oldAIS.getSequence(name)); | 238 | excludedSequences.add(oldAIS.getSequence(name)); |
112 | 220 | } | 239 | } |
113 | 240 | |||
114 | 241 | for(String name : desc.getIdentityAdded()) { | ||
115 | 242 | Column col = newTable.getColumn(name); | ||
116 | 243 | identityToFix.add(new IdentityInfo(desc.getNewName(), name, col.getDefaultIdentity(), col.getIdentityGenerator())); | ||
117 | 244 | } | ||
118 | 221 | } | 245 | } |
119 | 222 | 246 | ||
120 | 223 | return AISCloner.clone( | 247 | return AISCloner.clone( |
121 | @@ -481,6 +505,11 @@ | |||
122 | 481 | index.setTreeName((info.tree != null) ? info.tree : nameGenerator.generateIndexTreeName(index)); | 505 | index.setTreeName((info.tree != null) ? info.tree : nameGenerator.generateIndexTreeName(index)); |
123 | 482 | } | 506 | } |
124 | 483 | 507 | ||
125 | 508 | for(IdentityInfo info : identityToFix) { | ||
126 | 509 | addIdentitySequence(builder, info.tableName.getSchemaName(), info.tableName.getTableName(), info.columnName, | ||
127 | 510 | info.defaultIdentity, info.sequence); | ||
128 | 511 | } | ||
129 | 512 | |||
130 | 484 | builder.akibanInformationSchema().validate(AISValidations.LIVE_AIS_VALIDATIONS).throwIfNecessary(); | 513 | builder.akibanInformationSchema().validate(AISValidations.LIVE_AIS_VALIDATIONS).throwIfNecessary(); |
131 | 485 | builder.akibanInformationSchema().freeze(); | 514 | builder.akibanInformationSchema().freeze(); |
132 | 486 | } | 515 | } |
133 | @@ -529,16 +558,8 @@ | |||
134 | 529 | newColumn.setInitialAutoIncrementValue(column.getInitialAutoIncrementValue()); | 558 | newColumn.setInitialAutoIncrementValue(column.getInitialAutoIncrementValue()); |
135 | 530 | } | 559 | } |
136 | 531 | if (column.getDefaultIdentity() != null) { | 560 | if (column.getDefaultIdentity() != null) { |
147 | 532 | TableName sequenceName = nameGenerator.generateIdentitySequenceName(new TableName(schemaName, tableName)); | 561 | addIdentitySequence(builder, schemaName, tableName, column.getName(), |
148 | 533 | Sequence sequence = column.getIdentityGenerator(); | 562 | column.getDefaultIdentity(), column.getIdentityGenerator()); |
139 | 534 | builder.sequence(sequenceName.getSchemaName(), sequenceName.getTableName(), | ||
140 | 535 | sequence.getStartsWith(), | ||
141 | 536 | sequence.getIncrement(), | ||
142 | 537 | sequence.getMinValue(), | ||
143 | 538 | sequence.getMaxValue(), | ||
144 | 539 | sequence.isCycle()); | ||
145 | 540 | builder.columnAsIdentity(schemaName, tableName, column.getName(), sequenceName.getTableName(), column.getDefaultIdentity()); | ||
146 | 541 | LOG.debug("Generated sequence: {}, with tree name; {}", sequenceName, sequence.getTreeName()); | ||
149 | 542 | } | 563 | } |
150 | 543 | // Proactively cache, can go away if Column ever cleans itself up | 564 | // Proactively cache, can go away if Column ever cleans itself up |
151 | 544 | newColumn.getMaxStorageSize(); | 565 | newColumn.getMaxStorageSize(); |
152 | @@ -546,6 +567,19 @@ | |||
153 | 546 | } | 567 | } |
154 | 547 | } | 568 | } |
155 | 548 | 569 | ||
156 | 570 | private void addIdentitySequence(AISBuilder builder, String schemaName, String tableName, String column, | ||
157 | 571 | boolean defaultIdentity, Sequence sequence) { | ||
158 | 572 | TableName sequenceName = nameGenerator.generateIdentitySequenceName(new TableName(schemaName, tableName)); | ||
159 | 573 | Sequence newSeq = builder.sequence(sequenceName.getSchemaName(), sequenceName.getTableName(), | ||
160 | 574 | sequence.getStartsWith(), | ||
161 | 575 | sequence.getIncrement(), | ||
162 | 576 | sequence.getMinValue(), | ||
163 | 577 | sequence.getMaxValue(), | ||
164 | 578 | sequence.isCycle()); | ||
165 | 579 | builder.columnAsIdentity(schemaName, tableName, column, sequenceName.getTableName(), defaultIdentity); | ||
166 | 580 | LOG.debug("Generated sequence: {}, with tree name; {}", sequenceName, newSeq.getTreeName()); | ||
167 | 581 | } | ||
168 | 582 | |||
169 | 549 | private void addNewGroup (AISBuilder builder, UserTable rootTable) { | 583 | private void addNewGroup (AISBuilder builder, UserTable rootTable) { |
170 | 550 | TableName groupName = rootTable.getName(); | 584 | TableName groupName = rootTable.getName(); |
171 | 551 | builder.createGroup(groupName.getTableName(), groupName.getSchemaName()); | 585 | builder.createGroup(groupName.getTableName(), groupName.getSchemaName()); |
172 | @@ -650,13 +684,18 @@ | |||
173 | 650 | 684 | ||
174 | 651 | public AkibanInformationSchema mergeSequence(Sequence sequence) | 685 | public AkibanInformationSchema mergeSequence(Sequence sequence) |
175 | 652 | { | 686 | { |
176 | 687 | mergeSequenceInternal(sequence); | ||
177 | 688 | targetAIS.validate(AISValidations.LIVE_AIS_VALIDATIONS).throwIfNecessary(); | ||
178 | 689 | targetAIS.freeze(); | ||
179 | 690 | return targetAIS; | ||
180 | 691 | } | ||
181 | 692 | |||
182 | 693 | private Sequence mergeSequenceInternal(Sequence sequence) | ||
183 | 694 | { | ||
184 | 653 | Sequence newSeq = Sequence.create(targetAIS, sequence); | 695 | Sequence newSeq = Sequence.create(targetAIS, sequence); |
185 | 654 | newSeq.setTreeName(nameGenerator.generateSequenceTreeName(newSeq)); | 696 | newSeq.setTreeName(nameGenerator.generateSequenceTreeName(newSeq)); |
191 | 655 | targetAIS.addSequence(newSeq); | 697 | return newSeq; |
192 | 656 | targetAIS.validate(AISValidations.LIVE_AIS_VALIDATIONS).throwIfNecessary(); | 698 | } |
188 | 657 | targetAIS.freeze(); | ||
189 | 658 | return targetAIS; | ||
190 | 659 | } | ||
193 | 660 | 699 | ||
194 | 661 | public static AkibanInformationSchema mergeRoutine(AkibanInformationSchema oldAIS, | 700 | public static AkibanInformationSchema mergeRoutine(AkibanInformationSchema oldAIS, |
195 | 662 | Routine routine) { | 701 | Routine routine) { |
196 | 663 | 702 | ||
197 | === modified file 'src/main/java/com/akiban/ais/model/AkibanInformationSchema.java' | |||
198 | --- src/main/java/com/akiban/ais/model/AkibanInformationSchema.java 2013-03-22 20:05:57 +0000 | |||
199 | +++ src/main/java/com/akiban/ais/model/AkibanInformationSchema.java 2013-04-15 20:33:27 +0000 | |||
200 | @@ -642,7 +642,7 @@ | |||
201 | 642 | invalidateTableIdMap(); | 642 | invalidateTableIdMap(); |
202 | 643 | } | 643 | } |
203 | 644 | 644 | ||
205 | 645 | void removeSequence (TableName name) { | 645 | public void removeSequence (TableName name) { |
206 | 646 | sequences.remove(name); | 646 | sequences.remove(name); |
207 | 647 | Schema schema = getSchema(name.getSchemaName()); | 647 | Schema schema = getSchema(name.getSchemaName()); |
208 | 648 | if (schema != null) { | 648 | if (schema != null) { |
209 | 649 | 649 | ||
210 | === modified file 'src/main/java/com/akiban/ais/model/DefaultNameGenerator.java' | |||
211 | --- src/main/java/com/akiban/ais/model/DefaultNameGenerator.java 2013-03-22 20:05:57 +0000 | |||
212 | +++ src/main/java/com/akiban/ais/model/DefaultNameGenerator.java 2013-04-15 20:33:27 +0000 | |||
213 | @@ -34,6 +34,8 @@ | |||
214 | 34 | public class DefaultNameGenerator implements NameGenerator { | 34 | public class DefaultNameGenerator implements NameGenerator { |
215 | 35 | private static final Logger LOG = LoggerFactory.getLogger(DefaultNameGenerator.class); | 35 | private static final Logger LOG = LoggerFactory.getLogger(DefaultNameGenerator.class); |
216 | 36 | 36 | ||
217 | 37 | public static final String IDENTITY_SEQUENCE_PREFIX = "_sequence-"; | ||
218 | 38 | |||
219 | 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. |
220 | 38 | static final int USER_TABLE_ID_OFFSET = 1; | 40 | static final int USER_TABLE_ID_OFFSET = 1; |
221 | 39 | static final int IS_TABLE_ID_OFFSET = 1000000000; | 41 | static final int IS_TABLE_ID_OFFSET = 1000000000; |
222 | @@ -99,7 +101,7 @@ | |||
223 | 99 | 101 | ||
224 | 100 | @Override | 102 | @Override |
225 | 101 | public TableName generateIdentitySequenceName(TableName tableName) { | 103 | public TableName generateIdentitySequenceName(TableName tableName) { |
227 | 102 | TableName seqName = new TableName(tableName.getSchemaName(), "_sequence-" + tableName.hashCode()); | 104 | TableName seqName = new TableName(tableName.getSchemaName(), IDENTITY_SEQUENCE_PREFIX + tableName.hashCode()); |
228 | 103 | return makeUnique(sequenceNames, seqName); | 105 | return makeUnique(sequenceNames, seqName); |
229 | 104 | } | 106 | } |
230 | 105 | 107 | ||
231 | 106 | 108 | ||
232 | === modified file 'src/main/java/com/akiban/ais/model/aisb2/AISBBasedBuilder.java' | |||
233 | --- src/main/java/com/akiban/ais/model/aisb2/AISBBasedBuilder.java 2013-04-10 23:46:56 +0000 | |||
234 | +++ src/main/java/com/akiban/ais/model/aisb2/AISBBasedBuilder.java 2013-04-15 20:33:27 +0000 | |||
235 | @@ -214,29 +214,35 @@ | |||
236 | 214 | 214 | ||
237 | 215 | @Override | 215 | @Override |
238 | 216 | public NewUserTableBuilder colLong(String name) { | 216 | public NewUserTableBuilder colLong(String name) { |
240 | 217 | return colLong(name, NULLABLE_DEFAULT, null); | 217 | return colLong(name, NULLABLE_DEFAULT, null, null); |
241 | 218 | } | 218 | } |
242 | 219 | 219 | ||
243 | 220 | @Override | 220 | @Override |
244 | 221 | public NewUserTableBuilder colLong(String name, boolean nullable) { | 221 | public NewUserTableBuilder colLong(String name, boolean nullable) { |
246 | 222 | return colLong(name, nullable, null); | 222 | return colLong(name, nullable, null, null); |
247 | 223 | } | 223 | } |
248 | 224 | 224 | ||
249 | 225 | @Override | 225 | @Override |
250 | 226 | public NewUserTableBuilder autoIncLong(String name, int initialValue) { | 226 | public NewUserTableBuilder autoIncLong(String name, int initialValue) { |
255 | 227 | return colLong(name, false, initialValue); | 227 | return colLong(name, false, initialValue, true); |
256 | 228 | } | 228 | } |
257 | 229 | 229 | ||
258 | 230 | private NewUserTableBuilder colLong(String name, boolean nullable, Integer initialAutoInc) { | 230 | @Override |
259 | 231 | public NewUserTableBuilder autoIncLong(String name, int initialValue, boolean always) { | ||
260 | 232 | return colLong(name, false, initialValue, !always); | ||
261 | 233 | } | ||
262 | 234 | |||
263 | 235 | private NewUserTableBuilder colLong(String name, boolean nullable, Integer initialAutoInc, Boolean defaultIdentity) { | ||
264 | 231 | checkUsable(); | 236 | checkUsable(); |
265 | 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); |
266 | 233 | if (initialAutoInc != null) { | 238 | if (initialAutoInc != null) { |
267 | 239 | assert defaultIdentity != null; | ||
268 | 234 | String sequenceName = "temp-seq-" + userTable + "-" + name; | 240 | String sequenceName = "temp-seq-" + userTable + "-" + name; |
269 | 235 | long initValue = initialAutoInc.longValue(); | 241 | long initValue = initialAutoInc.longValue(); |
270 | 236 | aisb.sequence(schema, sequenceName, | 242 | aisb.sequence(schema, sequenceName, |
271 | 237 | initValue, 1L, initValue, Long.MAX_VALUE, | 243 | initValue, 1L, initValue, Long.MAX_VALUE, |
272 | 238 | false); | 244 | false); |
274 | 239 | aisb.columnAsIdentity(schema, userTable, name, sequenceName, true); | 245 | aisb.columnAsIdentity(schema, userTable, name, sequenceName, defaultIdentity); |
275 | 240 | aisb.akibanInformationSchema(). | 246 | aisb.akibanInformationSchema(). |
276 | 241 | getUserTable(schema, userTable). | 247 | getUserTable(schema, userTable). |
277 | 242 | getColumn(name). | 248 | getColumn(name). |
278 | 243 | 249 | ||
279 | === modified file 'src/main/java/com/akiban/ais/model/aisb2/NewUserTableBuilder.java' | |||
280 | --- src/main/java/com/akiban/ais/model/aisb2/NewUserTableBuilder.java 2013-04-01 18:36:36 +0000 | |||
281 | +++ src/main/java/com/akiban/ais/model/aisb2/NewUserTableBuilder.java 2013-04-15 20:33:27 +0000 | |||
282 | @@ -67,13 +67,23 @@ | |||
283 | 67 | NewUserTableBuilder colLong(String name, boolean nullable); | 67 | NewUserTableBuilder colLong(String name, boolean nullable); |
284 | 68 | 68 | ||
285 | 69 | /** | 69 | /** |
287 | 70 | * Adds a non-nullable, sequence backed, auto-incrementing column | 70 | * Adds a non-nullable, sequence backed, auto-incrementing BY DEFAULT identity column |
288 | 71 | * @param name the column's name | 71 | * @param name the column's name |
289 | 72 | * @param initialValue the START WITH value | ||
290 | 72 | * @return this | 73 | * @return this |
291 | 73 | */ | 74 | */ |
292 | 74 | NewUserTableBuilder autoIncLong(String name, int initialValue); | 75 | NewUserTableBuilder autoIncLong(String name, int initialValue); |
293 | 75 | 76 | ||
294 | 76 | /** | 77 | /** |
295 | 78 | * Adds a non-nullable, sequence backed, auto-incrementing identity column | ||
296 | 79 | * @param name the column's name | ||
297 | 80 | * @param initialValue the START WITH value | ||
298 | 81 | * @param always ALWAYS if <code>true</code>, otherwise DEFAULT | ||
299 | 82 | * @return this | ||
300 | 83 | */ | ||
301 | 84 | NewUserTableBuilder autoIncLong(String name, int initialValue, boolean always); | ||
302 | 85 | |||
303 | 86 | /** | ||
304 | 77 | * Adds an optionally nullable boolean column | 87 | * Adds an optionally nullable boolean column |
305 | 78 | * @param name the column's name | 88 | * @param name the column's name |
306 | 79 | * @param nullable whether the column is nullable | 89 | * @param nullable whether the column is nullable |
307 | 80 | 90 | ||
308 | === modified file 'src/main/java/com/akiban/ais/util/ChangedTableDescription.java' | |||
309 | --- src/main/java/com/akiban/ais/util/ChangedTableDescription.java 2013-03-22 20:05:57 +0000 | |||
310 | +++ src/main/java/com/akiban/ais/util/ChangedTableDescription.java 2013-04-15 20:33:27 +0000 | |||
311 | @@ -38,6 +38,7 @@ | |||
312 | 38 | private final Map<String,String> parentColNames; | 38 | private final Map<String,String> parentColNames; |
313 | 39 | private final Map<String,String> preserveIndexes; | 39 | private final Map<String,String> preserveIndexes; |
314 | 40 | private final Collection<TableName> droppedSequences; | 40 | private final Collection<TableName> droppedSequences; |
315 | 41 | private final Collection<String> identityAdded; | ||
316 | 41 | 42 | ||
317 | 42 | /** | 43 | /** |
318 | 43 | * @param tableName Current name of the table being changed. | 44 | * @param tableName Current name of the table being changed. |
319 | @@ -46,7 +47,8 @@ | |||
320 | 46 | */ | 47 | */ |
321 | 47 | public ChangedTableDescription(TableName tableName, UserTable newDefinition, Map<String,String> colNames, | 48 | public ChangedTableDescription(TableName tableName, UserTable newDefinition, Map<String,String> colNames, |
322 | 48 | ParentChange parentChange, TableName parentName, Map<String,String> parentColNames, | 49 | ParentChange parentChange, TableName parentName, Map<String,String> parentColNames, |
324 | 49 | Map<String, String> preserveIndexes, Collection<TableName> droppedSequences) { | 50 | Map<String, String> preserveIndexes, Collection<TableName> droppedSequences, |
325 | 51 | Collection<String> identityAdded) { | ||
326 | 50 | ArgumentValidation.notNull("tableName", tableName); | 52 | ArgumentValidation.notNull("tableName", tableName); |
327 | 51 | ArgumentValidation.notNull("preserveIndexes", preserveIndexes); | 53 | ArgumentValidation.notNull("preserveIndexes", preserveIndexes); |
328 | 52 | this.tableName = tableName; | 54 | this.tableName = tableName; |
329 | @@ -57,6 +59,7 @@ | |||
330 | 57 | this.parentColNames = parentColNames; | 59 | this.parentColNames = parentColNames; |
331 | 58 | this.preserveIndexes = preserveIndexes; | 60 | this.preserveIndexes = preserveIndexes; |
332 | 59 | this.droppedSequences = droppedSequences; | 61 | this.droppedSequences = droppedSequences; |
333 | 62 | this.identityAdded = identityAdded; | ||
334 | 60 | } | 63 | } |
335 | 61 | 64 | ||
336 | 62 | public TableName getOldName() { | 65 | public TableName getOldName() { |
337 | @@ -95,6 +98,10 @@ | |||
338 | 95 | return droppedSequences; | 98 | return droppedSequences; |
339 | 96 | } | 99 | } |
340 | 97 | 100 | ||
341 | 101 | public Collection<String> getIdentityAdded() { | ||
342 | 102 | return identityAdded; | ||
343 | 103 | } | ||
344 | 104 | |||
345 | 98 | public boolean isNewGroup() { | 105 | public boolean isNewGroup() { |
346 | 99 | return (parentChange != ParentChange.NONE); | 106 | return (parentChange != ParentChange.NONE); |
347 | 100 | } | 107 | } |
348 | 101 | 108 | ||
349 | === modified file 'src/main/java/com/akiban/ais/util/TableChangeValidator.java' | |||
350 | --- src/main/java/com/akiban/ais/util/TableChangeValidator.java 2013-04-11 04:48:29 +0000 | |||
351 | +++ src/main/java/com/akiban/ais/util/TableChangeValidator.java 2013-04-15 20:33:27 +0000 | |||
352 | @@ -393,9 +393,9 @@ | |||
353 | 393 | primaryKeyChanged = containsOldOrNew(indexChanges, Index.PRIMARY_KEY_CONSTRAINT); | 393 | primaryKeyChanged = containsOldOrNew(indexChanges, Index.PRIMARY_KEY_CONSTRAINT); |
354 | 394 | 394 | ||
355 | 395 | List<TableName> droppedSequences = new ArrayList<>(); | 395 | List<TableName> droppedSequences = new ArrayList<>(); |
356 | 396 | List<String> addedIdentity = new ArrayList<>(); | ||
357 | 396 | Map<String,String> renamedColumns = new HashMap<>(); | 397 | Map<String,String> renamedColumns = new HashMap<>(); |
358 | 397 | for(TableChange change : columnChanges) { | 398 | for(TableChange change : columnChanges) { |
359 | 398 | Sequence seqToDrop = null; | ||
360 | 399 | switch(change.getChangeType()) { | 399 | switch(change.getChangeType()) { |
361 | 400 | case MODIFY: { | 400 | case MODIFY: { |
362 | 401 | if(!change.getOldName().equals(change.getNewName())) { | 401 | if(!change.getOldName().equals(change.getNewName())) { |
363 | @@ -403,20 +403,24 @@ | |||
364 | 403 | } | 403 | } |
365 | 404 | Column oldColumn = oldTable.getColumn(change.getOldName()); | 404 | Column oldColumn = oldTable.getColumn(change.getOldName()); |
366 | 405 | Column newColumn = newTable.getColumn(change.getNewName()); | 405 | Column newColumn = newTable.getColumn(change.getNewName()); |
369 | 406 | if((oldColumn != null) && (oldColumn.getIdentityGenerator() != null) && (newColumn.getIdentityGenerator() == null)) { | 406 | if((oldColumn != null)) { |
370 | 407 | seqToDrop = oldColumn.getIdentityGenerator(); | 407 | Sequence oldSeq = oldColumn.getIdentityGenerator(); |
371 | 408 | Sequence newSeq = newColumn.getIdentityGenerator(); | ||
372 | 409 | if((oldSeq == null) && (newSeq != null)) { | ||
373 | 410 | addedIdentity.add(newColumn.getName()); | ||
374 | 411 | } else if((oldSeq != null) && (newSeq == null)) { | ||
375 | 412 | droppedSequences.add(oldSeq.getSequenceName()); | ||
376 | 413 | } | ||
377 | 414 | // else both not null and not equal, not yet supported | ||
378 | 408 | } | 415 | } |
379 | 409 | } break; | 416 | } break; |
380 | 410 | case DROP: { | 417 | case DROP: { |
381 | 411 | Column oldColumn = oldTable.getColumn(change.getOldName()); | 418 | Column oldColumn = oldTable.getColumn(change.getOldName()); |
384 | 412 | if(oldColumn != null) { | 419 | if((oldColumn != null) && (oldColumn.getIdentityGenerator() != null)) { |
385 | 413 | seqToDrop = oldColumn.getIdentityGenerator(); | 420 | droppedSequences.add(oldColumn.getIdentityGenerator().getSequenceName()); |
386 | 414 | } | 421 | } |
387 | 415 | } break; | 422 | } break; |
388 | 416 | } | 423 | } |
389 | 417 | if(seqToDrop != null) { | ||
390 | 418 | droppedSequences.add(seqToDrop.getSequenceName()); | ||
391 | 419 | } | ||
392 | 420 | } | 424 | } |
393 | 421 | 425 | ||
394 | 422 | boolean renamed = !oldTable.getName().equals(newTable.getName()) || !renamedColumns.isEmpty(); | 426 | boolean renamed = !oldTable.getName().equals(newTable.getName()) || !renamedColumns.isEmpty(); |
395 | @@ -425,7 +429,7 @@ | |||
396 | 425 | TableName parentName = (newTable.getParentJoin() != null) ? newTable.getParentJoin().getParent().getName() : null; | 429 | TableName parentName = (newTable.getParentJoin() != null) ? newTable.getParentJoin().getParent().getName() : null; |
397 | 426 | changedTables.add(new ChangedTableDescription(oldTable.getName(), newTable, renamedColumns, | 430 | changedTables.add(new ChangedTableDescription(oldTable.getName(), newTable, renamedColumns, |
398 | 427 | parentChange, parentName, EMPTY_STRING_MAP, preserveIndexes, | 431 | parentChange, parentName, EMPTY_STRING_MAP, preserveIndexes, |
400 | 428 | droppedSequences)); | 432 | droppedSequences, addedIdentity)); |
401 | 429 | 433 | ||
402 | 430 | if(!isParentChanged() && !primaryKeyChanged) { | 434 | if(!isParentChanged() && !primaryKeyChanged) { |
403 | 431 | for(Index index : newTable.getIndexesIncludingInternal()) { | 435 | for(Index index : newTable.getIndexesIncludingInternal()) { |
404 | @@ -507,7 +511,7 @@ | |||
405 | 507 | parentRenames = (parentRenames != null) ? parentRenames : EMPTY_STRING_MAP; | 511 | parentRenames = (parentRenames != null) ? parentRenames : EMPTY_STRING_MAP; |
406 | 508 | changedTables.add(new ChangedTableDescription(table.getName(), null, EMPTY_STRING_MAP, | 512 | changedTables.add(new ChangedTableDescription(table.getName(), null, EMPTY_STRING_MAP, |
407 | 509 | parentChange, parentName, parentRenames, preserved, | 513 | parentChange, parentName, parentRenames, preserved, |
409 | 510 | EMPTY_TABLE_NAME_LIST)); | 514 | EMPTY_TABLE_NAME_LIST, Collections.<String>emptyList())); |
410 | 511 | } | 515 | } |
411 | 512 | 516 | ||
412 | 513 | private static boolean containsOldOrNew(List<TableChange> changes, String name) { | 517 | private static boolean containsOldOrNew(List<TableChange> changes, String name) { |
413 | 514 | 518 | ||
414 | === added file 'src/main/java/com/akiban/server/error/ColumnAlreadyGeneratedException.java' | |||
415 | --- src/main/java/com/akiban/server/error/ColumnAlreadyGeneratedException.java 1970-01-01 00:00:00 +0000 | |||
416 | +++ src/main/java/com/akiban/server/error/ColumnAlreadyGeneratedException.java 2013-04-15 20:33:27 +0000 | |||
417 | @@ -0,0 +1,31 @@ | |||
418 | 1 | /** | ||
419 | 2 | * Copyright (C) 2009-2013 Akiban Technologies, Inc. | ||
420 | 3 | * | ||
421 | 4 | * This program is free software: you can redistribute it and/or modify | ||
422 | 5 | * it under the terms of the GNU Affero General Public License as published by | ||
423 | 6 | * the Free Software Foundation, either version 3 of the License, or | ||
424 | 7 | * (at your option) any later version. | ||
425 | 8 | * | ||
426 | 9 | * This program is distributed in the hope that it will be useful, | ||
427 | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
428 | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
429 | 12 | * GNU Affero General Public License for more details. | ||
430 | 13 | * | ||
431 | 14 | * You should have received a copy of the GNU Affero General Public License | ||
432 | 15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
433 | 16 | */ | ||
434 | 17 | |||
435 | 18 | package com.akiban.server.error; | ||
436 | 19 | |||
437 | 20 | import com.akiban.ais.model.Column; | ||
438 | 21 | |||
439 | 22 | public class ColumnAlreadyGeneratedException extends InvalidOperationException { | ||
440 | 23 | public ColumnAlreadyGeneratedException(Column column) { | ||
441 | 24 | super(ErrorCode.COLUMN_ALREADY_GENERATED, | ||
442 | 25 | column.getColumnar().getName().getSchemaName(), | ||
443 | 26 | column.getColumnar().getName().getTableName(), | ||
444 | 27 | column.getName(), | ||
445 | 28 | column.getIdentityGenerator().getSchemaName(), | ||
446 | 29 | column.getIdentityGenerator().getSequenceName().getTableName()); | ||
447 | 30 | } | ||
448 | 31 | } | ||
449 | 0 | 32 | ||
450 | === added file 'src/main/java/com/akiban/server/error/ColumnNotGeneratedException.java' | |||
451 | --- src/main/java/com/akiban/server/error/ColumnNotGeneratedException.java 1970-01-01 00:00:00 +0000 | |||
452 | +++ src/main/java/com/akiban/server/error/ColumnNotGeneratedException.java 2013-04-15 20:33:27 +0000 | |||
453 | @@ -0,0 +1,29 @@ | |||
454 | 1 | /** | ||
455 | 2 | * Copyright (C) 2009-2013 Akiban Technologies, Inc. | ||
456 | 3 | * | ||
457 | 4 | * This program is free software: you can redistribute it and/or modify | ||
458 | 5 | * it under the terms of the GNU Affero General Public License as published by | ||
459 | 6 | * the Free Software Foundation, either version 3 of the License, or | ||
460 | 7 | * (at your option) any later version. | ||
461 | 8 | * | ||
462 | 9 | * This program is distributed in the hope that it will be useful, | ||
463 | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
464 | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
465 | 12 | * GNU Affero General Public License for more details. | ||
466 | 13 | * | ||
467 | 14 | * You should have received a copy of the GNU Affero General Public License | ||
468 | 15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
469 | 16 | */ | ||
470 | 17 | |||
471 | 18 | package com.akiban.server.error; | ||
472 | 19 | |||
473 | 20 | import com.akiban.ais.model.Column; | ||
474 | 21 | |||
475 | 22 | public class ColumnNotGeneratedException extends InvalidOperationException { | ||
476 | 23 | public ColumnNotGeneratedException(Column column) { | ||
477 | 24 | super(ErrorCode.COLUMN_NOT_GENERATED, | ||
478 | 25 | column.getColumnar().getName().getSchemaName(), | ||
479 | 26 | column.getColumnar().getName().getTableName(), | ||
480 | 27 | column.getName()); | ||
481 | 28 | } | ||
482 | 29 | } | ||
483 | 0 | 30 | ||
484 | === modified file 'src/main/java/com/akiban/server/error/ErrorCode.java' | |||
485 | --- src/main/java/com/akiban/server/error/ErrorCode.java 2013-04-15 14:38:06 +0000 | |||
486 | +++ src/main/java/com/akiban/server/error/ErrorCode.java 2013-04-15 20:33:27 +0000 | |||
487 | @@ -373,6 +373,8 @@ | |||
488 | 373 | INVALID_ROUTINE ("50", "024", Importance.DEBUG, InvalidRoutineException.class), | 373 | INVALID_ROUTINE ("50", "024", Importance.DEBUG, InvalidRoutineException.class), |
489 | 374 | INVALID_INDEX_ID ("50", "025", Importance.DEBUG, InvalidIndexIDException.class), | 374 | INVALID_INDEX_ID ("50", "025", Importance.DEBUG, InvalidIndexIDException.class), |
490 | 375 | MODEL_BUILDER_ERROR ("50", "026", Importance.DEBUG, ModelBuilderException.class), | 375 | MODEL_BUILDER_ERROR ("50", "026", Importance.DEBUG, ModelBuilderException.class), |
491 | 376 | COLUMN_NOT_GENERATED ("50", "027", Importance.DEBUG, ColumnNotGeneratedException.class), | ||
492 | 377 | COLUMN_ALREADY_GENERATED ("50", "028", Importance.DEBUG, ColumnAlreadyGeneratedException.class), | ||
493 | 376 | 378 | ||
494 | 377 | // Class 51 - Internal problems created by user configuration | 379 | // Class 51 - Internal problems created by user configuration |
495 | 378 | STALE_AIS ("51", "001", Importance.TRACE, OldAISException.class), | 380 | STALE_AIS ("51", "001", Importance.TRACE, OldAISException.class), |
496 | 379 | 381 | ||
497 | === modified file 'src/main/java/com/akiban/server/service/dxl/BasicDDLFunctions.java' | |||
498 | --- src/main/java/com/akiban/server/service/dxl/BasicDDLFunctions.java 2013-04-11 18:35:20 +0000 | |||
499 | +++ src/main/java/com/akiban/server/service/dxl/BasicDDLFunctions.java 2013-04-15 20:33:27 +0000 | |||
500 | @@ -31,6 +31,7 @@ | |||
501 | 31 | 31 | ||
502 | 32 | import com.akiban.ais.model.AkibanInformationSchema; | 32 | import com.akiban.ais.model.AkibanInformationSchema; |
503 | 33 | import com.akiban.ais.model.Column; | 33 | import com.akiban.ais.model.Column; |
504 | 34 | import com.akiban.ais.model.DefaultNameGenerator; | ||
505 | 34 | import com.akiban.ais.model.Group; | 35 | import com.akiban.ais.model.Group; |
506 | 35 | import com.akiban.ais.model.GroupIndex; | 36 | import com.akiban.ais.model.GroupIndex; |
507 | 36 | import com.akiban.ais.model.Index; | 37 | import com.akiban.ais.model.Index; |
508 | @@ -752,7 +753,7 @@ | |||
509 | 752 | for (Sequence sequence : schema.getSequences().values()) { | 753 | for (Sequence sequence : schema.getSequences().values()) { |
510 | 753 | // Drop the sequences in this schema, but not the | 754 | // Drop the sequences in this schema, but not the |
511 | 754 | // generator sequences, which will be dropped with the table. | 755 | // generator sequences, which will be dropped with the table. |
513 | 755 | if (!(sequence.getSequenceName().getTableName().startsWith("_sequence-"))) { | 756 | if (!(sequence.getSequenceName().getTableName().startsWith(DefaultNameGenerator.IDENTITY_SEQUENCE_PREFIX))) { |
514 | 756 | sequencesToDrop.add(sequence); | 757 | sequencesToDrop.add(sequence); |
515 | 757 | } | 758 | } |
516 | 758 | } | 759 | } |
517 | 759 | 760 | ||
518 | === modified file 'src/main/java/com/akiban/sql/aisddl/AlterTableDDL.java' | |||
519 | --- src/main/java/com/akiban/sql/aisddl/AlterTableDDL.java 2013-03-22 20:05:57 +0000 | |||
520 | +++ src/main/java/com/akiban/sql/aisddl/AlterTableDDL.java 2013-04-15 20:33:27 +0000 | |||
521 | @@ -17,7 +17,10 @@ | |||
522 | 17 | 17 | ||
523 | 18 | package com.akiban.sql.aisddl; | 18 | package com.akiban.sql.aisddl; |
524 | 19 | 19 | ||
525 | 20 | import com.akiban.ais.model.Sequence; | ||
526 | 20 | import com.akiban.server.error.AkibanInternalException; | 21 | import com.akiban.server.error.AkibanInternalException; |
527 | 22 | import com.akiban.server.error.ColumnAlreadyGeneratedException; | ||
528 | 23 | import com.akiban.server.error.ColumnNotGeneratedException; | ||
529 | 21 | import com.akiban.sql.parser.AlterTableRenameColumnNode; | 24 | import com.akiban.sql.parser.AlterTableRenameColumnNode; |
530 | 22 | import com.akiban.sql.parser.AlterTableRenameNode; | 25 | import com.akiban.sql.parser.AlterTableRenameNode; |
531 | 23 | import com.akiban.ais.AISCloner; | 26 | import com.akiban.ais.AISCloner; |
532 | @@ -122,8 +125,7 @@ | |||
533 | 122 | List<ColumnDefinitionNode> columnDefNodes = new ArrayList<>(); | 125 | List<ColumnDefinitionNode> columnDefNodes = new ArrayList<>(); |
534 | 123 | List<FKConstraintDefinitionNode> fkDefNodes= new ArrayList<>(); | 126 | List<FKConstraintDefinitionNode> fkDefNodes= new ArrayList<>(); |
535 | 124 | List<ConstraintDefinitionNode> conDefNodes = new ArrayList<>(); | 127 | List<ConstraintDefinitionNode> conDefNodes = new ArrayList<>(); |
538 | 125 | List<String> newCols = null; | 128 | |
537 | 126 | |||
539 | 127 | for(TableElementNode node : elements) { | 129 | for(TableElementNode node : elements) { |
540 | 128 | switch(node.getNodeType()) { | 130 | switch(node.getNodeType()) { |
541 | 129 | case NodeTypes.COLUMN_DEFINITION_NODE: { | 131 | case NodeTypes.COLUMN_DEFINITION_NODE: { |
542 | @@ -181,7 +183,6 @@ | |||
543 | 181 | } break; | 183 | } break; |
544 | 182 | 184 | ||
545 | 183 | case NodeTypes.AT_RENAME_NODE: | 185 | case NodeTypes.AT_RENAME_NODE: |
546 | 184 | |||
547 | 185 | TableName newName = DDLHelper.convertName(defaultSchema, | 186 | TableName newName = DDLHelper.convertName(defaultSchema, |
548 | 186 | ((AlterTableRenameNode)node).newName()); | 187 | ((AlterTableRenameNode)node).newName()); |
549 | 187 | TableName oldName = table.getName(); | 188 | TableName oldName = table.getName(); |
550 | @@ -189,18 +190,14 @@ | |||
551 | 189 | return ChangeLevel.METADATA; | 190 | return ChangeLevel.METADATA; |
552 | 190 | 191 | ||
553 | 191 | case NodeTypes.AT_RENAME_COLUMN_NODE: | 192 | case NodeTypes.AT_RENAME_COLUMN_NODE: |
554 | 192 | |||
555 | 193 | AlterTableRenameColumnNode alterRenameCol = (AlterTableRenameColumnNode) node; | 193 | AlterTableRenameColumnNode alterRenameCol = (AlterTableRenameColumnNode) node; |
556 | 194 | String oldColName = alterRenameCol.getName(); | 194 | String oldColName = alterRenameCol.getName(); |
557 | 195 | String newColName = alterRenameCol.newName(); | 195 | String newColName = alterRenameCol.newName(); |
558 | 196 | final Column oldCol = table.getColumn(oldColName); | 196 | final Column oldCol = table.getColumn(oldColName); |
559 | 197 | if (oldCol == null) | 197 | if (oldCol == null) |
560 | 198 | throw new NoSuchColumnException(oldColName); | 198 | throw new NoSuchColumnException(oldColName); |
561 | 199 | if (newCols == null) | ||
562 | 200 | newCols = new ArrayList<>(); | ||
563 | 201 | newCols.add(newColName); | ||
564 | 202 | columnChanges.add(TableChange.createModify(oldColName, newColName)); | 199 | columnChanges.add(TableChange.createModify(oldColName, newColName)); |
566 | 203 | break; | 200 | break; |
567 | 204 | 201 | ||
568 | 205 | default: | 202 | default: |
569 | 206 | return null; // Something unsupported | 203 | return null; // Something unsupported |
570 | @@ -216,38 +213,11 @@ | |||
571 | 216 | for(ColumnDefinitionNode cdn : columnDefNodes) { | 213 | for(ColumnDefinitionNode cdn : columnDefNodes) { |
572 | 217 | if(cdn instanceof ModifyColumnNode) { | 214 | if(cdn instanceof ModifyColumnNode) { |
573 | 218 | ModifyColumnNode modNode = (ModifyColumnNode) cdn; | 215 | ModifyColumnNode modNode = (ModifyColumnNode) cdn; |
598 | 219 | Column column = tableCopy.getColumn(modNode.getColumnName()); | 216 | handleModifyColumnNode(modNode, builder, tableCopy); |
575 | 220 | if(column == null) { | ||
576 | 221 | throw new NoSuchColumnException(modNode.getColumnName()); | ||
577 | 222 | } | ||
578 | 223 | switch(modNode.getNodeType()) { | ||
579 | 224 | case NodeTypes.MODIFY_COLUMN_DEFAULT_NODE: | ||
580 | 225 | column.setDefaultValue(TableDDL.getColumnDefault(modNode)); | ||
581 | 226 | break; | ||
582 | 227 | case NodeTypes.MODIFY_COLUMN_CONSTRAINT_NODE: // Type only comes from NULL | ||
583 | 228 | column.setNullable(true); | ||
584 | 229 | break; | ||
585 | 230 | case NodeTypes.MODIFY_COLUMN_CONSTRAINT_NOT_NULL_NODE: // Type only comes from NOT NULL | ||
586 | 231 | column.setNullable(false); | ||
587 | 232 | break; | ||
588 | 233 | case NodeTypes.MODIFY_COLUMN_TYPE_NODE: | ||
589 | 234 | tableCopy.dropColumn(modNode.getColumnName()); | ||
590 | 235 | TableDDL.addColumn(builder, table.getName().getSchemaName(), table.getName().getTableName(), | ||
591 | 236 | column.getName(), column.getPosition(), cdn.getType(), column.getNullable(), | ||
592 | 237 | column.getInitialAutoIncrementValue() != null, | ||
593 | 238 | column.getDefaultValue()); | ||
594 | 239 | break; | ||
595 | 240 | default: | ||
596 | 241 | throw new IllegalStateException("Unexpected node type: " + modNode); | ||
597 | 242 | } | ||
599 | 243 | } else { | 217 | } else { |
600 | 244 | TableDDL.addColumn(builder, cdn, table.getName().getSchemaName(), table.getName().getTableName(), pos++); | 218 | TableDDL.addColumn(builder, cdn, table.getName().getSchemaName(), table.getName().getTableName(), pos++); |
601 | 245 | } | 219 | } |
602 | 246 | } | 220 | } |
603 | 247 | if (newCols != null) | ||
604 | 248 | for (String name : newCols) | ||
605 | 249 | if (tableCopy.getColumn(name) == null) | ||
606 | 250 | throw new AkibanInternalException("New Columns " + newCols + " not created successfully"); | ||
607 | 251 | copyTableIndexes(table, tableCopy, columnChanges, indexChanges); | 221 | copyTableIndexes(table, tableCopy, columnChanges, indexChanges); |
608 | 252 | 222 | ||
609 | 253 | IndexNameGenerator indexNamer = DefaultIndexNameGenerator.forTable(tableCopy); | 223 | IndexNameGenerator indexNamer = DefaultIndexNameGenerator.forTable(tableCopy); |
610 | @@ -283,6 +253,77 @@ | |||
611 | 283 | return ddl.alterTable(session, table.getName(), tableCopy, columnChanges, indexChanges, context); | 253 | return ddl.alterTable(session, table.getName(), tableCopy, columnChanges, indexChanges, context); |
612 | 284 | } | 254 | } |
613 | 285 | 255 | ||
614 | 256 | private static void handleModifyColumnNode(ModifyColumnNode modNode, AISBuilder builder, UserTable tableCopy) { | ||
615 | 257 | AkibanInformationSchema aisCopy = tableCopy.getAIS(); | ||
616 | 258 | Column column = tableCopy.getColumn(modNode.getColumnName()); | ||
617 | 259 | if(column == null) { | ||
618 | 260 | throw new NoSuchColumnException(modNode.getColumnName()); | ||
619 | 261 | } | ||
620 | 262 | switch(modNode.getNodeType()) { | ||
621 | 263 | case NodeTypes.MODIFY_COLUMN_DEFAULT_NODE: | ||
622 | 264 | if(modNode.isAutoincrementColumn()) { | ||
623 | 265 | int autoIncType = (int)modNode.getAutoinc_create_or_modify_Start_Increment(); | ||
624 | 266 | switch(autoIncType) { | ||
625 | 267 | case ColumnDefinitionNode.CREATE_AUTOINCREMENT: { | ||
626 | 268 | if(column.getIdentityGenerator() != null) { | ||
627 | 269 | throw new ColumnAlreadyGeneratedException(column); | ||
628 | 270 | } | ||
629 | 271 | TableName name = tableCopy.getName(); | ||
630 | 272 | TableDDL.setAutoIncrement(builder, name.getSchemaName(), name.getTableName(), modNode); | ||
631 | 273 | } | ||
632 | 274 | break; | ||
633 | 275 | case ColumnDefinitionNode.MODIFY_AUTOINCREMENT_INC_VALUE: { | ||
634 | 276 | Sequence curSeq = column.getIdentityGenerator(); | ||
635 | 277 | if(curSeq == null) { | ||
636 | 278 | throw new ColumnNotGeneratedException(column); | ||
637 | 279 | } | ||
638 | 280 | aisCopy.removeSequence(curSeq.getSequenceName()); | ||
639 | 281 | Sequence newSeq = Sequence.create(aisCopy, | ||
640 | 282 | curSeq.getSchemaName(), | ||
641 | 283 | curSeq.getSequenceName().getTableName(), | ||
642 | 284 | curSeq.getStartsWith(), | ||
643 | 285 | modNode.getAutoincrementIncrement(), | ||
644 | 286 | curSeq.getMinValue(), | ||
645 | 287 | curSeq.getMaxValue(), | ||
646 | 288 | curSeq.isCycle()); | ||
647 | 289 | aisCopy.addSequence(newSeq); | ||
648 | 290 | column.setIdentityGenerator(newSeq); | ||
649 | 291 | } | ||
650 | 292 | break; | ||
651 | 293 | case ColumnDefinitionNode.MODIFY_AUTOINCREMENT_RESTART_VALUE: | ||
652 | 294 | // Requires Accumulator reset | ||
653 | 295 | throw new UnsupportedSQLException("Not yet implemented", modNode); | ||
654 | 296 | default: | ||
655 | 297 | throw new IllegalStateException("Unknown autoIncType: " + autoIncType); | ||
656 | 298 | } | ||
657 | 299 | } else { | ||
658 | 300 | // DROP DEFAULT will come though as a NULL default, clears both GENERATED and DEFAULT | ||
659 | 301 | Sequence seq = column.getIdentityGenerator(); | ||
660 | 302 | if(seq != null) { | ||
661 | 303 | column.setDefaultIdentity(null); | ||
662 | 304 | column.setIdentityGenerator(null); | ||
663 | 305 | aisCopy.removeSequence(seq.getSequenceName()); | ||
664 | 306 | } | ||
665 | 307 | column.setDefaultValue(TableDDL.getColumnDefault(modNode)); | ||
666 | 308 | } | ||
667 | 309 | break; | ||
668 | 310 | case NodeTypes.MODIFY_COLUMN_CONSTRAINT_NODE: // Type only comes from NULL | ||
669 | 311 | column.setNullable(true); | ||
670 | 312 | break; | ||
671 | 313 | case NodeTypes.MODIFY_COLUMN_CONSTRAINT_NOT_NULL_NODE: // Type only comes from NOT NULL | ||
672 | 314 | column.setNullable(false); | ||
673 | 315 | break; | ||
674 | 316 | case NodeTypes.MODIFY_COLUMN_TYPE_NODE: | ||
675 | 317 | tableCopy.dropColumn(modNode.getColumnName()); | ||
676 | 318 | TableDDL.addColumn(builder, tableCopy.getName().getSchemaName(), tableCopy.getName().getTableName(), | ||
677 | 319 | column.getName(), column.getPosition(), modNode.getType(), column.getNullable(), | ||
678 | 320 | column.getDefaultValue()); | ||
679 | 321 | break; | ||
680 | 322 | default: | ||
681 | 323 | throw new IllegalStateException("Unexpected node type: " + modNode); | ||
682 | 324 | } | ||
683 | 325 | } | ||
684 | 326 | |||
685 | 286 | private static void checkColumnChange(UserTable table, String columnName) { | 327 | private static void checkColumnChange(UserTable table, String columnName) { |
686 | 287 | Column column = table.getColumn(columnName); | 328 | Column column = table.getColumn(columnName); |
687 | 288 | if(column == null) { | 329 | if(column == null) { |
688 | 289 | 330 | ||
689 | === modified file 'src/main/java/com/akiban/sql/aisddl/TableDDL.java' | |||
690 | --- src/main/java/com/akiban/sql/aisddl/TableDDL.java 2013-04-11 05:21:42 +0000 | |||
691 | +++ src/main/java/com/akiban/sql/aisddl/TableDDL.java 2013-04-15 20:33:27 +0000 | |||
692 | @@ -213,7 +213,7 @@ | |||
693 | 213 | // BIGINT NOT NULL | 213 | // BIGINT NOT NULL |
694 | 214 | DataTypeDescriptor bigint = new DataTypeDescriptor (TypeId.BIGINT_ID, false); | 214 | DataTypeDescriptor bigint = new DataTypeDescriptor (TypeId.BIGINT_ID, false); |
695 | 215 | addColumn (builder, schemaName, tableName, cdn.getColumnName(), colpos, | 215 | addColumn (builder, schemaName, tableName, cdn.getColumnName(), colpos, |
697 | 216 | bigint, false, true, getColumnDefault(cdn)); | 216 | bigint, false, getColumnDefault(cdn)); |
698 | 217 | // GENERATED ALWAYS AS IDENTITY | 217 | // GENERATED ALWAYS AS IDENTITY |
699 | 218 | setAutoIncrement (builder, schemaName, tableName, cdn.getColumnName(), false, 1, 1); | 218 | setAutoIncrement (builder, schemaName, tableName, cdn.getColumnName(), false, 1, 1); |
700 | 219 | // UNIQUE (KEY) | 219 | // UNIQUE (KEY) |
701 | @@ -221,24 +221,25 @@ | |||
702 | 221 | builder.index(schemaName, tableName, cdn.getColumnName(), true, constraint); | 221 | builder.index(schemaName, tableName, cdn.getColumnName(), true, constraint); |
703 | 222 | builder.indexColumn(schemaName, tableName, cdn.getColumnName(), cdn.getColumnName(), 0, true, null); | 222 | builder.indexColumn(schemaName, tableName, cdn.getColumnName(), cdn.getColumnName(), 0, true, null); |
704 | 223 | } else { | 223 | } else { |
705 | 224 | boolean autoIncrement = cdn.isAutoincrementColumn(); | ||
706 | 225 | |||
707 | 226 | addColumn(builder, schemaName, tableName, cdn.getColumnName(), colpos, | 224 | addColumn(builder, schemaName, tableName, cdn.getColumnName(), colpos, |
709 | 227 | cdn.getType(), cdn.getType().isNullable(), autoIncrement, getColumnDefault(cdn)); | 225 | cdn.getType(), cdn.getType().isNullable(), getColumnDefault(cdn)); |
710 | 228 | 226 | ||
717 | 229 | if (autoIncrement) { | 227 | if (cdn.isAutoincrementColumn()) { |
718 | 230 | // if the cdn has a default node-> GENERATE BY DEFAULT | 228 | setAutoIncrement(builder, schemaName, tableName, cdn); |
713 | 231 | // if no default node -> GENERATE ALWAYS | ||
714 | 232 | Boolean defaultIdentity = cdn.getDefaultNode() != null; | ||
715 | 233 | setAutoIncrement (builder, schemaName, tableName, cdn.getColumnName(), | ||
716 | 234 | defaultIdentity, cdn.getAutoincrementStart(), cdn.getAutoincrementIncrement()); | ||
719 | 235 | } | 229 | } |
720 | 236 | } | 230 | } |
721 | 237 | } | 231 | } |
722 | 238 | 232 | ||
726 | 239 | static void setAutoIncrement (final AISBuilder builder, | 233 | public static void setAutoIncrement(AISBuilder builder, String schema, String table, ColumnDefinitionNode cdn) { |
727 | 240 | String schemaName, String tableName, String columnName, boolean defaultIdentity, | 234 | // if the cdn has a default node-> GENERATE BY DEFAULT |
728 | 241 | long start, long increment) { | 235 | // if no default node -> GENERATE ALWAYS |
729 | 236 | Boolean defaultIdentity = cdn.getDefaultNode() != null; | ||
730 | 237 | setAutoIncrement(builder, schema, table, cdn.getColumnName(), | ||
731 | 238 | defaultIdentity, cdn.getAutoincrementStart(), cdn.getAutoincrementIncrement()); | ||
732 | 239 | } | ||
733 | 240 | |||
734 | 241 | public static void setAutoIncrement(AISBuilder builder, String schemaName, String tableName, String columnName, | ||
735 | 242 | boolean defaultIdentity, long start, long increment) { | ||
736 | 242 | // The merge process will generate a real sequence name | 243 | // The merge process will generate a real sequence name |
737 | 243 | final String sequenceName = "temp-sequence-1"; | 244 | final String sequenceName = "temp-sequence-1"; |
738 | 244 | builder.sequence(schemaName, sequenceName, | 245 | builder.sequence(schemaName, sequenceName, |
739 | @@ -267,7 +268,7 @@ | |||
740 | 267 | 268 | ||
741 | 268 | static void addColumn(final AISBuilder builder, | 269 | static void addColumn(final AISBuilder builder, |
742 | 269 | final String schemaName, final String tableName, final String columnName, | 270 | final String schemaName, final String tableName, final String columnName, |
744 | 270 | int colpos, DataTypeDescriptor type, boolean nullable, boolean autoIncrement, | 271 | int colpos, DataTypeDescriptor type, boolean nullable, |
745 | 271 | final String defaultValue) { | 272 | final String defaultValue) { |
746 | 272 | Long[] typeParameters = new Long[2]; | 273 | Long[] typeParameters = new Long[2]; |
747 | 273 | Type builderType = columnType(type, typeParameters, schemaName, tableName, columnName); | 274 | Type builderType = columnType(type, typeParameters, schemaName, tableName, columnName); |
748 | @@ -280,7 +281,7 @@ | |||
749 | 280 | colpos, | 281 | colpos, |
750 | 281 | builderType.name(), typeParameters[0], typeParameters[1], | 282 | builderType.name(), typeParameters[0], typeParameters[1], |
751 | 282 | nullable, | 283 | nullable, |
753 | 283 | autoIncrement, | 284 | false, |
754 | 284 | charset, collation, | 285 | charset, collation, |
755 | 285 | defaultValue); | 286 | defaultValue); |
756 | 286 | } | 287 | } |
757 | 287 | 288 | ||
758 | === modified file 'src/main/java/com/akiban/sql/aisddl/ViewDDL.java' | |||
759 | --- src/main/java/com/akiban/sql/aisddl/ViewDDL.java 2013-03-22 20:05:57 +0000 | |||
760 | +++ src/main/java/com/akiban/sql/aisddl/ViewDDL.java 2013-04-15 20:33:27 +0000 | |||
761 | @@ -86,7 +86,7 @@ | |||
762 | 86 | type = new DataTypeDescriptor(TypeId.CHAR_ID, true, 0); | 86 | type = new DataTypeDescriptor(TypeId.CHAR_ID, true, 0); |
763 | 87 | } | 87 | } |
764 | 88 | TableDDL.addColumn(builder, schemaName, viewName, rc.getName(), colpos++, | 88 | TableDDL.addColumn(builder, schemaName, viewName, rc.getName(), colpos++, |
766 | 89 | type, type.isNullable(), false, null); | 89 | type, type.isNullable(), null); |
767 | 90 | } | 90 | } |
768 | 91 | View view = builder.akibanInformationSchema().getView(schemaName, viewName); | 91 | View view = builder.akibanInformationSchema().getView(schemaName, viewName); |
769 | 92 | ddlFunctions.createView(session, view); | 92 | ddlFunctions.createView(session, view); |
770 | 93 | 93 | ||
771 | === modified file 'src/main/resources/com/akiban/server/error/error_code.properties' | |||
772 | --- src/main/resources/com/akiban/server/error/error_code.properties 2013-04-15 14:38:06 +0000 | |||
773 | +++ src/main/resources/com/akiban/server/error/error_code.properties 2013-04-15 20:33:27 +0000 | |||
774 | @@ -249,6 +249,8 @@ | |||
775 | 249 | INVALID_ROUTINE = Invalid procedure `{0}.`{1}`: {2} | 249 | INVALID_ROUTINE = Invalid procedure `{0}.`{1}`: {2} |
776 | 250 | INVALID_INDEX_ID = Index `{0}.`{1}`.`{2}` has an invalid ID: {3} | 250 | INVALID_INDEX_ID = Index `{0}.`{1}`.`{2}` has an invalid ID: {3} |
777 | 251 | MODEL_BUILDER_ERROR = Error building model for `{0}`.`{1}`: {2} | 251 | MODEL_BUILDER_ERROR = Error building model for `{0}`.`{1}`: {2} |
778 | 252 | COLUMN_NOT_GENERATED = Column `{0}`.`{1}`.`{2}` is not generated | ||
779 | 253 | COLUMN_ALREADY_GENERATED = Column `{0}`.`{1}`.`{2}` already generated by sequence `{3}`.`{4}` | ||
780 | 252 | # | 254 | # |
781 | 253 | # Class 51 - Internal problems created by user configuration | 255 | # Class 51 - Internal problems created by user configuration |
782 | 254 | # | 256 | # |
783 | 255 | 257 | ||
784 | === modified file 'src/test/java/com/akiban/server/test/it/dxl/AlterTableBasicIT.java' | |||
785 | --- src/test/java/com/akiban/server/test/it/dxl/AlterTableBasicIT.java 2013-04-11 04:48:29 +0000 | |||
786 | +++ src/test/java/com/akiban/server/test/it/dxl/AlterTableBasicIT.java 2013-04-15 20:33:27 +0000 | |||
787 | @@ -21,6 +21,7 @@ | |||
788 | 21 | import com.akiban.ais.model.AISBuilder; | 21 | import com.akiban.ais.model.AISBuilder; |
789 | 22 | import com.akiban.ais.model.AkibanInformationSchema; | 22 | import com.akiban.ais.model.AkibanInformationSchema; |
790 | 23 | import com.akiban.ais.model.Column; | 23 | import com.akiban.ais.model.Column; |
791 | 24 | import com.akiban.ais.model.DefaultNameGenerator; | ||
792 | 24 | import com.akiban.ais.model.Index; | 25 | import com.akiban.ais.model.Index; |
793 | 25 | import com.akiban.ais.model.Sequence; | 26 | import com.akiban.ais.model.Sequence; |
794 | 26 | import com.akiban.ais.model.TableName; | 27 | import com.akiban.ais.model.TableName; |
795 | @@ -1180,12 +1181,15 @@ | |||
796 | 1180 | Sequence seq = column.getIdentityGenerator(); | 1181 | Sequence seq = column.getIdentityGenerator(); |
797 | 1181 | assertNotNull("id column has sequence", seq); | 1182 | assertNotNull("id column has sequence", seq); |
798 | 1182 | 1183 | ||
803 | 1183 | AkibanInformationSchema copy = AISCloner.clone(ais()); | 1184 | runAlter(ChangeLevel.METADATA, "ALTER TABLE c ALTER COLUMN id DROP DEFAULT"); |
804 | 1184 | copy.getUserTable(id).getColumn("id").setDefaultIdentity(false); | 1185 | assertNull("Old seq was dropped", ais().getSequence(seq.getSequenceName())); |
801 | 1185 | runAlter(ChangeLevel.METADATA, C_NAME, copy.getUserTable(id), | ||
802 | 1186 | Arrays.asList(TableChange.createModify("id", "id")), Arrays.<TableChange>asList()); | ||
805 | 1187 | 1186 | ||
806 | 1187 | runAlter(ChangeLevel.METADATA, "ALTER TABLE c ALTER COLUMN id SET GENERATED ALWAYS AS IDENTITY"); | ||
807 | 1188 | Column newColumn = getUserTable(id).getColumn("id"); | 1188 | Column newColumn = getUserTable(id).getColumn("id"); |
808 | 1189 | assertEquals("altered is always", false, newColumn.getDefaultIdentity()); | 1189 | assertEquals("altered is always", false, newColumn.getDefaultIdentity()); |
809 | 1190 | seq = newColumn.getIdentityGenerator(); | ||
810 | 1191 | assertEquals("Sequence name prefix", | ||
811 | 1192 | true, | ||
812 | 1193 | seq.getSequenceName().getTableName().startsWith(DefaultNameGenerator.IDENTITY_SEQUENCE_PREFIX)); | ||
813 | 1190 | } | 1194 | } |
814 | 1191 | } | 1195 | } |
815 | 1192 | 1196 | ||
816 | === modified file 'src/test/java/com/akiban/sql/aisddl/AlterTableDDLTest.java' | |||
817 | --- src/test/java/com/akiban/sql/aisddl/AlterTableDDLTest.java 2013-03-22 20:05:57 +0000 | |||
818 | +++ src/test/java/com/akiban/sql/aisddl/AlterTableDDLTest.java 2013-04-15 20:33:27 +0000 | |||
819 | @@ -24,6 +24,7 @@ | |||
820 | 24 | import com.akiban.ais.model.IndexColumn; | 24 | import com.akiban.ais.model.IndexColumn; |
821 | 25 | import com.akiban.ais.model.Join; | 25 | import com.akiban.ais.model.Join; |
822 | 26 | import com.akiban.ais.model.JoinColumn; | 26 | import com.akiban.ais.model.JoinColumn; |
823 | 27 | import com.akiban.ais.model.Sequence; | ||
824 | 27 | import com.akiban.ais.model.TableName; | 28 | import com.akiban.ais.model.TableName; |
825 | 28 | import com.akiban.ais.model.UserTable; | 29 | import com.akiban.ais.model.UserTable; |
826 | 29 | import com.akiban.ais.model.aisb2.AISBBasedBuilder; | 30 | import com.akiban.ais.model.aisb2.AISBBasedBuilder; |
827 | @@ -31,6 +32,8 @@ | |||
828 | 31 | import com.akiban.ais.util.TableChange; | 32 | import com.akiban.ais.util.TableChange; |
829 | 32 | import com.akiban.qp.operator.QueryContext; | 33 | import com.akiban.qp.operator.QueryContext; |
830 | 33 | import com.akiban.server.api.ddl.DDLFunctionsMockBase; | 34 | import com.akiban.server.api.ddl.DDLFunctionsMockBase; |
831 | 35 | import com.akiban.server.error.ColumnAlreadyGeneratedException; | ||
832 | 36 | import com.akiban.server.error.ColumnNotGeneratedException; | ||
833 | 34 | import com.akiban.server.error.DuplicateColumnNameException; | 37 | import com.akiban.server.error.DuplicateColumnNameException; |
834 | 35 | import com.akiban.server.error.DuplicateIndexException; | 38 | import com.akiban.server.error.DuplicateIndexException; |
835 | 36 | import com.akiban.server.error.JoinColumnMismatchException; | 39 | import com.akiban.server.error.JoinColumnMismatchException; |
836 | @@ -42,6 +45,7 @@ | |||
837 | 42 | import com.akiban.server.error.NoSuchTableException; | 45 | import com.akiban.server.error.NoSuchTableException; |
838 | 43 | import com.akiban.server.error.NoSuchUniqueException; | 46 | import com.akiban.server.error.NoSuchUniqueException; |
839 | 44 | import com.akiban.server.error.UnsupportedCheckConstraintException; | 47 | import com.akiban.server.error.UnsupportedCheckConstraintException; |
840 | 48 | import com.akiban.server.error.UnsupportedSQLException; | ||
841 | 45 | import com.akiban.server.service.session.Session; | 49 | import com.akiban.server.service.session.Session; |
842 | 46 | import com.akiban.server.types3.Types3Switch; | 50 | import com.akiban.server.types3.Types3Switch; |
843 | 47 | import com.akiban.sql.StandardException; | 51 | import com.akiban.sql.StandardException; |
844 | @@ -208,7 +212,7 @@ | |||
845 | 208 | expectColumnChanges("ADD:new"); | 212 | expectColumnChanges("ADD:new"); |
846 | 209 | expectIndexChanges(); | 213 | expectIndexChanges(); |
847 | 210 | if (Types3Switch.ON) { | 214 | if (Types3Switch.ON) { |
849 | 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)"); |
850 | 212 | } else { | 216 | } else { |
851 | 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)"); |
852 | 214 | } | 218 | } |
853 | @@ -221,7 +225,7 @@ | |||
854 | 221 | expectColumnChanges("ADD:new"); | 225 | expectColumnChanges("ADD:new"); |
855 | 222 | expectIndexChanges("ADD:PRIMARY"); | 226 | expectIndexChanges("ADD:PRIMARY"); |
856 | 223 | if (Types3Switch.ON) { | 227 | if (Types3Switch.ON) { |
858 | 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)"); |
859 | 225 | } else { | 229 | } else { |
860 | 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)"); |
861 | 227 | } | 231 | } |
862 | @@ -540,6 +544,84 @@ | |||
863 | 540 | } | 544 | } |
864 | 541 | 545 | ||
865 | 542 | // | 546 | // |
866 | 547 | // ALTER COLUMN DROP DEFAULT (where default is generated) | ||
867 | 548 | // | ||
868 | 549 | @Test | ||
869 | 550 | public void alterColumnDropDefaultGenerated() throws StandardException { | ||
870 | 551 | buildCWithGeneratedID(1, true); | ||
871 | 552 | parseAndRun("ALTER TABLE c ALTER COLUMN id DROP DEFAULT"); | ||
872 | 553 | expectColumnChanges("MODIFY:id->id"); | ||
873 | 554 | expectIndexChanges(); | ||
874 | 555 | expectFinalTable(C_NAME, "id MCOMPAT_ INTEGER(11) NOT NULL", "PRIMARY(id)"); | ||
875 | 556 | } | ||
876 | 557 | |||
877 | 558 | // | ||
878 | 559 | // ALTER COLUMN SET INCREMENT BY <number> | ||
879 | 560 | // | ||
880 | 561 | |||
881 | 562 | @Test | ||
882 | 563 | public void alterColumnSetIncrementByLess() throws StandardException { | ||
883 | 564 | buildCWithGeneratedID(1, true); | ||
884 | 565 | parseAndRun("ALTER TABLE c ALTER COLUMN id SET INCREMENT BY -1"); | ||
885 | 566 | expectColumnChanges("MODIFY:id->id"); | ||
886 | 567 | expectIndexChanges(); | ||
887 | 568 | expectFinalTable(C_NAME, "id MCOMPAT_ INTEGER(11) NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY -1)", "PRIMARY(id)"); | ||
888 | 569 | } | ||
889 | 570 | |||
890 | 571 | @Test | ||
891 | 572 | public void alterColumnSetIncrementByMore() throws StandardException { | ||
892 | 573 | buildCWithGeneratedID(1, true); | ||
893 | 574 | parseAndRun("ALTER TABLE c ALTER COLUMN id SET INCREMENT BY 5"); | ||
894 | 575 | expectColumnChanges("MODIFY:id->id"); | ||
895 | 576 | expectIndexChanges(); | ||
896 | 577 | expectFinalTable(C_NAME, "id MCOMPAT_ INTEGER(11) NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 5)", "PRIMARY(id)"); | ||
897 | 578 | } | ||
898 | 579 | |||
899 | 580 | @Test(expected=ColumnNotGeneratedException.class) | ||
900 | 581 | public void alterColumnSetIncrementInvalid() throws StandardException { | ||
901 | 582 | buildCWithID(); | ||
902 | 583 | parseAndRun("ALTER TABLE c ALTER COLUMN id SET INCREMENT BY 5"); | ||
903 | 584 | } | ||
904 | 585 | |||
905 | 586 | // | ||
906 | 587 | // ALTER COLUMN RESTART WITH <number> | ||
907 | 588 | // | ||
908 | 589 | |||
909 | 590 | @Test(expected=UnsupportedSQLException.class) | ||
910 | 591 | public void alterColumnRestartWith() throws StandardException { | ||
911 | 592 | buildCWithGeneratedID(1, true); | ||
912 | 593 | parseAndRun("ALTER TABLE c ALTER COLUMN id RESTART WITH 10"); | ||
913 | 594 | } | ||
914 | 595 | |||
915 | 596 | // | ||
916 | 597 | // ALTER COLUMN [SET] GENERATED <BY DEFAULT | ALWAYS> | ||
917 | 598 | // | ||
918 | 599 | |||
919 | 600 | @Test | ||
920 | 601 | public void alterColumnSetGeneratedByDefault() throws StandardException { | ||
921 | 602 | buildCWithID(); | ||
922 | 603 | parseAndRun("ALTER TABLE c ALTER COLUMN id SET GENERATED BY DEFAULT AS IDENTITY (START WITH 10, INCREMENT BY 50)"); | ||
923 | 604 | expectColumnChanges("MODIFY:id->id"); | ||
924 | 605 | expectIndexChanges(); | ||
925 | 606 | expectFinalTable(C_NAME, "id MCOMPAT_ INTEGER(11) NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 10, INCREMENT BY 50)", "PRIMARY(id)"); | ||
926 | 607 | } | ||
927 | 608 | |||
928 | 609 | @Test | ||
929 | 610 | public void alterColumnSetGeneratedAlways() throws StandardException { | ||
930 | 611 | buildCWithID(); | ||
931 | 612 | parseAndRun("ALTER TABLE c ALTER COLUMN id SET GENERATED ALWAYS AS IDENTITY (START WITH 42, INCREMENT BY 100)"); | ||
932 | 613 | expectColumnChanges("MODIFY:id->id"); | ||
933 | 614 | expectIndexChanges(); | ||
934 | 615 | expectFinalTable(C_NAME, "id MCOMPAT_ INTEGER(11) NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 42, INCREMENT BY 100)", "PRIMARY(id)"); | ||
935 | 616 | } | ||
936 | 617 | |||
937 | 618 | @Test(expected=ColumnAlreadyGeneratedException.class) | ||
938 | 619 | public void alterColumnSetGeneratedAlreadyGenerated() throws StandardException { | ||
939 | 620 | buildCWithGeneratedID(1, true); | ||
940 | 621 | parseAndRun("ALTER TABLE c ALTER COLUMN id SET GENERATED ALWAYS AS IDENTITY (START WITH 42, INCREMENT BY 100)"); | ||
941 | 622 | } | ||
942 | 623 | |||
943 | 624 | // | ||
944 | 543 | // ADD [CONSTRAINT] UNIQUE | 625 | // ADD [CONSTRAINT] UNIQUE |
945 | 544 | // | 626 | // |
946 | 545 | 627 | ||
947 | @@ -1155,6 +1237,14 @@ | |||
948 | 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"); |
949 | 1156 | } | 1238 | } |
950 | 1157 | 1239 | ||
951 | 1240 | private void buildCWithGeneratedID(int startWith, boolean always) { | ||
952 | 1241 | builder.userTable(C_NAME).autoIncLong("id", startWith, always).pk("id"); | ||
953 | 1242 | } | ||
954 | 1243 | |||
955 | 1244 | private void buildCWithID() { | ||
956 | 1245 | builder.userTable(C_NAME).colLong("id", false).pk("id"); | ||
957 | 1246 | } | ||
958 | 1247 | |||
959 | 1158 | private static class DDLFunctionsMock extends DDLFunctionsMockBase { | 1248 | private static class DDLFunctionsMock extends DDLFunctionsMockBase { |
960 | 1159 | final AkibanInformationSchema ais; | 1249 | final AkibanInformationSchema ais; |
961 | 1160 | final List<String> columnChangeDesc = new ArrayList<>(); | 1250 | final List<String> columnChangeDesc = new ArrayList<>(); |
962 | @@ -1212,6 +1302,17 @@ | |||
963 | 1212 | sb.append(" DEFAULT "); | 1302 | sb.append(" DEFAULT "); |
964 | 1213 | sb.append(defaultVal); | 1303 | sb.append(defaultVal); |
965 | 1214 | } | 1304 | } |
966 | 1305 | Boolean identity = col.getDefaultIdentity(); | ||
967 | 1306 | if(identity != null) { | ||
968 | 1307 | Sequence seq = col.getIdentityGenerator(); | ||
969 | 1308 | sb.append(" GENERATED "); | ||
970 | 1309 | sb.append(identity ? "BY DEFAULT" : "ALWAYS"); | ||
971 | 1310 | sb.append(" AS IDENTITY (START WITH "); | ||
972 | 1311 | sb.append(seq.getStartsWith()); | ||
973 | 1312 | sb.append(", INCREMENT BY "); | ||
974 | 1313 | sb.append(seq.getIncrement()); | ||
975 | 1314 | sb.append(')'); | ||
976 | 1315 | } | ||
977 | 1215 | } | 1316 | } |
978 | 1216 | for(Index index : table.getIndexes()) { | 1317 | for(Index index : table.getIndexes()) { |
979 | 1217 | sb.append(", "); | 1318 | sb.append(", "); |
980 | 1218 | 1319 | ||
981 | === modified file 'src/test/java/com/akiban/sql/aisddl/TableDDLIT.java' | |||
982 | --- src/test/java/com/akiban/sql/aisddl/TableDDLIT.java 2013-04-11 05:21:42 +0000 | |||
983 | +++ src/test/java/com/akiban/sql/aisddl/TableDDLIT.java 2013-04-15 20:33:27 +0000 | |||
984 | @@ -106,7 +106,7 @@ | |||
985 | 106 | assertNotNull(table); | 106 | assertNotNull(table); |
986 | 107 | assertEquals(table.getColumn(0).getType(), Types.INT); | 107 | assertEquals(table.getColumn(0).getType(), Types.INT); |
987 | 108 | assertEquals(table.getPrimaryKey().getColumns().get(0), table.getColumn(0)); | 108 | assertEquals(table.getPrimaryKey().getColumns().get(0), table.getColumn(0)); |
989 | 109 | assertEquals(1000L, table.getColumn(0).getInitialAutoIncrementValue().longValue()); | 109 | assertEquals(1000L, table.getColumn(0).getIdentityGenerator().getStartsWith()); |
990 | 110 | } | 110 | } |
991 | 111 | 111 | ||
992 | 112 | @Test | 112 | @Test |
993 | 113 | 113 | ||
994 | === modified file 'src/test/resources/com/akiban/sql/pg/yaml/functional/test-identity.yaml' | |||
995 | --- src/test/resources/com/akiban/sql/pg/yaml/functional/test-identity.yaml 2012-09-26 03:50:12 +0000 | |||
996 | +++ src/test/resources/com/akiban/sql/pg/yaml/functional/test-identity.yaml 2013-04-15 20:33:27 +0000 | |||
997 | @@ -146,4 +146,17 @@ | |||
998 | 146 | --- | 146 | --- |
999 | 147 | - Statement: select * from t | 147 | - Statement: select * from t |
1000 | 148 | - output: [[1, 1, null]] | 148 | - output: [[1, 1, null]] |
1001 | 149 | --- | ||
1002 | 150 | - DropTable: t | ||
1003 | 151 | |||
1004 | 152 | --- | ||
1005 | 153 | - CreateTable: t (id int not null primary key) | ||
1006 | 154 | --- | ||
1007 | 155 | - Statement: ALTER TABLE t ALTER COLUMN id SET GENERATED BY DEFAULT AS IDENTITY (START WITH 42, INCREMENT BY 5) | ||
1008 | 156 | --- | ||
1009 | 157 | - Statement: INSERT INTO t VALUES (NULL),(NULL),(NULL) | ||
1010 | 158 | --- | ||
1011 | 159 | - Statement: SELECT * FROM t | ||
1012 | 160 | - output: [[42],[47],[52]] | ||
1013 | 161 | |||
1014 | 149 | ... | 162 | ... |
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.