2014-09-24 1 views
29

동일한 indexeddb에 두 개의 서로 다른 객체 저장소가있는 경우 문제는 모든 저장소에서 기본 키 값이 "공유"된 것처럼 보입니다.IndexedDb의 iOS8 구현에 대한 주요한 주요 문제

<body> 
    <script type="text/javascript"> 
     //prefixes of implementation that we want to test 
window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB; 

//prefixes of window.IDB objects 
window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction; 
window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange 

if (!window.indexedDB) { 
    window.alert("Your browser doesn't support a stable version of IndexedDB.") 
} 


var db; 
var request = window.indexedDB.open("newDatabase", 4); 

request.onerror = function(event) { 
    console.log("error: "); 
}; 

request.onsuccess = function(event) { 
    db = request.result; 
    console.log("success: "+ db); 
}; 

request.onupgradeneeded = function(event) { 
     var db = event.target.result; 
     var objectStore = db.createObjectStore("customers", {keyPath: "arseid"}); 
    var objectStore = db.createObjectStore("test", {keyPath: "id"}); 
} 



function add1() { 
     var x = new Date(); 
    var h1 = x.getHours(); 
    var m1 = x.getMinutes(); 
    var s1 = x.getSeconds(); 
    console.log('starting insert on ' + h1 + ':' + m1 + ':' + s1); 

    var tx = db.transaction(["customers"], "readwrite"); 
    for (var i = 0; i < 1000; i++) { 
     var request = tx.objectStore("customers") 
       .put({ arseid: i, name: "Jonathan Smith", email: "[email protected]", favourite: "chocolate cake", pet: "rudolph the red nose reindeer", address: "999 letsbe avenue, townton, countyshire" }); 
    } 


    tx.oncomplete = function (e) { 
      // Re-render all the todo's 
      var x2 = new Date(); 
      var h2 = x2.getHours(); 
      var m2 = x2.getMinutes(); 
      var s2 = x2.getSeconds(); 
       console.log('transaction complete ' + h2 + ':' + m2 + ':' + s2); 
     } 
} 


function add2() { 
    //tx 2 
    var tx2 = db.transaction(["test"], "readwrite"); 
    for (var i = 0; i < 1000; i++) { 
     var request2 = tx2.objectStore("test") 
       .put({ id: i, name: "Robwin Mwengway", email: "[email protected]", favourite: "chocolate cake", pet: "rudolph the red nose reindeer", address: "999 letsbe avenue, townton, countyshire" }); 
    } 

    tx2.oncomplete = function (e) { 
      var x3 = new Date(); 
      var h3 = x3.getHours(); 
      var m3 = x3.getMinutes(); 
      var s3 = x3.getSeconds(); 
       console.log('transaction complete ' + h3 + ':' + m3 + ':' + s3); 
     } 
} 


    </script> 
<button onclick="add1()">Add1 data to indexedDb</button> 
<button onclick="add2()">Add2 data to indexedDb</button> 
</body> 

(바이올린 : http://jsfiddle.net/jonnyknowsbest/4pdp8vxe/) 당신이 바이올린을 실행하고 "색인화에 ADD1 데이터"를 클릭하면 iOS8의에서

는 다음 1000 항목은 "고객"테이블에 추가됩니다. "Added to data to IndexedDb"를 클릭하면 1000 개의 항목이 "공급 업체"테이블에 추가되지만 "customers"의 1000은 제거됩니다.

누구도이 문제를 알고 있습니까? 이 부분은 IndexedDb 사양의 일부입니까? Chrome에이 문제가없는 것으로 보입니다.

편집 : 발견했습니다 W3 Org IndexedDB Recommendation : "동일한 키가있는 특정 개체 저장소에 여러 레코드가있을 수 없습니다." 애플은 데이터베이스 수준에서 이것을 적용한 것으로 보인다.

+0

은 와우, 나쁜. 아직 iOS 8을 사용해 본 적이 없지만 iOS 8 기반의 iOS 기반 앱이 iOS 8에서 전혀 실행되지 않는다는 일부 사용자의보고가있었습니다. 나는 놀랍다 고 말할 수 없다. 내 음모 이론에 잘 들어 맞는다. http://stackoverflow.com/a/20110477/786644 :) – dumbmatter

+1

Jeeze. autoIncreement를 지정하도록 지정해도 그것은 손상된 것 같습니다. –

+1

으. 하나의 트랜잭션을 사용하여 문제를 해결하려고했습니다. 하나의 트랜잭션에서 N 개의 객체 저장소를 지정할 수 있습니다. 아니, 오류가 발생합니다. –

답변

20

iOS8이 확실히 여기에 버그가 있음을 확인할 수 있습니다. 몇 가지 해결 방법을 시도했지만, 제안 할 수있는 최선의 방법은 objectStore의 이름과 같은 고유 한 문자열과 숫자를 결합한 기본 키입니다. 예를 들어, 사람과 노트라는 두 objectStores을 부여 그래서, 정말 같은 키와 데이터를 저장하는 것 :

명/X 노트/X

당신은 .count를 사용하여 수동으로 X를 설정하거나 할 수

() 메서드를 사용하여 개수를 찾아서 추가합니다. 다음은 예입니다.

//Define a person 
var person = { 
    name:"Ray", 
    created:new Date().toString(), 
} 

//Perform the add 
db.transaction(["people"],"readwrite").objectStore("people").count().onsuccess = function(event) { 
    var total = event.target.result; 
    console.log(total); 
    person.id = "person/" + (total+1); 

    var request = db.transaction(["people"],"readwrite").objectStore("people").add(person); 

    request.onerror = function(e) { 
     console.log("Error",e.target.error.name); 
     //some type of error handler 
    } 

    request.onsuccess = function(e) { 
     console.log("Woot! Did it"); 
    } 

} 

이 OS에 대해 "id"라는 keyPath를 지정했음을 유의하십시오.

+6

iOS가 https://github.com/WebKit/webkit/blob/master/Source/WebKit2/DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite의 코드와 함께 IndexedDB의 SQLite 기반 구현을 사용한다고 가정합니다. cpp, 객체 데이터는 SQLite DB에 'key'필드가있는 'Records'테이블에 저장됩니다. 키 필드에는 UNIQUE 제약 조건이 있으며 저장소 ID는 키의 일부가 아닙니다. 아! (!). 나는 이것이 OS X 10.10의 사파리에도 영향을 미칠 것이라고 생각한다. –

+2

며칠 전에 Apple에서 픽스를 확인한 것 같습니다 : https://github.com/WebKit/webkit/commit/daadc48666e5015e3b7f1ccba22588e6711a0706 – Lee

+0

iOS 9에서 수정 된 것 같습니다. https://gist.github.com/nolanlawson/08eb857c6b17a30c1b26 – Nux

1

objectstore에 대한 첫 번째 삽입은 사용자 이름과 전자 메일로 된 작은 배열 이었지만 두 번째 objectstore는 여러 중첩 된 데이터 배열로 매우 큽니다.

아래의 삽입 메소드는 모든 항목에 대해 성공을 다시 호출하지만 두 번째 객체 저장소 만 db에 올바르게 기록됩니다.

큰 개체 저장소 항목과 사용자 이름/전자 메일 초를 쓰면서 데이터베이스에 쓰려고 할 때 두 개체 저장소가 올바르게 작성되었지만 기본 키가 두 개체 저장소간에 공유되었지만 순서를 바꾸려고 시도했습니다. 조종사 기본 키 : 1,2,3,4,5 AC 기본 키 : 6,7,8는 ...

function insert_GroupRecord(Record, Store){ 
    //update individual sync record 
    var trans = dbGroup.transaction([Store],"readwrite"); 
    var store = trans.objectStore(Store); 
    var request = store.put(Record); 
    request.onsuccess = function(e){ 
     IOS_postMessage({Message:"SyncStatus", status:"Group_Insert "+Store}); 
    }; 
    request.onerror = function(e){ 
     GroupSyncERROR = true; 
     //IOS_postMessage({Message:"SyncStatus", status:"GroupSyncFail "+Store}); 
    }; 

    request.onupgradeneeded = function(evt){ 
     var objectStore = evt.currentTarget.result.createObjectStore("AC",{ keyPath: "id", autoIncrement: true }); 
     objectStore.createIndex("ident", "ident", { unique: true }); 
     var objectStore2 = evt.currentTarget.result.createObjectStore("Pilots",{ keyPath: "id", autoIncrement: true }); 
     objectStore2.createIndex("chatname", "chatname", { unique: true }); 
     console.log("KFM_Group Upgrade Completed"); 

    }; 
}