| 1 65 66 67 package org.hsqldb; 68 69 import java.sql.Date ; 70 import java.sql.Time ; 71 import java.sql.Timestamp ; 72 73 import org.hsqldb.HsqlNameManager.HsqlName; 74 import org.hsqldb.jdbc.jdbcConnection; 75 import org.hsqldb.lib.ArrayUtil; 76 import org.hsqldb.lib.HashMappedList; 77 import org.hsqldb.lib.HsqlArrayList; 78 import org.hsqldb.lib.IntKeyHashMap; 79 import org.hsqldb.lib.SimpleLog; 80 import org.hsqldb.lib.java.JavaSystem; 81 import org.hsqldb.store.ValuePool; 82 83 97 113 public class Session implements SessionInterface { 114 115 private volatile boolean isAutoCommit; 117 private volatile boolean isReadOnly; 118 private volatile boolean isClosed; 119 120 Database database; 122 private User user; 123 HsqlArrayList rowActionList; 124 private boolean isNestedTransaction; 125 private int nestedOldTransIndex; 126 int isolationMode = SessionInterface.TX_READ_COMMITTED; 127 long actionTimestamp; 128 long transactionTimestamp; 129 private int currentMaxRows; 130 private int sessionMaxRows; 131 private Number lastIdentity = ValuePool.getInt(0); 132 private final int sessionId; 133 HashMappedList savepoints; 134 private boolean script; 135 private Tokenizer tokenizer; 136 private Parser parser; 137 static final Result emptyUpdateCount = 138 new Result(ResultConstants.UPDATECOUNT); 139 140 private jdbcConnection intConnection; 142 143 public HsqlName currentSchema; 145 public HsqlName loggedSchema; 146 private HsqlName oldSchema; 147 148 boolean isProcessingScript; 150 boolean isProcessingLog; 151 152 private IntKeyHashMap indexArrayMap; 154 private IntKeyHashMap indexArrayKeepMap; 155 156 157 Session getSession() { 158 return this; 159 } 160 161 170 Session(Database db, User user, boolean autocommit, boolean readonly, 171 int id) { 172 173 sessionId = id; 174 database = db; 175 this.user = user; 176 rowActionList = new HsqlArrayList(true); 177 savepoints = new HashMappedList(4); 178 isAutoCommit = autocommit; 179 isReadOnly = readonly; 180 dbCommandInterpreter = new DatabaseCommandInterpreter(this); 181 compiledStatementExecutor = new CompiledStatementExecutor(this); 182 compiledStatementManager = db.compiledStatementManager; 183 tokenizer = new Tokenizer(); 184 parser = new Parser(this, database, tokenizer); 185 186 resetSchema(); 187 } 188 189 void resetSchema() { 190 191 HsqlName initialSchema = user.getInitialSchema(); 192 193 currentSchema = ((initialSchema == null) 194 ? database.schemaManager.getDefaultSchemaHsqlName() 195 : initialSchema); 196 } 197 198 203 public int getId() { 204 return sessionId; 205 } 206 207 210 public void close() { 211 212 if (isClosed) { 213 return; 214 } 215 216 synchronized (database) { 217 218 if (isClosed) { 220 return; 221 } 222 223 database.sessionManager.removeSession(this); 224 rollback(); 225 226 try { 227 database.logger.writeToLog(this, Token.T_DISCONNECT); 228 } catch (HsqlException e) {} 229 230 clearIndexRoots(); 231 clearIndexRootsKeep(); 232 compiledStatementManager.removeSession(sessionId); 233 database.closeIfLast(); 234 235 database = null; 236 user = null; 237 rowActionList = null; 238 savepoints = null; 239 intConnection = null; 240 compiledStatementExecutor = null; 241 compiledStatementManager = null; 242 dbCommandInterpreter = null; 243 lastIdentity = null; 244 isClosed = true; 245 } 246 } 247 248 253 public boolean isClosed() { 254 return isClosed; 255 } 256 257 public void setIsolation(int level) throws HsqlException { 258 isolationMode = level; 259 } 260 261 public int getIsolation() throws HsqlException { 262 return isolationMode; 263 } 264 265 270 void setLastIdentity(Number i) { 271 lastIdentity = i; 272 } 273 274 279 Number getLastIdentity() { 280 return lastIdentity; 281 } 282 283 289 Database getDatabase() { 290 return database; 291 } 292 293 299 String getUsername() { 300 return user.getName(); 301 } 302 303 309 public User getUser() { 310 return user; 311 } 312 313 319 void setUser(User user) { 320 this.user = user; 321 } 322 323 int getMaxRows() { 324 return currentMaxRows; 325 } 326 327 int getSQLMaxRows() { 328 return sessionMaxRows; 329 } 330 331 338 void setSQLMaxRows(int rows) { 339 currentMaxRows = sessionMaxRows = rows; 340 } 341 342 349 void checkAdmin() throws HsqlException { 350 user.checkAdmin(); 351 } 352 353 362 void check(HsqlName object, int right) throws HsqlException { 363 user.check(object, right); 364 } 365 366 372 void check(String object) throws HsqlException { 373 user.check(object); 374 } 375 376 380 void checkReadWrite() throws HsqlException { 381 382 if (isReadOnly) { 383 throw Trace.error(Trace.DATABASE_IS_READONLY); 384 } 385 } 386 387 391 void checkDDLWrite() throws HsqlException { 392 393 if (database.isFilesReadOnly() &&!user.isSys()) { 394 throw Trace.error(Trace.DATABASE_IS_READONLY); 395 } 396 } 397 398 405 boolean addDeleteAction(Table table, Row row) throws HsqlException { 406 407 if (!isAutoCommit || isNestedTransaction) { 408 Transaction t = new Transaction(true, table, row, 409 actionTimestamp); 410 411 rowActionList.add(t); 412 database.txManager.addTransaction(this, t); 413 414 return true; 415 } else { 416 table.removeRowFromStore(row); 417 } 418 419 return false; 420 } 421 422 429 boolean addInsertAction(Table table, Row row) throws HsqlException { 430 431 if (!isAutoCommit || isNestedTransaction) { 432 Transaction t = new Transaction(false, table, row, 433 actionTimestamp); 434 435 rowActionList.add(t); 436 database.txManager.addTransaction(this, t); 437 438 return true; 439 } else { 440 table.commitRowToStore(row); 441 } 442 443 return false; 444 } 445 446 452 public void setAutoCommit(boolean autocommit) { 453 454 if (isClosed) { 455 return; 456 } 457 458 synchronized (database) { 459 if (autocommit != isAutoCommit) { 460 commit(); 461 462 isAutoCommit = autocommit; 463 464 try { 465 database.logger.writeToLog(this, 466 getAutoCommitStatement()); 467 } catch (HsqlException e) {} 468 } 469 } 470 } 471 472 public void startPhasedTransaction() throws HsqlException {} 473 474 public void prepareCommit() throws HsqlException {} 475 476 481 public void commit() { 482 483 if (isClosed) { 484 return; 485 } 486 487 synchronized (database) { 488 if (!rowActionList.isEmpty()) { 489 try { 490 database.logger.writeCommitStatement(this); 491 } catch (HsqlException e) {} 492 } 493 494 database.txManager.commit(this); 495 clearIndexRoots(); 496 } 497 } 498 499 504 public void rollback() { 505 506 if (isClosed) { 507 return; 508 } 509 510 synchronized (database) { 511 if (rowActionList.size() != 0) { 512 try { 513 database.logger.writeToLog(this, Token.T_ROLLBACK); 514 } catch (HsqlException e) {} 515 } 516 517 database.txManager.rollback(this); 518 clearIndexRoots(); 519 } 520 } 521 522 525 public void resetSession() throws HsqlException { 526 throw new HsqlException("", "", 0); 527 } 528 529 536 void savepoint(String name) throws HsqlException { 537 538 savepoints.remove(name); 539 savepoints.add(name, ValuePool.getInt(rowActionList.size())); 540 541 try { 542 database.logger.writeToLog(this, Token.T_SAVEPOINT + " " + name); 543 } catch (HsqlException e) {} 544 } 545 546 553 void rollbackToSavepoint(String name) throws HsqlException { 554 555 if (isClosed) { 556 return; 557 } 558 559 try { 560 database.logger.writeToLog(this, 561 Token.T_ROLLBACK + " " + Token.T_TO 562 + " " + Token.T_SAVEPOINT + " " 563 + name); 564 } catch (HsqlException e) {} 565 566 database.txManager.rollbackSavepoint(this, name); 567 } 568 569 576 void releaseSavepoint(String name) throws HsqlException { 577 578 int index = savepoints.getIndex(name); 580 581 Trace.check(index >= 0, Trace.SAVEPOINT_NOT_FOUND, name); 582 583 while (savepoints.size() > index) { 584 savepoints.remove(savepoints.size() - 1); 585 } 586 } 587 588 593 void beginNestedTransaction() throws HsqlException { 594 595 if (isNestedTransaction) { 596 Trace.doAssert(false, "beginNestedTransaction"); 597 } 598 599 nestedOldTransIndex = rowActionList.size(); 600 isNestedTransaction = true; 601 602 if (isAutoCommit) { 603 try { 604 database.logger.writeToLog(this, "SET AUTOCOMMIT FALSE"); 605 } catch (HsqlException e) {} 606 } 607 } 608 609 616 617 623 void endNestedTransaction(boolean rollback) throws HsqlException { 624 625 if (!isNestedTransaction) { 626 Trace.doAssert(false, "endNestedTransaction"); 627 } 628 629 if (rollback) { 630 database.txManager.rollbackTransactions(this, 631 nestedOldTransIndex, true); 632 } 633 634 isNestedTransaction = false; 636 637 if (isAutoCommit) { 638 database.txManager.commit(this); 639 640 try { 641 database.logger.writeToLog(this, "SET AUTOCOMMIT TRUE"); 642 } catch (HsqlException e) {} 643 } 644 } 645 646 651 public void setReadOnly(boolean readonly) throws HsqlException { 652 653 if (!readonly && database.databaseReadOnly) { 654 throw Trace.error(Trace.DATABASE_IS_READONLY); 655 } 656 657 isReadOnly = readonly; 658 } 659 660 665 public boolean isReadOnly() { 666 return isReadOnly; 667 } 668 669 674 boolean isNestedTransaction() { 675 return isNestedTransaction; 676 } 677 678 683 public boolean isAutoCommit() { 684 return isAutoCommit; 685 } 686 687 697 void setScripting(boolean script) { 698 this.script = script; 699 } 700 701 706 boolean getScripting() { 707 return script; 708 } 709 710 public String getAutoCommitStatement() { 711 return isAutoCommit ? "SET AUTOCOMMIT TRUE" 712 : "SET AUTOCOMMIT FALSE"; 713 } 714 715 721 jdbcConnection getInternalConnection() throws HsqlException { 722 723 if (intConnection == null) { 724 intConnection = new jdbcConnection(this); 725 } 726 727 return intConnection; 728 } 729 730 private final long connectTime = System.currentTimeMillis(); 733 734 736 741 boolean isAdmin() { 742 return user.isAdmin(); 743 } 744 745 750 long getConnectTime() { 751 return connectTime; 752 } 753 754 759 int getTransactionSize() { 760 return rowActionList.size(); 761 } 762 763 769 boolean isAccessible(String dbobject) throws HsqlException { 770 return user.isAccessible(dbobject); 771 } 772 773 boolean isAccessible(HsqlName dbobject) throws HsqlException { 774 return user.isAccessible(dbobject); 775 } 776 777 DatabaseCommandInterpreter dbCommandInterpreter; 780 CompiledStatementExecutor compiledStatementExecutor; 781 CompiledStatementManager compiledStatementManager; 782 783 CompiledStatement sqlCompileStatement(String sql) throws HsqlException { 784 785 parser.reset(sql); 786 787 CompiledStatement cs; 788 int brackets = 0; 789 String token = tokenizer.getString(); 790 int cmd = Token.get(token); 791 792 switch (cmd) { 793 794 case Token.OPENBRACKET : { 795 brackets = parser.parseOpenBracketsSelect() + 1; 796 } 797 case Token.SELECT : { 798 cs = parser.compileSelectStatement(brackets); 799 800 break; 801 } 802 case Token.INSERT : { 803 cs = parser.compileInsertStatement(); 804 805 break; 806 } 807 case Token.UPDATE : { 808 cs = parser.compileUpdateStatement(); 809 810 break; 811 } 812 case Token.DELETE : { 813 cs = parser.compileDeleteStatement(); 814 815 break; 816 } 817 case Token.CALL : { 818 cs = parser.compileCallStatement(); 819 820 break; 821 } 822 default : { 823 824 cs = new CompiledStatement(currentSchema); 826 827 break; 828 } 829 } 830 831 if (cs.type != CompiledStatement.DDL) { 837 while (tokenizer.getPosition() < tokenizer.getLength()) { 838 token = tokenizer.getString(); 839 840 if (token.length() != 0 &&!token.equals(Token.T_SEMICOLON)) { 841 throw Trace.error(Trace.UNEXPECTED_TOKEN, token); 842 } 843 } 844 } 845 846 cs.sql = sql; 849 850 return cs; 851 } 852 853 859 public Result execute(Result cmd) { 860 861 try { 862 if (isClosed) { 863 Trace.check(false, Trace.ACCESS_IS_DENIED, 864 Trace.getMessage(Trace.Session_execute)); 865 } 866 } catch (Throwable t) { 867 return new Result(t, null); 868 } 869 870 synchronized (database) { 871 int type = cmd.mode; 872 873 if (sessionMaxRows == 0) { 874 currentMaxRows = cmd.updateCount; 875 } 876 877 actionTimestamp = database.txManager.nextActionTimestamp(); 879 880 JavaSystem.gc(); 881 882 switch (type) { 883 884 case ResultConstants.SQLEXECUTE : { 885 Result resultout = sqlExecute(cmd); 886 887 resultout = performPostExecute(resultout); 888 889 return resultout; 890 } 891 case ResultConstants.BATCHEXECUTE : { 892 Result resultout = sqlExecuteBatch(cmd); 893 894 resultout = performPostExecute(resultout); 895 896 return resultout; 897 } 898 case ResultConstants.SQLEXECDIRECT : { 899 Result resultout = 900 sqlExecuteDirectNoPreChecks(cmd.getMainString()); 901 902 resultout = performPostExecute(resultout); 903 904 return resultout; 905 } 906 case ResultConstants.BATCHEXECDIRECT : { 907 Result resultout = sqlExecuteBatchDirect(cmd); 908 909 resultout = performPostExecute(resultout); 910 911 return resultout; 912 } 913 case ResultConstants.SQLPREPARE : { 914 CompiledStatement cs; 915 916 try { 917 cs = compiledStatementManager.compile( 918 this, cmd.getMainString()); 919 } catch (Throwable t) { 920 return new Result(t, cmd.getMainString()); 921 } 922 923 Result rmd = cs.describeResult(); 924 Result pmd = cs.describeParameters(); 925 926 return Result.newPrepareResponse(cs.id, rmd, pmd); 927 } 928 case ResultConstants.SQLFREESTMT : { 929 compiledStatementManager.freeStatement( 930 cmd.getStatementID(), sessionId, false); 931 932 return emptyUpdateCount; 933 } 934 case ResultConstants.GETSESSIONATTR : { 935 return getAttributes(); 936 } 937 case ResultConstants.SETSESSIONATTR : { 938 return setAttributes(cmd); 939 } 940 case ResultConstants.SQLENDTRAN : { 941 switch (cmd.getEndTranType()) { 942 943 case ResultConstants.COMMIT : 944 commit(); 945 break; 946 947 case ResultConstants.ROLLBACK : 948 rollback(); 949 break; 950 951 case ResultConstants.SAVEPOINT_NAME_RELEASE : 952 try { 953 String name = cmd.getMainString(); 954 955 releaseSavepoint(name); 956 } catch (Throwable t) { 957 return new Result(t, null); 958 } 959 break; 960 961 case ResultConstants.SAVEPOINT_NAME_ROLLBACK : 962 try { 963 rollbackToSavepoint(cmd.getMainString()); 964 } catch (Throwable t) { 965 return new Result(t, null); 966 } 967 break; 968 969 } 973 974 return emptyUpdateCount; 975 } 976 case ResultConstants.SQLSETCONNECTATTR : { 977 switch (cmd.getConnectionAttrType()) { 978 979 case ResultConstants.SQL_ATTR_SAVEPOINT_NAME : 980 try { 981 &
|