예제 #1
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();
   }
 }
예제 #2
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);
   }
 }
예제 #3
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;
 }
예제 #4
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());
   }
 }
예제 #6
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);
   }
 }
예제 #7
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);
   }
 }
예제 #8
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);
   }
 }
예제 #9
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;
 }
예제 #10
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);
   }
 }
예제 #11
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;
 }
예제 #12
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);
 }