1 5 package org.h2.engine; 6 7 import java.sql.SQLException ; 8 import java.util.HashMap ; 9 import java.util.HashSet ; 10 import java.util.Iterator ; 11 import java.util.Random ; 12 13 import org.h2.command.Command; 14 import org.h2.command.CommandInterface; 15 import org.h2.command.Parser; 16 import org.h2.command.Prepared; 17 import org.h2.command.dml.SetTypes; 18 import org.h2.jdbc.JdbcConnection; 19 import org.h2.message.Message; 20 import org.h2.message.Trace; 21 import org.h2.message.TraceSystem; 22 import org.h2.schema.Schema; 23 import org.h2.store.DataHandler; 24 import org.h2.store.InDoubtTransaction; 25 import org.h2.store.LogSystem; 26 import org.h2.store.UndoLog; 27 import org.h2.store.UndoLogRecord; 28 import org.h2.table.Table; 29 import org.h2.table.TableData; 30 import org.h2.util.ObjectArray; 31 import org.h2.value.Value; 32 33 36 public class Session implements SessionInterface { 37 private User user; 38 private int id; 39 private Database database; 40 private ObjectArray locks = new ObjectArray(); 41 private UndoLog undoLog; 44 private boolean autoCommit = true; 45 private Random random; 47 private LogSystem logSystem; 48 private int lockTimeout; 49 private long lastIdentity; 50 private int firstUncommittedLog = LogSystem.LOG_WRITTEN; 51 private int firstUncommittedPos = LogSystem.LOG_WRITTEN; 52 private HashMap savepoints; 53 private Exception stackTrace = new Exception (); 54 private HashMap localTempTables; 55 private int throttle; 56 private long lastThrottle; 57 private Command currentCommand; 58 private boolean allowLiterals; 59 private String currentSchemaName; 60 private String traceModuleName; 61 private HashSet unlinkSet; 62 63 public Table findLocalTempTable(String name) { 64 Table t = null; 65 if(t == null && localTempTables != null) { 66 t = (Table) localTempTables.get(name); 67 } 68 return t; 69 } 70 71 public ObjectArray getLocalTempTables() { 72 if(localTempTables == null) { 73 return new ObjectArray(); 74 } 75 ObjectArray list = new ObjectArray(localTempTables.values()); 76 return list; 77 } 78 79 public String getNewLocalTempTransactionTableName() { 80 String name = Constants.TEMP_TABLE_TRANSACTION_PREFIX; 82 for(int i=0; ; i++) { 83 String n = name + i; 84 if(findLocalTempTable(n) == null) { 85 return n; 86 } 87 } 88 } 89 90 public void addLocalTempTable(TableData table) throws SQLException { 91 cleanTempTables(); 92 if(localTempTables == null) { 93 localTempTables = new HashMap (); 94 } 95 if(localTempTables.get(table.getName()) != null) { 96 throw Message.getSQLException(Message.TABLE_OR_VIEW_ALREADY_EXISTS_1, table.getSQL()); 97 } 98 localTempTables.put(table.getName(), table); 99 } 100 101 public void removeLocalTempTable(Table table) throws SQLException { 102 localTempTables.remove(table.getName()); 103 table.removeChildrenAndResources(this); 104 } 105 106 protected void finalize() { 107 if(!Constants.RUN_FINALIZERS) { 108 return; 109 } 110 if(database != null) { 111 throw Message.getInternalError("not closed", stackTrace); 112 } 113 } 114 115 public boolean getAutoCommit() { 116 return autoCommit; 117 } 118 119 public User getUser() { 120 return user; 121 } 122 123 public void setAutoCommit(boolean b) { 124 autoCommit = b; 125 } 126 127 public int getLockTimeout() { 128 return lockTimeout; 129 } 130 131 public void setLockTimeout(int lockTimeout) { 132 this.lockTimeout = lockTimeout; 133 } 134 135 public Session() { 136 137 } 138 139 public SessionInterface createSession(ConnectionInfo ci) throws SQLException { 140 return Engine.getInstance().getSession(ci); 141 } 142 143 Session(Database database, User user, int id) { 144 this.database = database; 145 this.undoLog = new UndoLog(this); 146 this.user = user; 147 this.id = id; 148 this.logSystem = database.getLog(); 149 Setting setting = database.findSetting(SetTypes.getTypeName(SetTypes.DEFAULT_LOCK_TIMEOUT)); 150 this.lockTimeout = setting == null ? Constants.INITIAL_LOCK_TIMEOUT : setting.getIntValue(); 151 this.currentSchemaName = Constants.SCHEMA_MAIN; 152 } 153 154 public CommandInterface prepareCommand(String sql) throws SQLException { 155 return prepareLocal(sql); 156 } 157 158 public Prepared prepare(String sql) throws SQLException { 159 return prepare(sql, false); 160 } 161 162 public Prepared prepare(String sql, boolean rightsChecked) throws SQLException { 163 Parser parser = new Parser(this); 164 parser.setRightsChecked(rightsChecked); 165 return parser.prepare(sql); 166 } 167 168 public Command prepareLocal(String sql) throws SQLException { 169 if(database == null) { 170 throw Message.getSQLException(Message.CONNECTION_BROKEN); 171 } 172 Parser parser = new Parser(this); 173 return parser.prepareCommand(sql); 174 } 175 176 public Database getDatabase() { 177 return database; 178 } 179 180 public int getPowerOffCount() { 181 return database == null ? 0 : database.getPowerOffCount(); 182 } 183 184 public void setPowerOffCount(int count) { 185 if(database != null) { 186 database.setPowerOffCount(count); 187 } 188 } 189 190 public void commit() throws SQLException { 191 if(containsUncommitted()) { 192 logSystem.commit(this); 194 } 195 if(undoLog.size() > 0) { 196 undoLog.clear(); 197 cleanTempTables(); 198 } 199 if(unlinkSet != null && unlinkSet.size() > 0) { 200 logSystem.flush(); 202 Iterator it = unlinkSet.iterator(); 203 while(it.hasNext()) { 204 Value v = (Value) it.next(); 205 v.unlink(database); 206 } 207 unlinkSet = null; 208 } 209 unlockAll(); 210 } 211 212 public void rollback() throws SQLException { 213 boolean needCommit = false; 214 if (undoLog.size() > 0) { 215 rollbackTo(0); 216 needCommit = true; 217 } 218 if(locks.size() > 0 || needCommit) { 219 logSystem.commit(this); 220 } 221 cleanTempTables(); 222 unlockAll(); 223 } 224 225 public void rollbackTo(int index) throws SQLException { 226 while (undoLog.size() > index) { 227 UndoLogRecord entry = undoLog.getAndRemoveLast(); 228 entry.undo(this); 229 } 230 if(savepoints != null) { 231 String [] names = new String [savepoints.size()]; 232 savepoints.keySet().toArray(names); 233 for(int i=0; i<names.length; i++) { 234 String name = names[i]; 235 Integer id = (Integer ) savepoints.get(names[i]); 236 if(id.intValue() > index) { 237 savepoints.remove(name); 238 } 239 } 240 } 241 } 242 243 public int getLogId() { 244 return undoLog.size(); 245 } 246 247 public int getId() { 248 return id; 249 } 250 251 public void close() throws SQLException { 252 if(database != null) { 253 try { 254 database.removeSession(this); 255 } finally { 256 database = null; 257 } 258 } 259 } 260 261 public void addLock(Table table) { 262 if(Constants.CHECK) { 263 if(locks.indexOf(table)>=0) { 264 throw Message.getInternalError(); 265 } 266 } 267 locks.add(table); 268 } 269 270 public void log(UndoLogRecord log) throws SQLException { 271 if(Constants.CHECK) { 274 int lockMode = database.getLockMode(); 275 if(lockMode != Constants.LOCK_MODE_OFF) { 276 if(locks.indexOf(log.getTable())<0 && log.getTable().getTableType() != Table.TABLE_LINK) { 277 throw Message.getInternalError(); 278 } 279 } 280 } 281 undoLog.add(log); 282 } 283 284 private void unlockAll() throws SQLException { 285 if(Constants.CHECK) { 286 if(undoLog.size() > 0) { 287 throw Message.getInternalError(); 288 } 289 } 290 for(int i=0; i<locks.size(); i++) { 291 Table t = (Table)locks.get(i); 292 t.unlock(this); 293 } 294 locks.clear(); 295 savepoints = null; 296 } 297 298 private void cleanTempTables() throws SQLException { 299 if(localTempTables != null && localTempTables.size()>0) { 300 ObjectArray list = new ObjectArray(localTempTables.values()); 301 for(int i=0; i<list.size(); i++) { 302 TableData table = (TableData) list.get(i); 303 if(table.isOnCommitDrop()) { 304 table.setModified(); 305 localTempTables.remove(table.getName()); 306 table.removeChildrenAndResources(this); 307 } else if(table.isOnCommitTruncate()) { 308 table.truncate(this); 309 } 310 } 311 } 312 } 313 314 public Random getRandom() { 315 if(random == null) { 316 random = new Random (); 317 } 318 return random; 319 } 320 321 public Trace getTrace() { 322 if(traceModuleName == null) { 323 traceModuleName = Trace.JDBC + "[" + id + "]"; 324 } 325 if(database == null) { 326 return new TraceSystem(null).getTrace(traceModuleName); 327 } 328 return database.getTrace(traceModuleName); 329 } 330 331 public void setLastIdentity(long last) { 332 this.lastIdentity = last; 333 } 334 335 public long getLastIdentity() { 336 return lastIdentity; 337 } 338 339 public void addLogPos(int logId, int pos) { 340 if (firstUncommittedLog == LogSystem.LOG_WRITTEN) { 341 firstUncommittedLog = logId; 342 firstUncommittedPos = pos; 343 } 344 } 345 346 public int getFirstUncommittedLog() { 347 return firstUncommittedLog; 348 } 349 350 public int getFirstUncommittedPos() { 351 return firstUncommittedPos; 352 } 353 354 public void setAllCommitted() { 355 firstUncommittedLog = LogSystem.LOG_WRITTEN; 356 firstUncommittedPos = LogSystem.LOG_WRITTEN; 357 } 358 359 private boolean containsUncommitted() { 360 return firstUncommittedLog != LogSystem.LOG_WRITTEN; 361 } 362 363 public void addSavepoint(String name) { 364 if(savepoints == null) { 365 savepoints = new HashMap (); 366 } 367 savepoints.put(name, new Integer (getLogId())); 368 } 369 370 public void rollbackToSavepoint(String name) throws SQLException { 371 if(savepoints == null) { 372 throw Message.getSQLException(Message.SAVEPOINT_IS_INVALID_1, name); 373 } 374 Integer id = (Integer )savepoints.get(name); 375 if(id==null) { 376 throw Message.getSQLException(Message.SAVEPOINT_IS_INVALID_1, name); 377 } 378 int i = id.intValue(); 379 rollbackTo(i); 380 } 381 382 public void prepareCommit(String transactionName) throws SQLException { 383 if(containsUncommitted()) { 384 logSystem.prepareCommit(this, transactionName); 386 } 387 } 388 389 public void setPreparedTransaction(String transactionName, boolean commit) throws SQLException { 390 ObjectArray list = logSystem.getInDoubtTransactions(); 391 int state = commit ? InDoubtTransaction.COMMIT : InDoubtTransaction.ROLLBACK; 392 for(int i=0; list!=null && i<list.size(); i++) { 393 InDoubtTransaction p = (InDoubtTransaction)list.get(i); 394 if(p.getTransaction().equals(transactionName)) { 395 p.setState(state); 396 } 397 } 398 } 399 400 public boolean isClosed() { 401 return database == null; 402 } 403 404 public void setThrottle(int throttle) { 405 this.throttle = throttle; 406 } 407 408 public void throttle() { 409 if(throttle == 0) { 410 return; 411 } 412 long time = System.currentTimeMillis(); 413 if(lastThrottle + Constants.THROTTLE_DELAY > time) { 414 return; 415 } 416 lastThrottle = time + throttle; 417 try { 418 Thread.sleep(throttle); 419 } catch(Exception e) { 420 } 422 } 423 424 public void setCurrentCommand(Command command) { 425 this.currentCommand = command; 426 } 427 428 public void checkCancelled() throws SQLException { 429 if(currentCommand != null) { 430 currentCommand.checkCancelled(); 431 } 432 } 433 434 public boolean getAllowLiterals() { 435 return allowLiterals; 436 } 437 438 public void setAllowLiterals(boolean b) { 439 this.allowLiterals = b; 440 } 441 442 public void setCurrentSchema(Schema schema) { 443 this.currentSchemaName = schema.getName(); 444 } 445 446 public String getCurrentSchemaName() { 447 return currentSchemaName; 448 } 449 450 public JdbcConnection createConnection(boolean columnList) throws SQLException { 451 String url; 452 if(columnList) { 453 url = Constants.CONN_URL_COLUMNLIST; 454 } else { 455 url = Constants.CONN_URL_INTERNAL; 456 } 457 return new JdbcConnection(this, getUser().getName(), url); 458 } 459 460 public DataHandler getDataHandler() { 461 return database; 462 } 463 464 public void unlinkAtCommit(Value v) { 465 if(unlinkSet == null) { 466 unlinkSet = new HashSet (); 467 } 468 unlinkSet.add(v); 469 } 470 471 public void unlinkAtCommitStop(Value v) { 472 if(unlinkSet != null) { 473 unlinkSet.remove(v); 474 } 475 } 476 477 } 478 | Popular Tags |