зеркало из https://github.com/mozilla/pjs.git
Bug 618135 - 'IndexedDB: Implement update() on index cursors (not on index key cursors)'. r-sicking, a=blocking.
This commit is contained in:
Родитель
dfd8298239
Коммит
ea75742e0c
|
@ -145,7 +145,8 @@ AsyncConnectionHelper::Run()
|
||||||
mRequest->SetDone();
|
mRequest->SetDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
SetCurrentTransaction(mTransaction);
|
IDBTransaction* oldTransaction = gCurrentTransaction;
|
||||||
|
gCurrentTransaction = mTransaction;
|
||||||
|
|
||||||
// Call OnError if the database had an error or if the OnSuccess handler
|
// Call OnError if the database had an error or if the OnSuccess handler
|
||||||
// has an error.
|
// has an error.
|
||||||
|
@ -154,9 +155,8 @@ AsyncConnectionHelper::Run()
|
||||||
OnError(mRequest, mResultCode);
|
OnError(mRequest, mResultCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_ASSERTION(GetCurrentTransaction() == mTransaction,
|
NS_ASSERTION(gCurrentTransaction == mTransaction, "Should be unchanged!");
|
||||||
"Should be unchanged!");
|
gCurrentTransaction = oldTransaction;
|
||||||
SetCurrentTransaction(nsnull);
|
|
||||||
|
|
||||||
if (mDispatched && mTransaction) {
|
if (mDispatched && mTransaction) {
|
||||||
mTransaction->OnRequestFinished();
|
mTransaction->OnRequestFinished();
|
||||||
|
@ -319,20 +319,6 @@ AsyncConnectionHelper::GetCurrentTransaction()
|
||||||
return gCurrentTransaction;
|
return gCurrentTransaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
|
||||||
void
|
|
||||||
AsyncConnectionHelper::SetCurrentTransaction(IDBTransaction* aTransaction)
|
|
||||||
{
|
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
|
||||||
|
|
||||||
if (aTransaction) {
|
|
||||||
NS_ASSERTION(!gCurrentTransaction, "Overwriting current transaction!");
|
|
||||||
}
|
|
||||||
|
|
||||||
gCurrentTransaction = aTransaction;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
AsyncConnectionHelper::Init()
|
AsyncConnectionHelper::Init()
|
||||||
{
|
{
|
||||||
|
|
|
@ -87,7 +87,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
static IDBTransaction* GetCurrentTransaction();
|
static IDBTransaction* GetCurrentTransaction();
|
||||||
static void SetCurrentTransaction(IDBTransaction* aTransaction);
|
|
||||||
|
|
||||||
nsISupports* GetSource()
|
nsISupports* GetSource()
|
||||||
{
|
{
|
||||||
|
|
|
@ -63,57 +63,6 @@ USING_INDEXEDDB_NAMESPACE
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
class UpdateHelper : public AsyncConnectionHelper
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
UpdateHelper(IDBTransaction* aTransaction,
|
|
||||||
IDBRequest* aRequest,
|
|
||||||
PRInt64 aObjectStoreID,
|
|
||||||
const nsAString& aValue,
|
|
||||||
const Key& aKey,
|
|
||||||
bool aAutoIncrement,
|
|
||||||
nsTArray<IndexUpdateInfo>& aIndexUpdateInfo)
|
|
||||||
: AsyncConnectionHelper(aTransaction, aRequest), mOSID(aObjectStoreID),
|
|
||||||
mValue(aValue), mKey(aKey), mAutoIncrement(aAutoIncrement)
|
|
||||||
{
|
|
||||||
mIndexUpdateInfo.SwapElements(aIndexUpdateInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult DoDatabaseWork(mozIStorageConnection* aConnection);
|
|
||||||
nsresult GetSuccessResult(nsIWritableVariant* aResult);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// In-params.
|
|
||||||
const PRInt64 mOSID;
|
|
||||||
const nsString mValue;
|
|
||||||
const Key mKey;
|
|
||||||
const bool mAutoIncrement;
|
|
||||||
nsTArray<IndexUpdateInfo> mIndexUpdateInfo;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DeleteHelper : public AsyncConnectionHelper
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DeleteHelper(IDBTransaction* aTransaction,
|
|
||||||
IDBRequest* aRequest,
|
|
||||||
PRInt64 aObjectStoreID,
|
|
||||||
const Key& aKey,
|
|
||||||
bool aAutoIncrement)
|
|
||||||
: AsyncConnectionHelper(aTransaction, aRequest), mOSID(aObjectStoreID),
|
|
||||||
mKey(aKey), mAutoIncrement(aAutoIncrement)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
nsresult DoDatabaseWork(mozIStorageConnection* aConnection);
|
|
||||||
nsresult GetSuccessResult(nsIWritableVariant* aResult);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// In-params.
|
|
||||||
const PRInt64 mOSID;
|
|
||||||
const nsString mValue;
|
|
||||||
const Key mKey;
|
|
||||||
const bool mAutoIncrement;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline
|
inline
|
||||||
already_AddRefed<IDBRequest>
|
already_AddRefed<IDBRequest>
|
||||||
GenerateRequest(IDBCursor* aCursor)
|
GenerateRequest(IDBCursor* aCursor)
|
||||||
|
@ -247,7 +196,7 @@ IDBCursor::Create(IDBRequest* aRequest,
|
||||||
NS_ASSERTION(cursor, "This shouldn't fail!");
|
NS_ASSERTION(cursor, "This shouldn't fail!");
|
||||||
|
|
||||||
cursor->mIndex = aIndex;
|
cursor->mIndex = aIndex;
|
||||||
cursor->mType = INDEX;
|
cursor->mType = INDEXKEY;
|
||||||
cursor->mKey = aKey,
|
cursor->mKey = aKey,
|
||||||
cursor->mObjectKey = aObjectKey;
|
cursor->mObjectKey = aObjectKey;
|
||||||
|
|
||||||
|
@ -452,7 +401,7 @@ IDBCursor::GetValue(JSContext* aCx,
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
if (mType == INDEX) {
|
if (mType == INDEXKEY) {
|
||||||
NS_ASSERTION(!mObjectKey.IsUnset(), "Bad key!");
|
NS_ASSERTION(!mObjectKey.IsUnset(), "Bad key!");
|
||||||
|
|
||||||
rv = IDBObjectStore::GetJSValFromKey(mObjectKey, aCx, aValue);
|
rv = IDBObjectStore::GetJSValFromKey(mObjectKey, aCx, aValue);
|
||||||
|
@ -535,7 +484,7 @@ IDBCursor::Continue(const jsval &aKey,
|
||||||
helper = new ContinueObjectStoreHelper(this);
|
helper = new ContinueObjectStoreHelper(this);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INDEX:
|
case INDEXKEY:
|
||||||
helper = new ContinueIndexHelper(this);
|
helper = new ContinueIndexHelper(this);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -561,239 +510,75 @@ IDBCursor::Update(const jsval& aValue,
|
||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
if (!mTransaction->TransactionIsOpen() || !mTransaction->IsWriteAllowed()) {
|
if (mType == INDEXKEY) {
|
||||||
return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
|
return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mType != OBJECTSTORE) {
|
NS_ASSERTION(mObjectStore, "This cannot be null!");
|
||||||
NS_WARNING("Update for non-objectStore cursors is not implemented!");
|
NS_ASSERTION(!mKey.IsUnset() , "Bad key!");
|
||||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
NS_ASSERTION(mType != INDEXOBJECT || !mObjectKey.IsUnset(), "Bad key!");
|
||||||
|
|
||||||
|
nsresult rv;
|
||||||
|
|
||||||
|
JSAutoRequest ar(aCx);
|
||||||
|
|
||||||
|
const Key& objectKey = (mType == OBJECTSTORE) ? mKey : mObjectKey;
|
||||||
|
|
||||||
|
if (!mObjectStore->KeyPath().IsEmpty()) {
|
||||||
|
// This has to be an object.
|
||||||
|
if (JSVAL_IS_PRIMITIVE(aValue)) {
|
||||||
|
return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the object given has the correct keyPath value set on it.
|
||||||
|
const nsString& keyPath = mObjectStore->KeyPath();
|
||||||
|
|
||||||
|
jsval prop;
|
||||||
|
JSBool ok = JS_GetUCProperty(aCx, JSVAL_TO_OBJECT(aValue),
|
||||||
|
reinterpret_cast<const jschar*>(keyPath.get()),
|
||||||
|
keyPath.Length(), &prop);
|
||||||
|
NS_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||||
|
|
||||||
|
Key key;
|
||||||
|
rv = IDBObjectStore::GetKeyFromJSVal(prop, key);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key != objectKey) {
|
||||||
|
return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mObjectStore->Put(aValue, JSVAL_VOID, aCx, 0, _retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
jsval keyVal;
|
||||||
|
rv = IDBObjectStore::GetJSValFromKey(objectKey, aCx, &keyVal);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
return mObjectStore->Put(aValue, keyVal, aCx, 1, _retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
IDBCursor::Delete(JSContext* aCx,
|
||||||
|
nsIIDBRequest** _retval)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
|
||||||
|
if (mType == INDEXKEY) {
|
||||||
|
return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_ASSERTION(mObjectStore, "This cannot be null!");
|
NS_ASSERTION(mObjectStore, "This cannot be null!");
|
||||||
NS_ASSERTION(!mKey.IsUnset() , "Bad key!");
|
NS_ASSERTION(!mKey.IsUnset() , "Bad key!");
|
||||||
|
|
||||||
JSAutoRequest ar(aCx);
|
const Key& objectKey = (mType == OBJECTSTORE) ? mKey : mObjectKey;
|
||||||
|
|
||||||
js::AutoValueRooter clone(aCx, aValue);
|
jsval key;
|
||||||
|
nsresult rv = IDBObjectStore::GetJSValFromKey(objectKey, aCx, &key);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
nsresult rv;
|
return mObjectStore->Delete(key, aCx, _retval);
|
||||||
if (!mObjectStore->KeyPath().IsEmpty()) {
|
|
||||||
// Make sure the object given has the correct keyPath value set on it or
|
|
||||||
// we will add it.
|
|
||||||
const nsString& keyPath = mObjectStore->KeyPath();
|
|
||||||
const jschar* keyPathChars = reinterpret_cast<const jschar*>(keyPath.get());
|
|
||||||
const size_t keyPathLen = keyPath.Length();
|
|
||||||
|
|
||||||
js::AutoValueRooter prop(aCx);
|
|
||||||
JSBool ok = JS_GetUCProperty(aCx, JSVAL_TO_OBJECT(clone.jsval_value()),
|
|
||||||
keyPathChars, keyPathLen, prop.jsval_addr());
|
|
||||||
NS_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
|
||||||
|
|
||||||
if (JSVAL_IS_VOID(prop.jsval_value())) {
|
|
||||||
rv = IDBObjectStore::GetJSValFromKey(mKey, aCx, prop.jsval_addr());
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
ok = JS_StructuredClone(aCx, clone.jsval_value(), clone.jsval_addr());
|
|
||||||
NS_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_SERIAL_ERR);
|
|
||||||
|
|
||||||
ok = JS_DefineUCProperty(aCx, JSVAL_TO_OBJECT(clone.jsval_value()),
|
|
||||||
keyPathChars, keyPathLen, prop.jsval_value(), nsnull,
|
|
||||||
nsnull, JSPROP_ENUMERATE);
|
|
||||||
NS_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Key newKey;
|
|
||||||
rv = IDBObjectStore::GetKeyFromJSVal(prop.jsval_value(), newKey);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
if (newKey.IsUnset() || newKey != mKey) {
|
|
||||||
return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectStoreInfo* info;
|
|
||||||
if (!ObjectStoreInfo::Get(mTransaction->Database()->Id(),
|
|
||||||
mObjectStore->Name(), &info)) {
|
|
||||||
NS_ERROR("This should never fail!");
|
|
||||||
}
|
|
||||||
|
|
||||||
nsTArray<IndexUpdateInfo> indexUpdateInfo;
|
|
||||||
rv = IDBObjectStore::GetIndexUpdateInfo(info, aCx, clone.jsval_value(),
|
|
||||||
indexUpdateInfo);
|
|
||||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIJSON> json(new nsJSON());
|
|
||||||
|
|
||||||
nsString jsonValue;
|
|
||||||
rv = json->EncodeFromJSVal(clone.jsval_addr(), aCx, jsonValue);
|
|
||||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_SERIAL_ERR);
|
|
||||||
|
|
||||||
nsRefPtr<IDBRequest> request = GenerateRequest(this);
|
|
||||||
NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
|
||||||
|
|
||||||
nsRefPtr<UpdateHelper> helper =
|
|
||||||
new UpdateHelper(mTransaction, request, mObjectStore->Id(), jsonValue, mKey,
|
|
||||||
mObjectStore->IsAutoIncrement(), indexUpdateInfo);
|
|
||||||
|
|
||||||
rv = helper->DispatchToTransactionPool();
|
|
||||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
|
||||||
|
|
||||||
request.forget(_retval);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
IDBCursor::Delete(nsIIDBRequest** _retval)
|
|
||||||
{
|
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
|
||||||
|
|
||||||
if (!mTransaction->TransactionIsOpen() || !mTransaction->IsWriteAllowed()) {
|
|
||||||
return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mType != OBJECTSTORE) {
|
|
||||||
NS_WARNING("Delete for non-objectStore cursors is not implemented!");
|
|
||||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_ASSERTION(mObjectStore, "This cannot be null!");
|
|
||||||
NS_ASSERTION(!mKey.IsUnset(), "Bad key!");
|
|
||||||
|
|
||||||
nsRefPtr<IDBRequest> request = GenerateRequest(this);
|
|
||||||
NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
|
||||||
|
|
||||||
nsRefPtr<DeleteHelper> helper =
|
|
||||||
new DeleteHelper(mTransaction, request, mObjectStore->Id(), mKey,
|
|
||||||
mObjectStore->IsAutoIncrement());
|
|
||||||
|
|
||||||
nsresult rv = helper->DispatchToTransactionPool();
|
|
||||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
|
||||||
|
|
||||||
request.forget(_retval);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
UpdateHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
|
||||||
{
|
|
||||||
NS_PRECONDITION(aConnection, "Passed a null connection!");
|
|
||||||
|
|
||||||
nsresult rv;
|
|
||||||
NS_ASSERTION(!mKey.IsUnset(), "Badness!");
|
|
||||||
|
|
||||||
nsCOMPtr<mozIStorageStatement> stmt =
|
|
||||||
mTransaction->AddStatement(false, true, mAutoIncrement);
|
|
||||||
NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
|
||||||
|
|
||||||
mozStorageStatementScoper scoper(stmt);
|
|
||||||
|
|
||||||
NS_NAMED_LITERAL_CSTRING(keyValue, "key_value");
|
|
||||||
|
|
||||||
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("osid"), mOSID);
|
|
||||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
|
||||||
|
|
||||||
if (mKey.IsInt()) {
|
|
||||||
rv = stmt->BindInt64ByName(keyValue, mKey.IntValue());
|
|
||||||
}
|
|
||||||
else if (mKey.IsString()) {
|
|
||||||
rv = stmt->BindStringByName(keyValue, mKey.StringValue());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
NS_NOTREACHED("Unknown key type!");
|
|
||||||
}
|
|
||||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
|
||||||
|
|
||||||
rv = stmt->BindStringByName(NS_LITERAL_CSTRING("data"), mValue);
|
|
||||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
|
||||||
|
|
||||||
if (NS_FAILED(stmt->Execute())) {
|
|
||||||
return NS_ERROR_DOM_INDEXEDDB_CONSTRAINT_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update our indexes if needed.
|
|
||||||
if (!mIndexUpdateInfo.IsEmpty()) {
|
|
||||||
PRInt64 objectDataId = mAutoIncrement ? mKey.IntValue() : LL_MININT;
|
|
||||||
rv = IDBObjectStore::UpdateIndexes(mTransaction, mOSID, mKey,
|
|
||||||
mAutoIncrement, true,
|
|
||||||
objectDataId, mIndexUpdateInfo);
|
|
||||||
if (rv == NS_ERROR_STORAGE_CONSTRAINT) {
|
|
||||||
return NS_ERROR_DOM_INDEXEDDB_CONSTRAINT_ERR;
|
|
||||||
}
|
|
||||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
UpdateHelper::GetSuccessResult(nsIWritableVariant* aResult)
|
|
||||||
{
|
|
||||||
NS_ASSERTION(!mKey.IsUnset(), "Badness!");
|
|
||||||
|
|
||||||
if (mKey.IsString()) {
|
|
||||||
aResult->SetAsAString(mKey.StringValue());
|
|
||||||
}
|
|
||||||
else if (mKey.IsInt()) {
|
|
||||||
aResult->SetAsInt64(mKey.IntValue());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
NS_NOTREACHED("Bad key!");
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
DeleteHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
|
||||||
{
|
|
||||||
NS_PRECONDITION(aConnection, "Passed a null connection!");
|
|
||||||
|
|
||||||
nsCOMPtr<mozIStorageStatement> stmt =
|
|
||||||
mTransaction->DeleteStatement(mAutoIncrement);
|
|
||||||
NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
|
||||||
mozStorageStatementScoper scoper(stmt);
|
|
||||||
|
|
||||||
nsresult rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("osid"), mOSID);
|
|
||||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
|
||||||
|
|
||||||
NS_ASSERTION(!mKey.IsUnset(), "Must have a key here!");
|
|
||||||
|
|
||||||
NS_NAMED_LITERAL_CSTRING(key_value, "key_value");
|
|
||||||
|
|
||||||
if (mKey.IsInt()) {
|
|
||||||
rv = stmt->BindInt64ByName(key_value, mKey.IntValue());
|
|
||||||
}
|
|
||||||
else if (mKey.IsString()) {
|
|
||||||
rv = stmt->BindStringByName(key_value, mKey.StringValue());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
NS_NOTREACHED("Unknown key type!");
|
|
||||||
}
|
|
||||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
|
||||||
|
|
||||||
// Search for it!
|
|
||||||
rv = stmt->Execute();
|
|
||||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
DeleteHelper::GetSuccessResult(nsIWritableVariant* aResult)
|
|
||||||
{
|
|
||||||
NS_ASSERTION(!mKey.IsUnset(), "Badness!");
|
|
||||||
|
|
||||||
if (mKey.IsString()) {
|
|
||||||
aResult->SetAsAString(mKey.StringValue());
|
|
||||||
}
|
|
||||||
else if (mKey.IsInt()) {
|
|
||||||
aResult->SetAsInt64(mKey.IntValue());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
NS_NOTREACHED("Unknown key type!");
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
|
|
@ -118,7 +118,7 @@ public:
|
||||||
enum Type
|
enum Type
|
||||||
{
|
{
|
||||||
OBJECTSTORE = 0,
|
OBJECTSTORE = 0,
|
||||||
INDEX,
|
INDEXKEY,
|
||||||
INDEXOBJECT
|
INDEXOBJECT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -744,16 +744,24 @@ IDBObjectStore::GetAddInfo(JSContext* aCx,
|
||||||
{
|
{
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
|
// Return DATA_ERR if a key was passed in and this objectStore uses inline
|
||||||
|
// keys.
|
||||||
|
if (!JSVAL_IS_VOID(aKeyVal) && !mKeyPath.IsEmpty()) {
|
||||||
|
return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
JSAutoRequest ar(aCx);
|
JSAutoRequest ar(aCx);
|
||||||
|
|
||||||
if (mKeyPath.IsEmpty()) {
|
if (mKeyPath.IsEmpty()) {
|
||||||
|
// Out-of-line keys must be passed in.
|
||||||
rv = GetKeyFromJSVal(aKeyVal, aKey);
|
rv = GetKeyFromJSVal(aKeyVal, aKey);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Inline keys live on the object. Make sure it is an object.
|
// Inline keys live on the object. Make sure that the value passed in is an
|
||||||
|
// object.
|
||||||
if (JSVAL_IS_PRIMITIVE(aValue)) {
|
if (JSVAL_IS_PRIMITIVE(aValue)) {
|
||||||
return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR;
|
return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = GetKeyFromObject(aCx, JSVAL_TO_OBJECT(aValue), mKeyPath, aKey);
|
rv = GetKeyFromObject(aCx, JSVAL_TO_OBJECT(aValue), mKeyPath, aKey);
|
||||||
|
@ -1025,7 +1033,8 @@ IDBObjectStore::Put(const jsval& aValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
IDBObjectStore::Delete(nsIVariant* aKey,
|
IDBObjectStore::Delete(const jsval& aKey,
|
||||||
|
JSContext* aCx,
|
||||||
nsIIDBRequest** _retval)
|
nsIIDBRequest** _retval)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||||
|
@ -1035,7 +1044,7 @@ IDBObjectStore::Delete(nsIVariant* aKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
Key key;
|
Key key;
|
||||||
nsresult rv = GetKeyFromVariant(aKey, key);
|
nsresult rv = GetKeyFromJSVal(aKey, key);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -1421,8 +1430,6 @@ AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||||
rv = stmt->Execute();
|
rv = stmt->Execute();
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
if (mayOverwrite && rv == NS_ERROR_STORAGE_CONSTRAINT) {
|
if (mayOverwrite && rv == NS_ERROR_STORAGE_CONSTRAINT) {
|
||||||
scoper.Abandon();
|
|
||||||
|
|
||||||
stmt = mTransaction->AddStatement(false, true, autoIncrement);
|
stmt = mTransaction->AddStatement(false, true, autoIncrement);
|
||||||
NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
NS_ENSURE_TRUE(stmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||||
|
|
||||||
|
@ -1431,20 +1438,18 @@ AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||||
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("osid"), osid);
|
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("osid"), osid);
|
||||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||||
|
|
||||||
if (!autoIncrement) {
|
NS_ASSERTION(!mKey.IsUnset(), "This shouldn't happen!");
|
||||||
NS_ASSERTION(!mKey.IsUnset(), "This shouldn't happen!");
|
|
||||||
|
|
||||||
if (mKey.IsInt()) {
|
if (mKey.IsInt()) {
|
||||||
rv = stmt->BindInt64ByName(keyValue, mKey.IntValue());
|
rv = stmt->BindInt64ByName(keyValue, mKey.IntValue());
|
||||||
}
|
|
||||||
else if (mKey.IsString()) {
|
|
||||||
rv = stmt->BindStringByName(keyValue, mKey.StringValue());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
NS_NOTREACHED("Unknown key type!");
|
|
||||||
}
|
|
||||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
|
||||||
}
|
}
|
||||||
|
else if (mKey.IsString()) {
|
||||||
|
rv = stmt->BindStringByName(keyValue, mKey.StringValue());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
NS_NOTREACHED("Unknown key type!");
|
||||||
|
}
|
||||||
|
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||||
|
|
||||||
rv = stmt->BindStringByName(NS_LITERAL_CSTRING("data"), mValue);
|
rv = stmt->BindStringByName(NS_LITERAL_CSTRING("data"), mValue);
|
||||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||||
|
@ -1978,7 +1983,9 @@ CreateIndexHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
||||||
|
|
||||||
// Now we need to populate the index with data from the object store.
|
// Now we need to populate the index with data from the object store.
|
||||||
rv = InsertDataFromObjectStore(aConnection);
|
rv = InsertDataFromObjectStore(aConnection);
|
||||||
NS_ENSURE_TRUE(rv, rv);
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ interface nsIVariant;
|
||||||
* http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-IDBCursor for more
|
* http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-IDBCursor for more
|
||||||
* information.
|
* information.
|
||||||
*/
|
*/
|
||||||
[scriptable, uuid(12c99a5b-6e67-4d5c-8ae7-3a58da690375)]
|
[scriptable, uuid(585d4d50-11a8-4d65-951e-805787f59d89)]
|
||||||
interface nsIIDBCursor : nsISupports
|
interface nsIIDBCursor : nsISupports
|
||||||
{
|
{
|
||||||
const unsigned short NEXT = 0;
|
const unsigned short NEXT = 0;
|
||||||
|
@ -77,5 +77,6 @@ interface nsIIDBCursor : nsISupports
|
||||||
nsIIDBRequest update(in jsval value);
|
nsIIDBRequest update(in jsval value);
|
||||||
|
|
||||||
// Success fires IDBTransactionEvent, result == null
|
// Success fires IDBTransactionEvent, result == null
|
||||||
|
[implicit_jscontext]
|
||||||
nsIIDBRequest delete();
|
nsIIDBRequest delete();
|
||||||
};
|
};
|
||||||
|
|
|
@ -55,7 +55,7 @@ interface nsIDOMDOMStringList;
|
||||||
* http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-nsIIDBObjectStore
|
* http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-nsIIDBObjectStore
|
||||||
* for more information.
|
* for more information.
|
||||||
*/
|
*/
|
||||||
[scriptable, uuid(626fd729-d66a-4b49-bbaf-058f1c375449)]
|
[scriptable, uuid(64f34805-d3e3-4305-91f8-b2cafac3d33c)]
|
||||||
interface nsIIDBObjectStore : nsISupports
|
interface nsIIDBObjectStore : nsISupports
|
||||||
{
|
{
|
||||||
readonly attribute DOMString name;
|
readonly attribute DOMString name;
|
||||||
|
@ -89,8 +89,9 @@ interface nsIIDBObjectStore : nsISupports
|
||||||
[optional /* undefined */] in jsval key);
|
[optional /* undefined */] in jsval key);
|
||||||
|
|
||||||
// Success fires IDBTransactionEvent, result == null
|
// Success fires IDBTransactionEvent, result == null
|
||||||
|
[implicit_jscontext]
|
||||||
nsIIDBRequest
|
nsIIDBRequest
|
||||||
delete(in nsIVariant key);
|
delete(in jsval key);
|
||||||
|
|
||||||
// Success fires IDBTransactionEvent, result == null
|
// Success fires IDBTransactionEvent, result == null
|
||||||
nsIIDBRequest
|
nsIIDBRequest
|
||||||
|
|
|
@ -68,6 +68,7 @@ TEST_FILES = \
|
||||||
test_global_data.html \
|
test_global_data.html \
|
||||||
test_index_getAll.html \
|
test_index_getAll.html \
|
||||||
test_index_getAllObjects.html \
|
test_index_getAllObjects.html \
|
||||||
|
test_index_object_cursors.html \
|
||||||
test_indexes.html \
|
test_indexes.html \
|
||||||
test_indexes_bad_values.html \
|
test_indexes_bad_values.html \
|
||||||
test_key_requirements.html \
|
test_key_requirements.html \
|
||||||
|
|
|
@ -0,0 +1,161 @@
|
||||||
|
<!--
|
||||||
|
Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
-->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Indexed Database Property Test</title>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
|
||||||
|
<script type="text/javascript;version=1.7">
|
||||||
|
function testSteps()
|
||||||
|
{
|
||||||
|
const objectStoreData = [
|
||||||
|
{ name: "3", keyPath: "id", autoIncrement: true },
|
||||||
|
{ name: "1", keyPath: "ss", autoIncrement: false },
|
||||||
|
{ name: "2", keyPath: "", autoIncrement: false },
|
||||||
|
{ name: "4", keyPath: "", autoIncrement: true },
|
||||||
|
];
|
||||||
|
|
||||||
|
const indexData = [
|
||||||
|
{ name: "name", keyPath: "name", unique: true },
|
||||||
|
{ name: "height", keyPath: "height", unique: false }
|
||||||
|
];
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
{ ss: "237-23-7732", name: "Ann", height: 60 },
|
||||||
|
{ ss: "237-23-7733", name: "Bob", height: 65 }
|
||||||
|
];
|
||||||
|
|
||||||
|
let request = moz_indexedDB.open(window.location.pathname);
|
||||||
|
request.onerror = errorHandler;
|
||||||
|
request.onsuccess = grabEventAndContinueHandler;
|
||||||
|
let event = yield;
|
||||||
|
|
||||||
|
let db = event.result;
|
||||||
|
db.onerror = errorHandler;
|
||||||
|
|
||||||
|
db.setVersion("1").onsuccess = grabEventAndContinueHandler;
|
||||||
|
event = yield;
|
||||||
|
|
||||||
|
event.result.oncomplete = continueToNextStep;
|
||||||
|
|
||||||
|
for (let objectStoreIndex in objectStoreData) {
|
||||||
|
const objectStoreInfo = objectStoreData[objectStoreIndex];
|
||||||
|
let objectStore = db.createObjectStore(objectStoreInfo.name,
|
||||||
|
objectStoreInfo.keyPath,
|
||||||
|
objectStoreInfo.autoIncrement);
|
||||||
|
for (let indexIndex in indexData) {
|
||||||
|
const indexInfo = indexData[indexIndex];
|
||||||
|
let index = objectStore.createIndex(indexInfo.name,
|
||||||
|
indexInfo.keyPath,
|
||||||
|
indexInfo.unique);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yield;
|
||||||
|
|
||||||
|
ok(true, "Initial setup");
|
||||||
|
|
||||||
|
for (let objectStoreIndex in objectStoreData) {
|
||||||
|
const info = objectStoreData[objectStoreIndex];
|
||||||
|
|
||||||
|
for (let indexIndex in indexData) {
|
||||||
|
const objectStoreName = objectStoreData[objectStoreIndex].name;
|
||||||
|
const indexName = indexData[indexIndex].name;
|
||||||
|
|
||||||
|
let objectStore =
|
||||||
|
db.transaction(objectStoreName, IDBTransaction.READ_WRITE)
|
||||||
|
.objectStore(objectStoreName);
|
||||||
|
ok(true, "Got objectStore " + objectStoreName);
|
||||||
|
|
||||||
|
for (let dataIndex in data) {
|
||||||
|
const obj = data[dataIndex];
|
||||||
|
let key;
|
||||||
|
if (!info.keyPath && !info.autoIncrement) {
|
||||||
|
key = obj.ss;
|
||||||
|
}
|
||||||
|
objectStore.add(obj, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
let index = objectStore.index(indexName);
|
||||||
|
ok(true, "Got index " + indexName);
|
||||||
|
|
||||||
|
let keyIndex = 0;
|
||||||
|
|
||||||
|
index.openCursor().onsuccess = function(event) {
|
||||||
|
let cursor = event.result;
|
||||||
|
if (!cursor) {
|
||||||
|
continueToNextStep();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
is(cursor.key, data[keyIndex][indexName], "Good key");
|
||||||
|
is(cursor.value.ss, data[keyIndex].ss, "Correct ss");
|
||||||
|
is(cursor.value.name, data[keyIndex].name, "Correct name");
|
||||||
|
is(cursor.value.height, data[keyIndex].height, "Correct height");
|
||||||
|
|
||||||
|
if (!keyIndex) {
|
||||||
|
let obj = cursor.value;
|
||||||
|
obj.updated = true;
|
||||||
|
|
||||||
|
cursor.update(obj).onsuccess = function(event) {
|
||||||
|
ok(true, "Object updated");
|
||||||
|
cursor.continue();
|
||||||
|
keyIndex++
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor.delete().onsuccess = function(event) {
|
||||||
|
ok(true, "Object deleted");
|
||||||
|
cursor.continue();
|
||||||
|
keyIndex++
|
||||||
|
}
|
||||||
|
};
|
||||||
|
yield;
|
||||||
|
|
||||||
|
is(keyIndex, 2, "Saw all the items");
|
||||||
|
|
||||||
|
keyIndex = 0;
|
||||||
|
|
||||||
|
db.transaction(objectStoreName).objectStore(objectStoreName)
|
||||||
|
.openCursor()
|
||||||
|
.onsuccess = function(event) {
|
||||||
|
let cursor = event.result;
|
||||||
|
if (!cursor) {
|
||||||
|
continueToNextStep();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
is(cursor.value.ss, data[keyIndex].ss, "Correct ss");
|
||||||
|
is(cursor.value.name, data[keyIndex].name, "Correct name");
|
||||||
|
is(cursor.value.height, data[keyIndex].height, "Correct height");
|
||||||
|
is(cursor.value.updated, true, "Correct updated flag");
|
||||||
|
|
||||||
|
cursor.continue();
|
||||||
|
keyIndex++;
|
||||||
|
};
|
||||||
|
yield;
|
||||||
|
|
||||||
|
is(keyIndex, 1, "Saw all the items");
|
||||||
|
|
||||||
|
db.transaction(objectStoreName, IDBTransaction.READ_WRITE)
|
||||||
|
.objectStore(objectStoreName).clear()
|
||||||
|
.onsuccess = continueToNextStep();
|
||||||
|
yield;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
finishTest();
|
||||||
|
yield;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script type="text/javascript;version=1.7" src="helpers.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body onload="runTest();"></body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -133,6 +133,14 @@
|
||||||
ok(true, "add with no key threw");
|
ok(true, "add with no key threw");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
objectStore.add({id:5}, 5);
|
||||||
|
ok(false, "add with inline key and passed key should throw!");
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
ok(true, "add with inline key and passed key threw");
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
objectStore.put({});
|
objectStore.put({});
|
||||||
ok(false, "put with no key should throw!");
|
ok(false, "put with no key should throw!");
|
||||||
|
@ -266,6 +274,14 @@
|
||||||
ok(true, "remove with no key threw");
|
ok(true, "remove with no key threw");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
objectStore.add({id:5}, 5);
|
||||||
|
ok(false, "add with inline key and passed key should throw!");
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
ok(true, "add with inline key and passed key threw");
|
||||||
|
}
|
||||||
|
|
||||||
request = objectStore.delete(key2);
|
request = objectStore.delete(key2);
|
||||||
request.onerror = errorHandler;
|
request.onerror = errorHandler;
|
||||||
request.onsuccess = grabEventAndContinueHandler;
|
request.onsuccess = grabEventAndContinueHandler;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче