/** * Get the value of the given property. * * @param key the property key * @param defaultValue the default value * @return the value as a String */ public String getProperty(String key, String defaultValue) { if (SysProperties.CHECK && !isKnownSetting(key)) { DbException.throwInternalError(key); } String s = getProperty(key); return s == null ? defaultValue : s; }
static { ArrayList<String> list = SetTypes.getTypes(); HashSet<String> set = KNOWN_SETTINGS; set.addAll(list); String[] connectionTime = { "ACCESS_MODE_DATA", "AUTOCOMMIT", "CIPHER", "CREATE", "CACHE_TYPE", "FILE_LOCK", "IGNORE_UNKNOWN_SETTINGS", "IFEXISTS", "INIT", "PASSWORD", "RECOVER", "RECOVER_TEST", "USER", "AUTO_SERVER", "AUTO_SERVER_PORT", "NO_UPGRADE", "AUTO_RECONNECT", "OPEN_NEW", "PAGE_SIZE", "PASSWORD_HASH", "JMX" }; for (String key : connectionTime) { if (SysProperties.CHECK && set.contains(key)) { DbException.throwInternalError(key); } set.add(key); } }
/** * Remove a String property if it is set and return the value. * * @param key the property name * @param defaultValue the default value * @return the value */ String removeProperty(String key, String defaultValue) { if (SysProperties.CHECK && !isKnownSetting(key)) { DbException.throwInternalError(key); } Object x = prop.remove(key); return x == null ? defaultValue : x.toString(); }
/** * Get the value of the given property. * * @param key the property key * @param defaultValue the default value * @return the value as a String */ int getProperty(String key, int defaultValue) { if (SysProperties.CHECK && !isKnownSetting(key)) { DbException.throwInternalError(key); } String s = getProperty(key); return s == null ? defaultValue : Integer.parseInt(s); }
/** * 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); } }
/** * Add or update a key value pair. * * @param key the key * @param value the new value */ public void put(Value key, V value) { checkSizePut(); int index = getIndex(key); int plus = 1; int deleted = -1; do { Value k = keys[index]; if (k == null) { // found an empty record if (deleted >= 0) { index = deleted; deletedCount--; } size++; keys[index] = key; values[index] = value; return; } else if (k == ValueNull.DELETED) { // found a deleted record if (deleted < 0) { deleted = index; } } else if (k.equals(key)) { // update existing values[index] = value; return; } index = (index + plus++) & mask; } while (plus <= len); // no space DbException.throwInternalError("hashmap is full"); }
/** * Add an undo log entry to this session. * * @param table the table * @param operation the operation type (see {@link UndoLogRecord}) * @param row the row */ public void log(Table table, short operation, Row row) { if (table.isMVStore()) { return; } if (undoLogEnabled) { UndoLogRecord log = new UndoLogRecord(table, operation, row); // called _after_ the row was inserted successfully into the table, // otherwise rollback will try to rollback a not-inserted row if (SysProperties.CHECK) { int lockMode = database.getLockMode(); if (lockMode != Constants.LOCK_MODE_OFF && !database.isMultiVersion()) { String tableType = log.getTable().getTableType(); if (locks.indexOf(log.getTable()) < 0 && !Table.TABLE_LINK.equals(tableType) && !Table.EXTERNAL_TABLE_ENGINE.equals(tableType)) { DbException.throwInternalError(); } } } undoLog.add(log); } else { if (database.isMultiVersion()) { // see also UndoLogRecord.commit ArrayList<Index> indexes = table.getIndexes(); for (int i = 0, size = indexes.size(); i < size; i++) { Index index = indexes.get(i); index.commit(operation, row); } row.commit(); } } }
@Override public int update() { session.getUser().checkAdmin(); session.commit(true); Database db = session.getDatabase(); if (db.findRole(userName) != null) { throw DbException.get(ErrorCode.ROLE_ALREADY_EXISTS_1, userName); } if (db.findUser(userName) != null) { if (ifNotExists) { return 0; } throw DbException.get(ErrorCode.USER_ALREADY_EXISTS_1, userName); } int id = getObjectId(); User user = new User(db, id, userName, false); user.setAdmin(admin); user.setComment(comment); if (hash != null && salt != null) { user.setSaltAndHash(getByteArray(salt), getByteArray(hash)); } else if (password != null) { char[] passwordChars = getCharArray(password); byte[] userPasswordHash; if (userName.length() == 0 && passwordChars.length == 0) { userPasswordHash = new byte[0]; } else { userPasswordHash = SHA256.getKeyPasswordHash(userName, passwordChars); } user.setUserPasswordHash(userPasswordHash); } else { throw DbException.throwInternalError(); } db.addDatabaseObject(session, user); return 0; }
@Override public void add(Session session, Row row) { if (closed) { throw DbException.throwInternalError(); } TreeNode i = new TreeNode(row); TreeNode n = root, x = n; boolean isLeft = true; while (true) { if (n == null) { if (x == null) { root = i; rowCount++; return; } set(x, isLeft, i); break; } Row r = n.row; int compare = compareRows(row, r); if (compare == 0) { if (indexType.isUnique()) { if (!containsNullAndAllowMultipleNull(row)) { throw getDuplicateKeyException(row.toString()); } } compare = compareKeys(row, r); } isLeft = compare < 0; x = n; n = child(x, isLeft); } balance(x, isLeft); rowCount++; }
/** * Remove all pages until the given data page. * * @param trunkPage the first trunk page * @param firstDataPageToKeep the first data page to keep * @return the trunk page of the data page to keep */ private int removeUntil(int trunkPage, int firstDataPageToKeep) { trace.debug("log.removeUntil " + trunkPage + " " + firstDataPageToKeep); int last = trunkPage; while (true) { Page p = store.getPage(trunkPage); PageStreamTrunk t = (PageStreamTrunk) p; if (t == null) { throw DbException.throwInternalError( "log.removeUntil not found: " + firstDataPageToKeep + " last " + last); } logKey = t.getLogKey(); last = t.getPos(); if (t.contains(firstDataPageToKeep)) { return last; } trunkPage = t.getNextTrunk(); IntArray list = new IntArray(); list.add(t.getPos()); for (int i = 0; ; i++) { int next = t.getPageData(i); if (next == -1) { break; } list.add(next); } freeLogPages(list); pageOut.free(t); } }
/** * Add a lock for the given table. The object is unlocked on commit or rollback. * * @param table the table that is locked */ public void addLock(Table table) { if (SysProperties.CHECK) { if (locks.contains(table)) { DbException.throwInternalError(); } } locks.add(table); }
/** * Remember that the given LOB value must be un-linked (disconnected from the table) at commit. * * @param v the value */ public void unlinkAtCommit(Value v) { if (SysProperties.CHECK && !v.isLinked()) { DbException.throwInternalError(); } if (unlinkLobMap == null) { unlinkLobMap = New.hashMap(); } unlinkLobMap.put(v.toString(), v); }
public void decrypt(byte[] bytes, int off, int len) { if (SysProperties.CHECK) { if (len % ALIGN != 0) { DbException.throwInternalError("unaligned len " + len); } } for (int i = off; i < off + len; i += 8) { decryptBlock(bytes, bytes, i); } }
public MVDelegateIndex( MVTable table, int id, String name, MVPrimaryIndex mainIndex, IndexType indexType) { IndexColumn[] cols = IndexColumn.wrap(new Column[] {table.getColumn(mainIndex.getMainIndexColumn())}); this.initBaseIndex(table, id, name, cols, indexType); this.mainIndex = mainIndex; if (id < 0) { throw DbException.throwInternalError("" + name); } }
PageData split(int splitPoint) { int newPageId = index.getPageStore().allocatePage(); PageDataLeaf p2 = PageDataLeaf.create(index, newPageId, parentPageId); for (int i = splitPoint; i < entryCount; ) { int split = p2.addRowTry(getRowAt(splitPoint)); if (split != -1) { DbException.throwInternalError("split " + split); } removeRow(splitPoint); } return p2; }
/** * Get the key from the row. * * @param row the row * @param ifEmpty the value to use if the row is empty * @param ifNull the value to use if the column is NULL * @return the key */ long getKey(SearchRow row, long ifEmpty, long ifNull) { if (row == null) { return ifEmpty; } Value v = row.getValue(mainIndexColumn); if (v == null) { throw DbException.throwInternalError(row.toString()); } else if (v == ValueNull.INSTANCE) { return ifNull; } return v.getLong(); }
/** * Set the overflow page id. * * @param old the old overflow page id * @param overflow the new overflow page id */ void setOverflow(int old, int overflow) { if (SysProperties.CHECK && old != firstOverflowPageId) { DbException.throwInternalError("move " + this + " " + firstOverflowPageId); } index.getPageStore().logUndo(this, data); firstOverflowPageId = overflow; if (written) { changeCount = index.getPageStore().getChangeCount(); writeHead(); data.writeInt(firstOverflowPageId); } index.getPageStore().update(this); }
@Override public InputStream getInputStream(ValueLobDb lob, byte[] hmac, long byteCount) throws IOException { init(); Object[] value = lobMap.get(lob.getLobId()); if (value == null) { if (lob.getTableId() == LobStorageFrontend.TABLE_RESULT || lob.getTableId() == LobStorageFrontend.TABLE_ID_SESSION_VARIABLE) { throw DbException.get( ErrorCode.LOB_CLOSED_ON_TIMEOUT_1, "" + lob.getLobId() + "/" + lob.getTableId()); } throw DbException.throwInternalError( "Lob not found: " + lob.getLobId() + "/" + lob.getTableId()); } byte[] streamStoreId = (byte[]) value[0]; return streamStore.get(streamStoreId); }
private Permutations(T[] in, T[] out, int m) { this.n = in.length; this.m = m; if (n < m || m < 0) { DbException.throwInternalError("n < m or m < 0"); } this.in = in; this.out = out; index = new int[n]; for (int i = 0; i < n; i++) { index[i] = i; } // The elements from m to n are always kept ascending right to left. // This keeps the dip in the interesting region. reverseAfter(m - 1); }
private void unlockAll() { if (SysProperties.CHECK) { if (undoLog.size() > 0) { DbException.throwInternalError(); } } if (locks.size() > 0) { // don't use the enhanced for loop to save memory for (int i = 0, size = locks.size(); i < size; i++) { Table t = locks.get(i); t.unlock(this); } locks.clear(); } savepoints = null; sessionStateChanged = true; }
/** * Split the file name into size and base file name. * * @param fileName the file name * @return an array with size and file name */ private String[] parse(String fileName) { if (!fileName.startsWith(getScheme())) { DbException.throwInternalError(fileName + " doesn't start with " + getScheme()); } fileName = fileName.substring(getScheme().length() + 1); String size; if (fileName.length() > 0 && Character.isDigit(fileName.charAt(0))) { int idx = fileName.indexOf(':'); size = fileName.substring(0, idx); try { fileName = fileName.substring(idx + 1); } catch (NumberFormatException e) { // ignore } } else { size = Long.toString(SysProperties.SPLIT_FILE_SIZE_SHIFT); } return new String[] {size, fileName}; }
public boolean isEverything(ExpressionVisitor visitor) { if (!this.left.isEverything(visitor)) { return false; } switch (visitor.getType()) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: return true; } throw DbException.throwInternalError("type=" + visitor.getType()); }
@Override public Cursor findFirstOrLast(Session session, boolean first) { if (closed) { throw DbException.throwInternalError(); } if (first) { // TODO optimization: this loops through NULL Cursor cursor = find(session, null, null); while (cursor.next()) { SearchRow row = cursor.getSearchRow(); Value v = row.getValue(columnIds[0]); if (v != ValueNull.INSTANCE) { return cursor; } } return cursor; } TreeNode x = root, n; while (x != null) { n = x.right; if (n == null) { break; } x = n; } TreeCursor cursor = new TreeCursor(this, x, null, null); if (x == null) { return cursor; } // TODO optimization: this loops through NULL elements do { SearchRow row = cursor.getSearchRow(); if (row == null) { break; } Value v = row.getValue(columnIds[0]); if (v != ValueNull.INSTANCE) { return cursor; } } while (cursor.previous()); return cursor; }
private void removeRow(int i) { index.getPageStore().logUndo(this, data); written = false; changeCount = index.getPageStore().getChangeCount(); if (!optimizeUpdate) { readAllRows(); } Row r = getRowAt(i); if (r != null) { memoryChange(false, r); } entryCount--; if (entryCount < 0) { DbException.throwInternalError(); } if (firstOverflowPageId != 0) { start -= 4; freeOverflow(); firstOverflowPageId = 0; overflowRowSize = 0; rowRef = null; } int keyOffsetPairLen = 2 + Data.getVarLongLen(keys[i]); int startNext = i > 0 ? offsets[i - 1] : index.getPageStore().getPageSize(); int rowLength = startNext - offsets[i]; if (optimizeUpdate) { if (writtenData) { byte[] d = data.getBytes(); int dataStart = offsets[entryCount]; System.arraycopy(d, dataStart, d, dataStart + rowLength, offsets[i] - dataStart); Arrays.fill(d, dataStart, dataStart + rowLength, (byte) 0); } } else { int clearStart = offsets[entryCount]; Arrays.fill(data.getBytes(), clearStart, clearStart + rowLength, (byte) 0); } start -= keyOffsetPairLen; offsets = remove(offsets, entryCount + 1, i); add(offsets, i, entryCount, rowLength); keys = remove(keys, entryCount + 1, i); rows = remove(rows, entryCount + 1, i); }
private void writeHead() { data.reset(); int type; if (firstOverflowPageId == 0) { type = Page.TYPE_DATA_LEAF | Page.FLAG_LAST; } else { type = Page.TYPE_DATA_LEAF; } data.writeByte((byte) type); data.writeShortInt(0); if (SysProperties.CHECK2) { if (data.length() != START_PARENT) { DbException.throwInternalError(); } } data.writeInt(parentPageId); data.writeVarInt(index.getId()); data.writeVarInt(columnCount); data.writeShortInt(entryCount); }
private void balance(TreeNode x, boolean isLeft) { while (true) { int sign = isLeft ? 1 : -1; switch (x.balance * sign) { case 1: x.balance = 0; return; case 0: x.balance = -sign; break; case -1: TreeNode l = child(x, isLeft); if (l.balance == -sign) { replace(x, l); set(x, isLeft, child(l, !isLeft)); set(l, !isLeft, x); x.balance = 0; l.balance = 0; } else { TreeNode r = child(l, !isLeft); replace(x, r); set(l, !isLeft, child(r, isLeft)); set(r, isLeft, l); set(x, isLeft, child(r, !isLeft)); set(r, !isLeft, x); int rb = r.balance; x.balance = (rb == -sign) ? sign : 0; l.balance = (rb == sign) ? -sign : 0; r.balance = 0; } return; default: DbException.throwInternalError("b:" + x.balance * sign); } if (x == root) { return; } isLeft = x.isFromLeft(); x = x.parent; } }
@Override public void addGlobalCondition(Parameter param, int columnId, int comparisonType) { addParameter(param); switch (unionType) { case UNION_ALL: case UNION: case INTERSECT: { left.addGlobalCondition(param, columnId, comparisonType); right.addGlobalCondition(param, columnId, comparisonType); break; } case EXCEPT: { left.addGlobalCondition(param, columnId, comparisonType); break; } default: DbException.throwInternalError("type=" + unionType); } }
@Override public void init() { if (SysProperties.CHECK && checkInit) { DbException.throwInternalError(); } checkInit = true; left.init(); right.init(); int len = left.getColumnCount(); if (len != right.getColumnCount()) { throw DbException.get(ErrorCode.COLUMN_COUNT_DOES_NOT_MATCH); } ArrayList<Expression> le = left.getExpressions(); // set the expressions to get the right column count and names, // but can't validate at this time expressions = New.arrayList(); for (int i = 0; i < len; i++) { Expression l = le.get(i); expressions.add(l); } }
/** * Add an undo entry to the log. The page data is only written once until the next checkpoint. * * @param pageId the page id * @param page the old page data */ void addUndo(int pageId, Data page) { if (undo.get(pageId) || freeing) { return; } if (trace.isDebugEnabled()) { trace.debug("log undo " + pageId); } if (SysProperties.CHECK) { if (page == null) { DbException.throwInternalError("Undo entry not written"); } } undo.set(pageId); undoAll.set(pageId); Data buffer = getBuffer(); buffer.writeByte((byte) UNDO); buffer.writeVarInt(pageId); if (page.getBytes()[0] == 0) { buffer.writeVarInt(1); } else { int pageSize = store.getPageSize(); if (COMPRESS_UNDO) { int size = compress.compress(page.getBytes(), pageSize, compressBuffer, 0); if (size < pageSize) { buffer.writeVarInt(size); buffer.checkCapacity(size); buffer.write(compressBuffer, 0, size); } else { buffer.writeVarInt(0); buffer.checkCapacity(pageSize); buffer.write(page.getBytes(), 0, pageSize); } } else { buffer.writeVarInt(0); buffer.checkCapacity(pageSize); buffer.write(page.getBytes(), 0, pageSize); } } write(buffer); }
@Override public String getPlanSQL() { StringBuilder buff = new StringBuilder(); buff.append('(').append(left.getPlanSQL()).append(')'); switch (unionType) { case UNION_ALL: buff.append("\nUNION ALL\n"); break; case UNION: buff.append("\nUNION\n"); break; case INTERSECT: buff.append("\nINTERSECT\n"); break; case EXCEPT: buff.append("\nEXCEPT\n"); break; default: DbException.throwInternalError("type=" + unionType); } buff.append('(').append(right.getPlanSQL()).append(')'); Expression[] exprList = expressions.toArray(new Expression[expressions.size()]); if (sort != null) { buff.append("\nORDER BY ").append(sort.getSQL(exprList, exprList.length)); } if (limitExpr != null) { buff.append("\nLIMIT ").append(StringUtils.unEnclose(limitExpr.getSQL())); if (offsetExpr != null) { buff.append("\nOFFSET ").append(StringUtils.unEnclose(offsetExpr.getSQL())); } } if (sampleSizeExpr != null) { buff.append("\nSAMPLE_SIZE ").append(StringUtils.unEnclose(sampleSizeExpr.getSQL())); } if (isForUpdate) { buff.append("\nFOR UPDATE"); } return buff.toString(); }