예제 #1
0
 /**
  * Returns the current transaction isolation level.
  *
  * @return the isolation level.
  * @throws SQLException if the connection is closed
  */
 public int getTransactionIsolation() throws SQLException {
   try {
     debugCodeCall("getTransactionIsolation");
     checkClosed();
     getLockMode = prepareCommand("CALL LOCK_MODE()", getLockMode);
     ResultInterface result = getLockMode.executeQuery(0, false);
     result.next();
     int lockMode = result.currentRow()[0].getInt();
     result.close();
     int transactionIsolationLevel;
     switch (lockMode) {
       case Constants.LOCK_MODE_OFF:
         transactionIsolationLevel = Connection.TRANSACTION_READ_UNCOMMITTED;
         break;
       case Constants.LOCK_MODE_READ_COMMITTED:
         transactionIsolationLevel = Connection.TRANSACTION_READ_COMMITTED;
         break;
       case Constants.LOCK_MODE_TABLE:
       case Constants.LOCK_MODE_TABLE_GC:
         transactionIsolationLevel = Connection.TRANSACTION_SERIALIZABLE;
         break;
       default:
         throw DbException.throwInternalError("lockMode:" + lockMode);
     }
     return transactionIsolationLevel;
   } catch (Exception e) {
     throw logAndConvert(e);
   }
 }
예제 #2
0
 private int insertRows() {
   session.getUser().checkRight(table, Right.INSERT);
   setCurrentRowNumber(0);
   table.fire(session, Trigger.INSERT, true);
   rowNumber = 0;
   int listSize = list.size();
   if (listSize > 0) {
     int columnLen = columns.length;
     for (int x = 0; x < listSize; x++) {
       Row newRow = table.getTemplateRow(); // newRow的长度是全表字段的个数是,会>=columns的长度
       Expression[] expr = list.get(x);
       setCurrentRowNumber(x + 1);
       for (int i = 0; i < columnLen; i++) {
         Column c = columns[i];
         int index = c.getColumnId(); // 从0开始
         Expression e = expr[i];
         if (e != null) {
           // e can be null (DEFAULT)
           e = e.optimize(session);
           try {
             Value v = c.convert(e.getValue(session));
             newRow.setValue(index, v);
           } catch (DbException ex) {
             throw setRow(ex, x, getSQL(expr));
           }
         }
       }
       rowNumber++;
       table.validateConvertUpdateSequence(session, newRow);
       boolean done = table.fireBeforeRow(session, null, newRow); // INSTEAD OF触发器会返回true
       if (!done) {
         // 直到事务commit或rollback时才解琐,见org.h2.engine.Session.unlockAll()
         table.lock(session, true, false);
         table.addRow(session, newRow);
         // 在org.h2.index.PageDataIndex.addTry(Session, Row)中事先记了一次PageLog
         // 也就是org.h2.store.PageStore.logAddOrRemoveRow(Session, int, Row, boolean)
         // 这里又记了一次UndoLog
         // UndoLog在org.h2.engine.Session.commit(boolean)时就清除了
         session.log(table, UndoLogRecord.INSERT, newRow);
         table.fireAfterRow(session, null, newRow, false);
       }
     }
   } else {
     table.lock(session, true, false);
     // 这种方式主要是避免循环两次,因为query内部己循环一次了,得到记录后像else中的非insertFromSelect一样,还要循环一次
     if (insertFromSelect) {
       query.query(0, this); // 每遍历一行会回调下面的addRow方法
     } else {
       ResultInterface rows = query.query(0);
       while (rows.next()) {
         Value[] r = rows.currentRow();
         addRow(r);
       }
       rows.close();
     }
   }
   table.fire(session, Trigger.INSERT, false);
   return rowNumber;
 }
예제 #3
0
 private boolean getInternalAutoCommit() {
   getAutoCommit = prepareCommand("CALL AUTOCOMMIT()", getAutoCommit);
   ResultInterface result = getAutoCommit.executeQuery(0, false);
   result.next();
   boolean autoCommit = result.currentRow()[0].getBoolean().booleanValue();
   result.close();
   return autoCommit;
 }
 private void checkNoNullValues() {
   String sql =
       "SELECT COUNT(*) FROM " + table.getSQL() + " WHERE " + oldColumn.getSQL() + " IS NULL";
   Prepared command = session.prepare(sql);
   ResultInterface result = command.query(0);
   result.next();
   if (result.currentRow()[0].getInt() > 0) {
     throw DbException.get(ErrorCode.COLUMN_CONTAINS_NULL_VALUES_1, oldColumn.getSQL());
   }
 }
예제 #5
0
 /**
  * Returns true if the database is read-only.
  *
  * @return if the database is read-only
  * @throws SQLException if the connection is closed
  */
 public boolean isReadOnly() throws SQLException {
   try {
     debugCodeCall("isReadOnly");
     checkClosed();
     getReadOnly = prepareCommand("CALL READONLY()", getReadOnly);
     ResultInterface result = getReadOnly.executeQuery(0, false);
     result.next();
     boolean readOnly = result.currentRow()[0].getBoolean().booleanValue();
     return readOnly;
   } catch (Exception e) {
     throw logAndConvert(e);
   }
 }
예제 #6
0
 private void sendRow(ResultInterface result) throws IOException {
   if (result.next()) {
     transfer.writeBoolean(true);
     Value[] v = result.currentRow();
     for (int i = 0; i < result.getVisibleColumnCount(); i++) {
       if (clientVersion >= Constants.TCP_PROTOCOL_VERSION_12) {
         transfer.writeValue(v[i]);
       } else {
         writeValue(v[i]);
       }
     }
   } else {
     transfer.writeBoolean(false);
   }
 }
예제 #7
0
 /**
  * Gets the current catalog name.
  *
  * @return the catalog name
  * @throws SQLException if the connection is closed
  */
 public String getCatalog() throws SQLException {
   try {
     debugCodeCall("getCatalog");
     checkClosed();
     if (catalog == null) {
       CommandInterface cat = prepareCommand("CALL DATABASE()", Integer.MAX_VALUE);
       ResultInterface result = cat.executeQuery(0, false);
       result.next();
       catalog = result.currentRow()[0].getString();
       cat.close();
     }
     return catalog;
   } catch (Exception e) {
     throw logAndConvert(e);
   }
 }
예제 #8
0
 /**
  * Read the serializer name from the persistent database settings.
  *
  * @return the serializer
  */
 private String readSerializationSettings() {
   String javaObjectSerializerFQN = null;
   CommandInterface ci =
       prepareCommand(
           "SELECT VALUE FROM INFORMATION_SCHEMA.SETTINGS "
               + " WHERE NAME='JAVA_OBJECT_SERIALIZER'",
           Integer.MAX_VALUE);
   try {
     ResultInterface result = ci.executeQuery(0, false);
     if (result.next()) {
       Value[] row = result.currentRow();
       javaObjectSerializerFQN = row[0].getString();
     }
   } finally {
     ci.close();
   }
   return javaObjectSerializerFQN;
 }
예제 #9
0
 /** INTERNAL */
 public int getQueryTimeout() throws SQLException {
   try {
     debugCodeCall("getQueryTimeout");
     checkClosed();
     getQueryTimeout =
         prepareCommand(
             "SELECT VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE NAME=?", getQueryTimeout);
     getQueryTimeout.getParameters().get(0).setValue(ValueString.get("QUERY_TIMEOUT"), false);
     ResultInterface result = getQueryTimeout.executeQuery(0, false);
     result.next();
     int queryTimeout = result.currentRow()[0].getInt();
     result.close();
     if (queryTimeout == 0) {
       return 0;
     }
     // round to the next second, otherwise 999 millis would return 0 seconds
     return (queryTimeout + 999) / 1000;
   } catch (Exception e) {
     throw logAndConvert(e);
   }
 }
예제 #10
0
 @Override
 public Value getValue(Session session) {
   query.setSession(session);
   ResultInterface result = query.query(2);
   try {
     int rowcount = result.getRowCount();
     if (rowcount > 1) {
       throw DbException.get(ErrorCode.SCALAR_SUBQUERY_CONTAINS_MORE_THAN_ONE_ROW);
     }
     Value v;
     if (rowcount <= 0) {
       v = ValueNull.INSTANCE;
     } else {
       result.next();
       Value[] values = result.currentRow();
       if (result.getVisibleColumnCount() == 1) {
         v = values[0];
       } else {
         v = ValueArray.get(values);
       }
     }
     return v;
   } finally {
     result.close();
   }
 }
예제 #11
0
 // 总共18条命令,这里包含16条
 // 下面这两条在run方法中特殊处理
 // SESSION_CANCEL_STATEMENT
 // SESSION_CHECK_KEY
 // 分三种级别,从大到小: SESSION级、COMMAND级、RESULT级
 private void process() throws IOException {
   int operation = transfer.readInt();
   switch (operation) {
     case SessionRemote.SESSION_PREPARE_READ_PARAMS:
     case SessionRemote.SESSION_PREPARE:
       {
         int id = transfer.readInt();
         String sql = transfer.readString();
         int old = session.getModificationId();
         Command command = session.prepareLocal(sql);
         boolean readonly = command.isReadOnly();
         cache.addObject(id, command);
         boolean isQuery = command.isQuery();
         ArrayList<? extends ParameterInterface> params = command.getParameters();
         transfer
             .writeInt(getState(old))
             .writeBoolean(isQuery)
             .writeBoolean(readonly)
             .writeInt(params.size());
         if (operation == SessionRemote.SESSION_PREPARE_READ_PARAMS) {
           for (ParameterInterface p : params) {
             ParameterRemote.writeMetaData(transfer, p);
           }
         }
         transfer.flush();
         break;
       }
     case SessionRemote.SESSION_CLOSE:
       {
         stop = true;
         closeSession();
         transfer.writeInt(SessionRemote.STATUS_OK).flush();
         close();
         break;
       }
     case SessionRemote.COMMAND_COMMIT:
       {
         // 并不是通过org.h2.jdbc.JdbcConnection.commit()触发,此方法是通过发送COMMIT SQL触发
         // 触发SessionRemote.COMMAND_COMMIT的是在集群环境下,通过org.h2.engine.SessionRemote.autoCommitIfCluster()触发
         if (commit == null) {
           commit = session.prepareLocal("COMMIT");
         }
         int old = session.getModificationId();
         commit.executeUpdate();
         transfer.writeInt(getState(old)).flush();
         break;
       }
     case SessionRemote.COMMAND_GET_META_DATA:
       {
         int id = transfer.readInt();
         int objectId = transfer.readInt();
         Command command = (Command) cache.getObject(id, false);
         ResultInterface result = command.getMetaData();
         cache.addObject(objectId, result);
         int columnCount = result.getVisibleColumnCount();
         transfer.writeInt(SessionRemote.STATUS_OK).writeInt(columnCount).writeInt(0);
         for (int i = 0; i < columnCount; i++) {
           ResultColumn.writeColumn(transfer, result, i);
         }
         transfer.flush();
         break;
       }
     case SessionRemote.COMMAND_EXECUTE_QUERY:
       {
         int id = transfer.readInt();
         int objectId = transfer.readInt();
         int maxRows = transfer.readInt();
         int fetchSize = transfer.readInt();
         Command command = (Command) cache.getObject(id, false);
         setParameters(command);
         int old = session.getModificationId();
         ResultInterface result;
         synchronized (session) {
           result = command.executeQuery(maxRows, false);
         }
         cache.addObject(objectId, result);
         int columnCount = result.getVisibleColumnCount();
         int state = getState(old);
         transfer.writeInt(state).writeInt(columnCount);
         int rowCount = result.getRowCount();
         transfer.writeInt(rowCount);
         for (int i = 0; i < columnCount; i++) {
           ResultColumn.writeColumn(transfer, result, i);
         }
         int fetch = Math.min(rowCount, fetchSize);
         for (int i = 0; i < fetch; i++) {
           sendRow(result);
         }
         transfer.flush();
         break;
       }
     case SessionRemote.COMMAND_EXECUTE_UPDATE:
       {
         int id = transfer.readInt();
         Command command = (Command) cache.getObject(id, false);
         // if(command!=null)throw new Error();
         setParameters(command);
         int old = session.getModificationId();
         int updateCount;
         synchronized (session) {
           updateCount = command.executeUpdate();
         }
         int status;
         if (session.isClosed()) {
           status = SessionRemote.STATUS_CLOSED;
         } else {
           status = getState(old);
         }
         transfer.writeInt(status).writeInt(updateCount).writeBoolean(session.getAutoCommit());
         transfer.flush();
         break;
       }
     case SessionRemote.COMMAND_CLOSE:
       {
         int id = transfer.readInt();
         Command command = (Command) cache.getObject(id, true);
         if (command != null) {
           command.close();
           cache.freeObject(id);
         }
         break;
       }
     case SessionRemote.RESULT_FETCH_ROWS:
       {
         int id = transfer.readInt();
         int count = transfer.readInt();
         ResultInterface result = (ResultInterface) cache.getObject(id, false);
         transfer.writeInt(SessionRemote.STATUS_OK);
         for (int i = 0; i < count; i++) {
           sendRow(result);
         }
         transfer.flush();
         break;
       }
     case SessionRemote.RESULT_RESET:
       {
         int id = transfer.readInt();
         ResultInterface result = (ResultInterface) cache.getObject(id, false);
         result.reset();
         break;
       }
     case SessionRemote.RESULT_CLOSE:
       {
         int id = transfer.readInt();
         ResultInterface result = (ResultInterface) cache.getObject(id, true);
         if (result != null) {
           result.close();
           cache.freeObject(id);
         }
         break;
       }
     case SessionRemote.CHANGE_ID:
       {
         int oldId = transfer.readInt();
         int newId = transfer.readInt();
         Object obj = cache.getObject(oldId, false);
         cache.freeObject(oldId);
         cache.addObject(newId, obj);
         break;
       }
     case SessionRemote.SESSION_SET_ID:
       {
         sessionId = transfer.readString();
         transfer.writeInt(SessionRemote.STATUS_OK).flush();
         break;
       }
     case SessionRemote.SESSION_SET_AUTOCOMMIT:
       {
         boolean autoCommit = transfer.readBoolean();
         session.setAutoCommit(autoCommit);
         transfer.writeInt(SessionRemote.STATUS_OK).flush();
         break;
       }
     case SessionRemote.SESSION_HAS_PENDING_TRANSACTION:
       {
         transfer
             .writeInt(SessionRemote.STATUS_OK)
             .writeInt(session.hasPendingTransaction() ? 1 : 0)
             .flush();
         break;
       }
     case SessionRemote.LOB_READ:
       {
         long lobId = transfer.readLong();
         byte[] hmac;
         CachedInputStream in;
         boolean verifyMac;
         if (clientVersion >= Constants.TCP_PROTOCOL_VERSION_11) {
           if (clientVersion >= Constants.TCP_PROTOCOL_VERSION_12) {
             hmac = transfer.readBytes();
             verifyMac = true;
           } else {
             hmac = null;
             verifyMac = false;
           }
           in = lobs.get(lobId);
           if (in == null && verifyMac) {
             in = new CachedInputStream(null);
             lobs.put(lobId, in);
           }
         } else {
           verifyMac = false;
           hmac = null;
           in = lobs.get(lobId);
         }
         long offset = transfer.readLong();
         int length = transfer.readInt();
         if (verifyMac) {
           transfer.verifyLobMac(hmac, lobId);
         }
         if (in == null) {
           throw DbException.get(ErrorCode.OBJECT_CLOSED);
         }
         if (in.getPos() != offset) {
           LobStorageInterface lobStorage = session.getDataHandler().getLobStorage();
           InputStream lobIn = lobStorage.getInputStream(lobId, hmac, -1);
           in = new CachedInputStream(lobIn);
           lobs.put(lobId, in);
           lobIn.skip(offset);
         }
         // limit the buffer size
         length = Math.min(16 * Constants.IO_BUFFER_SIZE, length);
         byte[] buff = new byte[length];
         length = IOUtils.readFully(in, buff, 0, length);
         transfer.writeInt(SessionRemote.STATUS_OK);
         transfer.writeInt(length);
         transfer.writeBytes(buff, 0, length);
         transfer.flush();
         break;
       }
     default:
       trace("Unknown operation: " + operation);
       closeSession();
       close();
   }
 }
예제 #12
0
 @Override
 protected LocalResult queryWithoutCache(int maxRows, ResultTarget target) {
   if (maxRows != 0) {
     // maxRows is set (maxRows 0 means no limit)
     int l;
     if (limitExpr == null) {
       l = -1;
     } else {
       Value v = limitExpr.getValue(session);
       l = v == ValueNull.INSTANCE ? -1 : v.getInt();
     }
     if (l < 0) {
       // for limitExpr, 0 means no rows, and -1 means no limit
       l = maxRows;
     } else {
       l = Math.min(l, maxRows);
     }
     limitExpr = ValueExpression.get(ValueInt.get(l));
   }
   if (session.getDatabase().getSettings().optimizeInsertFromSelect) {
     if (unionType == UNION_ALL && target != null) {
       if (sort == null && !distinct && maxRows == 0 && offsetExpr == null && limitExpr == null) {
         left.query(0, target);
         right.query(0, target);
         return null;
       }
     }
   }
   int columnCount = left.getColumnCount();
   LocalResult result = new LocalResult(session, expressionArray, columnCount);
   if (sort != null) {
     result.setSortOrder(sort);
   }
   if (distinct) {
     left.setDistinct(true);
     right.setDistinct(true);
     result.setDistinct();
   }
   if (randomAccessResult) {
     result.setRandomAccess();
   }
   switch (unionType) {
     case UNION:
     case EXCEPT:
       left.setDistinct(true);
       right.setDistinct(true);
       result.setDistinct();
       break;
     case UNION_ALL:
       break;
     case INTERSECT:
       left.setDistinct(true);
       right.setDistinct(true);
       break;
     default:
       DbException.throwInternalError("type=" + unionType);
   }
   ResultInterface l = left.query(0);
   ResultInterface r = right.query(0);
   l.reset();
   r.reset();
   switch (unionType) {
     case UNION_ALL:
     case UNION:
       {
         while (l.next()) {
           result.addRow(convert(l.currentRow(), columnCount));
         }
         while (r.next()) {
           result.addRow(convert(r.currentRow(), columnCount));
         }
         break;
       }
     case EXCEPT:
       {
         while (l.next()) {
           result.addRow(convert(l.currentRow(), columnCount));
         }
         while (r.next()) {
           result.removeDistinct(convert(r.currentRow(), columnCount));
         }
         break;
       }
     case INTERSECT:
       {
         LocalResult temp = new LocalResult(session, expressionArray, columnCount);
         temp.setDistinct();
         temp.setRandomAccess();
         while (l.next()) {
           temp.addRow(convert(l.currentRow(), columnCount));
         }
         while (r.next()) {
           Value[] values = convert(r.currentRow(), columnCount);
           if (temp.containsDistinct(values)) {
             result.addRow(values);
           }
         }
         break;
       }
     default:
       DbException.throwInternalError("type=" + unionType);
   }
   if (offsetExpr != null) {
     result.setOffset(offsetExpr.getValue(session).getInt());
   }
   if (limitExpr != null) {
     Value v = limitExpr.getValue(session);
     if (v != ValueNull.INSTANCE) {
       result.setLimit(v.getInt());
     }
   }
   result.done();
   if (target != null) {
     while (result.next()) {
       target.addRow(result.currentRow());
     }
     result.close();
     return null;
   }
   return result;
 }
예제 #13
0
 public Cursor find(Session session, SearchRow first, SearchRow last) {
   if (recursive) {
     if (view.getRecursiveResult() != null) {
       ResultInterface r = view.getRecursiveResult();
       r.reset();
       return new ViewCursor(table, r);
     }
     if (query == null) {
       query = (Query) createSession.prepare(querySQL, true);
       planSQL = query.getPlanSQL();
     }
     if (!(query instanceof SelectUnion)) {
       throw DbException.get(ErrorCode.SYNTAX_ERROR_2, "recursive queries without UNION ALL");
     }
     SelectUnion union = (SelectUnion) query;
     if (union.getUnionType() != SelectUnion.UNION_ALL) {
       throw DbException.get(ErrorCode.SYNTAX_ERROR_2, "recursive queries without UNION ALL");
     }
     Query left = union.getLeft();
     ResultInterface r = left.query(0);
     LocalResult result = union.getEmptyResult();
     while (r.next()) {
       result.addRow(r.currentRow());
     }
     Query right = union.getRight();
     r.reset();
     view.setRecursiveResult(r);
     while (true) {
       r = right.query(0);
       if (r.getRowCount() == 0) {
         break;
       }
       while (r.next()) {
         result.addRow(r.currentRow());
       }
       r.reset();
       view.setRecursiveResult(r);
     }
     return new ViewCursor(table, result);
   }
   ArrayList<Parameter> paramList = query.getParameters();
   for (int i = 0; originalParameters != null && i < originalParameters.size(); i++) {
     Parameter orig = originalParameters.get(i);
     int idx = orig.getIndex();
     Value value = orig.getValue(session);
     setParameter(paramList, idx, value);
   }
   int len;
   if (first != null) {
     len = first.getColumnCount();
   } else if (last != null) {
     len = last.getColumnCount();
   } else {
     len = 0;
   }
   int idx = originalParameters == null ? 0 : originalParameters.size();
   idx += view.getParameterOffset();
   for (int i = 0; i < len; i++) {
     if (first != null) {
       Value v = first.getValue(i);
       if (v != null) {
         int x = idx++;
         setParameter(paramList, x, v);
       }
     }
     // for equality, only one parameter is used (first == last)
     if (last != null && indexMasks[i] != IndexCondition.EQUALITY) {
       Value v = last.getValue(i);
       if (v != null) {
         int x = idx++;
         setParameter(paramList, x, v);
       }
     }
   }
   ResultInterface result = query.query(0);
   return new ViewCursor(table, result);
 }