コード例 #1
0
nsresult
CountHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
{
  nsCString table;
  if (mIndex->IsUnique()) {
    table.AssignLiteral("unique_index_data");
  }
  else {
    table.AssignLiteral("index_data");
  }

  NS_NAMED_LITERAL_CSTRING(lowerKeyName, "lower_key");
  NS_NAMED_LITERAL_CSTRING(upperKeyName, "upper_key");
  NS_NAMED_LITERAL_CSTRING(value, "value");

  nsCAutoString keyRangeClause;
  if (mKeyRange) {
    if (!mKeyRange->Lower().IsUnset()) {
      AppendConditionClause(value, lowerKeyName, false,
                            !mKeyRange->IsLowerOpen(), keyRangeClause);
    }
    if (!mKeyRange->Upper().IsUnset()) {
      AppendConditionClause(value, upperKeyName, true,
                            !mKeyRange->IsUpperOpen(), keyRangeClause);
    }
  }

  nsCString query = NS_LITERAL_CSTRING("SELECT count(*) FROM ") + table +
                    NS_LITERAL_CSTRING(" WHERE index_id = :id") +
                    keyRangeClause;

  nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
  NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);

  mozStorageStatementScoper scoper(stmt);

  nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("id"), mIndex->Id());
  NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);

  if (mKeyRange) {
    if (!mKeyRange->Lower().IsUnset()) {
      rv = mKeyRange->Lower().BindToStatement(stmt, lowerKeyName);
      NS_ENSURE_SUCCESS(rv, rv);
    }
    if (!mKeyRange->Upper().IsUnset()) {
      rv = mKeyRange->Upper().BindToStatement(stmt, upperKeyName);
      NS_ENSURE_SUCCESS(rv, rv);
    }
  }

  bool hasResult;
  rv = stmt->ExecuteStep(&hasResult);
  NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  NS_ENSURE_TRUE(hasResult, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);

  mCount = stmt->AsInt64(0);
  return NS_OK;
}
コード例 #2
0
nsresult
OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
{
  NS_ASSERTION(aConnection, "Passed a null connection!");

  nsCString indexTable;
  if (mIndex->IsUnique()) {
    indexTable.AssignLiteral("unique_index_data");
  }
  else {
    indexTable.AssignLiteral("index_data");
  }

  NS_NAMED_LITERAL_CSTRING(value, "index_table.value");

  nsCString keyRangeClause;
  if (mKeyRange) {
    mKeyRange->GetBindingClause(value, keyRangeClause);
  }

  nsCAutoString directionClause(" ORDER BY index_table.value ");
  switch (mDirection) {
    case nsIIDBCursor::NEXT:
    case nsIIDBCursor::NEXT_NO_DUPLICATE:
      directionClause +=
        NS_LITERAL_CSTRING("ASC, index_table.object_data_key ASC");
      break;

    case nsIIDBCursor::PREV:
      directionClause +=
        NS_LITERAL_CSTRING("DESC, index_table.object_data_key DESC");
      break;

    case nsIIDBCursor::PREV_NO_DUPLICATE:
      directionClause +=
        NS_LITERAL_CSTRING("DESC, index_table.object_data_key ASC");
      break;

    default:
      NS_NOTREACHED("Unknown direction!");
  }

  nsCString firstQuery =
    NS_LITERAL_CSTRING("SELECT index_table.value, "
                       "index_table.object_data_key, object_data.data, "
                       "object_data.file_ids FROM ") +
    indexTable +
    NS_LITERAL_CSTRING(" AS index_table INNER JOIN object_data ON "
                       "index_table.object_data_id = object_data.id "
                       "WHERE index_table.index_id = :id") +
    keyRangeClause + directionClause +
    NS_LITERAL_CSTRING(" LIMIT 1");

  nsCOMPtr<mozIStorageStatement> stmt =
    mTransaction->GetCachedStatement(firstQuery);
  NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);

  mozStorageStatementScoper scoper(stmt);

  nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("id"), mIndex->Id());
  NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);

  if (mKeyRange) {
    rv = mKeyRange->BindToStatement(stmt);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  bool hasResult;
  rv = stmt->ExecuteStep(&hasResult);
  NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);

  if (!hasResult) {
    mKey.Unset();
    return NS_OK;
  }

  rv = mKey.SetFromStatement(stmt, 0);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = mObjectKey.SetFromStatement(stmt, 1);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = IDBObjectStore::GetStructuredCloneReadInfoFromStatement(stmt, 2, 3,
    mDatabase->Manager(), mCloneReadInfo);
  NS_ENSURE_SUCCESS(rv, rv);

  // Now we need to make the query to get the next match.
  nsCAutoString queryStart =
    NS_LITERAL_CSTRING("SELECT index_table.value, "
                       "index_table.object_data_key, object_data.data, "
                       "object_data.file_ids FROM ") +
    indexTable +
    NS_LITERAL_CSTRING(" AS index_table INNER JOIN object_data ON "
                       "index_table.object_data_id = object_data.id "
                       "WHERE index_table.index_id = :id");

  NS_NAMED_LITERAL_CSTRING(rangeKey, "range_key");

  NS_NAMED_LITERAL_CSTRING(limit, " LIMIT ");

  switch (mDirection) {
    case nsIIDBCursor::NEXT:
      if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
        AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
                              queryStart);
        mRangeKey = mKeyRange->Upper();
      }
      mContinueQuery =
        queryStart +
        NS_LITERAL_CSTRING(" AND index_table.value >= :current_key AND "
                           "( index_table.value > :current_key OR "
                           "  index_table.object_data_key > :object_key ) ") +
        directionClause + limit;
      mContinueToQuery =
        queryStart +
        NS_LITERAL_CSTRING(" AND index_table.value >= :current_key") +
        directionClause + limit;
      break;

    case nsIIDBCursor::NEXT_NO_DUPLICATE:
      if (mKeyRange && !mKeyRange->Upper().IsUnset()) {
        AppendConditionClause(value, rangeKey, true, !mKeyRange->IsUpperOpen(),
                              queryStart);
        mRangeKey = mKeyRange->Upper();
      }
      mContinueQuery =
        queryStart +
        NS_LITERAL_CSTRING(" AND index_table.value > :current_key") +
        directionClause + limit;
      mContinueToQuery =
        queryStart +
        NS_LITERAL_CSTRING(" AND index_table.value >= :current_key") +
        directionClause + limit;
      break;

    case nsIIDBCursor::PREV:
      if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
        AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
                              queryStart);
        mRangeKey = mKeyRange->Lower();
      }
      mContinueQuery =
        queryStart +
        NS_LITERAL_CSTRING(" AND index_table.value <= :current_key AND "
                           "( index_table.value < :current_key OR "
                           "  index_table.object_data_key < :object_key ) ") +
        directionClause + limit;
      mContinueToQuery =
        queryStart +
        NS_LITERAL_CSTRING(" AND index_table.value <= :current_key") +
        directionClause + limit;
      break;

    case nsIIDBCursor::PREV_NO_DUPLICATE:
      if (mKeyRange && !mKeyRange->Lower().IsUnset()) {
        AppendConditionClause(value, rangeKey, false, !mKeyRange->IsLowerOpen(),
                              queryStart);
        mRangeKey = mKeyRange->Lower();
      }
      mContinueQuery =
        queryStart +
        NS_LITERAL_CSTRING(" AND index_table.value < :current_key") +
        directionClause + limit;
      mContinueToQuery =
        queryStart +
        NS_LITERAL_CSTRING(" AND index_table.value <= :current_key") +
        directionClause + limit;
      break;

    default:
      NS_NOTREACHED("Unknown direction type!");
  }

  return NS_OK;
}
コード例 #3
0
nsresult
OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
{
  NS_ASSERTION(aConnection, "Passed a null connection!");

  nsCString indexTable;
  nsCString objectTable;
  nsCString objectDataIdColumn;
  nsCString keyValueColumn;

  if (mIndex->IsAutoIncrement()) {
    objectTable.AssignLiteral("ai_object_data");
    objectDataIdColumn.AssignLiteral("ai_object_data_id");
    keyValueColumn.AssignLiteral("id");
    if (mIndex->IsUnique()) {
      indexTable.AssignLiteral("ai_unique_index_data");
    }
    else {
      indexTable.AssignLiteral("ai_index_data");
    }
  }
  else {
    objectTable.AssignLiteral("object_data");
    objectDataIdColumn.AssignLiteral("object_data_id");
    keyValueColumn.AssignLiteral("key_value");
    if (mIndex->IsUnique()) {
      indexTable.AssignLiteral("unique_index_data");
    }
    else {
      indexTable.AssignLiteral("index_data");
    }
  }

  NS_NAMED_LITERAL_CSTRING(id, "id");
  NS_NAMED_LITERAL_CSTRING(lowerKeyName, "lower_key");
  NS_NAMED_LITERAL_CSTRING(upperKeyName, "upper_key");

  nsCString value = indexTable + NS_LITERAL_CSTRING(".value");
  nsCString data = objectTable + NS_LITERAL_CSTRING(".data");
  nsCString keyValue = objectTable + NS_LITERAL_CSTRING(".") + keyValueColumn;

  nsCAutoString keyRangeClause;
  if (!mLowerKey.IsUnset()) {
    AppendConditionClause(value, lowerKeyName, false, !mLowerOpen,
                          keyRangeClause);
  }
  if (!mUpperKey.IsUnset()) {
    AppendConditionClause(value, upperKeyName, true, !mUpperOpen,
                          keyRangeClause);
  }

  nsCAutoString directionClause = NS_LITERAL_CSTRING(" ORDER BY ") + value;
  switch (mDirection) {
    case nsIIDBCursor::NEXT:
    case nsIIDBCursor::NEXT_NO_DUPLICATE:
      directionClause.AppendLiteral(" ASC");
      break;

    case nsIIDBCursor::PREV:
    case nsIIDBCursor::PREV_NO_DUPLICATE:
      directionClause.AppendLiteral(" DESC");
      break;

    default:
      NS_NOTREACHED("Unknown direction!");
  }
  directionClause += NS_LITERAL_CSTRING(", ") + keyValue +
                     NS_LITERAL_CSTRING(" ASC");

  nsCString firstQuery = NS_LITERAL_CSTRING("SELECT ") + value +
                         NS_LITERAL_CSTRING(", ") + keyValue +
                         NS_LITERAL_CSTRING(", ") + data +
                         NS_LITERAL_CSTRING(" FROM ") + objectTable +
                         NS_LITERAL_CSTRING(" INNER JOIN ") + indexTable +
                         NS_LITERAL_CSTRING(" ON ") + indexTable +
                         NS_LITERAL_CSTRING(".") + objectDataIdColumn +
                         NS_LITERAL_CSTRING(" = ") + objectTable +
                         NS_LITERAL_CSTRING(".id WHERE ") + indexTable +
                         NS_LITERAL_CSTRING(".index_id = :id") +
                         keyRangeClause + directionClause +
                         NS_LITERAL_CSTRING(" LIMIT 1");

  nsCOMPtr<mozIStorageStatement> stmt =
    mTransaction->GetCachedStatement(firstQuery);
  NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);

  mozStorageStatementScoper scoper(stmt);

  nsresult rv = stmt->BindInt64ByName(id, mIndex->Id());
  NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);

  if (!mLowerKey.IsUnset()) {
    if (mLowerKey.IsString()) {
      rv = stmt->BindStringByName(lowerKeyName, mLowerKey.StringValue());
    }
    else if (mLowerKey.IsInt()) {
      rv = stmt->BindInt64ByName(lowerKeyName, mLowerKey.IntValue());
    }
    else {
      NS_NOTREACHED("Bad key!");
    }
    NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  }

  if (!mUpperKey.IsUnset()) {
    if (mUpperKey.IsString()) {
      rv = stmt->BindStringByName(upperKeyName, mUpperKey.StringValue());
    }
    else if (mUpperKey.IsInt()) {
      rv = stmt->BindInt64ByName(upperKeyName, mUpperKey.IntValue());
    }
    else {
      NS_NOTREACHED("Bad key!");
    }
    NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  }

  PRBool hasResult;
  rv = stmt->ExecuteStep(&hasResult);
  NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);

  if (!hasResult) {
    mKey = Key::UNSETKEY;
    return NS_OK;
  }

  PRInt32 keyType;
  rv = stmt->GetTypeOfIndex(0, &keyType);
  NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);

  NS_ASSERTION(keyType == mozIStorageStatement::VALUE_TYPE_INTEGER ||
               keyType == mozIStorageStatement::VALUE_TYPE_TEXT,
               "Bad key type!");

  if (keyType == mozIStorageStatement::VALUE_TYPE_INTEGER) {
    mKey = stmt->AsInt64(0);
  }
  else if (keyType == mozIStorageStatement::VALUE_TYPE_TEXT) {
    rv = stmt->GetString(0, mKey.ToString());
    NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  }
  else {
    NS_NOTREACHED("Bad SQLite type!");
  }

  rv = stmt->GetTypeOfIndex(1, &keyType);
  NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);

  NS_ASSERTION(keyType == mozIStorageStatement::VALUE_TYPE_INTEGER ||
               keyType == mozIStorageStatement::VALUE_TYPE_TEXT,
               "Bad key type!");

  if (keyType == mozIStorageStatement::VALUE_TYPE_INTEGER) {
    mObjectKey = stmt->AsInt64(1);
  }
  else if (keyType == mozIStorageStatement::VALUE_TYPE_TEXT) {
    rv = stmt->GetString(1, mObjectKey.ToString());
    NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
  }
  else {
    NS_NOTREACHED("Bad SQLite type!");
  }

  rv = IDBObjectStore::GetStructuredCloneDataFromStatement(stmt, 2,
                                                           mCloneBuffer);
  NS_ENSURE_SUCCESS(rv, rv);

  // Now we need to make the query to get the next match.
  nsCAutoString queryStart = NS_LITERAL_CSTRING("SELECT ") + value +
                             NS_LITERAL_CSTRING(", ") + keyValue +
                             NS_LITERAL_CSTRING(", ") + data +
                             NS_LITERAL_CSTRING(" FROM ") + objectTable +
                             NS_LITERAL_CSTRING(" INNER JOIN ") + indexTable +
                             NS_LITERAL_CSTRING(" ON ") + indexTable +
                             NS_LITERAL_CSTRING(".") + objectDataIdColumn +
                             NS_LITERAL_CSTRING(" = ") + objectTable +
                             NS_LITERAL_CSTRING(".id WHERE ") + indexTable +
                             NS_LITERAL_CSTRING(".index_id = :id");

  NS_NAMED_LITERAL_CSTRING(currentKey, "current_key");
  NS_NAMED_LITERAL_CSTRING(rangeKey, "range_key");
  NS_NAMED_LITERAL_CSTRING(objectKey, "object_key");

  switch (mDirection) {
    case nsIIDBCursor::NEXT:
      if (!mUpperKey.IsUnset()) {
        AppendConditionClause(value, rangeKey, true, !mUpperOpen, queryStart);
        mRangeKey = mUpperKey;
      }
      mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND ( ( ") +
                       value + NS_LITERAL_CSTRING(" = :") + currentKey +
                       NS_LITERAL_CSTRING(" AND ") + keyValue +
                       NS_LITERAL_CSTRING(" > :") + objectKey +
                       NS_LITERAL_CSTRING(" ) OR ( ") + value +
                       NS_LITERAL_CSTRING(" > :") + currentKey +
                       NS_LITERAL_CSTRING(" ) )") + directionClause +
                       NS_LITERAL_CSTRING(" LIMIT 1");
      mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND ") + value +
                         NS_LITERAL_CSTRING(" >= :") +
                         currentKey + directionClause +
                         NS_LITERAL_CSTRING(" LIMIT 1");
      break;

    case nsIIDBCursor::NEXT_NO_DUPLICATE:
      if (!mUpperKey.IsUnset()) {
        AppendConditionClause(value, rangeKey, true, !mUpperOpen, queryStart);
        mRangeKey = mUpperKey;
      }
      mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND ") + value +
                       NS_LITERAL_CSTRING(" > :") + currentKey +
                       directionClause + NS_LITERAL_CSTRING(" LIMIT 1");
      mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND ") + value +
                         NS_LITERAL_CSTRING(" >= :") + currentKey +
                         directionClause + NS_LITERAL_CSTRING(" LIMIT 1");
      break;

    case nsIIDBCursor::PREV:
      if (!mLowerKey.IsUnset()) {
        AppendConditionClause(value, rangeKey, false, !mLowerOpen, queryStart);
        mRangeKey = mLowerKey;
      }
      mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND ( ( ") +
                       value + NS_LITERAL_CSTRING(" = :") + currentKey +
                       NS_LITERAL_CSTRING(" AND ") + keyValue +
                       NS_LITERAL_CSTRING(" < :") + objectKey +
                       NS_LITERAL_CSTRING(" ) OR ( ") + value +
                       NS_LITERAL_CSTRING(" < :") + currentKey +
                       NS_LITERAL_CSTRING(" ) )") + directionClause +
                       NS_LITERAL_CSTRING(" LIMIT 1");
      mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND ") + value +
                         NS_LITERAL_CSTRING(" <= :") +
                         currentKey + directionClause +
                         NS_LITERAL_CSTRING(" LIMIT 1");
      break;

    case nsIIDBCursor::PREV_NO_DUPLICATE:
      if (!mLowerKey.IsUnset()) {
        AppendConditionClause(value, rangeKey, false, !mLowerOpen, queryStart);
        mRangeKey = mLowerKey;
      }
      mContinueQuery = queryStart + NS_LITERAL_CSTRING(" AND ") + value +
                       NS_LITERAL_CSTRING(" < :") + currentKey +
                       directionClause + NS_LITERAL_CSTRING(" LIMIT 1");
      mContinueToQuery = queryStart + NS_LITERAL_CSTRING(" AND ") + value +
                         NS_LITERAL_CSTRING(" <= :") + currentKey +
                         directionClause + NS_LITERAL_CSTRING(" LIMIT 1");
      break;

    default:
      NS_NOTREACHED("Unknown direction type!");
  }

  return NS_OK;
}