Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
jio
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Roque
jio
Commits
ea9a9ec4
Commit
ea9a9ec4
authored
Apr 26, 2019
by
Romain Courteaud
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[indexeddb] Support database indexes handling
Thanks to Preet Batth for his work on this topic.
parent
96bf766f
Changes
2
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
376 additions
and
49 deletions
+376
-49
src/jio.storage/indexeddbstorage.js
src/jio.storage/indexeddbstorage.js
+83
-46
test/jio.storage/indexeddbstorage.tests.js
test/jio.storage/indexeddbstorage.tests.js
+293
-3
No files found.
src/jio.storage/indexeddbstorage.js
View file @
ea9a9ec4
...
@@ -43,14 +43,15 @@
...
@@ -43,14 +43,15 @@
/*jslint nomen: true */
/*jslint nomen: true */
/*global indexedDB, jIO, RSVP, Blob, Math, IDBKeyRange, IDBOpenDBRequest,
/*global indexedDB, jIO, RSVP, Blob, Math, IDBKeyRange, IDBOpenDBRequest,
DOMError,
Even
t*/
DOMError,
Se
t*/
(
function
(
indexedDB
,
jIO
,
RSVP
,
Blob
,
Math
,
IDBKeyRange
,
IDBOpenDBRequest
,
(
function
(
indexedDB
,
jIO
,
RSVP
,
Blob
,
Math
,
IDBKeyRange
,
IDBOpenDBRequest
,
DOMError
)
{
DOMError
,
Set
)
{
"
use strict
"
;
"
use strict
"
;
// Read only as changing it can lead to data corruption
// Read only as changing it can lead to data corruption
var
UNITE
=
2000000
;
var
UNITE
=
2000000
,
INDEX_PREFIX
=
'
doc.
'
;
function
IndexedDBStorage
(
description
)
{
function
IndexedDBStorage
(
description
)
{
if
(
typeof
description
.
database
!==
"
string
"
||
if
(
typeof
description
.
database
!==
"
string
"
||
...
@@ -59,6 +60,8 @@
...
@@ -59,6 +60,8 @@
"
must be a non-empty string
"
);
"
must be a non-empty string
"
);
}
}
this
.
_database_name
=
"
jio:
"
+
description
.
database
;
this
.
_database_name
=
"
jio:
"
+
description
.
database
;
this
.
_version
=
description
.
version
;
this
.
_index_key_list
=
description
.
index_key_list
||
[];
}
}
IndexedDBStorage
.
prototype
.
hasCapacity
=
function
(
name
)
{
IndexedDBStorage
.
prototype
.
hasCapacity
=
function
(
name
)
{
...
@@ -69,35 +72,65 @@
...
@@ -69,35 +72,65 @@
return
key_list
.
join
(
"
_
"
);
return
key_list
.
join
(
"
_
"
);
}
}
function
handleUpgradeNeeded
(
evt
)
{
function
handleUpgradeNeeded
(
evt
,
index_key_list
)
{
var
db
=
evt
.
target
.
result
,
var
db
=
evt
.
target
.
result
,
store
;
store
,
current_store_list
=
Array
.
from
(
db
.
objectStoreNames
),
current_index_list
,
i
,
index_key
;
if
(
current_store_list
.
indexOf
(
"
metadata
"
)
===
-
1
)
{
store
=
db
.
createObjectStore
(
"
metadata
"
,
{
keyPath
:
"
_id
"
,
autoIncrement
:
false
});
// It is not possible to use openKeyCursor on keypath directly
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=19955
store
.
createIndex
(
"
_id
"
,
"
_id
"
,
{
unique
:
true
});
}
else
{
store
=
evt
.
target
.
transaction
.
objectStore
(
"
metadata
"
);
}
store
=
db
.
createObjectStore
(
"
metadata
"
,
{
current_index_list
=
new
Set
(
store
.
indexNames
);
keyPath
:
"
_id
"
,
current_index_list
.
delete
(
"
_id
"
);
autoIncrement
:
false
for
(
i
=
0
;
i
<
index_key_list
.
length
;
i
+=
1
)
{
});
// Prefix the index name to prevent conflict with _id
// It is not possible to use openKeyCursor on keypath directly
index_key
=
INDEX_PREFIX
+
index_key_list
[
i
];
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=19955
if
(
current_index_list
.
has
(
index_key
))
{
store
.
createIndex
(
"
_id
"
,
"
_id
"
,
{
unique
:
true
});
current_index_list
.
delete
(
index_key
);
}
else
{
store
.
createIndex
(
index_key
,
index_key
,
{
unique
:
false
});
}
}
current_index_list
=
Array
.
from
(
current_index_list
);
for
(
i
=
0
;
i
<
current_index_list
.
length
;
i
+=
1
)
{
store
.
deleteIndex
(
current_index_list
[
i
]);
}
store
=
db
.
createObjectStore
(
"
attachment
"
,
{
if
(
current_store_list
.
indexOf
(
"
attachment
"
)
===
-
1
)
{
keyPath
:
"
_key_path
"
,
store
=
db
.
createObjectStore
(
"
attachment
"
,
{
autoIncrement
:
false
keyPath
:
"
_key_path
"
,
});
autoIncrement
:
false
store
.
createIndex
(
"
_id
"
,
"
_id
"
,
{
unique
:
false
});
});
store
.
createIndex
(
"
_id
"
,
"
_id
"
,
{
unique
:
false
});
}
store
=
db
.
createObjectStore
(
"
blob
"
,
{
if
(
current_store_list
.
indexOf
(
"
blob
"
)
===
-
1
)
{
keyPath
:
"
_key_path
"
,
store
=
db
.
createObjectStore
(
"
blob
"
,
{
autoIncrement
:
false
keyPath
:
"
_key_path
"
,
});
autoIncrement
:
false
store
.
createIndex
(
"
_id_attachment
"
,
});
[
"
_id
"
,
"
_attachment
"
],
{
unique
:
false
});
store
.
createIndex
(
"
_id_attachment
"
,
store
.
createIndex
(
"
_id
"
,
"
_id
"
,
{
unique
:
false
});
[
"
_id
"
,
"
_attachment
"
],
{
unique
:
false
});
store
.
createIndex
(
"
_id
"
,
"
_id
"
,
{
unique
:
false
});
}
}
}
function
waitForOpenIndexedDB
(
db_name
,
callback
)
{
function
waitForOpenIndexedDB
(
storage
,
callback
)
{
var
request
;
var
request
,
db_name
=
storage
.
_database_name
;
function
canceller
()
{
function
canceller
()
{
if
((
request
!==
undefined
)
&&
(
request
.
result
!==
undefined
))
{
if
((
request
!==
undefined
)
&&
(
request
.
result
!==
undefined
))
{
...
@@ -107,7 +140,7 @@
...
@@ -107,7 +140,7 @@
function
resolver
(
resolve
,
reject
)
{
function
resolver
(
resolve
,
reject
)
{
// Open DB //
// Open DB //
request
=
indexedDB
.
open
(
db_name
);
request
=
indexedDB
.
open
(
db_name
,
storage
.
_version
);
request
.
onerror
=
function
(
error
)
{
request
.
onerror
=
function
(
error
)
{
canceller
();
canceller
();
if
((
error
!==
undefined
)
&&
if
((
error
!==
undefined
)
&&
...
@@ -135,7 +168,9 @@
...
@@ -135,7 +168,9 @@
};
};
// Create DB if necessary //
// Create DB if necessary //
request
.
onupgradeneeded
=
handleUpgradeNeeded
;
request
.
onupgradeneeded
=
function
(
evt
)
{
handleUpgradeNeeded
(
evt
,
storage
.
_index_key_list
);
};
request
.
onversionchange
=
function
()
{
request
.
onversionchange
=
function
()
{
canceller
();
canceller
();
...
@@ -233,7 +268,7 @@
...
@@ -233,7 +268,7 @@
function
pushIncludedMetadata
(
cursor
)
{
function
pushIncludedMetadata
(
cursor
)
{
result_list
.
push
({
result_list
.
push
({
"
id
"
:
cursor
.
k
ey
,
"
id
"
:
cursor
.
primaryK
ey
,
"
value
"
:
{},
"
value
"
:
{},
"
doc
"
:
cursor
.
value
.
doc
"
doc
"
:
cursor
.
value
.
doc
});
});
...
@@ -241,24 +276,25 @@
...
@@ -241,24 +276,25 @@
function
pushMetadata
(
cursor
)
{
function
pushMetadata
(
cursor
)
{
result_list
.
push
({
result_list
.
push
({
"
id
"
:
cursor
.
k
ey
,
"
id
"
:
cursor
.
primaryK
ey
,
"
value
"
:
{}
"
value
"
:
{}
});
});
}
}
return
new
RSVP
.
Queue
()
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
.
push
(
function
()
{
return
waitForOpenIndexedDB
(
context
.
_database_name
,
function
(
db
)
{
return
waitForOpenIndexedDB
(
context
,
function
(
db
)
{
return
waitForTransaction
(
db
,
[
"
metadata
"
],
"
readonly
"
,
return
waitForTransaction
(
db
,
[
"
metadata
"
],
"
readonly
"
,
function
(
tx
)
{
function
(
tx
)
{
var
key
=
"
_id
"
;
if
(
options
.
include_docs
===
true
)
{
if
(
options
.
include_docs
===
true
)
{
return
waitForAllSynchronousCursor
(
return
waitForAllSynchronousCursor
(
tx
.
objectStore
(
"
metadata
"
).
index
(
"
_id
"
).
openCursor
(),
tx
.
objectStore
(
"
metadata
"
).
index
(
key
).
openCursor
(),
pushIncludedMetadata
pushIncludedMetadata
);
);
}
}
return
waitForAllSynchronousCursor
(
return
waitForAllSynchronousCursor
(
tx
.
objectStore
(
"
metadata
"
).
index
(
"
_id
"
).
openKeyCursor
(),
tx
.
objectStore
(
"
metadata
"
).
index
(
key
).
openKeyCursor
(),
pushMetadata
pushMetadata
);
);
});
});
...
@@ -273,7 +309,7 @@
...
@@ -273,7 +309,7 @@
var
context
=
this
;
var
context
=
this
;
return
new
RSVP
.
Queue
()
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
.
push
(
function
()
{
return
waitForOpenIndexedDB
(
context
.
_database_name
,
function
(
db
)
{
return
waitForOpenIndexedDB
(
context
,
function
(
db
)
{
return
waitForTransaction
(
db
,
[
"
metadata
"
],
"
readonly
"
,
return
waitForTransaction
(
db
,
[
"
metadata
"
],
"
readonly
"
,
function
(
tx
)
{
function
(
tx
)
{
return
waitForIDBRequest
(
tx
.
objectStore
(
"
metadata
"
).
get
(
id
));
return
waitForIDBRequest
(
tx
.
objectStore
(
"
metadata
"
).
get
(
id
));
...
@@ -301,7 +337,7 @@
...
@@ -301,7 +337,7 @@
return
new
RSVP
.
Queue
()
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
.
push
(
function
()
{
return
waitForOpenIndexedDB
(
context
.
_database_name
,
function
(
db
)
{
return
waitForOpenIndexedDB
(
context
,
function
(
db
)
{
return
waitForTransaction
(
db
,
[
"
metadata
"
,
"
attachment
"
],
"
readonly
"
,
return
waitForTransaction
(
db
,
[
"
metadata
"
,
"
attachment
"
],
"
readonly
"
,
function
(
tx
)
{
function
(
tx
)
{
return
RSVP
.
all
([
return
RSVP
.
all
([
...
@@ -330,7 +366,7 @@
...
@@ -330,7 +366,7 @@
};
};
IndexedDBStorage
.
prototype
.
put
=
function
(
id
,
metadata
)
{
IndexedDBStorage
.
prototype
.
put
=
function
(
id
,
metadata
)
{
return
waitForOpenIndexedDB
(
this
.
_database_name
,
function
(
db
)
{
return
waitForOpenIndexedDB
(
this
,
function
(
db
)
{
return
waitForTransaction
(
db
,
[
"
metadata
"
],
"
readwrite
"
,
return
waitForTransaction
(
db
,
[
"
metadata
"
],
"
readwrite
"
,
function
(
tx
)
{
function
(
tx
)
{
return
waitForIDBRequest
(
tx
.
objectStore
(
"
metadata
"
).
put
({
return
waitForIDBRequest
(
tx
.
objectStore
(
"
metadata
"
).
put
({
...
@@ -342,7 +378,7 @@
...
@@ -342,7 +378,7 @@
};
};
IndexedDBStorage
.
prototype
.
remove
=
function
(
id
)
{
IndexedDBStorage
.
prototype
.
remove
=
function
(
id
)
{
return
waitForOpenIndexedDB
(
this
.
_database_name
,
function
(
db
)
{
return
waitForOpenIndexedDB
(
this
,
function
(
db
)
{
return
waitForTransaction
(
db
,
[
"
metadata
"
,
"
attachment
"
,
"
blob
"
],
return
waitForTransaction
(
db
,
[
"
metadata
"
,
"
attachment
"
,
"
blob
"
],
"
readwrite
"
,
function
(
tx
)
{
"
readwrite
"
,
function
(
tx
)
{
...
@@ -386,10 +422,10 @@
...
@@ -386,10 +422,10 @@
if
(
options
===
undefined
)
{
if
(
options
===
undefined
)
{
options
=
{};
options
=
{};
}
}
var
db_name
=
this
.
_database_name
,
var
start
,
start
,
end
,
end
,
array_buffer_list
=
[];
array_buffer_list
=
[],
context
=
this
;
start
=
options
.
start
||
0
;
start
=
options
.
start
||
0
;
end
=
options
.
end
;
end
=
options
.
end
;
...
@@ -410,7 +446,7 @@
...
@@ -410,7 +446,7 @@
return
new
RSVP
.
Queue
()
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
.
push
(
function
()
{
return
waitForOpenIndexedDB
(
db_name
,
function
(
db
)
{
return
waitForOpenIndexedDB
(
context
,
function
(
db
)
{
return
waitForTransaction
(
db
,
[
"
blob
"
],
"
readonly
"
,
return
waitForTransaction
(
db
,
[
"
blob
"
],
"
readonly
"
,
function
(
tx
)
{
function
(
tx
)
{
var
key_path
=
buildKeyPath
([
id
,
name
]),
var
key_path
=
buildKeyPath
([
id
,
name
]),
...
@@ -488,7 +524,7 @@
...
@@ -488,7 +524,7 @@
// Request the full blob
// Request the full blob
return
new
RSVP
.
Queue
()
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
.
push
(
function
()
{
return
waitForOpenIndexedDB
(
db_name
,
function
(
db
)
{
return
waitForOpenIndexedDB
(
context
,
function
(
db
)
{
return
waitForTransaction
(
db
,
[
"
attachment
"
,
"
blob
"
],
"
readonly
"
,
return
waitForTransaction
(
db
,
[
"
attachment
"
,
"
blob
"
],
"
readonly
"
,
function
(
tx
)
{
function
(
tx
)
{
var
key_path
=
buildKeyPath
([
id
,
name
]),
var
key_path
=
buildKeyPath
([
id
,
name
]),
...
@@ -555,7 +591,7 @@
...
@@ -555,7 +591,7 @@
};
};
IndexedDBStorage
.
prototype
.
putAttachment
=
function
(
id
,
name
,
blob
)
{
IndexedDBStorage
.
prototype
.
putAttachment
=
function
(
id
,
name
,
blob
)
{
var
db_name
=
this
.
_database_name
;
var
context
=
this
;
return
new
RSVP
.
Queue
()
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
.
push
(
function
()
{
// Split the blob first
// Split the blob first
...
@@ -573,7 +609,7 @@
...
@@ -573,7 +609,7 @@
handled_size
+=
UNITE
;
handled_size
+=
UNITE
;
}
}
return
waitForOpenIndexedDB
(
db_name
,
function
(
db
)
{
return
waitForOpenIndexedDB
(
context
,
function
(
db
)
{
return
waitForTransaction
(
db
,
[
"
attachment
"
,
"
blob
"
],
"
readwrite
"
,
return
waitForTransaction
(
db
,
[
"
attachment
"
,
"
blob
"
],
"
readwrite
"
,
function
(
tx
)
{
function
(
tx
)
{
var
blob_store
,
var
blob_store
,
...
@@ -640,7 +676,7 @@
...
@@ -640,7 +676,7 @@
};
};
IndexedDBStorage
.
prototype
.
removeAttachment
=
function
(
id
,
name
)
{
IndexedDBStorage
.
prototype
.
removeAttachment
=
function
(
id
,
name
)
{
return
waitForOpenIndexedDB
(
this
.
_database_name
,
function
(
db
)
{
return
waitForOpenIndexedDB
(
this
,
function
(
db
)
{
return
waitForTransaction
(
db
,
[
"
attachment
"
,
"
blob
"
],
"
readwrite
"
,
return
waitForTransaction
(
db
,
[
"
attachment
"
,
"
blob
"
],
"
readwrite
"
,
function
(
tx
)
{
function
(
tx
)
{
var
promise_list
=
[],
var
promise_list
=
[],
...
@@ -672,4 +708,5 @@
...
@@ -672,4 +708,5 @@
};
};
jIO
.
addStorage
(
"
indexeddb
"
,
IndexedDBStorage
);
jIO
.
addStorage
(
"
indexeddb
"
,
IndexedDBStorage
);
}(
indexedDB
,
jIO
,
RSVP
,
Blob
,
Math
,
IDBKeyRange
,
IDBOpenDBRequest
,
DOMError
));
}(
indexedDB
,
jIO
,
RSVP
,
Blob
,
Math
,
IDBKeyRange
,
IDBOpenDBRequest
,
DOMError
,
Set
));
test/jio.storage/indexeddbstorage.tests.js
View file @
ea9a9ec4
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment