001package gudusoft.gsqlparser.nodes;
002
003import gudusoft.gsqlparser.*;
004import gudusoft.gsqlparser.stmt.TCreateTableSqlStatement;
005
006/**
007 * Use a constraint to define an integrity constraint, a rule that restricts the values in a database.
008 * <p>Oracle Database lets you create six types of constraints and lets you declare them in two ways.
009 * <ul>
010 * <li>A NOT NULL constraint prohibits a database value from being null.</li>
011 * <li>A unique constraint prohibits multiple rows from having the same value in the same column or combination of columns but allows some values to be null.
012 * call method {@link #getColumnList()} to result columns of this unique key.
013 * </li>
014 * <li>A primary key constraint combines a NOT NULL constraint and a unique
015 * constraint in a single declaration. It prohibits multiple rows from having the same
016 * value in the same column or combination of columns and prohibits values from being null.
017 * call method {@link #getColumnList()} to result columns of this primary key.
018 * </li>
019 * <li>A foreign key constraint requires values in one table to match values in another table.
020 * call method {@link #getColumnList()} to result columns of this foreign key.
021 * </li>
022 * <li>A check constraint requires a value in the database to comply with a specified condition.
023 * call method {@link #getCheckCondition()} to return this condition.
024 * </li>
025 * <li>A REF column by definition references an object in another object type or in a relational table.
026 * A REF constraint lets you further describe the relationship between the REF column and the object it references.
027 </li>
028 * <li>default constraint is valid in sql server.</li>
029 * </ul>
030 *
031 * @see EConstraintType#notnull
032 * @see EConstraintType#unique
033 * @see EConstraintType#primary_key
034 * @see EConstraintType#foreign_key
035 * @see EConstraintType#check
036 * @see EConstraintType#reference
037 * @see EConstraintType#default_value
038 */
039
040public class TConstraint extends TParseTreeNode {
041
042    private TColumnGeneratedClause columnGeneratedClause;
043
044    public void setColumnGeneratedClause(TColumnGeneratedClause columnGeneratedClause) {
045        this.columnGeneratedClause = columnGeneratedClause;
046    }
047
048    public TColumnGeneratedClause getColumnGeneratedClause() {
049        return columnGeneratedClause;
050    }
051
052    public void setOnFilegroup(TDummy onFilegroup) {
053        this.onFilegroup = onFilegroup;
054    }
055
056    public TDummy getOnFilegroup() {
057        return onFilegroup;
058    }
059
060    private TDummy onFilegroup = null;
061
062    private TDummy withIndexoption = null;
063
064    public void setWithIndexoption(TDummy withIndexoption) {
065        this.withIndexoption = withIndexoption;
066    }
067
068    public TDummy getWithIndexoption() {
069        return withIndexoption;
070    }
071
072    private TObjectName indexName;
073
074    /**
075     * SQL Server, index name of table index when {@link #getConstraint_type} is {@link EConstraintType#table_index}
076     * or index name of column index when {@link #getConstraint_type} is {@link EConstraintType#column_index}
077     *
078     * @return index name
079     */
080    public TObjectName getIndexName() {
081        return indexName;
082    }
083
084    private EConstraintType constraint_type;
085    private TObjectName constraintName = null;
086    private  TPTNodeList <TKeyAction> keyActions;
087
088    private TObjectName commentObject;
089
090    public void setCommentObject(TObjectName commentObject) {
091        this.commentObject = commentObject;
092    }
093
094    private TObjectName forObjectName;
095
096    public void setForObjectName(TObjectName forObjectName) {
097        this.forObjectName = forObjectName;
098    }
099
100    public TObjectName getForObjectName() {
101        return forObjectName;
102    }
103
104    public TObjectName getCommentObject() {
105
106        return commentObject;
107    }
108
109    public void setKeyActions(TPTNodeList<TKeyAction> keyActions) {
110        this.keyActions = keyActions;
111    }
112
113    public TPTNodeList<TKeyAction> getKeyActions() {
114
115        return keyActions;
116    }
117
118    public void setConstraintLevel(int constraintLevel) {
119        this.constraintLevel = constraintLevel;
120    }
121
122    /**
123     *
124     * @return is this a columnn level constraint or table level constraint
125     * TBaseType.constraint_level_table or TBaseType.constraint_level_column.
126
127     */
128    public int getConstraintLevel() {
129        return constraintLevel;
130    }
131
132    private int constraintLevel = TBaseType.constraint_level_table;
133
134    private TExpression defaultExpression = null;
135
136    public void setDefaultExpression(TExpression defaultExpression) {
137        this.defaultExpression = defaultExpression;
138    }
139
140    /**
141     *
142     * @return default expression of sql server.
143     */
144    public TExpression getDefaultExpression() {
145
146        return defaultExpression;
147    }
148
149    public void setConstraintName(TObjectName constraintName) {
150        this.constraintName = constraintName;
151    }
152
153    /**
154     *
155     * @return name for the constraint, it's optional.
156     */
157    public TObjectName getConstraintName() {
158
159        return constraintName;
160    }
161
162    public void setConstraint_type(EConstraintType constraint_type) {
163        this.constraint_type = constraint_type;
164    }
165
166    /**
167     * 
168     * @return type of constraints.
169     * @see EConstraintType#notnull
170     * @see EConstraintType#unique
171     * @see EConstraintType#primary_key
172     * @see EConstraintType#foreign_key
173     * @see EConstraintType#check
174     * @see EConstraintType#reference
175     * @see EConstraintType#default_value
176     */
177    public EConstraintType getConstraint_type() {
178
179        return constraint_type;
180    }
181
182    public void setClustered(boolean clustered) {
183        this.clustered = clustered;
184    }
185
186    public void setClusteredToken(TSourceToken clusteredToken)
187    {
188        if (clusteredToken == null) return;
189        if (clusteredToken.toString().equalsIgnoreCase("clustered")){
190            clustered = true;
191        }else if (clusteredToken.toString().equalsIgnoreCase("nonclustered")){
192            nonClustered = true;
193        }
194    }
195
196    public boolean isClustered() {
197
198        return clustered;
199    }
200
201    private boolean clustered = false;
202    private boolean nonClustered = false;
203
204    public boolean isNonClustered() {
205        return nonClustered;
206    }
207
208    public void setNonClustered(boolean nonClustered) {
209
210        this.nonClustered = nonClustered;
211    }
212
213    private TPTNodeList<TColumnWithSortOrder> columnList = null;
214    private TExpression checkCondition = null;
215    private TPTNodeList <TAutomaticProperty>  automaticProperties = null;
216
217    public void setAutomaticProperties(TPTNodeList<TAutomaticProperty> automaticProperties) {
218        this.automaticProperties = automaticProperties;
219    }
220
221    /**
222     *
223     * @return    Automatic Initialization and Updating for TIMESTAMP in MySQL
224     */
225    public TPTNodeList<TAutomaticProperty> getAutomaticProperties() {
226
227        return automaticProperties;
228    }
229
230    /**
231     * 
232     * @return   used in check constraint, requires a value in the database to comply with this specified condition.
233     */
234    public TExpression getCheckCondition() {
235        return checkCondition;
236    }
237
238    /**
239     *
240     * @return column name list used when constraint type is unique, primary key or foreign key.
241     */
242    public TPTNodeList<TColumnWithSortOrder> getColumnList() {
243        return columnList;
244    }
245
246    public void setColumnList(TPTNodeList<TColumnWithSortOrder> columnList) {
247        this.columnList = columnList;
248    }
249
250    private TPTNodeList <TIndexColName> indexCols;
251
252    /**
253     * @deprecated since 1.8.7.2, use {@link #getColumnList()} instead.
254     * @return
255     */
256    public TPTNodeList<TIndexColName> getIndexCols() {
257        return indexCols;
258    }
259
260
261    public void init(Object arg1){
262        if (arg1 instanceof TExpression){
263            this.checkCondition = (TExpression)arg1;
264        }else if (arg1 instanceof TPTNodeList){
265           this.columnList = (TPTNodeList<TColumnWithSortOrder>)arg1;
266        }else if (arg1 instanceof TObjectNameList){
267            // column in TObjectNameList not changed to TPTNodeList<TColumnWithSortOrder> in .y file
268            // so we convert it here
269            this.columnList = new TPTNodeList<TColumnWithSortOrder>();
270            TObjectNameList onl = (TObjectNameList)arg1;
271            for(int i=0;i<onl.size();i++){
272                this.columnList.addElement(new TColumnWithSortOrder(onl.getObjectName(i)));
273            }
274//            indexCols = (TPTNodeList)arg1;
275        }
276    }
277
278    private TObjectName indexColumnName = null;
279
280
281    /**
282     * Snowflake index table constraint: CREATE TABLE t1 (c1 INT, c2 INT, CONSTRAINT c1_idx INDEX (c1));
283     * @return
284     */
285    public TObjectName getIndexColumnName() {
286        return indexColumnName;
287    }
288
289    public void init(Object arg1, Object arg2,Object arg3){
290        init(arg1,arg2);
291        switch (constraint_type){
292            case table_index:
293                indexColumnName = (TObjectName)arg3;
294                indexColumnName.setDbObjectType(EDbObjectType.column);
295                break;
296            default:
297                break;
298        }
299    }
300
301    public void init(Object arg1, Object arg2){
302        constraint_type = (EConstraintType)arg1;
303        switch (constraint_type){
304            case table_index:
305                indexName = (TObjectName)arg2;
306                indexName.setDbObjectType(EDbObjectType.index);
307                break;
308            case cluster:
309                break;
310            case default_value:
311                this.defaultExpression = (TExpression) arg2;
312                break;
313            default:
314                break;
315        }
316    }
317
318    private TObjectName referencedObject = null;
319
320    public void setReferencedColumnList(TObjectNameList referencedColumnList) {
321        this.referencedColumnList = referencedColumnList;
322    }
323
324    /**
325     * 
326     * @return column name list of referenced object in reference clause when constraint type is REF constraint.
327     */
328    public TObjectNameList getReferencedColumnList() {
329
330        return referencedColumnList;
331    }
332
333    private TObjectNameList referencedColumnList = null;
334
335
336    public void setReferencedObject(TObjectName referencedObject) {
337        this.referencedObject = referencedObject;
338    }
339
340    /**
341     *
342     * @return referenced object in reference clause when constraint type is REF constraint.
343     */
344    public TObjectName getReferencedObject() {
345
346        return referencedObject;
347    }
348
349    private TExpression seed;
350
351    public void setIncrement(TExpression increment) {
352        this.increment = increment;
353    }
354
355    public void setSeed(TExpression seed) {
356        this.seed = seed;
357    }
358
359    /**
360     * Used internal
361     * @return
362     */
363    public TExpression getIncrement() {
364
365        return increment;
366    }
367
368    /**
369     * Used internal
370     * @return
371     */
372    public TExpression getSeed() {
373        return seed;
374    }
375
376    private TExpression increment;
377
378    public void accept(TParseTreeVisitor v){
379        v.preVisit(this);
380        v.postVisit(this);
381    }
382
383    public void acceptChildren(TParseTreeVisitor v){
384        v.preVisit(this);
385        v.postVisit(this);
386    }
387
388    public void doParse(TCustomSqlStatement psql, ESqlClause plocation){
389        switch (getConstraint_type()){
390            case primary_key:
391            case unique:
392                if (getColumnList() != null){
393                    for(int i=0;i<getColumnList().size();i++){
394                        getColumnList().getElement(i).setOwnerConstraint(this);
395                        if (psql instanceof TCreateTableSqlStatement){
396                            getColumnList().getElement(i).setOwnerTable(psql.tables.getTable(0));
397                            psql.tables.getTable(0).getLinkedColumns().addObjectName(getColumnList().getElement(i).getColumnName());
398                            getColumnList().getElement(i).getColumnName().setSourceTable(psql.tables.getTable(0));
399                        }
400                        psql.getIndexColumns().addElement(getColumnList().getElement(i));
401                    }
402                }
403                break;
404            case foreign_key:
405            case reference:{
406                if (getColumnList() != null){
407                    for(int i=0;i<getColumnList().size();i++){
408                        getColumnList().getElement(i).setOwnerConstraint(this);
409                        if (psql instanceof TCreateTableSqlStatement){
410                            getColumnList().getElement(i).setOwnerTable(psql.tables.getTable(0));
411                        }
412                        psql.getIndexColumns().addElement(getColumnList().getElement(i));
413                    }
414                }
415
416                TTable lcTable = null;
417                if (referencedObject != null){
418                    referencedObject.setObjectType(TObjectName.ttobjTable);
419
420                    lcTable = new TTable(referencedObject);
421                    lcTable.setPropertyFromObjectName(referencedObject,ETableEffectType.tetConstraintReference);
422//                    lcTable.setStartToken(referencedObject.getStartToken());
423//                    lcTable.setEndToken(referencedObject.getEndToken());
424//                    lcTable.setGsqlparser(referencedObject.getGsqlparser());
425//                    lcTable.setEffectType(ETableEffectType.tetConstraintReference);
426//                    lcTable.setTableType(ETableSource.objectname);
427                    psql.addToTables(lcTable);
428                }
429                if (referencedColumnList!=null){
430                    for(int i=0;i<referencedColumnList.size();i++){
431                        referencedColumnList.getObjectName(i).setLocation(ESqlClause.constraintRef);
432                        lcTable.getLinkedColumns().addObjectName(referencedColumnList.getObjectName(i));
433                    }
434                }
435            };
436            break;
437            case check:
438                if ((checkCondition != null) &&(checkCondition.getBetweenOperand() == null)){
439                    // missing between operand in sql like this in teradata:
440                    // CREATE TABLE tab1 (Id CHAR(9) ,SalaryFactor DOUBLE PRECISION BETWEEN .1 AND 1E1 );
441
442                    // System.out.println(checkCondition.toString());
443                }
444                break;
445            default:;
446        }
447    }
448
449    public void setCheckCondition(TExpression checkCondition) {
450        this.checkCondition = checkCondition;
451    }
452
453    public void setIndexCols(TPTNodeList<TIndexColName> indexCols) {
454        this.indexCols = indexCols;
455    }
456}