@Override public Row getRow(Session session, long key) { TransactionMap<Value, Value> map = getMap(session); Value v = map.get(ValueLong.get(key)); ValueArray array = (ValueArray) v; Row row = new Row(array.getList(), 0); row.setKey(key); return row; }
private void testCastTrim() { Value v; String spaces = new String(new char[100]).replace((char) 0, ' '); v = ValueArray.get(new Value[] {ValueString.get("hello"), ValueString.get("world")}); assertEquals(10, v.getPrecision()); assertEquals(5, v.convertPrecision(5, true).getPrecision()); v = ValueArray.get(new Value[] {ValueString.get(""), ValueString.get("")}); assertEquals(0, v.getPrecision()); assertEquals("('')", v.convertPrecision(1, true).toString()); v = ValueBytes.get(spaces.getBytes()); assertEquals(100, v.getPrecision()); assertEquals(10, v.convertPrecision(10, false).getPrecision()); assertEquals(10, v.convertPrecision(10, false).getBytes().length); assertEquals(32, v.convertPrecision(10, false).getBytes()[9]); assertEquals(10, v.convertPrecision(10, true).getPrecision()); final Value vd = ValueDecimal.get(new BigDecimal("1234567890.123456789")); assertEquals(19, vd.getPrecision()); assertEquals("1234567890.1234567", vd.convertPrecision(10, true).getString()); new AssertThrows(ErrorCode.NUMERIC_VALUE_OUT_OF_RANGE_1) { @Override public void test() { vd.convertPrecision(10, false); } }; v = ValueLobDb.createSmallLob(Value.CLOB, spaces.getBytes(), 100); assertEquals(100, v.getPrecision()); assertEquals(10, v.convertPrecision(10, false).getPrecision()); assertEquals(10, v.convertPrecision(10, false).getString().length()); assertEquals(" ", v.convertPrecision(10, false).getString()); assertEquals(10, v.convertPrecision(10, true).getPrecision()); v = ValueLobDb.createSmallLob(Value.BLOB, spaces.getBytes(), 100); assertEquals(100, v.getPrecision()); assertEquals(10, v.convertPrecision(10, false).getPrecision()); assertEquals(10, v.convertPrecision(10, false).getBytes().length); assertEquals(32, v.convertPrecision(10, false).getBytes()[9]); assertEquals(10, v.convertPrecision(10, true).getPrecision()); ResultSet rs = new SimpleResultSet(); v = ValueResultSet.get(rs); assertEquals(Integer.MAX_VALUE, v.getPrecision()); assertEquals(Integer.MAX_VALUE, v.convertPrecision(10, false).getPrecision()); assertTrue(rs == v.convertPrecision(10, false).getObject()); assertFalse(rs == v.convertPrecision(10, true).getObject()); assertEquals(Integer.MAX_VALUE, v.convertPrecision(10, true).getPrecision()); v = ValueString.get(spaces); assertEquals(100, v.getPrecision()); assertEquals(10, v.convertPrecision(10, false).getPrecision()); assertEquals(" ", v.convertPrecision(10, false).getString()); assertEquals(" ", v.convertPrecision(10, true).getString()); }
@Override public Row get() { if (row == null) { if (current != null) { ValueArray array = (ValueArray) current.getValue(); row = session.createRow(array.getList(), 0); row.setKey(current.getKey().getLong()); } } return row; }
@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(); } }
@Override public Value getValue(Session session) { Value[] v = new Value[list.length]; for (int i = 0; i < list.length; i++) { v[i] = list[i].getValue(session); } return ValueArray.get(v); }
/** * Partially roll back the current transaction. * * @param savepoint the savepoint to which should be rolled back * @param trimToSize if the list should be trimmed */ public void rollbackTo(Savepoint savepoint, boolean trimToSize) { int index = savepoint == null ? 0 : savepoint.logIndex; while (undoLog.size() > index) { UndoLogRecord entry = undoLog.getLast(); entry.undo(this); undoLog.removeLast(trimToSize); } if (transaction != null) { long savepointId = savepoint == null ? 0 : savepoint.transactionSavepoint; HashMap<String, MVTable> tableMap = database.getMvStore().getTables(); Iterator<Change> it = transaction.getChanges(savepointId); while (it.hasNext()) { Change c = it.next(); MVTable t = tableMap.get(c.mapName); if (t != null) { long key = ((ValueLong) c.key).getLong(); ValueArray value = (ValueArray) c.value; short op; Row row; if (value == null) { op = UndoLogRecord.INSERT; row = t.getRow(this, key); } else { op = UndoLogRecord.DELETE; row = new Row(value.getList(), Row.MEMORY_CALCULATE); } row.setKey(key); UndoLogRecord log = new UndoLogRecord(t, op, row); log.undo(this); } } } if (savepoints != null) { String[] names = new String[savepoints.size()]; savepoints.keySet().toArray(names); for (String name : names) { Savepoint sp = savepoints.get(name); int savepointIndex = sp.logIndex; if (savepointIndex > index) { savepoints.remove(name); } } } }
@Override public void add(Session session, Row row) { if (mainIndexColumn == -1) { if (row.getKey() == 0) { row.setKey(++lastKey); } } else { long c = row.getValue(mainIndexColumn).getLong(); row.setKey(c); } if (mvTable.getContainsLargeObject()) { for (int i = 0, len = row.getColumnCount(); i < len; i++) { Value v = row.getValue(i); Value v2 = v.link(database, getId()); if (v2.isLinked()) { session.unlinkAtCommitStop(v2); } if (v != v2) { row.setValue(i, v2); } } } TransactionMap<Value, Value> map = getMap(session); Value key = ValueLong.get(row.getKey()); Value old = map.getLatest(key); if (old != null) { String sql = "PRIMARY KEY ON " + table.getSQL(); if (mainIndexColumn >= 0 && mainIndexColumn < indexColumns.length) { sql += "(" + indexColumns[mainIndexColumn].getSQL() + ")"; } DbException e = DbException.get(ErrorCode.DUPLICATE_KEY_1, sql); e.setSource(this); throw e; } try { map.put(key, ValueArray.get(row.getValueList())); } catch (IllegalStateException e) { throw DbException.get(ErrorCode.CONCURRENT_UPDATE_1, table.getName()); } lastKey = Math.max(lastKey, row.getKey()); }
private void queryGroup(int columnCount, LocalResult result) { ValueHashMap<HashMap<Expression, Object>> groups = ValueHashMap.newInstance(); int rowNumber = 0; setCurrentRowNumber(0); ValueArray defaultGroup = ValueArray.get(new Value[0]); while (topTableFilter.next()) { setCurrentRowNumber(rowNumber + 1); if (condition == null || Boolean.TRUE.equals(condition.getBooleanValue(session))) { Value key; rowNumber++; if (groupIndex == null) { key = defaultGroup; } else { Value[] keyValues = new Value[groupIndex.length]; // update group for (int i = 0; i < groupIndex.length; i++) { int idx = groupIndex[i]; Expression expr = expressions.get(idx); keyValues[i] = expr.getValue(session); } key = ValueArray.get(keyValues); } HashMap<Expression, Object> values = groups.get(key); if (values == null) { values = new HashMap<Expression, Object>(); groups.put(key, values); } currentGroup = values; currentGroupRowId++; int len = columnCount; for (int i = 0; i < len; i++) { if (groupByExpression == null || !groupByExpression[i]) { Expression expr = expressions.get(i); expr.updateAggregate(session); } } if (sampleSize > 0 && rowNumber >= sampleSize) { break; } } } if (groupIndex == null && groups.size() == 0) { groups.put(defaultGroup, new HashMap<Expression, Object>()); } ArrayList<Value> keys = groups.keys(); for (Value v : keys) { ValueArray key = (ValueArray) v; currentGroup = groups.get(key); Value[] keyValues = key.getList(); Value[] row = new Value[columnCount]; for (int j = 0; groupIndex != null && j < groupIndex.length; j++) { row[groupIndex[j]] = keyValues[j]; } for (int j = 0; j < columnCount; j++) { if (groupByExpression != null && groupByExpression[j]) { continue; } Expression expr = expressions.get(j); row[j] = expr.getValue(session); } if (isHavingNullOrFalse(row)) { continue; } row = keepOnlyDistinct(row, columnCount); result.addRow(row); } }
/** * Read a value. * * @return the value */ public Value readValue() { int type = data[pos++] & 255; switch (type) { case Value.NULL: return ValueNull.INSTANCE; case BOOLEAN_TRUE: return ValueBoolean.get(true); case BOOLEAN_FALSE: return ValueBoolean.get(false); case INT_NEG: return ValueInt.get(-readVarInt()); case Value.INT: return ValueInt.get(readVarInt()); case LONG_NEG: return ValueLong.get(-readVarLong()); case Value.LONG: return ValueLong.get(readVarLong()); case Value.BYTE: return ValueByte.get(readByte()); case Value.SHORT: return ValueShort.get(readShortInt()); case DECIMAL_0_1: return (ValueDecimal) ValueDecimal.ZERO; case DECIMAL_0_1 + 1: return (ValueDecimal) ValueDecimal.ONE; case DECIMAL_SMALL_0: return ValueDecimal.get(BigDecimal.valueOf(readVarLong())); case DECIMAL_SMALL: { int scale = readVarInt(); return ValueDecimal.get(BigDecimal.valueOf(readVarLong(), scale)); } case Value.DECIMAL: { int scale = readVarInt(); int len = readVarInt(); byte[] buff = DataUtils.newBytes(len); read(buff, 0, len); BigInteger b = new BigInteger(buff); return ValueDecimal.get(new BigDecimal(b, scale)); } case LOCAL_DATE: { return ValueDate.fromDateValue(readVarLong()); } case Value.DATE: { long x = readVarLong() * MILLIS_PER_MINUTE; return ValueDate.get(new Date(DateTimeUtils.getTimeUTCWithoutDst(x))); } case LOCAL_TIME: { long nanos = readVarLong() * 1000000 + readVarLong(); return ValueTime.fromNanos(nanos); } case Value.TIME: // need to normalize the year, month and day return ValueTime.get(new Time(DateTimeUtils.getTimeUTCWithoutDst(readVarLong()))); case LOCAL_TIMESTAMP: { long dateValue = readVarLong(); long nanos = readVarLong() * 1000000 + readVarLong(); return ValueTimestamp.fromDateValueAndNanos(dateValue, nanos); } case Value.TIMESTAMP: { Timestamp ts = new Timestamp(DateTimeUtils.getTimeUTCWithoutDst(readVarLong())); ts.setNanos(readVarInt()); return ValueTimestamp.get(ts); } case Value.BYTES: { int len = readVarInt(); byte[] b = DataUtils.newBytes(len); read(b, 0, len); return ValueBytes.getNoCopy(b); } case Value.GEOMETRY: { int len = readVarInt(); byte[] b = DataUtils.newBytes(len); read(b, 0, len); return ValueGeometry.get(b); } case Value.JAVA_OBJECT: { int len = readVarInt(); byte[] b = DataUtils.newBytes(len); read(b, 0, len); return ValueJavaObject.getNoCopy(null, b, handler); } case Value.UUID: return ValueUuid.get(readLong(), readLong()); case Value.STRING: return ValueString.get(readString()); case Value.STRING_IGNORECASE: return ValueStringIgnoreCase.get(readString()); case Value.STRING_FIXED: return ValueStringFixed.get(readString()); case FLOAT_0_1: return ValueFloat.get(0); case FLOAT_0_1 + 1: return ValueFloat.get(1); case DOUBLE_0_1: return ValueDouble.get(0); case DOUBLE_0_1 + 1: return ValueDouble.get(1); case Value.DOUBLE: return ValueDouble.get(Double.longBitsToDouble(Long.reverse(readVarLong()))); case Value.FLOAT: return ValueFloat.get(Float.intBitsToFloat(Integer.reverse(readVarInt()))); case Value.BLOB: case Value.CLOB: { int smallLen = readVarInt(); if (smallLen >= 0) { byte[] small = DataUtils.newBytes(smallLen); read(small, 0, smallLen); return ValueLobDb.createSmallLob(type, small); } else if (smallLen == -3) { int tableId = readVarInt(); long lobId = readVarLong(); long precision = readVarLong(); ValueLobDb lob = ValueLobDb.create(type, handler, tableId, lobId, null, precision); return lob; } else { int tableId = readVarInt(); int objectId = readVarInt(); long precision = 0; boolean compression = false; // -1: regular; -2: regular, but not linked (in this case: // including file name) if (smallLen == -1 || smallLen == -2) { precision = readVarLong(); compression = readByte() == 1; } if (smallLen == -2) { String filename = readString(); return ValueLob.openUnlinked( type, handler, tableId, objectId, precision, compression, filename); } return ValueLob.openLinked(type, handler, tableId, objectId, precision, compression); } } case Value.ARRAY: { int len = readVarInt(); Value[] list = new Value[len]; for (int i = 0; i < len; i++) { list[i] = readValue(); } return ValueArray.get(list); } case Value.RESULT_SET: { SimpleResultSet rs = new SimpleResultSet(); rs.setAutoClose(false); int columns = readVarInt(); for (int i = 0; i < columns; i++) { rs.addColumn(readString(), readVarInt(), readVarInt(), readVarInt()); } while (true) { if (readByte() == 0) { break; } Object[] o = new Object[columns]; for (int i = 0; i < columns; i++) { o[i] = readValue().getObject(); } rs.addRow(o); } return ValueResultSet.get(rs); } default: if (type >= INT_0_15 && type < INT_0_15 + 16) { return ValueInt.get(type - INT_0_15); } else if (type >= LONG_0_7 && type < LONG_0_7 + 8) { return ValueLong.get(type - LONG_0_7); } else if (type >= BYTES_0_31 && type < BYTES_0_31 + 32) { int len = type - BYTES_0_31; byte[] b = DataUtils.newBytes(len); read(b, 0, len); return ValueBytes.getNoCopy(b); } else if (type >= STRING_0_31 && type < STRING_0_31 + 32) { return ValueString.get(readString(type - STRING_0_31)); } throw DbException.get(ErrorCode.FILE_CORRUPTED_1, "type: " + type); } }