зеркало из 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();
|
||||
}
|
||||
|
||||
SetCurrentTransaction(mTransaction);
|
||||
IDBTransaction* oldTransaction = gCurrentTransaction;
|
||||
gCurrentTransaction = mTransaction;
|
||||
|
||||
// Call OnError if the database had an error or if the OnSuccess handler
|
||||
// has an error.
|
||||
|
@ -154,9 +155,8 @@ AsyncConnectionHelper::Run()
|
|||
OnError(mRequest, mResultCode);
|
||||
}
|
||||
|
||||
NS_ASSERTION(GetCurrentTransaction() == mTransaction,
|
||||
"Should be unchanged!");
|
||||
SetCurrentTransaction(nsnull);
|
||||
NS_ASSERTION(gCurrentTransaction == mTransaction, "Should be unchanged!");
|
||||
gCurrentTransaction = oldTransaction;
|
||||
|
||||
if (mDispatched && mTransaction) {
|
||||
mTransaction->OnRequestFinished();
|
||||
|
@ -319,20 +319,6 @@ AsyncConnectionHelper::GetCurrentTransaction()
|
|||
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
|
||||
AsyncConnectionHelper::Init()
|
||||
{
|
||||
|
|
|
@ -87,7 +87,6 @@ public:
|
|||
}
|
||||
|
||||
static IDBTransaction* GetCurrentTransaction();
|
||||
static void SetCurrentTransaction(IDBTransaction* aTransaction);
|
||||
|
||||
nsISupports* GetSource()
|
||||
{
|
||||
|
|
|
@ -63,57 +63,6 @@ USING_INDEXEDDB_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
|
||||
already_AddRefed<IDBRequest>
|
||||
GenerateRequest(IDBCursor* aCursor)
|
||||
|
@ -247,7 +196,7 @@ IDBCursor::Create(IDBRequest* aRequest,
|
|||
NS_ASSERTION(cursor, "This shouldn't fail!");
|
||||
|
||||
cursor->mIndex = aIndex;
|
||||
cursor->mType = INDEX;
|
||||
cursor->mType = INDEXKEY;
|
||||
cursor->mKey = aKey,
|
||||
cursor->mObjectKey = aObjectKey;
|
||||
|
||||
|
@ -452,7 +401,7 @@ IDBCursor::GetValue(JSContext* aCx,
|
|||
|
||||
nsresult rv;
|
||||
|
||||
if (mType == INDEX) {
|
||||
if (mType == INDEXKEY) {
|
||||
NS_ASSERTION(!mObjectKey.IsUnset(), "Bad key!");
|
||||
|
||||
rv = IDBObjectStore::GetJSValFromKey(mObjectKey, aCx, aValue);
|
||||
|
@ -535,7 +484,7 @@ IDBCursor::Continue(const jsval &aKey,
|
|||
helper = new ContinueObjectStoreHelper(this);
|
||||
break;
|
||||
|
||||
case INDEX:
|
||||
case INDEXKEY:
|
||||
helper = new ContinueIndexHelper(this);
|
||||
break;
|
||||
|
||||
|
@ -561,239 +510,75 @@ IDBCursor::Update(const jsval& aValue,
|
|||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (!mTransaction->TransactionIsOpen() || !mTransaction->IsWriteAllowed()) {
|
||||
if (mType == INDEXKEY) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
|
||||
}
|
||||
|
||||
if (mType != OBJECTSTORE) {
|
||||
NS_WARNING("Update 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!");
|
||||
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(!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;
|
||||
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;
|
||||
return mObjectStore->Delete(key, aCx, _retval);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -118,7 +118,7 @@ public:
|
|||
enum Type
|
||||
{
|
||||
OBJECTSTORE = 0,
|
||||
INDEX,
|
||||
INDEXKEY,
|
||||
INDEXOBJECT
|
||||
};
|
||||
|
||||
|
|
|
@ -744,16 +744,24 @@ IDBObjectStore::GetAddInfo(JSContext* aCx,
|
|||
{
|
||||
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);
|
||||
|
||||
if (mKeyPath.IsEmpty()) {
|
||||
// Out-of-line keys must be passed in.
|
||||
rv = GetKeyFromJSVal(aKeyVal, aKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
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)) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR;
|
||||
return NS_ERROR_DOM_INDEXEDDB_DATA_ERR;
|
||||
}
|
||||
|
||||
rv = GetKeyFromObject(aCx, JSVAL_TO_OBJECT(aValue), mKeyPath, aKey);
|
||||
|
@ -1025,7 +1033,8 @@ IDBObjectStore::Put(const jsval& aValue,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
IDBObjectStore::Delete(nsIVariant* aKey,
|
||||
IDBObjectStore::Delete(const jsval& aKey,
|
||||
JSContext* aCx,
|
||||
nsIIDBRequest** _retval)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
@ -1035,7 +1044,7 @@ IDBObjectStore::Delete(nsIVariant* aKey,
|
|||
}
|
||||
|
||||
Key key;
|
||||
nsresult rv = GetKeyFromVariant(aKey, key);
|
||||
nsresult rv = GetKeyFromJSVal(aKey, key);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -1421,8 +1430,6 @@ AddHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
|||
rv = stmt->Execute();
|
||||
if (NS_FAILED(rv)) {
|
||||
if (mayOverwrite && rv == NS_ERROR_STORAGE_CONSTRAINT) {
|
||||
scoper.Abandon();
|
||||
|
||||
stmt = mTransaction->AddStatement(false, true, autoIncrement);
|
||||
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);
|
||||
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()) {
|
||||
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);
|
||||
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);
|
||||
|
@ -1978,7 +1983,9 @@ CreateIndexHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
|
|||
|
||||
// Now we need to populate the index with data from the object store.
|
||||
rv = InsertDataFromObjectStore(aConnection);
|
||||
NS_ENSURE_TRUE(rv, rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ interface nsIVariant;
|
|||
* http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-IDBCursor for more
|
||||
* information.
|
||||
*/
|
||||
[scriptable, uuid(12c99a5b-6e67-4d5c-8ae7-3a58da690375)]
|
||||
[scriptable, uuid(585d4d50-11a8-4d65-951e-805787f59d89)]
|
||||
interface nsIIDBCursor : nsISupports
|
||||
{
|
||||
const unsigned short NEXT = 0;
|
||||
|
@ -77,5 +77,6 @@ interface nsIIDBCursor : nsISupports
|
|||
nsIIDBRequest update(in jsval value);
|
||||
|
||||
// Success fires IDBTransactionEvent, result == null
|
||||
[implicit_jscontext]
|
||||
nsIIDBRequest delete();
|
||||
};
|
||||
|
|
|
@ -55,7 +55,7 @@ interface nsIDOMDOMStringList;
|
|||
* http://dev.w3.org/2006/webapi/WebSimpleDB/#idl-def-nsIIDBObjectStore
|
||||
* for more information.
|
||||
*/
|
||||
[scriptable, uuid(626fd729-d66a-4b49-bbaf-058f1c375449)]
|
||||
[scriptable, uuid(64f34805-d3e3-4305-91f8-b2cafac3d33c)]
|
||||
interface nsIIDBObjectStore : nsISupports
|
||||
{
|
||||
readonly attribute DOMString name;
|
||||
|
@ -89,8 +89,9 @@ interface nsIIDBObjectStore : nsISupports
|
|||
[optional /* undefined */] in jsval key);
|
||||
|
||||
// Success fires IDBTransactionEvent, result == null
|
||||
[implicit_jscontext]
|
||||
nsIIDBRequest
|
||||
delete(in nsIVariant key);
|
||||
delete(in jsval key);
|
||||
|
||||
// Success fires IDBTransactionEvent, result == null
|
||||
nsIIDBRequest
|
||||
|
|
|
@ -68,6 +68,7 @@ TEST_FILES = \
|
|||
test_global_data.html \
|
||||
test_index_getAll.html \
|
||||
test_index_getAllObjects.html \
|
||||
test_index_object_cursors.html \
|
||||
test_indexes.html \
|
||||
test_indexes_bad_values.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");
|
||||
}
|
||||
|
||||
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 {
|
||||
objectStore.put({});
|
||||
ok(false, "put with no key should throw!");
|
||||
|
@ -266,6 +274,14 @@
|
|||
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.onerror = errorHandler;
|
||||
request.onsuccess = grabEventAndContinueHandler;
|
||||
|
|
Загрузка…
Ссылка в новой задаче