Beispiel #1
0
 /**
  * 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 (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();
     }
   }
 }
Beispiel #2
0
 /**
  * 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.indexOf(table) >= 0) {
       DbException.throwInternalError();
     }
   }
   locks.add(table);
 }
Beispiel #3
0
  Value getMergedValue(Database database, boolean distinct) {
    if (distinct) {
      count = 0;
      groupDistinct(database);
    }
    Value v = null;
    switch (aggregateType) {
      case Aggregate.COUNT:
      case Aggregate.COUNT_ALL:
        v = ValueLong.get(count);
        break;
      case Aggregate.SUM:
      case Aggregate.MIN:
      case Aggregate.MAX:
      case Aggregate.BOOL_OR:
      case Aggregate.BOOL_AND:
        v = value;
        break;
      case Aggregate.AVG:
      case Aggregate.STDDEV_POP:
      case Aggregate.STDDEV_SAMP:
      case Aggregate.VAR_POP:
      case Aggregate.VAR_SAMP:
        return value == null ? ValueNull.INSTANCE : value;

      case Aggregate.SELECTIVITY:
        if (value != null) {
          v = divide(value, count);
        }
        break;
      case Aggregate.GROUP_CONCAT:
        return null;

      case Aggregate.HISTOGRAM:
        ValueArray[] values = new ValueArray[distinctValues.size()];
        int i = 0;
        for (Value dv : distinctValues.keys()) {
          AggregateData d = distinctValues.get(dv);
          values[i] = ValueArray.get(new Value[] {dv, ValueLong.get(d.count)});
          i++;
        }
        final CompareMode compareMode = database.getCompareMode();
        Arrays.sort(
            values,
            new Comparator<ValueArray>() {
              public int compare(ValueArray v1, ValueArray v2) {
                Value a1 = v1.getList()[0];
                Value a2 = v2.getList()[0];
                return a1.compareTo(a2, compareMode);
              }
            });
        v = ValueArray.get(values);
        break;
      default:
        DbException.throwInternalError("type=" + aggregateType);
    }
    return v == null ? ValueNull.INSTANCE : v.convertTo(dataType);
  }
Beispiel #4
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);
 }
Beispiel #5
0
  public synchronized void checkTransfers() {
    if (transferList != null) {
      for (int i = 0; i < transferList.size(); i++) {
        Transfer transfer = transferList.get(i);

        try {
          if (transfer.available() > 0)
            throw DbException.throwInternalError(
                "the transfer available bytes was " + transfer.available());
        } catch (IOException e) {
          throw DbException.convert(e);
        }
      }
    }
  }
Beispiel #6
0
 private void unlockAll() {
   if (SysProperties.CHECK) {
     if (undoLog.size() > 0) {
       DbException.throwInternalError();
     }
   }
   if (locks.size() > 0) {
     synchronized (database) {
       // 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;
 }
Beispiel #7
0
  /**
   * Called to flush the output after data has been sent to the server and just before receiving
   * data. This method also reads the status code from the server and throws any exception the
   * server sent.
   *
   * @param transfer the transfer object
   * @throws DbException if the server sent an exception
   * @throws IOException if there is a communication problem between client and server
   */
  public void done(Transfer transfer) throws IOException {
    // 正常来讲不会出现这种情况,如果出现了,说明存在bug,找出为什么transfer的输入流没正常读完的原因
    if (transfer.available() > 0) {
      throw DbException.throwInternalError(
          "before transfer flush, the available bytes was " + transfer.available());
    }

    transfer.flush();
    int status = transfer.readInt();
    if (status == STATUS_ERROR) {
      parseError(transfer);
    } else if (status == STATUS_CLOSED) {
      transferList = null;
    } else if (status == STATUS_OK_STATE_CHANGED) {
      sessionStateChanged = true;
    } else if (status == STATUS_OK) {
      // ok
    } else {
      throw DbException.get(ErrorCode.CONNECTION_BROKEN_1, "unexpected status " + status);
    }
  }
Beispiel #8
0
 private void initDb() throws SQLException {
   Statement stat = null;
   ResultSet rs = null;
   try {
     synchronized (server) {
       // better would be: set the database to exclusive mode
       rs = conn.getMetaData().getTables(null, "PG_CATALOG", "PG_VERSION", null);
       boolean tableFound = rs.next();
       stat = conn.createStatement();
       if (!tableFound) {
         installPgCatalog(stat);
       }
       rs = stat.executeQuery("SELECT * FROM PG_CATALOG.PG_VERSION");
       if (!rs.next() || rs.getInt(1) < 2) {
         // installation incomplete, or old version
         installPgCatalog(stat);
       } else {
         // version 2 or newer: check the read version
         int versionRead = rs.getInt(2);
         if (versionRead > 2) {
           throw DbException.throwInternalError("Incompatible PG_VERSION");
         }
       }
     }
     stat.execute("set search_path = PUBLIC, pg_catalog");
     HashSet<Integer> typeSet = server.getTypeSet();
     if (typeSet.size() == 0) {
       rs = stat.executeQuery("SELECT OID FROM PG_CATALOG.PG_TYPE");
       while (rs.next()) {
         typeSet.add(rs.getInt(1));
       }
     }
   } finally {
     JdbcUtils.closeSilently(stat);
     JdbcUtils.closeSilently(rs);
   }
 }
Beispiel #9
0
 /**
  * Add a value to this aggregate.
  *
  * @param database the database
  * @param distinct if the calculation should be distinct
  * @param v the value
  */
 void add(Database database, boolean distinct, Value v) {
   if (aggregateType == Aggregate.SELECTIVITY) {
     count++;
     if (distinctHashes == null) {
       distinctHashes = new IntIntHashMap();
     }
     int size = distinctHashes.size();
     if (size > Constants.SELECTIVITY_DISTINCT_COUNT) {
       distinctHashes = new IntIntHashMap();
       m2 += size;
     }
     int hash = v.hashCode();
     // the value -1 is not supported
     distinctHashes.put(hash, 1);
     return;
   } else if (aggregateType == Aggregate.COUNT_ALL) {
     count++;
     return;
   } else if (aggregateType == Aggregate.HISTOGRAM) {
     if (distinctValues == null) {
       distinctValues = ValueHashMap.newInstance();
     }
     AggregateData a = distinctValues.get(v);
     if (a == null) {
       if (distinctValues.size() < Constants.SELECTIVITY_DISTINCT_COUNT) {
         a = new AggregateData(Aggregate.HISTOGRAM, dataType);
         distinctValues.put(v, a);
       }
     }
     if (a != null) {
       a.count++;
     }
     return;
   }
   if (v == ValueNull.INSTANCE) {
     return;
   }
   count++;
   if (distinct) {
     if (distinctValues == null) {
       distinctValues = ValueHashMap.newInstance();
     }
     distinctValues.put(v, this);
     return;
   }
   switch (aggregateType) {
     case Aggregate.COUNT:
     case Aggregate.HISTOGRAM:
       return;
     case Aggregate.SUM:
       if (value == null) {
         value = v.convertTo(dataType);
       } else {
         v = v.convertTo(value.getType());
         value = value.add(v);
       }
       break;
     case Aggregate.AVG:
       if (value == null) {
         value = v.convertTo(DataType.getAddProofType(dataType));
       } else {
         v = v.convertTo(value.getType());
         value = value.add(v);
       }
       break;
     case Aggregate.MIN:
       if (value == null || database.compare(v, value) < 0) {
         value = v;
       }
       break;
     case Aggregate.MAX:
       if (value == null || database.compare(v, value) > 0) {
         value = v;
       }
       break;
     case Aggregate.GROUP_CONCAT:
       {
         if (list == null) {
           list = New.arrayList();
         }
         list.add(v);
         break;
       }
     case Aggregate.STDDEV_POP:
     case Aggregate.STDDEV_SAMP:
     case Aggregate.VAR_POP:
     case Aggregate.VAR_SAMP:
       {
         // Using Welford's method, see also
         // http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
         // http://www.johndcook.com/standard_deviation.html
         double x = v.getDouble();
         if (count == 1) {
           mean = x;
           m2 = 0;
         } else {
           double delta = x - mean;
           mean += delta / count;
           m2 += delta * (x - mean);
         }
         break;
       }
     case Aggregate.BOOL_AND:
       v = v.convertTo(Value.BOOLEAN);
       if (value == null) {
         value = v;
       } else {
         value =
             ValueBoolean.get(value.getBoolean().booleanValue() && v.getBoolean().booleanValue());
       }
       break;
     case Aggregate.BOOL_OR:
       v = v.convertTo(Value.BOOLEAN);
       if (value == null) {
         value = v;
       } else {
         value =
             ValueBoolean.get(value.getBoolean().booleanValue() || v.getBoolean().booleanValue());
       }
       break;
     default:
       DbException.throwInternalError("type=" + aggregateType);
   }
 }
Beispiel #10
0
 /**
  * Get the aggregate result.
  *
  * @param database the database
  * @param distinct if distinct is used
  * @return the value
  */
 Value getValue(Database database, boolean distinct) {
   if (distinct) {
     count = 0;
     groupDistinct(database);
   }
   Value v = null;
   switch (aggregateType) {
     case Aggregate.SELECTIVITY:
       {
         int s = 0;
         if (count == 0) {
           s = 0;
         } else {
           m2 += distinctHashes.size();
           m2 = 100 * m2 / count;
           s = (int) m2;
           s = s <= 0 ? 1 : s > 100 ? 100 : s;
         }
         v = ValueInt.get(s);
         break;
       }
     case Aggregate.COUNT:
     case Aggregate.COUNT_ALL:
       v = ValueLong.get(count);
       break;
     case Aggregate.SUM:
     case Aggregate.MIN:
     case Aggregate.MAX:
     case Aggregate.BOOL_OR:
     case Aggregate.BOOL_AND:
       v = value;
       break;
     case Aggregate.AVG:
       if (value != null) {
         v = divide(value, count);
       }
       break;
     case Aggregate.GROUP_CONCAT:
       return null;
     case Aggregate.STDDEV_POP:
       {
         if (count < 1) {
           return ValueNull.INSTANCE;
         }
         v = ValueDouble.get(Math.sqrt(m2 / count));
         break;
       }
     case Aggregate.STDDEV_SAMP:
       {
         if (count < 2) {
           return ValueNull.INSTANCE;
         }
         v = ValueDouble.get(Math.sqrt(m2 / (count - 1)));
         break;
       }
     case Aggregate.VAR_POP:
       {
         if (count < 1) {
           return ValueNull.INSTANCE;
         }
         v = ValueDouble.get(m2 / count);
         break;
       }
     case Aggregate.VAR_SAMP:
       {
         if (count < 2) {
           return ValueNull.INSTANCE;
         }
         v = ValueDouble.get(m2 / (count - 1));
         break;
       }
     case Aggregate.HISTOGRAM:
       ValueArray[] values = new ValueArray[distinctValues.size()];
       int i = 0;
       for (Value dv : distinctValues.keys()) {
         AggregateData d = distinctValues.get(dv);
         values[i] = ValueArray.get(new Value[] {dv, ValueLong.get(d.count)});
         i++;
       }
       final CompareMode compareMode = database.getCompareMode();
       Arrays.sort(
           values,
           new Comparator<ValueArray>() {
             public int compare(ValueArray v1, ValueArray v2) {
               Value a1 = v1.getList()[0];
               Value a2 = v2.getList()[0];
               return a1.compareTo(a2, compareMode);
             }
           });
       v = ValueArray.get(values);
       break;
     default:
       DbException.throwInternalError("type=" + aggregateType);
   }
   return v == null ? ValueNull.INSTANCE : v.convertTo(dataType);
 }
Beispiel #11
0
 void merge(Database database, boolean distinct, Value v) {
   if (aggregateType == Aggregate.COUNT || aggregateType == Aggregate.COUNT_ALL) {
     count += v.getLong();
     return;
   } else if (aggregateType == Aggregate.HISTOGRAM) {
     if (distinctValues == null) {
       distinctValues = ValueHashMap.newInstance();
     }
     AggregateData a = distinctValues.get(v);
     if (a == null) {
       if (distinctValues.size() < Constants.SELECTIVITY_DISTINCT_COUNT) {
         a = new AggregateData(Aggregate.HISTOGRAM, dataType);
         distinctValues.put(v, a);
       }
     }
     if (a != null) {
       a.count++;
     }
     return;
   }
   if (v == ValueNull.INSTANCE) {
     return;
   }
   count++;
   if (distinct) {
     if (distinctValues == null) {
       distinctValues = ValueHashMap.newInstance();
     }
     distinctValues.put(v, this);
     return;
   }
   switch (aggregateType) {
     case Aggregate.COUNT:
     case Aggregate.HISTOGRAM:
       return;
     case Aggregate.SUM:
     case Aggregate.SELECTIVITY:
       if (value == null) {
         value = v.convertTo(dataType);
       } else {
         v = v.convertTo(value.getType());
         value = value.add(v);
       }
       break;
     case Aggregate.AVG:
       if (value == null) {
         value = v.convertTo(DataType.getAddProofType(dataType));
       } else {
         // AVG聚合函数merge的次数不会超过1
         DbException.throwInternalError("type=" + aggregateType);
       }
       break;
     case Aggregate.MIN:
       if (value == null || database.compare(v, value) < 0) {
         value = v;
       }
       break;
     case Aggregate.MAX:
       if (value == null || database.compare(v, value) > 0) {
         value = v;
       }
       break;
     case Aggregate.GROUP_CONCAT:
       {
         if (list == null) {
           list = New.arrayList();
         }
         list.add(v);
         break;
       }
     case Aggregate.STDDEV_POP:
     case Aggregate.STDDEV_SAMP:
     case Aggregate.VAR_POP:
     case Aggregate.VAR_SAMP:
       {
         v = v.convertTo(Value.DOUBLE);
         if (value == null) {
           value = v;
         } else {
           // 这4种聚合函数merge的次数不会超过1
           DbException.throwInternalError("type=" + aggregateType);
         }
         break;
       }
     case Aggregate.BOOL_AND:
       v = v.convertTo(Value.BOOLEAN);
       if (value == null) {
         value = v;
       } else {
         value =
             ValueBoolean.get(value.getBoolean().booleanValue() && v.getBoolean().booleanValue());
       }
       break;
     case Aggregate.BOOL_OR:
       v = v.convertTo(Value.BOOLEAN);
       if (value == null) {
         value = v;
       } else {
         value =
             ValueBoolean.get(value.getBoolean().booleanValue() || v.getBoolean().booleanValue());
       }
       break;
     default:
       DbException.throwInternalError("type=" + aggregateType);
   }
 }