private void testFormat() throws IOException {
    Map<Long, byte[]> map = New.hashMap();
    StreamStore store = new StreamStore(map);
    store.setMinBlockSize(10);
    store.setMaxBlockSize(20);
    store.setNextKey(123);

    byte[] id;

    id = store.put(new ByteArrayInputStream(new byte[200]));
    assertEquals(200, store.length(id));
    assertEquals("02c8018801", StringUtils.convertBytesToHex(id));

    id = store.put(new ByteArrayInputStream(new byte[0]));
    assertEquals("", StringUtils.convertBytesToHex(id));

    id = store.put(new ByteArrayInputStream(new byte[1]));
    assertEquals("000100", StringUtils.convertBytesToHex(id));

    id = store.put(new ByteArrayInputStream(new byte[3]));
    assertEquals("0003000000", StringUtils.convertBytesToHex(id));

    id = store.put(new ByteArrayInputStream(new byte[10]));
    assertEquals("010a8901", StringUtils.convertBytesToHex(id));

    byte[] combined = StringUtils.convertHexToBytes("0001aa0002bbcc");
    assertEquals(3, store.length(combined));
    InputStream in = store.get(combined);
    assertEquals(1, in.skip(1));
    assertEquals(0xbb, in.read());
    assertEquals(1, in.skip(1));
  }
 private void copyData() {
   if (table.isTemporary()) {
     throw DbException.getUnsupportedException("TEMP TABLE");
   }
   Database db = session.getDatabase();
   String baseName = table.getName();
   String tempName = db.getTempTableName(baseName, session);
   Column[] columns = table.getColumns();
   ArrayList<Column> newColumns = New.arrayList();
   Table newTable = cloneTableStructure(columns, db, tempName, newColumns);
   try {
     // check if a view would become invalid
     // (because the column to drop is referenced or so)
     checkViews(table, newTable);
   } catch (DbException e) {
     execute("DROP TABLE " + newTable.getName(), true);
     throw DbException.get(ErrorCode.VIEW_IS_INVALID_2, e, getSQL(), e.getMessage());
   }
   String tableName = table.getName();
   ArrayList<TableView> views = table.getViews();
   if (views != null) {
     views = New.arrayList(views);
     for (TableView view : views) {
       table.removeView(view);
     }
   }
   execute("DROP TABLE " + table.getSQL() + " IGNORE", true);
   db.renameSchemaObject(session, newTable, tableName);
   for (DbObject child : newTable.getChildren()) {
     if (child instanceof Sequence) {
       continue;
     }
     String name = child.getName();
     if (name == null || child.getCreateSQL() == null) {
       continue;
     }
     if (name.startsWith(tempName + "_")) {
       name = name.substring(tempName.length() + 1);
       SchemaObject so = (SchemaObject) child;
       if (so instanceof Constraint) {
         if (so.getSchema().findConstraint(session, name) != null) {
           name = so.getSchema().getUniqueConstraintName(session, newTable);
         }
       } else if (so instanceof Index) {
         if (so.getSchema().findIndex(session, name) != null) {
           name = so.getSchema().getUniqueIndexName(session, newTable, name);
         }
       }
       db.renameSchemaObject(session, so, name);
     }
   }
   if (views != null) {
     for (TableView view : views) {
       String sql = view.getCreateSQL(true, true);
       execute(sql, true);
     }
   }
 }
예제 #3
0
 @Override
 public void reset() {
   if (sort != null) {
     for (ResultDiskTape tape : tapes) {
       tape.pos = tape.start;
       tape.buffer = New.arrayList();
     }
   } else {
     mainTape.pos = FileStore.HEADER_LENGTH;
     mainTape.buffer = New.arrayList();
   }
 }
예제 #4
0
 private void initColumnsAndTables(Session session) {
   Column[] cols;
   removeViewFromTables();
   try {
     Query query = recompileQuery(session);
     tables = New.arrayList(query.getTables());
     ArrayList<Expression> expressions = query.getExpressions();
     ArrayList<Column> list = New.arrayList();
     for (int i = 0; i < query.getColumnCount(); i++) {
       Expression expr = expressions.get(i);
       String name = null;
       if (columnNames != null && columnNames.length > i) {
         name = columnNames[i];
       }
       if (name == null) {
         name = expr.getAlias();
       }
       int type = expr.getType();
       long precision = expr.getPrecision();
       int scale = expr.getScale();
       int displaySize = expr.getDisplaySize();
       Column col = new Column(name, type, precision, scale, displaySize);
       col.setTable(this, i);
       list.add(col);
     }
     cols = new Column[list.size()];
     list.toArray(cols);
     createException = null;
     viewQuery = query;
   } catch (DbException e) {
     createException = e;
     // if it can't be compiled, then it's a 'zero column table'
     // this avoids problems when creating the view when opening the
     // database
     tables = New.arrayList();
     cols = new Column[0];
     if (recursive && columnNames != null) {
       cols = new Column[columnNames.length];
       for (int i = 0; i < columnNames.length; i++) {
         cols[i] = new Column(columnNames[i], Value.STRING);
       }
       index.setRecursive(true);
       createException = null;
     }
   }
   setColumns(cols);
   if (getId() != 0) {
     addViewToTables();
   }
 }
예제 #5
0
 private ResultDiskBuffer(ResultDiskBuffer parent) {
   this.parent = parent;
   rowBuff = Data.create(parent.rowBuff.getHandler(), Constants.DEFAULT_PAGE_SIZE);
   file = parent.file;
   if (parent.tapes != null) {
     tapes = New.arrayList();
     for (ResultDiskTape t : parent.tapes) {
       ResultDiskTape t2 = new ResultDiskTape();
       t2.pos = t2.start = t.start;
       t2.end = t.end;
       tapes.add(t2);
     }
   } else {
     tapes = null;
   }
   if (parent.mainTape != null) {
     mainTape = new ResultDiskTape();
     mainTape.pos = FileStore.HEADER_LENGTH;
     mainTape.start = parent.mainTape.start;
     mainTape.end = parent.mainTape.end;
   } else {
     mainTape = null;
   }
   sort = parent.sort;
   columnCount = parent.columnCount;
   maxBufferSize = parent.maxBufferSize;
 }
예제 #6
0
 public HashSet<Table> getTables() {
   HashSet<Table> set = New.hashSet();
   for (TableFilter filter : filters) {
     set.add(filter.getTable());
   }
   return set;
 }
예제 #7
0
 private ArrayList<String> mapColumnNames(Object[] columns) {
   ArrayList<String> columnNames = New.arrayList();
   for (Object column : columns) {
     columnNames.add(getColumnName(column));
   }
   return columnNames;
 }
예제 #8
0
 public void reset() throws SQLException {
   log("reset;");
   DatabaseMetaData meta = conn.getMetaData();
   Statement stat = conn.createStatement();
   ArrayList<String> tables = New.arrayList();
   ResultSet rs = meta.getTables(null, null, null, new String[] {"TABLE"});
   while (rs.next()) {
     String schemaName = rs.getString("TABLE_SCHEM");
     if (!"INFORMATION_SCHEMA".equals(schemaName)) {
       tables.add(rs.getString("TABLE_NAME"));
     }
   }
   while (tables.size() > 0) {
     int dropped = 0;
     for (int i = 0; i < tables.size(); i++) {
       try {
         String table = tables.get(i);
         stat.execute("DROP TABLE " + table);
         dropped++;
         tables.remove(i);
         i--;
       } catch (SQLException e) {
         // maybe a referential integrity
       }
     }
     // could not drop any table and still tables to drop
     if (dropped == 0 && tables.size() > 0) {
       throw new AssertionError("Cannot drop " + tables);
     }
   }
 }
예제 #9
0
 public <A> QueryWhere<T> where(Filter filter) {
   HashMap<String, Object> fieldMap = New.hashMap();
   for (Field f : filter.getClass().getDeclaredFields()) {
     f.setAccessible(true);
     try {
       Object obj = f.get(filter);
       if (obj == from.getAlias()) {
         List<TableDefinition.FieldDefinition> fields = from.getAliasDefinition().getFields();
         String name = f.getName();
         for (TableDefinition.FieldDefinition field : fields) {
           String n = name + "." + field.field.getName();
           Object o = field.field.get(obj);
           fieldMap.put(n, o);
         }
       }
       fieldMap.put(f.getName(), f.get(filter));
     } catch (Exception e) {
       throw new RuntimeException(e);
     }
   }
   Token filterCode = new ClassReader().decompile(filter, fieldMap, "where");
   // String filterQuery = filterCode.toString();
   conditions.add(filterCode);
   return new QueryWhere<T>(this);
 }
예제 #10
0
 @SuppressWarnings("unchecked")
 private <X> List<X> selectSimple(X x, boolean distinct) {
   SQLStatement stat = getSelectStatement(distinct);
   appendSQL(stat, x);
   appendFromWhere(stat);
   ResultSet rs = stat.executeQuery();
   List<X> result = New.arrayList();
   Statement s = null;
   try {
     s = rs.getStatement();
     while (rs.next()) {
       try {
         X value;
         Object o = rs.getObject(1);
         int convertHereIsProbablyWrong;
         if (Clob.class.isAssignableFrom(o.getClass())) {
           value = (X) ClassUtils.convert(o, String.class);
         } else {
           value = (X) o;
         }
         result.add(value);
       } catch (Exception e) {
         throw new RuntimeException(e);
       }
     }
   } catch (SQLException e) {
     throw new RuntimeException(e);
   } finally {
     JdbcUtils.closeSilently(rs);
     JdbcUtils.closeSilently(s);
   }
   return result;
 }
예제 #11
0
 private void testIterateOverChanges() {
   String fileName = getBaseDir() + "/testIterate.h3";
   FileUtils.delete(fileName);
   MVStore s = openStore(fileName);
   s.setMaxPageSize(6);
   MVMap<Integer, String> m = s.openMap("data", Integer.class, String.class);
   for (int i = 0; i < 100; i++) {
     m.put(i, "Hi");
   }
   s.incrementVersion();
   s.store();
   for (int i = 20; i < 40; i++) {
     assertEquals("Hi", m.put(i, "Hello"));
   }
   long old = s.getCurrentVersion();
   s.incrementVersion();
   for (int i = 10; i < 15; i++) {
     m.put(i, "Hallo");
   }
   m.put(50, "Hallo");
   for (int i = 90; i < 93; i++) {
     assertEquals("Hi", m.remove(i));
   }
   assertEquals(null, m.put(100, "Hallo"));
   Iterator<Integer> it = m.changeIterator(old);
   ArrayList<Integer> list = New.arrayList();
   while (it.hasNext()) {
     list.add(it.next());
   }
   assertEquals("[10, 11, 12, 13, 14, 50, 100, 90, 91, 92]", list.toString());
   s.close();
 }
예제 #12
0
 /**
  * Defines an index with the specified column names.
  *
  * @param type the index type (STANDARD, HASH, UNIQUE, UNIQUE_HASH)
  * @param columnNames the ordered list of column names
  */
 void addIndex(IndexType type, List<String> columnNames) {
   IndexDefinition index = new IndexDefinition();
   index.indexName = tableName + "_" + indexes.size();
   index.columnNames = New.arrayList(columnNames);
   index.type = type;
   indexes.add(index);
 }
예제 #13
0
 private static void registerDefaultProviders() {
   if (providers == null || defaultProvider == null) {
     Map<String, FilePath> map = Collections.synchronizedMap(New.<String, FilePath>hashMap());
     // 默认是org.h2.store.fs.FilePathDisk, 所以这里不包含它
     // 但是少了org.h2.store.fs.FilePathRec、org.h2.mvstore.cache.FilePathCache
     // 不过org.h2.store.fs.FilePathRec是通过org.h2.store.fs.FilePath.register(FilePath)这个方法注册
     // 见org.h2.store.fs.FilePathRec.register(),
     // 在org.h2.engine.ConnectionInfo.ConnectionInfo(String, Properties)调用它了
     for (String c :
         new String[] {
           "org.h2.store.fs.FilePathDisk",
           "org.h2.store.fs.FilePathMem",
           "org.h2.store.fs.FilePathMemLZF",
           "org.h2.store.fs.FilePathNioMem",
           "org.h2.store.fs.FilePathNioMemLZF",
           "org.h2.store.fs.FilePathSplit",
           "org.h2.store.fs.FilePathNio",
           "org.h2.store.fs.FilePathNioMapped",
           "org.h2.store.fs.FilePathZip"
         }) {
       try {
         FilePath p = (FilePath) Class.forName(c).newInstance();
         map.put(p.getScheme(), p);
         if (defaultProvider == null) {
           defaultProvider = p;
         }
       } catch (Exception e) {
         // ignore - the files may be excluded in purpose
       }
     }
     providers = map;
   }
 }
예제 #14
0
 /**
  * Define a primary key by the specified column names.
  *
  * @param columnNames the ordered list of column names
  */
 void setPrimaryKey(List<String> columnNames) {
   primaryKeyColumnNames = New.arrayList(columnNames);
   // set isPrimaryKey flag for all field definitions
   for (FieldDefinition fieldDefinition : fieldMap.values()) {
     fieldDefinition.isPrimaryKey =
         this.primaryKeyColumnNames.contains(fieldDefinition.columnName);
   }
 }
예제 #15
0
 /**
  * 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);
 }
예제 #16
0
 /**
  * Keep a collection of the columns to pass to update if a duplicate key happens, for MySQL-style
  * INSERT ... ON DUPLICATE KEY UPDATE ....
  *
  * @param column the column
  * @param expression the expression
  */
 public void addAssignmentForDuplicate(Column column, Expression expression) {
   if (duplicateKeyAssignmentMap == null) {
     duplicateKeyAssignmentMap = New.hashMap();
   }
   if (duplicateKeyAssignmentMap.containsKey(column)) {
     throw DbException.get(ErrorCode.DUPLICATE_COLUMN_NAME_1, column.getName());
   }
   duplicateKeyAssignmentMap.put(column, expression);
 }
예제 #17
0
 List<IndexDefinition> getIndexes(IndexType type) {
   List<IndexDefinition> list = New.arrayList();
   for (IndexDefinition def : indexes) {
     if (def.type.equals(type)) {
       list.add(def);
     }
   }
   return list;
 }
예제 #18
0
 /**
  * Open a copy of the map in read-only mode.
  *
  * @return the opened map
  */
 protected MVMap<K, V> openReadOnly() {
   MVMap<K, V> m = new MVMap<K, V>(keyType, valueType);
   m.readOnly = true;
   HashMap<String, String> config = New.hashMap();
   config.put("id", String.valueOf(id));
   config.put("createVersion", String.valueOf(createVersion));
   m.init(store, config);
   m.root = root;
   return m;
 }
예제 #19
0
 ArrayList<InDoubtTransaction> getInDoubtTransactions() {
   ArrayList<InDoubtTransaction> list = New.arrayList();
   for (SessionState state : sessionStates.values()) {
     PageStoreInDoubtTransaction in = state.inDoubtTransaction;
     if (in != null) {
       list.add(in);
     }
   }
   return list;
 }
예제 #20
0
 /**
  * Commit the current transaction. If the statement was not a data definition statement, and if
  * there are temporary tables that should be dropped or truncated at commit, this is done as well.
  *
  * @param ddl if the statement was a data definition statement
  */
 public void commit(boolean ddl) {
   checkCommitRollback();
   currentTransactionName = null;
   transactionStart = 0;
   if (transaction != null) {
     // increment the data mod count, so that other sessions
     // see the changes
     // TODO should not rely on locking
     if (locks.size() > 0) {
       for (int i = 0, size = locks.size(); i < size; i++) {
         Table t = locks.get(i);
         if (t instanceof MVTable) {
           ((MVTable) t).commit();
         }
       }
     }
     transaction.commit();
     transaction = null;
   }
   if (containsUncommitted()) {
     // need to commit even if rollback is not possible
     // (create/drop table and so on)
     database.commit(this);
   }
   removeTemporaryLobs(true);
   if (undoLog.size() > 0) {
     // commit the rows when using MVCC
     if (database.isMultiVersion()) {
       ArrayList<Row> rows = New.arrayList();
       synchronized (database) {
         while (undoLog.size() > 0) {
           UndoLogRecord entry = undoLog.getLast();
           entry.commit();
           rows.add(entry.getRow());
           undoLog.removeLast(false);
         }
         for (int i = 0, size = rows.size(); i < size; i++) {
           Row r = rows.get(i);
           r.commit();
         }
       }
     }
     undoLog.clear();
   }
   if (!ddl) {
     // do not clean the temp tables if the last command was a
     // create/drop
     cleanTempTables(false);
     if (autoCommitAtTransactionEnd) {
       autoCommit = true;
       autoCommitAtTransactionEnd = false;
     }
   }
   endTransaction();
 }
예제 #21
0
 public DbSettings getDbSettings() {
   DbSettings defaultSettings = DbSettings.getDefaultSettings();
   HashMap<String, String> s = New.hashMap();
   for (Object k : prop.keySet()) {
     String key = k.toString();
     if (!isKnownSetting(key) && defaultSettings.containsKey(key)) {
       s.put(key, prop.getProperty(key));
     }
   }
   return DbSettings.getInstance(s);
 }
 private void checkDefaultReferencesTable(Expression defaultExpression) {
   if (defaultExpression == null) {
     return;
   }
   HashSet<DbObject> dependencies = New.hashSet();
   ExpressionVisitor visitor = ExpressionVisitor.getDependenciesVisitor(dependencies);
   defaultExpression.isEverything(visitor);
   if (dependencies.contains(table)) {
     throw DbException.get(ErrorCode.COLUMN_IS_REFERENCED_1, defaultExpression.getSQL());
   }
 }
 public ArrayList<FilePath> newDirectoryStream() {
   List<FilePath> list = getBase().newDirectoryStream();
   ArrayList<FilePath> newList = New.arrayList();
   for (int i = 0, size = list.size(); i < size; i++) {
     FilePath f = list.get(i);
     if (!f.getName().endsWith(PART_SUFFIX)) {
       newList.add(wrap(f));
     }
   }
   return newList;
 }
예제 #24
0
 /**
  * Remember the result set and close it as soon as the transaction is committed (if it needs to be
  * closed). This is done to delete temporary files as soon as possible, and free object ids of
  * temporary tables.
  *
  * @param result the temporary result set
  */
 public void addTemporaryResult(LocalResult result) {
   if (!result.needToClose()) {
     return;
   }
   if (temporaryResults == null) {
     temporaryResults = New.hashSet();
   }
   if (temporaryResults.size() < 100) {
     // reference at most 100 result sets to avoid memory problems
     temporaryResults.add(result);
   }
 }
예제 #25
0
 /**
  * Get a random column that can be used in a condition.
  *
  * @return the column
  */
 Column getRandomConditionColumn() {
   ArrayList<Column> list = New.arrayList();
   for (Column col : columns) {
     if (Column.isConditionType(config, col.getType())) {
       list.add(col);
     }
   }
   if (list.size() == 0) {
     return null;
   }
   return list.get(config.random().getInt(list.size()));
 }
예제 #26
0
 /**
  * Get a random column of the specified type.
  *
  * @param type the type
  * @return the column or null if no such column was found
  */
 Column getRandomColumnOfType(int type) {
   ArrayList<Column> list = New.arrayList();
   for (Column col : columns) {
     if (col.getType() == type) {
       list.add(col);
     }
   }
   if (list.size() == 0) {
     return null;
   }
   return list.get(config.random().getInt(list.size()));
 }
예제 #27
0
  private long[] getMemoryUsed(int count, int size) {
    long hash, tree, mv;
    ArrayList<Map<Integer, String>> mapList;
    long mem;

    mapList = New.arrayList();
    mem = getMemory();
    for (int i = 0; i < count; i++) {
      mapList.add(new HashMap<Integer, String>(size));
    }
    addEntries(mapList, size);
    hash = getMemory() - mem;
    mapList.size();

    mapList = New.arrayList();
    mem = getMemory();
    for (int i = 0; i < count; i++) {
      mapList.add(new TreeMap<Integer, String>());
    }
    addEntries(mapList, size);
    tree = getMemory() - mem;
    mapList.size();

    mapList = New.arrayList();
    mem = getMemory();
    MVStore store = MVStore.open(null);
    for (int i = 0; i < count; i++) {
      Map<Integer, String> map = store.openMap("t" + i);
      mapList.add(map);
    }
    addEntries(mapList, size);
    mv = getMemory() - mem;
    mapList.size();

    trace("hash: " + hash / 1024 / 1024 + " mb");
    trace("tree: " + tree / 1024 / 1024 + " mb");
    trace("mv: " + mv / 1024 / 1024 + " mb");

    return new long[] {hash, tree, mv};
  }
예제 #28
0
 /**
  * Adds a statement to the batch.
  *
  * @param sql the SQL statement
  */
 public void addBatch(String sql) throws SQLException {
   try {
     debugCodeCall("addBatch", sql);
     checkClosed();
     sql = JdbcConnection.translateSQL(sql, escapeProcessing);
     if (batchCommands == null) {
       batchCommands = New.arrayList();
     }
     batchCommands.add(sql);
   } catch (Exception e) {
     throw logAndConvert(e);
   }
 }
예제 #29
0
 public final Value[] getParameterValues() {
   ArrayList<Parameter> list = getParameters();
   if (list == null) {
     list = New.arrayList();
   }
   int size = list.size();
   Value[] params = new Value[size];
   for (int i = 0; i < size; i++) {
     Value v = list.get(i).getParamValue();
     params[i] = v;
   }
   return params;
 }
예제 #30
0
  private void queryGroupSorted(int columnCount, ResultTarget result) {
    int rowNumber = 0;
    setCurrentRowNumber(0);
    Value[] previousKeyValues = null;
    while (topTableFilter.next()) {
      setCurrentRowNumber(rowNumber + 1);
      if (condition == null || Boolean.TRUE.equals(condition.getBooleanValue(session))) {
        rowNumber++;
        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);
        }

        if (previousKeyValues == null) {
          previousKeyValues = keyValues;
          currentGroup = New.hashMap();
        } else if (!Arrays.equals(previousKeyValues, keyValues)) {
          addGroupSortedRow(previousKeyValues, columnCount, result);
          previousKeyValues = keyValues;
          currentGroup = New.hashMap();
        }
        currentGroupRowId++;

        for (int i = 0; i < columnCount; i++) {
          if (groupByExpression == null || !groupByExpression[i]) {
            Expression expr = expressions.get(i);
            expr.updateAggregate(session);
          }
        }
      }
    }
    if (previousKeyValues != null) {
      addGroupSortedRow(previousKeyValues, columnCount, result);
    }
  }