Bug 871846 - Handle locale aware indexes. r=janv

This commit is contained in:
Reuben Morais 2015-09-04 16:12:44 -03:00
Родитель 0e18f3afbd
Коммит 9a1f803114
5 изменённых файлов: 164 добавлений и 23 удалений

Просмотреть файл

@ -2688,11 +2688,13 @@ BackgroundCursorChild::HandleResponse(const IndexCursorResponse& aResponse)
if (mCursor) {
mCursor->Reset(Move(response.key()),
Move(response.sortKey()),
Move(response.objectKey()),
Move(cloneReadInfo));
} else {
newCursor = IDBCursor::Create(this,
Move(response.key()),
Move(response.sortKey()),
Move(response.objectKey()),
Move(cloneReadInfo));
mCursor = newCursor;
@ -2718,10 +2720,13 @@ BackgroundCursorChild::HandleResponse(const IndexKeyCursorResponse& aResponse)
nsRefPtr<IDBCursor> newCursor;
if (mCursor) {
mCursor->Reset(Move(response.key()), Move(response.objectKey()));
mCursor->Reset(Move(response.key()),
Move(response.sortKey()),
Move(response.objectKey()));
} else {
newCursor = IDBCursor::Create(this,
Move(response.key()),
Move(response.sortKey()),
Move(response.objectKey()));
mCursor = newCursor;
}

Просмотреть файл

@ -289,7 +289,7 @@ struct FullIndexMetadata
public:
FullIndexMetadata()
: mCommonMetadata(0, nsString(), KeyPath(0), false, false)
: mCommonMetadata(0, nsString(), KeyPath(0), nsCString(), false, false, false)
, mDeleted(false)
{
// This can happen either on the QuotaManager IO thread or on a
@ -5438,6 +5438,11 @@ protected:
BindKeyRangeToStatement(const SerializedKeyRange& aKeyRange,
mozIStorageStatement* aStatement);
static nsresult
BindKeyRangeToStatement(const SerializedKeyRange& aKeyRange,
mozIStorageStatement* aStatement,
const nsCString& aLocale);
static void
AppendConditionClause(const nsACString& aColumnName,
const nsACString& aArgName,
@ -7708,10 +7713,12 @@ private:
nsCString mContinueQuery;
nsCString mContinueToQuery;
nsCString mLocale;
Key mKey;
Key mObjectKey;
Key mRangeKey;
Key mSortKey;
CursorOpBase* mCurrentlyRunningOp;
@ -7764,6 +7771,11 @@ private:
virtual bool
RecvContinue(const CursorRequestParams& aParams, const Key& key) override;
bool
IsLocaleAware() const {
return !mLocale.IsEmpty();
}
};
class Cursor::CursorOpBase
@ -14668,6 +14680,10 @@ Cursor::Cursor(TransactionBase* aTransaction,
MOZ_ASSERT(mBackgroundParent);
}
if (aIndexMetadata) {
mLocale = aIndexMetadata->mCommonMetadata.locale();
}
static_assert(OpenCursorParams::T__None == 0 &&
OpenCursorParams::T__Last == 4,
"Lots of code here assumes only four types of cursors!");
@ -14713,6 +14729,8 @@ Cursor::VerifyRequestParams(const CursorRequestParams& aParams) const
return false;
}
const Key& sortKey = IsLocaleAware() ? mSortKey : mKey;
switch (aParams.type()) {
case CursorRequestParams::TContinueParams: {
const Key& key = aParams.get_ContinueParams().key();
@ -14720,7 +14738,7 @@ Cursor::VerifyRequestParams(const CursorRequestParams& aParams) const
switch (mDirection) {
case IDBCursor::NEXT:
case IDBCursor::NEXT_UNIQUE:
if (NS_WARN_IF(key <= mKey)) {
if (NS_WARN_IF(key <= sortKey)) {
ASSERT_UNLESS_FUZZING();
return false;
}
@ -14728,7 +14746,7 @@ Cursor::VerifyRequestParams(const CursorRequestParams& aParams) const
case IDBCursor::PREV:
case IDBCursor::PREV_UNIQUE:
if (NS_WARN_IF(key >= mKey)) {
if (NS_WARN_IF(key >= sortKey)) {
ASSERT_UNLESS_FUZZING();
return false;
}
@ -17479,24 +17497,21 @@ DatabaseOperationBase::BindKeyRangeToStatement(
MOZ_ASSERT(!IsOnBackgroundThread());
MOZ_ASSERT(aStatement);
NS_NAMED_LITERAL_CSTRING(lowerKey, "lower_key");
if (aKeyRange.isOnly()) {
return aKeyRange.lower().BindToStatement(aStatement, lowerKey);
}
nsresult rv;
nsresult rv = NS_OK;
if (!aKeyRange.lower().IsUnset()) {
rv = aKeyRange.lower().BindToStatement(aStatement, lowerKey);
rv = aKeyRange.lower().BindToStatement(aStatement, NS_LITERAL_CSTRING("lower_key"));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
if (aKeyRange.isOnly()) {
return rv;
}
if (!aKeyRange.upper().IsUnset()) {
rv = aKeyRange.upper().BindToStatement(aStatement,
NS_LITERAL_CSTRING("upper_key"));
rv = aKeyRange.upper().BindToStatement(aStatement, NS_LITERAL_CSTRING("upper_key"));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -17505,6 +17520,56 @@ DatabaseOperationBase::BindKeyRangeToStatement(
return NS_OK;
}
// static
nsresult
DatabaseOperationBase::BindKeyRangeToStatement(
const SerializedKeyRange& aKeyRange,
mozIStorageStatement* aStatement,
const nsCString& aLocale)
{
#ifndef ENABLE_INTL_API
return BindKeyRangeToStatement(aKeyRange, aStatement);
#else
MOZ_ASSERT(!IsOnBackgroundThread());
MOZ_ASSERT(aStatement);
MOZ_ASSERT(!aLocale.IsEmpty());
nsresult rv = NS_OK;
if (!aKeyRange.lower().IsUnset()) {
Key lower;
rv = aKeyRange.lower().ToLocaleBasedKey(lower, aLocale);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = lower.BindToStatement(aStatement, NS_LITERAL_CSTRING("lower_key"));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
if (aKeyRange.isOnly()) {
return rv;
}
if (!aKeyRange.upper().IsUnset()) {
Key upper;
rv = aKeyRange.upper().ToLocaleBasedKey(upper, aLocale);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = upper.BindToStatement(aStatement, NS_LITERAL_CSTRING("upper_key"));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
return NS_OK;
#endif
}
// static
void
DatabaseOperationBase::AppendConditionClause(const nsACString& aColumnName,
@ -17632,13 +17697,15 @@ DatabaseOperationBase::IndexDataValuesFromUpdateInfos(
const IndexUpdateInfo& updateInfo = aUpdateInfos[idxIndex];
const int64_t& indexId = updateInfo.indexId();
const Key& key = updateInfo.value();
const Key& sortKey = updateInfo.localizedValue();
bool unique;
MOZ_ALWAYS_TRUE(aUniqueIndexTable.Get(indexId, &unique));
IndexDataValue idv(indexId, unique, key, sortKey);
MOZ_ALWAYS_TRUE(
aIndexValues.InsertElementSorted(IndexDataValue(indexId, unique, key),
fallible));
aIndexValues.InsertElementSorted(idv, fallible));
}
return NS_OK;
@ -22242,6 +22309,7 @@ UpdateIndexDataValuesFunction::OnFunctionCall(mozIStorageValueArray* aValues,
metadata.keyPath(),
metadata.unique(),
metadata.multiEntry(),
metadata.locale(),
mCx,
clone,
updateInfos);
@ -22325,7 +22393,8 @@ UpdateIndexDataValuesFunction::OnFunctionCall(mozIStorageValueArray* aValues,
MOZ_ALWAYS_TRUE(
indexValues.InsertElementSorted(IndexDataValue(metadata.id(),
metadata.unique(),
info.value()),
info.value(),
info.localizedValue()),
fallible));
}
@ -22362,7 +22431,8 @@ UpdateIndexDataValuesFunction::OnFunctionCall(mozIStorageValueArray* aValues,
MOZ_ALWAYS_TRUE(
indexValues.InsertElementSorted(IndexDataValue(metadata.id(),
metadata.unique(),
info.value()),
info.value(),
info.localizedValue()),
fallible));
}
}
@ -24750,9 +24820,23 @@ OpenOp::GetRangeKeyInfo(bool aLowerBound, Key* aKey, bool* aOpen)
if (range.isOnly()) {
*aKey = range.lower();
*aOpen = false;
#ifdef ENABLE_INTL_API
if (mCursor->IsLocaleAware()) {
range.lower().ToLocaleBasedKey(*aKey, mCursor->mLocale);
}
#endif
} else {
*aKey = aLowerBound ? range.lower() : range.upper();
*aOpen = aLowerBound ? range.lowerOpen() : range.upperOpen();
#ifdef ENABLE_INTL_API
if (mCursor->IsLocaleAware()) {
if (aLowerBound) {
range.lower().ToLocaleBasedKey(*aKey, mCursor->mLocale);
} else {
range.upper().ToLocaleBasedKey(*aKey, mCursor->mLocale);
}
}
#endif
}
} else {
*aOpen = false;
@ -25663,8 +25747,14 @@ ContinueOp::DoDatabaseWork(DatabaseConnection* aConnection)
NS_NAMED_LITERAL_CSTRING(rangeKeyName, "range_key");
NS_NAMED_LITERAL_CSTRING(objectKeyName, "object_key");
const Key& currentKey =
hasContinueKey ? mParams.get_ContinueParams().key() : mCursor->mKey;
const bool localeAware = mCursor->IsLocaleAware();
Key& currentKey = mCursor->mKey;
if (hasContinueKey) {
currentKey = mParams.get_ContinueParams().key();
} else if (localeAware) {
currentKey = mCursor->mSortKey;
}
const bool usingRangeKey = !mCursor->mRangeKey.IsUnset();

Просмотреть файл

@ -904,12 +904,17 @@ IDBObjectStore::AppendIndexUpdateInfo(
const KeyPath& aKeyPath,
bool aUnique,
bool aMultiEntry,
const nsCString& aLocale,
JSContext* aCx,
JS::Handle<JS::Value> aVal,
nsTArray<IndexUpdateInfo>& aUpdateInfoArray)
{
nsresult rv;
#ifdef ENABLE_INTL_API
const bool localeAware = !aLocale.IsEmpty();
#endif
if (!aMultiEntry) {
Key key;
rv = aKeyPath.ExtractKey(aCx, aVal, key);
@ -926,6 +931,14 @@ IDBObjectStore::AppendIndexUpdateInfo(
IndexUpdateInfo* updateInfo = aUpdateInfoArray.AppendElement();
updateInfo->indexId() = aIndexID;
updateInfo->value() = key;
#ifdef ENABLE_INTL_API
if (localeAware) {
rv = key.ToLocaleBasedKey(updateInfo->localizedValue(), aLocale);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
}
#endif
return NS_OK;
}
@ -960,6 +973,14 @@ IDBObjectStore::AppendIndexUpdateInfo(
IndexUpdateInfo* updateInfo = aUpdateInfoArray.AppendElement();
updateInfo->indexId() = aIndexID;
updateInfo->value() = value;
#ifdef ENABLE_INTL_API
if (localeAware) {
rv = value.ToLocaleBasedKey(updateInfo->localizedValue(), aLocale);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
}
#endif
}
}
else {
@ -973,6 +994,14 @@ IDBObjectStore::AppendIndexUpdateInfo(
IndexUpdateInfo* updateInfo = aUpdateInfoArray.AppendElement();
updateInfo->indexId() = aIndexID;
updateInfo->value() = value;
#ifdef ENABLE_INTL_API
if (localeAware) {
rv = value.ToLocaleBasedKey(updateInfo->localizedValue(), aLocale);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
}
#endif
}
return NS_OK;
@ -1126,8 +1155,9 @@ IDBObjectStore::GetAddInfo(JSContext* aCx,
const IndexMetadata& metadata = indexes[idxIndex];
rv = AppendIndexUpdateInfo(metadata.id(), metadata.keyPath(),
metadata.unique(), metadata.multiEntry(), aCx,
aValue, aUpdateInfoArray);
metadata.unique(), metadata.multiEntry(),
metadata.locale(), aCx, aValue,
aUpdateInfoArray);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -1780,10 +1810,24 @@ IDBObjectStore::CreateIndexInternal(
const IndexMetadata* oldMetadataElements =
indexes.IsEmpty() ? nullptr : indexes.Elements();
// With this setup we only validate the passed in locale name by the time we
// get to encoding Keys. Maybe we should do it here right away and error out.
// Valid locale names are always ASCII as per BCP-47.
nsCString locale = NS_LossyConvertUTF16toASCII(aOptionalParameters.mLocale);
bool autoLocale = locale.EqualsASCII("auto");
#ifdef ENABLE_INTL_API
if (autoLocale) {
locale = IndexedDatabaseManager::GetLocale();
}
#endif
IndexMetadata* metadata = indexes.AppendElement(
IndexMetadata(transaction->NextIndexId(), nsString(aName), aKeyPath,
locale,
aOptionalParameters.mUnique,
aOptionalParameters.mMultiEntry));
aOptionalParameters.mMultiEntry,
autoLocale));
if (oldMetadataElements &&
oldMetadataElements != indexes.Elements()) {

Просмотреть файл

@ -75,6 +75,7 @@ public:
const KeyPath& aKeyPath,
bool aUnique,
bool aMultiEntry,
const nsCString& aLocale,
JSContext* aCx,
JS::Handle<JS::Value> aObject,
nsTArray<IndexUpdateInfo>& aUpdateInfoArray);

Просмотреть файл

@ -56,6 +56,7 @@ struct IndexUpdateInfo
{
int64_t indexId;
Key value;
Key localizedValue;
};
union OptionalKeyRange