1 30 31 32 package org.hsqldb; 33 34 import org.hsqldb.HsqlNameManager.HsqlName; 35 36 44 45 final class CompiledStatement { 49 50 static final String PCOL_PREFIX = "@p"; 51 static final String RETURN_COLUMN_NAME = "@p0"; 52 static final int UNKNOWN = 0; 53 54 static final int INSERT_VALUES = 1; 56 static final int INSERT_SELECT = 2; 57 static final int UPDATE = 3; 58 static final int DELETE = 4; 59 static final int SELECT = 5; 60 static final int SELECT_INTO = 6; 61 static final int CALL = 7; 62 63 static final int DML = 7; 65 static final int DQL = 8; 66 static final int DDL = 9; 67 68 69 int id; 70 71 72 boolean isValid = true; 73 74 75 Table targetTable; 76 77 78 TableFilter targetFilter; 79 80 81 Expression condition; 82 83 84 int[] columnMap; 85 86 87 Expression[] columnValues; 88 89 93 boolean[] checkColumns; 94 95 96 Expression expression; 97 98 102 Select select; 103 104 109 Expression[] parameters; 110 111 114 int[] paramTypes; 115 116 119 SubQuery[] subqueries; 120 121 137 int type; 138 139 142 String sql; 143 144 147 final HsqlName schemaHsqlName; 148 149 153 CompiledStatement(HsqlName schema) { 154 155 parameters = new Expression[0]; 156 paramTypes = new int[0]; 157 subqueries = new SubQuery[0]; 158 type = DDL; 159 schemaHsqlName = schema; 160 } 161 162 169 CompiledStatement(Session session, Database database, HsqlName schema, 170 TableFilter targetFilter, Expression deleteCondition, 171 SubQuery[] subqueries, 172 Expression[] params) throws HsqlException { 173 174 schemaHsqlName = schema; 175 this.targetFilter = targetFilter; 176 targetTable = targetFilter.filterTable; 177 178 if (deleteCondition != null) { 179 condition = new Expression(deleteCondition); 180 181 condition.resolveTables(targetFilter); 182 condition.resolveTypes(session); 183 targetFilter.setConditions(session, condition); 184 } 185 186 setParameters(params); 187 setSubqueries(subqueries); 188 189 type = DELETE; 190 } 191 192 201 CompiledStatement(Session session, Database database, HsqlName schema, 202 TableFilter targetFilter, int[] columnMap, 203 Expression[] columnValues, Expression updateCondition, 204 SubQuery[] subqueries, 205 Expression[] params) throws HsqlException { 206 207 schemaHsqlName = schema; 208 this.targetFilter = targetFilter; 209 targetTable = targetFilter.filterTable; 210 this.columnMap = columnMap; 211 this.columnValues = columnValues; 212 213 for (int i = 0; i < columnValues.length; i++) { 214 Expression cve = columnValues[i]; 215 216 if (cve.isParam()) { 217 cve.setTableColumnAttributes(targetTable, columnMap[i]); 218 } else { 219 cve.resolveTables(targetFilter); 220 cve.resolveTypes(session); 221 } 222 } 223 224 if (updateCondition != null) { 225 condition = new Expression(updateCondition); 226 227 condition.resolveTables(targetFilter); 228 condition.resolveTypes(session); 229 targetFilter.setConditions(session, condition); 230 } 231 232 setParameters(params); 233 setSubqueries(subqueries); 234 235 type = UPDATE; 236 } 237 238 247 CompiledStatement(HsqlName schema, Table targetTable, int[] columnMap, 248 Expression[] columnValues, boolean[] checkColumns, 249 SubQuery[] subqueries, 250 Expression[] params) throws HsqlException { 251 252 schemaHsqlName = schema; 253 this.targetTable = targetTable; 254 this.columnMap = columnMap; 255 this.checkColumns = checkColumns; 256 this.columnValues = columnValues; 257 258 for (int i = 0; i < columnValues.length; i++) { 259 Expression cve = columnValues[i]; 260 261 if (cve.isParam()) { 264 cve.setTableColumnAttributes(targetTable, columnMap[i]); 265 } 266 } 267 268 setParameters(params); 269 setSubqueries(subqueries); 270 271 type = INSERT_VALUES; 272 } 273 274 283 CompiledStatement(Session session, Database database, HsqlName schema, 284 Table targetTable, int[] columnMap, 285 boolean[] checkColumns, Select select, 286 SubQuery[] subqueries, 287 Expression[] params) throws HsqlException { 288 289 schemaHsqlName = schema; 290 this.targetTable = targetTable; 291 this.columnMap = columnMap; 292 this.checkColumns = checkColumns; 293 this.select = select; 294 295 resolveInsertParameterTypes(); 297 298 select.prepareResult(session); 300 setParameters(params); 301 setSubqueries(subqueries); 302 303 type = INSERT_SELECT; 304 } 305 306 312 CompiledStatement(Session session, Database database, HsqlName schema, 313 Select select, SubQuery[] subqueries, 314 Expression[] params) throws HsqlException { 315 316 schemaHsqlName = schema; 317 this.select = select; 318 319 for (int i = 0; i < select.iResultLen; i++) { 321 Expression colexpr = select.exprColumns[i]; 322 323 if (colexpr.getDataType() == Types.NULL) { 324 colexpr.setDataType(Types.VARCHAR); 325 } 326 } 327 328 select.prepareResult(session); 330 setParameters(params); 331 setSubqueries(subqueries); 332 333 type = SELECT; 334 } 335 336 342 CompiledStatement(Session session, Database database, HsqlName schema, 343 Expression expression, SubQuery[] subqueries, 344 Expression[] params) throws HsqlException { 345 346 schemaHsqlName = schema; 347 this.expression = expression; 348 349 expression.resolveTypes(session); 350 351 expression.paramMode = Expression.PARAM_OUT; 352 353 setParameters(params); 354 setSubqueries(subqueries); 355 356 type = CALL; 357 } 358 359 362 private void resolveInsertParameterTypes() { 363 364 for (int i = 0; i < select.iResultLen; i++) { 365 Expression colexpr = select.exprColumns[i]; 366 367 if (colexpr.getDataType() == Types.NULL) { 368 Column col = targetTable.getColumn(columnMap[i]); 369 370 colexpr.setDataType(col.getType()); 371 } 372 } 373 } 374 375 private void setParameters(Expression[] params) { 376 377 this.parameters = params; 378 379 int[] types = new int[parameters.length]; 380 381 for (int i = 0; i < parameters.length; i++) { 382 types[i] = parameters[i].getDataType(); 383 } 384 385 this.paramTypes = types; 386 } 387 388 private void setSubqueries(SubQuery[] subqueries) { 389 this.subqueries = subqueries; 390 } 391 392 void materializeSubQueries(Session session) throws HsqlException { 393 394 for (int i = 0; i < subqueries.length; i++) { 395 SubQuery sq = subqueries[i]; 396 397 if (sq.isMaterialised) { 399 continue; 400 } 401 402 if (sq.isResolved) { 403 sq.populateTable(session); 404 405 sq.isMaterialised = true; 406 } 407 } 408 } 409 410 void dematerializeSubQueries(Session session) { 411 412 if (subqueries == null) { 413 return; 414 } 415 416 for (int i = 0; i < subqueries.length; i++) { 417 subqueries[i].table.clearAllRows(session); 418 419 subqueries[i].isMaterialised = false; 420 } 421 } 422 423 void clearVariables() { 424 425 isValid = false; 426 targetTable = null; 427 targetFilter = null; 428 condition = null; 429 columnMap = null; 430 columnValues = null; 431 checkColumns = null; 432 expression = null; 433 select = null; 434 parameters = null; 435 paramTypes = null; 436 subqueries = null; 437 } 438 439 boolean canExecute(Session session) throws HsqlException { 440 441 switch (type) { 442 443 case CALL : {} 444 case SELECT : 445 for (int i = 0; i < select.tFilter.length; i++) { 446 HsqlName name = select.tFilter[i].filterTable.getName(); 447 448 session.check(name, UserManager.SELECT); 449 } 450 break; 451 452 case INSERT_SELECT : 453 break; 454 455 case DELETE : 456 session.check(targetTable.getName(), UserManager.DELETE); 457 break; 458 459 case INSERT_VALUES : 460 session.check(targetTable.getName(), UserManager.INSERT); 461 break; 462 463 case UPDATE : 464 session.check(targetTable.getName(), UserManager.UPDATE); 465 break; 466 467 case DDL : 468 } 469 470 return true; 471 } 472 473 void checkTableWriteAccess(Session session, 474 Table table) throws HsqlException { 475 476 session.checkReadWrite(); 478 479 if (table.isView()) { 481 throw Trace.error(Trace.NOT_A_TABLE, table.getName().name); 482 } 483 484 table.checkDataReadOnly(); 486 } 487 488 private static final Result updateCountResult = 489 new Result(ResultConstants.UPDATECOUNT); 490 491 Result describeResult() { 492 493 switch (type) { 494 495 case CALL : { 496 497 Expression e; 512 Result r; 513 514 e = expression; 515 r = Result.newSingleColumnResult( 516 CompiledStatement.RETURN_COLUMN_NAME, e.getDataType()); 517 r.metaData.classNames[0] = e.getValueClassName(); 518 519 return r; 521 } 522 case SELECT : 523 return select.sIntoTable == null ? select.describeResult() 524 : updateCountResult; 525 526 case DELETE : 527 case INSERT_SELECT : 528 case INSERT_VALUES : 529 case UPDATE : 530 case DDL : 531 532 return updateCountResult; 534 535 default : 536 return new Result( 537 Trace.runtimeError( 538 Trace.UNSUPPORTED_INTERNAL_OPERATION, 539 "CompiledStatement.describeResult()"), null); 540 } 541 } 542 543 Result describeParameters() { 544 545 Result out; 546 Expression e; 547 int outlen; 548 int offset; 549 int idx; 550 boolean hasReturnValue; 551 552 outlen = parameters.length; 553 offset = 0; 554 555 out = Result.newParameterDescriptionResult(outlen); 563 564 for (int i = 0; i < parameters.length; i++) { 577 e = parameters[i]; 578 idx = i + offset; 579 580 out.metaData.colNames[idx] = CompiledStatement.PCOL_PREFIX 583 + (i + 1); 584 585 out.metaData.classNames[idx] = e.getValueClassName(); 587 out.metaData.colTypes[idx] = e.getDataType(); 588 out.metaData.colSizes[idx] = e.getColumnSize(); 589 out.metaData.colScales[idx] = e.getColumnScale(); 590 out.metaData.colNullable[idx] = e.nullability; 591 out.metaData.isIdentity[idx] = e.isIdentity; 592 593 out.metaData.paramMode[idx] = e.paramMode; 595 } 596 597 return out; 598 } 599 600 605 public String describe(Session session) { 606 607 try { 608 return describeImpl(session); 609 } catch (Exception e) { 610 return e.toString(); 611 } 612 } 613 614 620 private String describeImpl(Session session) throws Exception { 621 622 StringBuffer sb; 623 624 sb = new StringBuffer (); 625 626 switch (type) { 627 628 case SELECT : { 629 sb.append(select.describe(session)); 630 appendParms(sb).append('\n'); 631 appendSubqueries(sb); 632 633 return sb.toString(); 634 } 635 case INSERT_VALUES : { 636 sb.append("INSERT VALUES"); 637 sb.append('[').append('\n'); 638 appendColumns(sb).append('\n'); 639 appendTable(sb).append('\n'); 640 appendParms(sb).append('\n'); 641 appendSubqueries(sb).append(']'); 642 643 return sb.toString(); 644 } 645 case INSERT_SELECT : { 646 sb.append("INSERT SELECT"); 647 sb.append('[').append('\n'); 648 appendColumns(sb).append('\n'); 649 appendTable(sb).append('\n'); 650 sb.append(select.describe(session)).append('\n'); 651 appendParms(sb).append('\n'); 652 appendSubqueries(sb).append(']'); 653 654 return sb.toString(); 655 } 656 case UPDATE : { 657 sb.append("UPDATE"); 658 sb.append('[').append('\n'); 659 appendColumns(sb).append('\n'); 660 appendTable(sb).append('\n'); 661 appendCondition(session, sb); 662 sb.append(targetFilter.describe(session)).append('\n'); 663 appendParms(sb).append('\n'); 664 appendSubqueries(sb).append(']'); 665 666 return sb.toString(); 667 } 668 case DELETE : { 669 sb.append("DELETE"); 670 sb.append('[').append('\n'); 671 appendTable(sb).append('\n'); 672 appendCondition(session, sb); 673 sb.append(targetFilter.describe(session)).append('\n'); 674 appendParms(sb).append('\n'); 675 appendSubqueries(sb).append(']'); 676 677 return sb.toString(); 678 } 679 case CALL : { 680 sb.append("CALL"); 681 sb.append('['); 682 sb.append(expression.describe(session)).append('\n'); 683 appendParms(sb).append('\n'); 684 appendSubqueries(sb).append(']'); 685 686 return sb.toString(); 687 } 688 default : { 689 return "UNKNOWN"; 690 } 691 } 692 } 693 694 private StringBuffer appendSubqueries(StringBuffer sb) { 695 696 sb.append("SUBQUERIES["); 697 698 for (int i = 0; i < subqueries.length; i++) { 699 sb.append("\n[level=").append(subqueries[i].level).append( 700 '\n').append("hasParams=").append( 701 subqueries[i].hasParams).append('\n'); 702 703 if (subqueries[i].select != null) { 704 sb.append("org.hsqldb.Select@").append( 705 Integer.toHexString(subqueries[i].select.hashCode())); 706 } 707 708 sb.append("]"); 709 } 710 711 sb.append(']'); 712 713 return sb; 714 } 715 716 private StringBuffer appendTable(StringBuffer sb) { 717 718 sb.append("TABLE[").append(targetTable.getName().name).append(']'); 719 720 return sb; 721 } 722 723 private StringBuffer appendColumns(StringBuffer sb) { 724 725 sb.append("COLUMNS=["); 726 727 for (int i = 0; i < columnMap.length; i++) { 728 sb.append('\n').append(columnMap[i]).append(':').append( 729 ' ').append( 730 targetTable.getColumn(columnMap[i]).columnName.name).append( 731 '[').append(columnValues[i]).append(']'); 732 } 733 734 sb.append(']'); 735 736 return sb; 737 } 738 739 private StringBuffer appendParms(StringBuffer sb) { 740 741 sb.append("PARAMETERS=["); 742 743 for (int i = 0; i < parameters.length; i++) { 744 sb.append('\n').append('@').append(i).append('[').append( 745 parameters[i]).append(']'); 746 } 747 748 sb.append(']'); 749 750 return sb; 751 } 752 753 private StringBuffer appendCondition(Session session, StringBuffer sb) { 754 755 return condition == null ? sb.append("CONDITION[]\n") 756 : sb.append("CONDITION[").append( 757 condition.describe(session)).append( 758 "]\n"); 759 } 760 } 761 | Popular Tags |