1 22 23 package org.xquark.extractor.algebra; 24 25 import java.sql.Types ; 26 import java.util.ArrayList ; 27 import java.util.List ; 28 29 import org.xquark.extractor.common.Debug; 30 import org.xquark.extractor.common.SqlWrapperException; 31 import org.xquark.extractor.xfunctions.*; 32 import org.xquark.jdbc.typing.DbType; 33 import org.xquark.jdbc.typing.JavaTypeInfo; 34 35 43 public final class AlgebraTypeVisitor extends DefaultAlgebraVisitor 44 implements Constants 45 { 46 private static final String RCSRevision = "$Revision: 1.16 $"; 47 private static final String RCSName = "$Name: $"; 48 49 private DbType ptBit = new DbType(Types.BIT); 50 private DbType ptBoolean = new DbType(DbType.BOOLEAN); 51 private DbType ptDate = new DbType(Types.DATE); 52 private DbType ptDecimal = new DbType(Types.DECIMAL); 53 private DbType ptDouble = new DbType(Types.DOUBLE); 54 private DbType ptFloat = new DbType(Types.FLOAT); 55 private DbType ptInteger = new DbType(Types.INTEGER); 56 private DbType ptNull = new DbType(Types.NULL); 57 private DbType ptTime = new DbType(Types.TIME); 58 private DbType ptTimeStamp = new DbType(Types.TIMESTAMP); 59 private DbType ptVarChar = new DbType(Types.VARCHAR); 60 61 public AlgebraTypeVisitor() { 62 } 63 64 public void reinit() { 65 } 66 67 public void visit(Expression arg) throws SqlWrapperException { 68 Debug.assertTrue(false, "NYI!!" + arg.toString()); 69 } 70 71 public void visit(Attribute arg) throws SqlWrapperException { 72 arg.setType(new SqlTypeAtom( 73 arg.getAttribute().getMappingInfo().getDBType(), 74 arg.getAttribute().getName(), 75 SqlType.ONE 76 )); 77 } 78 79 public void visit(Rowid arg) throws SqlWrapperException { 80 arg.setType(new SqlTypeAtom(new DbType(DbType.ORACLE_ROWID), arg.getName())); 81 } 82 83 public void visit(AttributeExpression arg) throws SqlWrapperException { 84 SqlTypeAtom type = null; 85 86 Expression underlyinExpr = arg.getUnderlyinExpr(); 87 if (underlyinExpr != null && !arg.getName().equals("*")) { 88 underlyinExpr.accept(this); 90 type = (SqlTypeAtom) underlyinExpr.getType().clone(); 91 type.setName(arg.getAttribute()); 92 } 93 94 arg.setType(type); 95 } 96 97 public void visit(BinOpArithmetic arg) throws SqlWrapperException { 98 arg.getLeftOperand().accept(this); 99 arg.getRightOperand().accept(this); 100 arg.setType(new SqlTypeAtom(ptDouble, null, SqlType.ONE)); 101 } 102 103 public void visit(BinOpBoolean arg) throws SqlWrapperException { 104 arg.getLeftOperand().accept(this); 105 arg.getRightOperand().accept(this); 106 arg.setType(new SqlTypeAtom(ptBit, null, SqlType.ONE)); 107 } 108 109 public void visit(BinOpCompare arg) throws SqlWrapperException { 110 arg.getLeftOperand().accept(this); 111 arg.getRightOperand().accept(this); 112 arg.setType(new SqlTypeAtom(ptBit, null, SqlType.ONE)); 113 } 114 115 public void visit(BinOpCompareAny arg) throws SqlWrapperException { 116 arg.getLeftOperand().accept(this); 117 arg.getRightOperand().accept(this); 118 arg.setType(new SqlTypeAtom(ptBit, null, SqlType.ONE)); 119 } 120 121 public void visit(BinOpDifference arg) throws SqlWrapperException { 122 Expression lOprnd = arg.getLeftOperand(); 123 Expression rOprnd = arg.getRightOperand(); 124 lOprnd.accept(this); 125 rOprnd.accept(this); 126 127 arg.setType((SqlType) lOprnd.getType().clone()); 128 } 129 130 public void visit(BinOpIntersect arg) throws SqlWrapperException { 131 Expression lOprnd = arg.getLeftOperand(); 132 Expression rOprnd = arg.getRightOperand(); 133 lOprnd.accept(this); 134 rOprnd.accept(this); 135 136 arg.setType((SqlType) lOprnd.getType().clone()); 137 } 138 139 public void visit(BinOpMerge arg) throws SqlWrapperException { 140 Expression lOprnd = arg.getLeftOperand(); 141 Expression rOprnd = arg.getRightOperand(); 142 lOprnd.accept(this); 143 rOprnd.accept(this); 144 145 arg.setType((SqlType) lOprnd.getType().clone()); 146 } 147 148 public void visit(BinOpOuterJoin arg) throws SqlWrapperException { 149 Expression lOprnd = arg.getLeftOperand(); 150 Expression rOprnd = arg.getRightOperand(); 151 lOprnd.accept(this); 152 rOprnd.accept(this); 153 154 SqlType leftType = (SqlType) lOprnd.getType().clone(); 155 SqlType rightType = (SqlType) rOprnd.getType().clone(); 156 SqlTypeCombinedStructure type = new SqlTypeCombinedStructure(); 157 type.addStructure(leftType); 158 type.addStructure(rightType); 159 arg.setType(type); 160 161 List predicateList = arg.getPredicateList(); 162 if (null != predicateList) { 163 Expression predicate = null; 164 for (int i = 0; i < predicateList.size(); i++) { 165 predicate = (Expression) predicateList.get(i); 166 predicate.accept(this); 167 } 168 } 169 } 170 171 public void visit(BinOpUnion arg) throws SqlWrapperException { 172 Expression lOprnd = arg.getLeftOperand(); 173 Expression rOprnd = arg.getRightOperand(); 174 lOprnd.accept(this); 175 rOprnd.accept(this); 176 177 SqlType type = (SqlType) lOprnd.getType().clone(); 178 arg.setType(type); 179 } 180 181 public void visit(DummyTable arg) throws SqlWrapperException { 182 arg.setType(new SqlTypeAtom(null, null, SqlType.MANY)); 183 } 184 185 public void visit(FunAggregate arg) throws SqlWrapperException { 186 Expression oprnd = arg.getOperand(); 187 oprnd.accept(this); 188 189 SqlType type = null; 190 int oprtr = arg.getOperator(); 191 switch (oprtr) { 192 case AVG : 193 type = new SqlTypeAtom(ptDouble, null, SqlType.ONE); break; 195 case COUNT : 196 type = new SqlTypeAtom(ptInteger, null, SqlType.ONE); 197 break; 198 case MIN : 199 type = (SqlType) oprnd.getType().clone(); 200 break; 201 case MAX : 202 type = (SqlType) oprnd.getType().clone(); 203 break; 204 case SUM : 205 type = (SqlType) oprnd.getType().clone(); 206 break; 207 default : 208 Debug.assertTrue(false, "internal error"); 209 break; 210 } 211 arg.setType(type); 212 } 213 214 public void visit(IfThenElse arg) throws SqlWrapperException { 215 Expression iif = arg.getIf(); 216 iif.accept(this); 217 218 Expression tthen = arg.getThen(); 219 tthen.accept(this); 220 221 Expression eelse = arg.getElse(); 222 eelse.accept(this); 223 224 225 int tthenCode = ((SqlTypeAtom) tthen.getType()).getType().getPrimitiveTypeCode(); 226 int eelseCode = ((SqlTypeAtom) eelse.getType()).getType().getPrimitiveTypeCode(); 227 Debug.assertTrue(tthenCode == eelseCode, "tthenCode == eelseCode"); 228 229 arg.setType((SqlTypeAtom) tthen.getType().clone()); 230 } 231 232 public void visit(Join arg) throws SqlWrapperException { 233 List operandList = arg.getOperandList(); 234 SqlType type = null; 235 Expression operand = null; 236 if (1 < operandList.size()) { 237 type = new SqlTypeCombinedStructure(); 238 for (int i = 0; i < operandList.size(); i++) { 239 operand = (Expression) operandList.get(i); 240 operand.accept(this); 241 SqlType operandType = (SqlType) operand.getType().clone(); 242 ((SqlTypeCombinedStructure) type).addStructure(operandType); 243 } 244 } 245 else { 246 operand = (Expression) operandList.get(0); 247 operand.accept(this); 248 type = (SqlType) operand.getType().clone(); 249 } 250 arg.setType(type); 251 252 List predicateList = arg.getPredicateList(); 253 if (null != predicateList) { 254 Expression predicate = null; 255 for (int i = 0; i < predicateList.size(); i++) { 256 predicate = (Expression) predicateList.get(i); 257 predicate.accept(this); 258 } 259 } 260 } 261 262 public void visit(ExternalVariable arg) throws SqlWrapperException { 263 SqlType sType = null; 264 265 switch (arg.getMappingInfo().getJavaType()) { case JavaTypeInfo.JAVA_STRING : 267 case JavaTypeInfo.SCHEMA_URI : 268 case JavaTypeInfo.SCHEMA_QNAME : 269 case JavaTypeInfo.SCHEMA_DURATION : 270 sType = new SqlTypeAtom(ptVarChar, null, SqlType.ONE); 271 break; 272 case JavaTypeInfo.JAVA_BOOLEAN : 273 sType = new SqlTypeAtom(ptBit, null, SqlType.ONE); 274 break; 275 case JavaTypeInfo.JAVA_BIG_DECIMAL : 276 sType = new SqlTypeAtom(ptDecimal, null, SqlType.ONE); 277 break; 278 case JavaTypeInfo.JAVA_FLOAT : 279 sType = new SqlTypeAtom(ptFloat, null, SqlType.ONE); 280 break; 281 case JavaTypeInfo.JAVA_DOUBLE : 282 sType = new SqlTypeAtom(ptDouble, null, SqlType.ONE); 283 break; 284 case JavaTypeInfo.JAVA_LONG : 285 sType = new SqlTypeAtom(ptInteger, null, SqlType.ONE); 286 break; 287 case JavaTypeInfo.SCHEMA_DATETIME : 288 sType = new SqlTypeAtom(ptDate, null, SqlType.ONE); 289 break; 290 default : 291 } 292 arg.setType(sType); 293 } 294 295 public void visit(LitBoolean arg) throws SqlWrapperException { 296 arg.setType(new SqlTypeAtom(ptBit, null, SqlType.ONE)); 297 } 298 299 public void visit(LitDate arg) throws SqlWrapperException { 300 arg.setType(new SqlTypeAtom(ptDate, null, SqlType.ONE)); 301 } 302 303 public void visit(LitDecimal arg) throws SqlWrapperException { 304 arg.setType(new SqlTypeAtom(ptDecimal, null, SqlType.ONE)); 305 } 306 307 public void visit(LitDouble arg) throws SqlWrapperException { 308 arg.setType(new SqlTypeAtom(ptDouble, null, SqlType.ONE)); 309 } 310 311 public void visit(LitFloat arg) throws SqlWrapperException { 312 arg.setType(new SqlTypeAtom(ptFloat, null, SqlType.ONE)); 313 } 314 315 public void visit(LitInteger arg) throws SqlWrapperException { 316 arg.setType(new SqlTypeAtom(ptInteger, null, SqlType.ONE)); 317 } 318 319 public void visit(LitList arg) throws SqlWrapperException { 320 SqlTypeAtom type = null; 321 List list = arg.getLitList(); 322 if (null != list && !list.isEmpty()) { 323 Literal element = (Literal) list.get(0); 324 element.accept(this); 325 type = (SqlTypeAtom) element.getType(); 326 for (int i = 1; i < list.size(); i++) { 327 element = (Literal) list.get(i); 328 element.setType(type); 329 } 330 type = new SqlTypeAtom(type.getType(), null, SqlType.MANY); 331 } 332 else 333 type = new SqlTypeAtom(ptNull, null, SqlType.MANY); 334 335 arg.setType(type); 336 } 337 338 public void visit(LitString arg) throws SqlWrapperException { 339 arg.setType(new SqlTypeAtom(new DbType(Types.VARCHAR, 341 arg.getValue().length()), 342 null, 343 SqlType.ONE 344 )); 345 } 346 347 public void visit(LitNull arg) throws SqlWrapperException { 348 arg.setType(new SqlTypeAtom(ptNull, null, SqlType.ONE)); 349 } 350 351 public void visit(RenameItem arg) throws SqlWrapperException { 352 Expression operand = arg.getOperand(); 353 operand.accept(this); 354 SqlTypeAtom type = (SqlTypeAtom) operand.getType(); 355 type.setName(arg.getName()); 356 arg.setType(type); 357 } 358 359 public void visit(RenameRelation arg) throws SqlWrapperException { 360 Expression operand = arg.getOperand(); 361 operand.accept(this); 362 SqlType oprndType = operand.getType(); 363 SqlType type = null; 364 if (oprndType instanceof SqlTypeAtom) { 365 type = (SqlTypeAtom) oprndType.clone(); 366 ((SqlTypeAtom) type).setRelationName(arg.getName()); 367 } else if (oprndType instanceof SqlTypeStructure) { 368 type = (SqlTypeStructure) oprndType.clone(); 369 ((SqlTypeStructure) type).setName(arg.getName()); 370 } else if (oprndType instanceof SqlTypeCombinedStructure) { 371 List attrList = ((SqlTypeCombinedStructure) oprndType).getAttributes(); 372 type = new SqlTypeStructure(arg.getName(), attrList, SqlType.MANY); 373 } 374 375 arg.setType(type); 376 } 377 378 public void visit(SortSpecification arg) throws SqlWrapperException { 379 Expression expr = arg.getSortExpression(); 380 expr.accept(this); 381 arg.setType(expr.getType()); 382 } 383 384 public void visit(Table arg) throws SqlWrapperException { 385 List attrList = arg.getAttributes(); 386 List attrTypeList = new ArrayList (); 387 SqlTypeStructure type = new SqlTypeStructure(); 388 type.setMultiplicity(SqlType.MANY); 389 390 for (int i = 0; i < attrList.size(); i++) { 391 Expression attr = (Expression) attrList.get(i); 392 attr.accept(this); 393 SqlTypeAtom attrType = (SqlTypeAtom) attr.getType(); 394 type.addAttribute(attrType); 395 } 396 arg.setType(type); 397 } 398 399 public void visit(TempValue arg) throws SqlWrapperException { 400 Expression operand = arg.getOperand(); 401 operand.accept(this); 402 arg.setType(operand.getType()); 403 } 404 405 public void visit(UnOpAggregate arg) throws SqlWrapperException { 406 visit((UnOpProject) arg); 407 SqlType type = arg.getType(); 408 type.setMultiplicity(SqlType.ONE); 409 410 } 411 412 public void visit(UnOpExists arg) throws SqlWrapperException { 413 Expression operand = arg.getOperand(); 414 operand.accept(this); 415 arg.setType(new SqlTypeAtom(ptBit, null, SqlType.ONE)); 416 } 417 418 public void visit(UnOpIsNull arg) throws SqlWrapperException { 419 Expression operand = arg.getOperand(); 420 operand.accept(this); 421 arg.setType(new SqlTypeAtom(ptBit, null, SqlType.ONE)); 422 } 423 424 public void visit(UnOpGroup arg) throws SqlWrapperException { 425 Expression operand = arg.getOperand(); 426 operand.accept(this); 427 arg.setType((SqlType) operand.getType().clone()); 428 } 429 430 public void visit(UnOpMinus arg) throws SqlWrapperException { 431 Expression operand = arg.getOperand(); 432 operand.accept(this); 433 arg.setType(operand.getType()); 434 } 435 436 public void visit(UnOpNot arg) throws SqlWrapperException { 437 Expression operand = arg.getOperand(); 438 operand.accept(this); 439 arg.setType(new SqlTypeAtom(ptBit, null, SqlType.ONE)); 440 } 441 442 public void visit(UnOpProject arg) throws SqlWrapperException { 443 Expression operand = arg.getOperand(); 444 operand.accept(this); 445 List selectList = arg.getItemList(); 446 List itemTypeList = new ArrayList (); 447 448 for (int i = 0; i < selectList.size(); i++) { 449 Expression item = (Expression) selectList.get(i); 450 item.accept(this); 451 itemTypeList.add((SqlTypeAtom) item.getType().clone()); 452 } 453 454 SqlType type = null; 455 if (1 < itemTypeList.size()) { 456 type = new SqlTypeStructure(itemTypeList, SqlType.MANY); 457 } else { 458 type = (SqlTypeAtom) itemTypeList.get(0); 459 type.setMultiplicity(SqlType.MANY); 460 } 461 462 arg.setType(type); 463 } 464 465 public void visit(UnOpRestrict arg) throws SqlWrapperException { 466 Expression operand = arg.getOperand(); 467 operand.accept(this); 468 arg.setType((SqlType) operand.getType().clone()); 469 470 List predicateList = arg.getPredicateList(); 471 if (null != predicateList) { 472 Expression predicate = null; 473 for (int i = 0; i < predicateList.size(); i++) { 474 predicate = (Expression) predicateList.get(i); 475 predicate.accept(this); 476 } 477 } 478 } 479 480 public void visit(UnOpSort arg) throws SqlWrapperException { 481 Expression operand = arg.getOperand(); 482 operand.accept(this); 483 arg.setType((SqlType) operand.getType().clone()); 484 485 List list = arg.getSortSpecificationList(); 486 SortSpecification sortSpec = null; 487 Expression sortExpr = null; 488 Expression predicate = null; 489 for (int i = 0; i < list.size(); i++) { 490 sortSpec = (SortSpecification) list.get(i); 491 sortExpr = sortSpec.getSortExpression(); 492 sortExpr.accept(this); 493 } 494 } 495 496 public void visit(AfTrim arg) throws SqlWrapperException { 497 ((Expression) arg.getArgument(0)).accept(this); 498 arg.setType(new SqlTypeAtom(ptVarChar, null, SqlType.ONE)); 501 } 502 503 public void visit(AfCast arg) throws SqlWrapperException { 504 ((Expression) arg.getExpression()).accept(this); 505 SqlTypeAtom type = new SqlTypeAtom(arg.getTargetType(), arg.getName()); 506 type.setName(arg.getName()); 507 arg.setType(type); 508 } 509 510 public void visit(XfCast arg) throws SqlWrapperException { 511 ((Expression) arg.getExpression()).accept(this); 512 arg.setType(new SqlTypeAtom(arg.getTargetType(), null)); 513 } 514 515 public void visit(XfAbs arg) throws SqlWrapperException { 516 Expression para = (Expression) arg.getArgument(0); 517 para.accept(this); 518 arg.setType((SqlType) para.getType().clone()); 519 } 520 521 public void visit(XfCeiling arg) throws SqlWrapperException { 522 ((Expression) arg.getArgument(0)).accept(this); 523 arg.setType(new SqlTypeAtom(ptInteger, null, SqlType.ONE)); 524 } 525 526 public void visit(XfConcat arg) throws SqlWrapperException { 527 Expression parameter; 528 int size = 0; 529 for (int i = 0; i < arg.getArgumentNumber(); i++) { 530 parameter = (Expression) arg.getArgument(i); 531 parameter.accept(this); 532 size += ((SqlTypeAtom) parameter.getType()).getType().getLength(); 533 } 534 535 arg.setType(new SqlTypeAtom(new DbType(Types.VARCHAR, size), null, SqlType.ONE)); 537 } 538 539 public void visit(XfContains arg) throws SqlWrapperException { 540 Expression para = (Expression) arg.getArgument(0); 541 para.accept(this); 542 para = (Expression) arg.getArgument(1); 543 para.accept(this); 544 arg.setType(new SqlTypeAtom(ptBoolean, null, SqlType.ONE)); 545 } 546 547 public void visit(XfCurrentDateTime arg) throws SqlWrapperException { 548 arg.setType(new SqlTypeAtom(ptTimeStamp, null, SqlType.ONE)); 549 } 550 551 public void visit(XfDate arg) throws SqlWrapperException { 552 ((Expression) arg.getArgument(0)).accept(this); 553 arg.setType(new SqlTypeAtom(ptDate, null, SqlType.ONE)); 554 } 555 556 public void visit(XfDateTime arg) throws SqlWrapperException { 557 ((Expression) arg.getArgument(0)).accept(this); 558 arg.setType(new SqlTypeAtom(ptTimeStamp, null, SqlType.ONE)); 559 } 560 561 public void visit(XfEndsWith arg) throws SqlWrapperException { 562 Expression para = (Expression) arg.getArgument(0); 563 para.accept(this); 564 para = (Expression) arg.getArgument(1); 565 para.accept(this); 566 arg.setType(new SqlTypeAtom(ptBoolean, null, SqlType.ONE)); 567 } 568 569 public void visit(XfFloor arg) throws SqlWrapperException { 570 ((Expression) arg.getArgument(0)).accept(this); 571 arg.setType(new SqlTypeAtom(ptInteger, null, SqlType.ONE)); 572 } 573 574 public void visit(XfLowerCase arg) throws SqlWrapperException { 575 Expression para = (Expression) arg.getArgument(0); 576 para.accept(this); 577 arg.setType(para.getType()); 578 } 579 580 public void visit(XfRound arg) throws SqlWrapperException { 581 ((Expression) arg.getArgument(0)).accept(this); 582 arg.setType(new SqlTypeAtom(ptInteger, null, SqlType.ONE)); 583 } 584 585 public void visit(XfStartsWith arg) throws SqlWrapperException { 586 Expression para = (Expression) arg.getArgument(0); 587 para.accept(this); 588 para = (Expression) arg.getArgument(1); 589 para.accept(this); 590 arg.setType(new SqlTypeAtom(ptBoolean, null, SqlType.ONE)); 591 } 592 593 public void visit(XfStringLength arg) throws SqlWrapperException { 594 ((Expression) arg.getArgument(0)).accept(this); 595 arg.setType(new SqlTypeAtom(ptInteger, null, SqlType.ONE)); 596 } 597 598 public void visit(XfSubString arg) throws SqlWrapperException { 599 Expression string = (Expression) arg.getArgument(0); 600 string.accept(this); 601 Expression startIndex = (Expression) arg.getArgument(1); 602 startIndex.accept(this); 603 Expression length = (Expression) arg.getArgument(2); 604 int size = 0; 605 if (length == null && startIndex instanceof LitInteger) { 606 size = (int) ((SqlTypeAtom) string.getType()).getType().getLength() - ((LitInteger) startIndex).getValue().intValue() + 1; 607 } 608 else { 609 length.accept(this); 610 if (length instanceof LitInteger) 611 size = ((LitInteger) length).getValue().intValue(); 612 } 613 614 if (size == 0) arg.setType(new SqlTypeAtom(ptVarChar, null, SqlType.ONE)); 616 else { 617 SqlTypeAtom type = (SqlTypeAtom) string.getType().clone(); 618 type.getType().setLength(size); 619 arg.setType(type); 620 } 621 } 622 623 public void visit(XfTime arg) throws SqlWrapperException { 624 ((Expression) arg.getArgument(0)).accept(this); 625 arg.setType(new SqlTypeAtom(ptTime, null, SqlType.ONE)); 626 } 627 628 public void visit(XfUpperCase arg) throws SqlWrapperException { 629 Expression para = (Expression) arg.getArgument(0); 630 para.accept(this); 631 arg.setType(para.getType()); 632 } 633 634 } 635 | Popular Tags |