@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(); } }
/** * 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); } }
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; }
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()); } }
/** * 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); } }
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); } }
/** * 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); } }
/** * 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; }
/** 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); } }
@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; }
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); }