Пример #1
0
 private boolean sameResultAsLast(Session s, Value[] params, Value[] lastParams, long lastEval) {
   if (!cacheableChecked) {
     long max = getMaxDataModificationId();
     noCache = max == Long.MAX_VALUE;
     cacheableChecked = true;
   }
   if (noCache) {
     return false;
   }
   Database db = s.getDatabase();
   for (int i = 0; i < params.length; i++) {
     Value a = lastParams[i], b = params[i];
     if (a.getType() != b.getType() || !db.areEqual(a, b)) {
       return false;
     }
   }
   if (!isEverything(ExpressionVisitor.DETERMINISTIC_VISITOR)
       || !isEverything(ExpressionVisitor.INDEPENDENT_VISITOR)) {
     return false;
   }
   if (db.getModificationDataId() > lastEval && getMaxDataModificationId() > lastEval) {
     return false;
   }
   return true;
 }
Пример #2
0
 /**
  * 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");
 }
Пример #3
0
 @Override
 public Value getValue(Session session) {
   Value l = left.getValue(session);
   if (l == ValueNull.INSTANCE) {
     return l;
   }
   boolean result = false;
   boolean hasNull = false;
   for (Expression e : valueList) {
     Value r = e.getValue(session);
     if (r == ValueNull.INSTANCE) {
       hasNull = true;
     } else {
       r = r.convertTo(l.getType());
       result = Comparison.compareNotNull(database, l, r, Comparison.EQUAL);
       if (result) {
         break;
       }
     }
   }
   if (!result && hasNull) {
     return ValueNull.INSTANCE;
   }
   return ValueBoolean.get(result);
 }
Пример #4
0
 @Override
 public Cursor find(Session session, SearchRow first, SearchRow last) {
   long min, max;
   if (first == null || mainIndexColumn < 0) {
     min = Long.MIN_VALUE;
   } else {
     Value v = first.getValue(mainIndexColumn);
     if (v == null) {
       min = 0;
     } else {
       min = v.getLong();
     }
   }
   if (last == null || mainIndexColumn < 0) {
     max = Long.MAX_VALUE;
   } else {
     Value v = last.getValue(mainIndexColumn);
     if (v == null) {
       max = Long.MAX_VALUE;
     } else {
       max = v.getLong();
     }
   }
   TransactionMap<Value, Value> map = getMap(session);
   return new MVStoreCursor(session, map.keyIterator(ValueLong.get(min)), max);
 }
Пример #5
0
 /**
  * Convert an object to the default Java object for the given SQL type. For example, LOB objects
  * are converted to java.sql.Clob / java.sql.Blob.
  *
  * @param v the value
  * @return the object
  */
 Object convertToDefaultObject(Value v) {
   Object o;
   switch (v.getType()) {
     case Value.CLOB:
       {
         if (SysProperties.RETURN_LOB_OBJECTS) {
           int id = getNextId(TraceObject.CLOB);
           o = new JdbcClob(this, v, id);
         } else {
           o = v.getObject();
         }
         break;
       }
     case Value.BLOB:
       {
         if (SysProperties.RETURN_LOB_OBJECTS) {
           int id = getNextId(TraceObject.BLOB);
           o = new JdbcBlob(this, v, id);
         } else {
           o = v.getObject();
         }
         break;
       }
     case Value.JAVA_OBJECT:
       o = Utils.deserialize(v.getBytesNoCopy());
       break;
     default:
       o = v.getObject();
   }
   return o;
 }
Пример #6
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);
 }
Пример #7
0
 /**
  * Get the sample size, if set.
  *
  * @param session the session
  * @return the sample size
  */
 int getSampleSizeValue(Session session) {
   if (sampleSizeExpr == null) {
     return 0;
   }
   Value v = sampleSizeExpr.optimize(session).getValue(session);
   if (v == ValueNull.INSTANCE) {
     return 0;
   }
   return v.getInt();
 }
Пример #8
0
 private boolean isHavingNullOrFalse(Value[] row) {
   if (havingIndex >= 0) {
     Value v = row[havingIndex];
     if (v == ValueNull.INSTANCE) {
       return true;
     }
     if (!Boolean.TRUE.equals(v.getBoolean())) {
       return true;
     }
   }
   return false;
 }
Пример #9
0
 private void writeValue(Value v) throws IOException {
   if (v.getType() == Value.CLOB || v.getType() == Value.BLOB) {
     if (v instanceof ValueLobDb) {
       ValueLobDb lob = (ValueLobDb) v;
       if (lob.isStored()) {
         long id = lob.getLobId();
         lobs.put(id, new CachedInputStream(null));
       }
     }
   }
   transfer.writeValue(v);
 }
Пример #10
0
 /**
  * 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();
 }
Пример #11
0
 @Override
 public Cursor findFirstOrLast(Session session, boolean first) {
   TransactionMap<Value, Value> map = getMap(session);
   Value v = first ? map.firstKey() : map.lastKey();
   if (v == null) {
     return new MVStoreCursor(session, Collections.<Value>emptyList().iterator(), 0);
   }
   long key = v.getLong();
   MVStoreCursor cursor =
       new MVStoreCursor(session, Arrays.asList((Value) ValueLong.get(key)).iterator(), key);
   cursor.next();
   return cursor;
 }
Пример #12
0
 @Override
 public String toString() {
   StatementBuilder buff = new StatementBuilder("( /* key:");
   buff.append(getKey());
   if (version != 0) {
     buff.append(" v:" + version);
   }
   buff.append(" */ ");
   for (Value v : data) {
     buff.appendExceptFirst(", ");
     buff.append(v == null ? "null" : v.getTraceSQL());
   }
   return buff.append(')').toString();
 }
Пример #13
0
 @Override
 public int getMemory() {
   if (memory == 0) {
     int len = data.length;
     memory = Constants.MEMORY_OBJECT + len * Constants.MEMORY_POINTER;
     for (int i = 0; i < len; i++) {
       Value v = data[i];
       if (v != null) {
         memory += v.getMemory();
       }
     }
   }
   return memory;
 }
Пример #14
0
 private void endTransaction() {
   if (removeLobMap != null && removeLobMap.size() > 0) {
     if (database.getMvStore() == null) {
       // need to flush the transaction log, because we can't unlink
       // lobs if the commit record is not written
       database.flush();
     }
     for (Value v : removeLobMap.values()) {
       v.remove();
     }
     removeLobMap = null;
   }
   unlockAll();
 }
Пример #15
0
 /**
  * Returns the length.
  *
  * @return the length
  */
 public long length() throws SQLException {
   try {
     debugCodeCall("length");
     checkClosed();
     if (value.getType() == Value.CLOB) {
       long precision = value.getPrecision();
       if (precision > 0) {
         return precision;
       }
     }
     return IOUtils.copyAndCloseInput(value.getReader(), null, Long.MAX_VALUE);
   } catch (Exception e) {
     throw logAndConvert(e);
   }
 }
Пример #16
0
 public MVPrimaryIndex(
     Database db, MVTable table, int id, IndexColumn[] columns, IndexType indexType) {
   this.mvTable = table;
   initBaseIndex(table, id, table.getName() + "_DATA", columns, indexType);
   int[] sortTypes = new int[columns.length];
   for (int i = 0; i < columns.length; i++) {
     sortTypes[i] = SortOrder.ASCENDING;
   }
   ValueDataType keyType = new ValueDataType(null, null, null);
   ValueDataType valueType = new ValueDataType(db.getCompareMode(), db, sortTypes);
   mapName = "table." + getId();
   dataMap = mvTable.getTransaction(null).openMap(mapName, keyType, valueType);
   Value k = dataMap.lastKey();
   lastKey = k == null ? 0 : k.getLong();
 }
Пример #17
0
 /**
  * Returns a substring.
  *
  * @param pos the position (the first character is at position 1)
  * @param length the number of characters
  * @return the string
  */
 public String getSubString(long pos, int length) throws SQLException {
   try {
     if (isDebugEnabled()) {
       debugCode("getSubString(" + pos + ", " + length + ");");
     }
     checkClosed();
     if (pos < 1) {
       throw DbException.getInvalidValueException("pos", pos);
     }
     if (length < 0) {
       throw DbException.getInvalidValueException("length", length);
     }
     StringWriter writer = new StringWriter(Math.min(Constants.IO_BUFFER_SIZE, length));
     Reader reader = value.getReader();
     try {
       IOUtils.skipFully(reader, pos - 1);
       IOUtils.copyAndCloseInput(reader, writer, length);
     } finally {
       reader.close();
     }
     return writer.toString();
   } catch (Exception e) {
     throw logAndConvert(e);
   }
 }
Пример #18
0
 private void testDouble(boolean useFloat) {
   double[] d = {Double.NEGATIVE_INFINITY, -1, 0, 1, Double.POSITIVE_INFINITY, Double.NaN};
   Value[] values = new Value[d.length];
   for (int i = 0; i < d.length; i++) {
     Value v = useFloat ? (Value) ValueFloat.get((float) d[i]) : (Value) ValueDouble.get(d[i]);
     values[i] = v;
     assertTrue(values[i].compareTypeSafe(values[i], null) == 0);
     assertTrue(v.equals(v));
     assertEquals(i < 2 ? -1 : i > 2 ? 1 : 0, v.getSignum());
   }
   for (int i = 0; i < d.length - 1; i++) {
     assertTrue(values[i].compareTypeSafe(values[i + 1], null) < 0);
     assertTrue(values[i + 1].compareTypeSafe(values[i], null) > 0);
     assertTrue(!values[i].equals(values[i + 1]));
   }
 }
Пример #19
0
 /**
  * Convert the timestamp to the specified time zone.
  *
  * @param value the timestamp (might be ValueNull)
  * @param calendar the calendar
  * @return the timestamp using the correct time zone
  */
 public static Timestamp convertTimestamp(Value value, Calendar calendar) {
   if (value == ValueNull.INSTANCE) {
     return null;
   }
   ValueTimestamp ts = (ValueTimestamp) value.convertTo(Value.TIMESTAMP);
   Calendar cal = (Calendar) calendar.clone();
   cal.clear();
   cal.setLenient(true);
   long dateValue = ts.getDateValue();
   long nanos = ts.getTimeNanos();
   long millis = nanos / 1000000;
   nanos -= millis * 1000000;
   long s = millis / 1000;
   millis -= s * 1000;
   long m = s / 60;
   s -= m * 60;
   long h = m / 60;
   m -= h * 60;
   setCalendarFields(
       cal,
       yearFromDateValue(dateValue),
       monthFromDateValue(dateValue),
       dayFromDateValue(dateValue),
       (int) h,
       (int) m,
       (int) s,
       (int) millis);
   long ms = cal.getTimeInMillis();
   Timestamp x = new Timestamp(ms);
   x.setNanos((int) (nanos + millis * 1000000));
   return x;
 }
Пример #20
0
 /**
  * Set the value of the given variable for this session.
  *
  * @param name the name of the variable (may not be null)
  * @param value the new value (may not be null)
  */
 public void setVariable(String name, Value value) {
   initVariables();
   modificationId++;
   Value old;
   if (value == ValueNull.INSTANCE) {
     old = variables.remove(name);
   } else {
     // link LOB values, to make sure we have our own object
     value = value.copy(database, LobStorageFrontend.TABLE_ID_SESSION_VARIABLE);
     old = variables.put(name, value);
   }
   if (old != null) {
     // remove the old value (in case it is a lob)
     old.remove();
   }
 }
Пример #21
0
 public int getMemory() {
   if (memory != MEMORY_CALCULATE) {
     return memory;
   }
   int m = Constants.MEMORY_ROW;
   if (data != null) {
     int len = data.length;
     m += Constants.MEMORY_OBJECT + len * Constants.MEMORY_POINTER;
     for (int i = 0; i < len; i++) {
       Value v = data[i];
       if (v != null) {
         m += v.getMemory();
       }
     }
   }
   return m;
 }
Пример #22
0
 /**
  * A record is added to a table, or removed from a table.
  *
  * @param session the session
  * @param tableId the table id
  * @param row the row to add
  * @param add true if the row is added, false if it is removed
  */
 void logAddOrRemoveRow(Session session, int tableId, Row row, boolean add) {
   if (trace.isDebugEnabled()) {
     trace.debug(
         "log "
             + (add ? "+" : "-")
             + " s: "
             + session.getId()
             + " table: "
             + tableId
             + " row: "
             + row);
   }
   session.addLogPos(logSectionId, logPos);
   logPos++;
   Data data = dataBuffer;
   data.reset();
   int columns = row.getColumnCount();
   data.writeVarInt(columns);
   data.checkCapacity(row.getByteCount(data));
   if (session.isRedoLogBinaryEnabled()) {
     for (int i = 0; i < columns; i++) {
       data.writeValue(row.getValue(i));
     }
   } else {
     for (int i = 0; i < columns; i++) {
       Value v = row.getValue(i);
       if (v.getType() == Value.BYTES) {
         data.writeValue(ValueNull.INSTANCE);
       } else {
         data.writeValue(v);
       }
     }
   }
   Data buffer = getBuffer();
   buffer.writeByte((byte) (add ? ADD : REMOVE));
   buffer.writeVarInt(session.getId());
   buffer.writeVarInt(tableId);
   buffer.writeVarLong(row.getKey());
   if (add) {
     buffer.writeVarInt(data.length());
     buffer.checkCapacity(data.length());
     buffer.write(data.getBytes(), 0, data.length());
   }
   write(buffer);
 }
Пример #23
0
 /**
  * Get the value for this key. This method returns null if the key was not found.
  *
  * @param key the key
  * @return the value for the given key
  */
 public V get(Value key) {
   int index = getIndex(key);
   int plus = 1;
   do {
     Value k = keys[index];
     if (k == null) {
       // found an empty record
       return null;
     } else if (k == ValueNull.DELETED) {
       // found a deleted record
     } else if (k.equals(key)) {
       // found it
       return values[index];
     }
     index = (index + plus++) & mask;
   } while (plus <= len);
   return null;
 }
Пример #24
0
 /**
  * Returns the reader.
  *
  * @return the reader
  */
 public Reader getCharacterStream() throws SQLException {
   try {
     debugCodeCall("getCharacterStream");
     checkClosed();
     return value.getReader();
   } catch (Exception e) {
     throw logAndConvert(e);
   }
 }
Пример #25
0
 @Override
 public void addTemporaryLob(Value v) {
   if (v.getType() != Value.CLOB && v.getType() != Value.BLOB) {
     return;
   }
   if (v.getTableId() == LobStorageFrontend.TABLE_RESULT
       || v.getTableId() == LobStorageFrontend.TABLE_TEMP) {
     if (temporaryResultLobs == null) {
       temporaryResultLobs = new LinkedList<TimeoutValue>();
     }
     temporaryResultLobs.add(new TimeoutValue(v));
   } else {
     if (temporaryLobs == null) {
       temporaryLobs = new ArrayList<Value>();
     }
     temporaryLobs.add(v);
   }
 }
Пример #26
0
  @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());
  }
Пример #27
0
 /**
  * Returns the input stream.
  *
  * @return the input stream
  */
 public InputStream getAsciiStream() throws SQLException {
   try {
     debugCodeCall("getAsciiStream");
     checkClosed();
     String s = value.getString();
     return IOUtils.getInputStreamFromString(s);
   } catch (Exception e) {
     throw logAndConvert(e);
   }
 }
Пример #28
0
 @Override
 public void remove(Session session, Row row) {
   if (mvTable.getContainsLargeObject()) {
     for (int i = 0, len = row.getColumnCount(); i < len; i++) {
       Value v = row.getValue(i);
       if (v.isLinked()) {
         session.unlinkAtCommit(v);
       }
     }
   }
   TransactionMap<Value, Value> map = getMap(session);
   try {
     Value old = map.remove(ValueLong.get(row.getKey()));
     if (old == null) {
       throw DbException.get(
           ErrorCode.ROW_NOT_FOUND_WHEN_DELETING_1, getSQL() + ": " + row.getKey());
     }
   } catch (IllegalStateException e) {
     throw DbException.get(ErrorCode.CONCURRENT_UPDATE_1, table.getName());
   }
 }
Пример #29
0
 /**
  * Get a writer to update the Clob. This is only supported for new, empty Clob objects that were
  * created with Connection.createClob() or createNClob(). The Clob is created in a separate
  * thread, and the object is only updated when Writer.close() is called. The position must be 1,
  * meaning the whole Clob data is set.
  *
  * @param pos where to start writing (the first character is at position 1)
  * @return a writer
  */
 public Writer setCharacterStream(long pos) throws SQLException {
   try {
     if (isDebugEnabled()) {
       debugCodeCall("setCharacterStream(" + pos + ");");
     }
     checkClosed();
     if (pos != 1) {
       throw DbException.getInvalidValueException("pos", pos);
     }
     if (value.getPrecision() != 0) {
       throw DbException.getInvalidValueException("length", value.getPrecision());
     }
     final JdbcConnection c = conn;
     // PipedReader / PipedWriter are a lot slower
     // than PipedInputStream / PipedOutputStream
     // (Sun/Oracle Java 1.6.0_20)
     final PipedInputStream in = new PipedInputStream();
     final Task task =
         new Task() {
           public void call() {
             value = c.createClob(IOUtils.getReader(in), -1);
           }
         };
     PipedOutputStream out =
         new PipedOutputStream(in) {
           public void close() throws IOException {
             super.close();
             try {
               task.get();
             } catch (Exception e) {
               throw DbException.convertToIOException(e);
             }
           }
         };
     task.execute();
     return IOUtils.getBufferedWriter(out);
   } catch (Exception e) {
     throw logAndConvert(e);
   }
 }
Пример #30
0
 /**
  * Create a {@link SortOrder} object given the list of {@link SelectOrderBy} objects. The
  * expression list is extended if necessary.
  *
  * @param orderList a list of {@link SelectOrderBy} elements
  * @param expressionCount the number of columns in the query
  * @return the {@link SortOrder} object
  */
 public SortOrder prepareOrder(ArrayList<SelectOrderBy> orderList, int expressionCount) {
   int size = orderList.size();
   int[] index = new int[size];
   int[] sortType = new int[size];
   for (int i = 0; i < size; i++) {
     SelectOrderBy o = orderList.get(i);
     int idx;
     boolean reverse = false;
     Expression expr = o.columnIndexExpr;
     Value v = expr.getValue(null);
     if (v == ValueNull.INSTANCE) {
       // parameter not yet set - order by first column
       idx = 0;
     } else {
       idx = v.getInt();
       if (idx < 0) {
         reverse = true;
         idx = -idx;
       }
       idx -= 1;
       if (idx < 0 || idx >= expressionCount) {
         throw DbException.get(ErrorCode.ORDER_BY_NOT_IN_RESULT, "" + (idx + 1));
       }
     }
     index[i] = idx;
     boolean desc = o.descending;
     if (reverse) {
       desc = !desc;
     }
     int type = desc ? SortOrder.DESCENDING : SortOrder.ASCENDING;
     if (o.nullsFirst) {
       type += SortOrder.NULLS_FIRST;
     } else if (o.nullsLast) {
       type += SortOrder.NULLS_LAST;
     }
     sortType[i] = type;
   }
   return new SortOrder(session.getDatabase(), index, sortType, orderList);
 }