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 private boolean notEnforced = false; 204 205 public boolean isNonClustered() { 206 return nonClustered; 207 } 208 209 public void setNonClustered(boolean nonClustered) { 210 211 this.nonClustered = nonClustered; 212 } 213 214 /** 215 * Flink SQL: Returns true if the constraint has the NOT ENFORCED modifier. 216 * <p>Flink SQL only supports NOT ENFORCED mode for PRIMARY KEY constraints, 217 * as Flink does not own the data and cannot enforce constraints.</p> 218 * 219 * @return true if NOT ENFORCED was specified, false otherwise 220 */ 221 public boolean isNotEnforced() { 222 return notEnforced; 223 } 224 225 /** 226 * Sets the NOT ENFORCED modifier for this constraint. 227 * 228 * @param notEnforced true if NOT ENFORCED is specified 229 */ 230 public void setNotEnforced(boolean notEnforced) { 231 this.notEnforced = notEnforced; 232 } 233 234 private TPTNodeList<TColumnWithSortOrder> columnList = null; 235 private TExpression checkCondition = null; 236 private TPTNodeList <TAutomaticProperty> automaticProperties = null; 237 238 public void setAutomaticProperties(TPTNodeList<TAutomaticProperty> automaticProperties) { 239 this.automaticProperties = automaticProperties; 240 } 241 242 /** 243 * 244 * @return Automatic Initialization and Updating for TIMESTAMP in MySQL 245 */ 246 public TPTNodeList<TAutomaticProperty> getAutomaticProperties() { 247 248 return automaticProperties; 249 } 250 251 /** 252 * 253 * @return used in check constraint, requires a value in the database to comply with this specified condition. 254 */ 255 public TExpression getCheckCondition() { 256 return checkCondition; 257 } 258 259 /** 260 * 261 * @return column name list used when constraint type is unique, primary key or foreign key. 262 */ 263 public TPTNodeList<TColumnWithSortOrder> getColumnList() { 264 return columnList; 265 } 266 267 public void setColumnList(TPTNodeList<TColumnWithSortOrder> columnList) { 268 this.columnList = columnList; 269 } 270 271 private TPTNodeList <TIndexColName> indexCols; 272 273 /** 274 * @deprecated since 1.8.7.2, use {@link #getColumnList()} instead. 275 * @return 276 */ 277 public TPTNodeList<TIndexColName> getIndexCols() { 278 return indexCols; 279 } 280 281 282 public void init(Object arg1){ 283 if (arg1 instanceof TExpression){ 284 this.checkCondition = (TExpression)arg1; 285 }else if (arg1 instanceof TPTNodeList){ 286 this.columnList = (TPTNodeList<TColumnWithSortOrder>)arg1; 287 }else if (arg1 instanceof TObjectNameList){ 288 // column in TObjectNameList not changed to TPTNodeList<TColumnWithSortOrder> in .y file 289 // so we convert it here 290 this.columnList = new TPTNodeList<TColumnWithSortOrder>(); 291 TObjectNameList onl = (TObjectNameList)arg1; 292 for(int i=0;i<onl.size();i++){ 293 this.columnList.addElement(new TColumnWithSortOrder(onl.getObjectName(i))); 294 } 295// indexCols = (TPTNodeList)arg1; 296 } 297 } 298 299 private TObjectName indexColumnName = null; 300 301 302 /** 303 * Snowflake index table constraint: CREATE TABLE t1 (c1 INT, c2 INT, CONSTRAINT c1_idx INDEX (c1)); 304 * @return 305 */ 306 public TObjectName getIndexColumnName() { 307 return indexColumnName; 308 } 309 310 public void init(Object arg1, Object arg2,Object arg3){ 311 init(arg1,arg2); 312 switch (constraint_type){ 313 case table_index: 314 indexColumnName = (TObjectName)arg3; 315 indexColumnName.setDbObjectType(EDbObjectType.column); 316 break; 317 default: 318 break; 319 } 320 } 321 322 public void init(Object arg1, Object arg2){ 323 constraint_type = (EConstraintType)arg1; 324 switch (constraint_type){ 325 case table_index: 326 indexName = (TObjectName)arg2; 327 indexName.setDbObjectType(EDbObjectType.index); 328 break; 329 case cluster: 330 break; 331 case default_value: 332 this.defaultExpression = (TExpression) arg2; 333 break; 334 default: 335 break; 336 } 337 } 338 339 private TObjectName referencedObject = null; 340 341 // Vertica CORRELATION constraint fields 342 private TObjectNameList determinesColumnList = null; 343 private TExpression strengthValue = null; 344 345 /** 346 * Vertica CORRELATION constraint: columns that are determined by the correlation columns. 347 * Syntax: CONSTRAINT name CORRELATION (col1) DETERMINES (col2) STRENGTH 0.95 348 * @return the DETERMINES column list 349 */ 350 public TObjectNameList getDeterminesColumnList() { 351 return determinesColumnList; 352 } 353 354 public void setDeterminesColumnList(TObjectNameList determinesColumnList) { 355 this.determinesColumnList = determinesColumnList; 356 } 357 358 /** 359 * Vertica CORRELATION constraint: the strength value indicating correlation coefficient. 360 * @return the STRENGTH value expression 361 */ 362 public TExpression getStrengthValue() { 363 return strengthValue; 364 } 365 366 public void setStrengthValue(TExpression strengthValue) { 367 this.strengthValue = strengthValue; 368 } 369 370 public void setReferencedColumnList(TObjectNameList referencedColumnList) { 371 this.referencedColumnList = referencedColumnList; 372 } 373 374 /** 375 * 376 * @return column name list of referenced object in reference clause when constraint type is REF constraint. 377 */ 378 public TObjectNameList getReferencedColumnList() { 379 380 return referencedColumnList; 381 } 382 383 private TObjectNameList referencedColumnList = null; 384 385 386 public void setReferencedObject(TObjectName referencedObject) { 387 this.referencedObject = referencedObject; 388 } 389 390 /** 391 * 392 * @return referenced object in reference clause when constraint type is REF constraint. 393 */ 394 public TObjectName getReferencedObject() { 395 396 return referencedObject; 397 } 398 399 private TExpression seed; 400 401 public void setIncrement(TExpression increment) { 402 this.increment = increment; 403 } 404 405 public void setSeed(TExpression seed) { 406 this.seed = seed; 407 } 408 409 /** 410 * Used internal 411 * @return 412 */ 413 public TExpression getIncrement() { 414 415 return increment; 416 } 417 418 /** 419 * Used internal 420 * @return 421 */ 422 public TExpression getSeed() { 423 return seed; 424 } 425 426 private TExpression increment; 427 428 public void accept(TParseTreeVisitor v){ 429 v.preVisit(this); 430 v.postVisit(this); 431 } 432 433 public void acceptChildren(TParseTreeVisitor v){ 434 v.preVisit(this); 435 v.postVisit(this); 436 } 437 438 public void doParse(TCustomSqlStatement psql, ESqlClause plocation){ 439 switch (getConstraint_type()){ 440 case primary_key: 441 case unique: 442 if (getColumnList() != null){ 443 for(int i=0;i<getColumnList().size();i++){ 444 TColumnWithSortOrder colWithSort = getColumnList().getElement(i); 445 colWithSort.setOwnerConstraint(this); 446 if (psql instanceof TCreateTableSqlStatement){ 447 colWithSort.setOwnerTable(psql.tables.getTable(0)); 448 // For functional indexes, getColumnName() returns null (use getExpression() instead) 449 if (colWithSort.getColumnName() != null) { 450 psql.tables.getTable(0).getLinkedColumns().addObjectName(colWithSort.getColumnName()); 451 colWithSort.getColumnName().setSourceTable(psql.tables.getTable(0)); 452 } 453 } 454 psql.getIndexColumns().addElement(colWithSort); 455 } 456 } 457 break; 458 case correlation: 459 // Vertica CORRELATION constraint: link both CORRELATION and DETERMINES columns to the table 460 if (getColumnList() != null){ 461 for(int i=0;i<getColumnList().size();i++){ 462 TColumnWithSortOrder colWithSort = getColumnList().getElement(i); 463 colWithSort.setOwnerConstraint(this); 464 if (psql instanceof TCreateTableSqlStatement){ 465 colWithSort.setOwnerTable(psql.tables.getTable(0)); 466 if (colWithSort.getColumnName() != null) { 467 psql.tables.getTable(0).getLinkedColumns().addObjectName(colWithSort.getColumnName()); 468 colWithSort.getColumnName().setSourceTable(psql.tables.getTable(0)); 469 } 470 } 471 } 472 } 473 if (getDeterminesColumnList() != null){ 474 for(int i=0;i<getDeterminesColumnList().size();i++){ 475 TObjectName colName = getDeterminesColumnList().getObjectName(i); 476 if (psql instanceof TCreateTableSqlStatement){ 477 psql.tables.getTable(0).getLinkedColumns().addObjectName(colName); 478 colName.setSourceTable(psql.tables.getTable(0)); 479 } 480 } 481 } 482 break; 483 case foreign_key: 484 case reference:{ 485 if (getColumnList() != null){ 486 for(int i=0;i<getColumnList().size();i++){ 487 TColumnWithSortOrder colWithSort = getColumnList().getElement(i); 488 colWithSort.setOwnerConstraint(this); 489 if (psql instanceof TCreateTableSqlStatement){ 490 colWithSort.setOwnerTable(psql.tables.getTable(0)); 491 } 492 psql.getIndexColumns().addElement(colWithSort); 493 } 494 } 495 496 TTable lcTable = null; 497 if (referencedObject != null){ 498 referencedObject.setObjectType(TObjectName.ttobjTable); 499 500 lcTable = new TTable(referencedObject); 501 lcTable.setPropertyFromObjectName(referencedObject,ETableEffectType.tetConstraintReference); 502// lcTable.setStartToken(referencedObject.getStartToken()); 503// lcTable.setEndToken(referencedObject.getEndToken()); 504// lcTable.setGsqlparser(referencedObject.getGsqlparser()); 505// lcTable.setEffectType(ETableEffectType.tetConstraintReference); 506// lcTable.setTableType(ETableSource.objectname); 507 psql.addToTables(lcTable); 508 } 509 if (referencedColumnList!=null){ 510 for(int i=0;i<referencedColumnList.size();i++){ 511 referencedColumnList.getObjectName(i).setLocation(ESqlClause.constraintRef); 512 lcTable.getLinkedColumns().addObjectName(referencedColumnList.getObjectName(i)); 513 } 514 } 515 }; 516 break; 517 case check: 518 if ((checkCondition != null) &&(checkCondition.getBetweenOperand() == null)){ 519 // missing between operand in sql like this in teradata: 520 // CREATE TABLE tab1 (Id CHAR(9) ,SalaryFactor DOUBLE PRECISION BETWEEN .1 AND 1E1 ); 521 522 // System.out.println(checkCondition.toString()); 523 } 524 break; 525 default:; 526 } 527 } 528 529 public void setCheckCondition(TExpression checkCondition) { 530 this.checkCondition = checkCondition; 531 } 532 533 public void setIndexCols(TPTNodeList<TIndexColName> indexCols) { 534 this.indexCols = indexCols; 535 } 536}