36 #include <nsComponentManagerUtils.h>
37 #include <nsServiceManagerUtils.h>
39 #include <nsIStringEnumerator.h>
41 #include <nsIWeakReference.h>
43 #include <nsStringGlue.h>
47 #include <sbIDatabaseQuery.h>
48 #include <sbIDatabaseResult.h>
49 #include <sbILibrary.h>
50 #include <sbIPropertyArray.h>
51 #include <sbIPropertyInfo.h>
52 #include <sbIPropertyManager.h>
53 #include <sbILocalDatabasePropertyCache.h>
54 #include <sbISQLBuilder.h>
63 #define DEFAULT_FETCH_SIZE 20
68 #define COUNT_COLUMN NS_LITERAL_STRING("count(1)")
69 #define GUID_COLUMN NS_LITERAL_STRING("guid")
70 #define OBJSORTABLE_COLUMN NS_LITERAL_STRING("obj_sortable")
71 #define MEDIAITEMID_COLUMN NS_LITERAL_STRING("media_item_id")
72 #define PROPERTIES_TABLE NS_LITERAL_STRING("resource_properties")
73 #define MEDIAITEMS_TABLE NS_LITERAL_STRING("media_items")
76 static const PRLogModuleInfo *gLocalDatabaseGUIDArrayLog = nsnull;
79 #define TRACE(args) PR_LOG(gLocalDatabaseGUIDArrayLog, PR_LOG_DEBUG, args)
80 #define LOG(args) PR_LOG(gLocalDatabaseGUIDArrayLog, PR_LOG_WARN, args)
87 mNeedNewKey(PR_FALSE),
88 mBaseConstraintValue(0),
91 mPrimarySortsCount(0),
92 mCacheMonitor(nsnull),
93 mIsDistinct(PR_FALSE),
94 mDistinctWithSortableValues(PR_FALSE),
96 mQueriesValid(PR_FALSE),
97 mNullsFirst(PR_FALSE),
98 mPrefetchedRows(PR_FALSE),
99 mIsFullLibrary(PR_FALSE),
103 if (!gLocalDatabaseGUIDArrayLog) {
104 gLocalDatabaseGUIDArrayLog = PR_NewLogModule(
"sbLocalDatabaseGUIDArray");
108 nsAutoLock::NewLock(
"sbLocalDatabaseGUIDArray::mPropIdsLock");
111 nsAutoMonitor::NewMonitor(
"sbLocalDatabaseGUIDArray::mCacheMonitor");
112 NS_WARN_IF_FALSE(mCacheMonitor,
"Failed to create mCacheMonitor.");
115 sbLocalDatabaseGUIDArray::~sbLocalDatabaseGUIDArray()
121 if(mLengthCache && !mCachedLengthKey.IsEmpty()) {
122 mLengthCache->RemoveCachedLength(mCachedLengthKey);
123 mLengthCache->RemoveCachedNonNullLength(mCachedLengthKey);
127 nsAutoMonitor::DestroyMonitor(mCacheMonitor);
131 nsAutoLock::DestroyLock(mPropIdsLock);
136 sbLocalDatabaseGUIDArray::GetDatabaseGUID(nsAString& aDatabaseGUID)
138 aDatabaseGUID = mDatabaseGUID;
143 sbLocalDatabaseGUIDArray::SetDatabaseGUID(
const nsAString& aDatabaseGUID)
145 mDatabaseGUID = aDatabaseGUID;
149 return Invalidate(PR_FALSE);
153 sbLocalDatabaseGUIDArray::GetDatabaseLocation(nsIURI** aDatabaseLocation)
155 NS_ENSURE_ARG_POINTER(aDatabaseLocation);
158 if (!mDatabaseLocation) {
159 *aDatabaseLocation = nsnull;
163 nsresult rv = mDatabaseLocation->Clone(aDatabaseLocation);
164 NS_ENSURE_SUCCESS(rv, rv);
170 sbLocalDatabaseGUIDArray::SetDatabaseLocation(nsIURI* aDatabaseLocation)
172 mDatabaseLocation = aDatabaseLocation;
176 return Invalidate(PR_FALSE);
180 sbLocalDatabaseGUIDArray::GetBaseTable(nsAString& aBaseTable)
182 aBaseTable = mBaseTable;
187 sbLocalDatabaseGUIDArray::SetBaseTable(
const nsAString& aBaseTable)
189 mBaseTable = aBaseTable;
193 return Invalidate(PR_FALSE);
197 sbLocalDatabaseGUIDArray::GetBaseConstraintColumn(nsAString& aBaseConstraintColumn)
199 aBaseConstraintColumn = mBaseConstraintColumn;
204 sbLocalDatabaseGUIDArray::SetBaseConstraintColumn(
const nsAString& aBaseConstraintColumn)
206 mBaseConstraintColumn = aBaseConstraintColumn;
210 return Invalidate(PR_FALSE);
214 sbLocalDatabaseGUIDArray::GetBaseConstraintValue(PRUint32 *aBaseConstraintValue)
216 NS_ENSURE_ARG_POINTER(aBaseConstraintValue);
217 *aBaseConstraintValue = mBaseConstraintValue;
222 sbLocalDatabaseGUIDArray::SetBaseConstraintValue(PRUint32 aBaseConstraintValue)
224 mBaseConstraintValue = aBaseConstraintValue;
228 return Invalidate(PR_FALSE);
232 sbLocalDatabaseGUIDArray::GetFetchSize(PRUint32 *aFetchSize)
234 NS_ENSURE_ARG_POINTER(aFetchSize);
235 *aFetchSize = mFetchSize;
240 sbLocalDatabaseGUIDArray::SetFetchSize(PRUint32 aFetchSize)
242 mFetchSize = aFetchSize;
248 sbLocalDatabaseGUIDArray::GetIsDistinct(PRBool *aIsDistinct)
250 NS_ENSURE_ARG_POINTER(aIsDistinct);
251 *aIsDistinct = mIsDistinct;
255 sbLocalDatabaseGUIDArray::SetIsDistinct(PRBool aIsDistinct)
257 mIsDistinct = aIsDistinct;
261 return Invalidate(PR_FALSE);
265 sbLocalDatabaseGUIDArray::GetIsValid(PRBool *aIsValid)
267 NS_ENSURE_ARG_POINTER(aIsValid);
273 sbLocalDatabaseGUIDArray::GetDistinctWithSortableValues(PRBool *aDistinctWithSortableValues)
275 NS_ENSURE_ARG_POINTER(aDistinctWithSortableValues);
276 *aDistinctWithSortableValues = mDistinctWithSortableValues;
281 sbLocalDatabaseGUIDArray::SetDistinctWithSortableValues(PRBool aDistinctWithSortableValues)
283 mDistinctWithSortableValues = aDistinctWithSortableValues;
287 return Invalidate(PR_FALSE);
294 NS_ENSURE_ARG_POINTER(aListener);
298 nsCOMPtr<sbILocalDatabaseGUIDArrayListener>
listener =
299 do_QueryReferent(mListener, &rv);
300 NS_ENSURE_SUCCESS(rv, rv);
303 NS_ADDREF(*aListener = listener);
318 mListener = do_GetWeakReference(aListener, &rv);
323 NS_ENSURE_SUCCESS(rv, rv);
331 NS_ENSURE_ARG_POINTER(aPropertyCache);
332 NS_IF_ADDREF(*aPropertyCache = mPropertyCache);
341 mPropertyCache->RemoveDependentGUIDArray(
this);
344 mPropertyCache = aPropertyCache;
348 mPropertyCache->AddDependentGUIDArray(
this);
355 sbLocalDatabaseGUIDArray::GetLength(PRUint32 *aLength)
357 NS_ENSURE_ARG_POINTER(aLength);
360 if (mValid == PR_FALSE) {
362 NS_ENSURE_SUCCESS(rv, rv);
371 sbLocalDatabaseGUIDArray::SetLengthCache(
374 mLengthCache = aLengthCache;
380 sbLocalDatabaseGUIDArray::GetLengthCache(
383 NS_ENSURE_ARG_POINTER(aLengthCache);
385 NS_IF_ADDREF(*aLengthCache = mLengthCache);
390 nsresult sbLocalDatabaseGUIDArray::AddSortInternal(
const nsAString& aProperty,
395 SortSpec* ss = mSorts.AppendElement();
396 NS_ENSURE_TRUE(ss, NS_ERROR_OUT_OF_MEMORY);
400 !mBaseTable.Equals(NS_LITERAL_STRING(
"simple_media_lists"))) {
401 NS_WARNING(
"Trying to sort by ordinal on a non-media list");
405 ss->property = aProperty;
407 ss->ascending = aAscending;
408 ss->secondary = aSecondary;
410 if (mPropertyCache) {
411 nsresult rv = mPropertyCache->GetPropertyDBID(aProperty, &ss->propertyId);
412 NS_ENSURE_SUCCESS(rv, rv);
418 nsresult sbLocalDatabaseGUIDArray::ClearSecondarySorts() {
419 for (PRUint32
i = 0;
i < mSorts.Length();
i++) {
420 const SortSpec& ss = mSorts[
i];
422 mSorts.RemoveElementAt(
i);
434 const PRUint32 * FindPropID(
const PRUint32 * aPropIDs,
438 const PRUint32 * result = std::lower_bound(aPropIDs, aPropIDs + aCount, aPropID);
439 if (result != aPropIDs + aCount && *result == aPropID) {
447 sbLocalDatabaseGUIDArray::MayInvalidate(PRUint32 * aDirtyPropIDs,
450 PRUint32 propertyDBID = 0;
451 nsresult rv = NS_ERROR_UNEXPECTED;
456 nsAutoLock mon(mPropIdsLock);
457 for (PRUint32 index = 0; index <
aCount; ++index) {
458 std::set<PRUint32>::iterator itEntry =
459 mPropIdsUsedInCacheKey.find(aDirtyPropIDs[index]);
460 if(itEntry != mPropIdsUsedInCacheKey.end()) {
461 mLengthCache->RemoveCachedLength(mCachedLengthKey);
462 mLengthCache->RemoveCachedNonNullLength(mCachedLengthKey);
469 const PRUint32 *
const dirtyPropIDsEnd = aDirtyPropIDs +
aCount;
472 PRUint32 filterCount = mFilters.Length();
473 for (PRUint32 index = 0; index < filterCount; index++) {
474 const FilterSpec& refSpec = mFilters.ElementAt(index);
476 rv = mPropertyCache->GetPropertyDBID(refSpec.property, &propertyDBID);
481 const PRUint32 *
const found = FindPropID(aDirtyPropIDs,
485 if (found != dirtyPropIDsEnd) {
487 return Invalidate(PR_TRUE);
492 PRUint32 sortCount = mSorts.Length();
493 for (PRUint32 index = 0; index < sortCount; index++) {
494 const SortSpec& sortSpec = mSorts.ElementAt(index);
496 const PRUint32 *
const found = FindPropID(aDirtyPropIDs,
498 sortSpec.propertyId);
499 if (found != dirtyPropIDsEnd) {
501 return Invalidate(PR_TRUE);
509 sbLocalDatabaseGUIDArray::AddSort(
const nsAString& aProperty,
516 rv = ClearSecondarySorts();
517 NS_ENSURE_SUCCESS(rv, rv);
520 rv = AddSortInternal(aProperty, aAscending, PR_FALSE);
521 NS_ENSURE_SUCCESS(rv, rv);
523 mPrimarySortsCount++;
529 NS_ENSURE_SUCCESS(rv, rv);
533 nsCOMPtr<sbIPropertyInfo> propertyInfo;
534 rv = mPropMan->GetPropertyInfo(aProperty,
535 getter_AddRefs(propertyInfo));
536 NS_ENSURE_SUCCESS(rv, rv);
538 nsCOMPtr<sbIPropertyArray> secondarySortProperties;
540 propertyInfo->GetSecondarySort(getter_AddRefs(secondarySortProperties));
541 NS_ENSURE_SUCCESS(rv, rv);
543 if (secondarySortProperties) {
544 PRUint32 secondarySortPropertyCount;
545 rv = secondarySortProperties->GetLength(&secondarySortPropertyCount);
546 NS_ENSURE_SUCCESS(rv, rv);
549 for (PRUint32
i=0;
i<secondarySortPropertyCount;
i++) {
550 nsCOMPtr<sbIProperty> property;
551 rv = secondarySortProperties->GetPropertyAt(
i, getter_AddRefs(property));
556 NS_ASSERTION(NS_SUCCEEDED(rv),
"Failed to get dependent property!");
557 if (NS_SUCCEEDED(rv)) {
559 rv =
property->GetId(propertyID);
560 NS_ASSERTION(NS_SUCCEEDED(rv),
"Failed to get dependent property ID!");
561 if (NS_SUCCEEDED(rv)) {
562 nsString propertyValue;
563 rv =
property->GetValue(propertyValue);
564 NS_ASSERTION(NS_SUCCEEDED(rv),
565 "Failed to get dependent property value!");
566 if (NS_SUCCEEDED(rv)) {
567 AddSortInternal(propertyID,
568 propertyValue.EqualsLiteral(
"a"),
580 return Invalidate(PR_FALSE);
584 sbLocalDatabaseGUIDArray::ClearSorts()
588 mPrimarySortsCount = 0;
592 return Invalidate(PR_FALSE);
598 NS_ENSURE_ARG_POINTER(aCurrentSort);
602 nsCOMPtr<sbIMutablePropertyArray> sort =
604 NS_ENSURE_SUCCESS(rv, rv);
606 rv = sort->SetStrict(PR_FALSE);
607 NS_ENSURE_SUCCESS(rv, rv);
609 for (PRUint32
i = 0;
i < mSorts.Length();
i++) {
610 const SortSpec& ss = mSorts[
i];
612 rv = sort->AppendProperty(ss.property,
613 ss.ascending ? NS_LITERAL_STRING(
"a") :
614 NS_LITERAL_STRING(
"d"));
615 NS_ENSURE_SUCCESS(rv, rv);
619 NS_ADDREF(*aCurrentSort = sort);
624 sbLocalDatabaseGUIDArray::AddFilter(
const nsAString& aProperty,
628 NS_ENSURE_ARG_POINTER(aValues);
632 FilterSpec* fs = mFilters.AppendElement();
633 NS_ENSURE_TRUE(fs, NS_ERROR_OUT_OF_MEMORY);
635 fs->property = aProperty;
636 fs->isSearch = aIsSearch;
640 rv = aValues->HasMore(&hasMore);
641 NS_ENSURE_SUCCESS(rv, rv);
644 rv = aValues->GetNext(s);
645 NS_ENSURE_SUCCESS(rv, rv);
646 nsString* success = fs->values.AppendElement(s);
647 NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
648 rv = aValues->HasMore(&hasMore);
649 NS_ENSURE_SUCCESS(rv, rv);
654 return Invalidate(PR_FALSE);
658 sbLocalDatabaseGUIDArray::ClearFilters()
664 return Invalidate(PR_FALSE);
668 sbLocalDatabaseGUIDArray::IsIndexCached(PRUint32 aIndex,
671 NS_ENSURE_ARG_POINTER(_retval);
674 nsAutoMonitor mon(mCacheMonitor);
675 if (aIndex < mCache.Length()) {
676 ArrayItem* item = mCache[aIndex];
689 sbLocalDatabaseGUIDArray::GetSortPropertyValueByIndex(PRUint32 aIndex,
695 rv = GetByIndexInternal(aIndex, &item);
696 if (rv == NS_ERROR_INVALID_ARG) {
699 NS_ENSURE_SUCCESS(rv, rv);
701 _retval.Assign(item->sortPropertyValue);
706 sbLocalDatabaseGUIDArray::GetMediaItemIdByIndex(PRUint32 aIndex,
709 NS_ENSURE_ARG_POINTER(_retval);
714 rv = GetByIndexInternal(aIndex, &item);
715 if (rv == NS_ERROR_INVALID_ARG) {
718 NS_ENSURE_SUCCESS(rv, rv);
720 *_retval = item->mediaItemId;
725 sbLocalDatabaseGUIDArray::GetOrdinalByIndex(PRUint32 aIndex,
731 rv = GetByIndexInternal(aIndex, &item);
732 if (rv == NS_ERROR_INVALID_ARG) {
735 NS_ENSURE_SUCCESS(rv, rv);
737 _retval.Assign(item->ordinal);
742 sbLocalDatabaseGUIDArray::GetGuidByIndex(PRUint32 aIndex,
748 rv = GetByIndexInternal(aIndex, &item);
749 if (rv == NS_ERROR_INVALID_ARG) {
752 NS_ENSURE_SUCCESS(rv, rv);
754 _retval.Assign(item->guid);
759 sbLocalDatabaseGUIDArray::GetRowidByIndex(PRUint32 aIndex,
762 NS_ENSURE_ARG_POINTER(_retval);
766 rv = GetByIndexInternal(aIndex, &item);
767 if (rv == NS_ERROR_INVALID_ARG) {
770 NS_ENSURE_SUCCESS(rv, rv);
772 *_retval = item->rowid;
777 sbLocalDatabaseGUIDArray::GetViewItemUIDByIndex(PRUint32 aIndex,
783 rv = GetByIndexInternal(aIndex, &item);
784 if (rv == NS_ERROR_INVALID_ARG) {
787 NS_ENSURE_SUCCESS(rv, rv);
794 _retval.AppendInt(item->mediaItemId);
799 sbLocalDatabaseGUIDArray::Invalidate(PRBool aInvalidateLength)
801 TRACE((
"sbLocalDatabaseGUIDArray[0x%.8x] - Invalidate",
this));
808 if (aInvalidateLength) {
810 mLengthCache->RemoveCachedLength(mCachedLengthKey);
811 mLengthCache->RemoveCachedNonNullLength(mCachedLengthKey);
815 mNeedNewKey = PR_TRUE;
818 if (mValid == PR_FALSE || mSuppress > 0) {
823 nsCOMPtr<sbILocalDatabaseGUIDArrayListener>
listener;
824 rv = GetMTListener(getter_AddRefs(listener));
825 NS_ENSURE_SUCCESS(rv, rv);
828 listener->OnBeforeInvalidate(aInvalidateLength);
833 nsAutoMonitor mon(mCacheMonitor);
836 mGuidToFirstIndexMap.Clear();
837 mViewItemUIDToIndexMap.Clear();
838 mPrefetchedRows = PR_FALSE;
840 if (mPrimarySortKeyPositionCache.IsInitialized()) {
841 mPrimarySortKeyPositionCache.Clear();
847 rv = GetMTListener(getter_AddRefs(listener));
848 NS_ENSURE_SUCCESS(rv, rv);
850 listener->OnAfterInvalidate();
863 NS_ENSURE_ARG_POINTER(_retval);
867 NS_ENSURE_TRUE(newArray, NS_ERROR_OUT_OF_MEMORY);
869 nsCOMPtr<sbILocalDatabaseGUIDArray> guidArray(newArray);
870 nsresult rv = CloneInto(guidArray);
871 NS_ENSURE_SUCCESS(rv, rv);
873 guidArray.forget(_retval);
881 NS_ENSURE_ARG_POINTER(aDest);
883 nsresult rv = aDest->SetDatabaseGUID(mDatabaseGUID);
884 NS_ENSURE_SUCCESS(rv, rv);
886 rv = aDest->SetDatabaseLocation(mDatabaseLocation);
887 NS_ENSURE_SUCCESS(rv, rv);
889 rv = aDest->SetBaseTable(mBaseTable);
890 NS_ENSURE_SUCCESS(rv, rv);
892 rv = aDest->SetBaseConstraintColumn(mBaseConstraintColumn);
893 NS_ENSURE_SUCCESS(rv, rv);
895 rv = aDest->SetBaseConstraintValue(mBaseConstraintValue);
896 NS_ENSURE_SUCCESS(rv, rv);
898 rv = aDest->SetFetchSize(mFetchSize);
899 NS_ENSURE_SUCCESS(rv, rv);
901 rv = aDest->SetPropertyCache(mPropertyCache);
902 NS_ENSURE_SUCCESS(rv, rv);
904 rv = aDest->SetIsDistinct(mIsDistinct);
905 NS_ENSURE_SUCCESS(rv, rv);
907 rv = aDest->SetDistinctWithSortableValues(mDistinctWithSortableValues);
908 NS_ENSURE_SUCCESS(rv, rv);
910 PRUint32 sortCount = mSorts.Length();
911 for (PRUint32 index = 0; index < sortCount; index++) {
912 const SortSpec refSpec = mSorts.ElementAt(index);
913 if (!refSpec.secondary) {
914 rv = aDest->AddSort(refSpec.property, refSpec.ascending);
915 NS_ENSURE_SUCCESS(rv, rv);
919 PRUint32 filterCount = mFilters.Length();
920 for (PRUint32 index = 0; index < filterCount; index++) {
921 const FilterSpec refSpec = mFilters.ElementAt(index);
923 nsTArray<nsString>* stringArray =
924 const_cast<nsTArray<nsString>*
>(&refSpec.values);
925 NS_ENSURE_STATE(stringArray);
927 nsCOMPtr<nsIStringEnumerator> enumerator =
929 NS_ENSURE_TRUE(enumerator, NS_ERROR_OUT_OF_MEMORY);
931 rv = aDest->AddFilter(refSpec.property, enumerator, refSpec.isSearch);
932 NS_ENSURE_SUCCESS(rv, rv);
935 rv = aDest->SetLengthCache(mLengthCache);
936 NS_ENSURE_SUCCESS(rv, rv);
942 sbLocalDatabaseGUIDArray::RemoveByIndex(PRUint32 aIndex)
946 nsAutoMonitor mon(mCacheMonitor);
948 if (mValid == PR_FALSE) {
950 NS_ENSURE_SUCCESS(rv, rv);
953 NS_ENSURE_TRUE(aIndex < mLength, NS_ERROR_INVALID_ARG);
957 if (aIndex < mCache.Length()) {
959 rv = GetGuidByIndex(aIndex, guid);
960 NS_ENSURE_SUCCESS(rv, rv);
961 mGuidToFirstIndexMap.Remove(guid);
963 nsString viewItemUID;
964 rv = GetViewItemUIDByIndex(aIndex, viewItemUID);
965 NS_ENSURE_SUCCESS(rv, rv);
967 mViewItemUIDToIndexMap.Remove(viewItemUID);
969 mCache.RemoveElementAt(aIndex);
976 if (aIndex < mNonNullLength) {
981 if (aIndex > mLength - mNonNullLength - 1) {
991 mLengthCache->RemoveCachedLength(mCachedLengthKey);
992 mLengthCache->RemoveCachedNonNullLength(mCachedLengthKey);
999 sbLocalDatabaseGUIDArray::GetFirstIndexByPrefix(
const nsAString&
aValue,
1002 NS_ENSURE_ARG_POINTER(_retval);
1007 if (mValid == PR_FALSE) {
1009 NS_ENSURE_SUCCESS(rv, rv);
1012 nsCOMPtr<sbIDatabaseQuery> query;
1013 rv = MakeQuery(mPrefixSearchStatement, getter_AddRefs(query));
1014 NS_ENSURE_SUCCESS(rv, rv);
1016 rv = query->BindStringParameter(0, aValue);
1017 NS_ENSURE_SUCCESS(rv, rv);
1019 rv = query->Execute(&dbOk);
1020 NS_ENSURE_SUCCESS(rv, rv);
1021 NS_ENSURE_TRUE(dbOk == 0, NS_ERROR_FAILURE);
1023 nsCOMPtr<sbIDatabaseResult> result;
1024 rv = query->GetResultObject(getter_AddRefs(result));
1025 NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
1028 rv = result->GetRowCount(&rowCount);
1029 NS_ENSURE_SUCCESS(rv, rv);
1031 if (rowCount == 0) {
1036 nsAutoString indexStr;
1037 rv = result->GetRowCell(0, 0, indexStr);
1038 NS_ENSURE_SUCCESS(rv, rv);
1041 index = indexStr.ToInteger(&rv);
1042 NS_ENSURE_SUCCESS(rv, rv);
1045 if (index == mNonNullLength) {
1046 return NS_ERROR_NOT_AVAILABLE;
1052 rv = GetSortPropertyValueByIndex(index, value);
1053 NS_ENSURE_SUCCESS(rv, rv);
1055 if (!StringBeginsWith(value, aValue)) {
1056 return NS_ERROR_NOT_AVAILABLE;
1064 sbLocalDatabaseGUIDArray::GetFirstIndexByGuid(
const nsAString& aGuid,
1067 TRACE((
"sbLocalDatabaseGUIDArray[0x%.8x] - GetFirstIndexByGuid",
this));
1069 NS_ENSURE_ARG_POINTER(_retval);
1073 nsAutoMonitor mon(mCacheMonitor);
1075 if (mValid == PR_FALSE) {
1077 NS_ENSURE_SUCCESS(rv, rv);
1082 PRBool uniqueGuids = PR_TRUE;
1083 if (mBaseTable.EqualsLiteral(
"simple_media_lists")) {
1084 uniqueGuids = PR_FALSE;
1087 PRUint32 firstUncached = 0;
1092 if (mGuidToFirstIndexMap.Get(aGuid, _retval)) {
1098 if (mCache.Length() == mLength) {
1099 return NS_ERROR_NOT_AVAILABLE;
1103 PRBool found = PR_FALSE;
1104 for (PRUint32
i = 0; !found &&
i < mCache.Length();
i++) {
1113 if (!found && mCache.Length() == mLength) {
1114 return NS_ERROR_NOT_AVAILABLE;
1120 PRBool foundFirstUncached = PR_FALSE;
1121 for (PRUint32
i = 0; !foundFirstUncached &&
i < mCache.Length();
i++) {
1122 ArrayItem* item = mCache[
i];
1124 if (item->guid.Equals(aGuid)) {
1131 foundFirstUncached = PR_TRUE;
1137 if (!foundFirstUncached && mCache.Length() == mLength) {
1138 return NS_ERROR_NOT_AVAILABLE;
1144 rv = FetchRows(firstUncached, mLength);
1145 NS_ENSURE_SUCCESS(rv, rv);
1147 NS_ASSERTION(mLength == mCache.Length(),
"Full read didn't work");
1150 if (mGuidToFirstIndexMap.Get(aGuid, _retval)) {
1154 return NS_ERROR_NOT_AVAILABLE;
1160 sbLocalDatabaseGUIDArray::GetIndexByViewItemUID
1161 (
const nsAString& aViewItemUID,
1164 TRACE((
"sbLocalDatabaseGUIDArray[0x%.8x] - GetIndexByRowid",
this));
1165 NS_ENSURE_ARG_POINTER(_retval);
1169 nsAutoMonitor mon(mCacheMonitor);
1171 if (mValid == PR_FALSE) {
1173 NS_ENSURE_SUCCESS(rv, rv);
1177 if (mViewItemUIDToIndexMap.Get(aViewItemUID, _retval)) {
1181 PRUint32 firstUncached = 0;
1185 PRBool found = PR_FALSE;
1186 for (PRUint32
i = 0; !found &&
i < mCache.Length();
i++) {
1194 if (!found && mLength == mCache.Length()) {
1195 return NS_ERROR_NOT_AVAILABLE;
1198 rv = FetchRows(firstUncached, mLength);
1199 NS_ENSURE_SUCCESS(rv, rv);
1200 NS_ASSERTION(mLength == mCache.Length(),
"Full read didn't work");
1203 if (mViewItemUIDToIndexMap.Get(aViewItemUID, _retval)) {
1207 return NS_ERROR_NOT_AVAILABLE;
1211 sbLocalDatabaseGUIDArray::ContainsGuid(
const nsAString& aGuid,
1214 TRACE((
"sbLocalDatabaseGUIDArray[0x%.8x] - ContainsGuid",
this));
1215 NS_ENSURE_ARG_POINTER(_retval);
1218 nsAutoMonitor mon(mCacheMonitor);
1220 if (mValid == PR_FALSE) {
1222 NS_ENSURE_SUCCESS(rv, rv);
1231 if (mGuidToFirstIndexMap.Get(aGuid, &index)) {
1236 PRUint32 firstUncached = 0;
1239 if (mCache.Length() == mLength) {
1240 *_retval = PR_FALSE;
1245 PRBool found = PR_FALSE;
1246 for (PRUint32
i = 0; !found &&
i < mCache.Length();
i++) {
1255 if (!found && mCache.Length() == mLength) {
1256 *_retval = PR_FALSE;
1262 rv = FetchRows(firstUncached, mLength);
1263 NS_ENSURE_SUCCESS(rv, rv);
1264 NS_ASSERTION(mLength == mCache.Length(),
"Full read didn't work");
1267 *_retval = mGuidToFirstIndexMap.Get(aGuid, &index);
1272 sbLocalDatabaseGUIDArray::SuppressInvalidation(PRBool aSuppress)
1277 else if(--mSuppress <= 0) {
1285 nsresult rv = Invalidate(PR_FALSE);
1286 NS_ENSURE_SUCCESS(rv, rv);
1293 sbLocalDatabaseGUIDArray::Initialize()
1295 TRACE((
"sbLocalDatabaseGUIDArray[0x%.8x] - Initialize",
this));
1296 NS_ASSERTION(mPropertyCache,
"No property cache!");
1298 nsresult rv = NS_ERROR_UNEXPECTED;
1301 if (mDatabaseGUID.IsEmpty() || mBaseTable.IsEmpty()) {
1302 return NS_ERROR_UNEXPECTED;
1306 if (mSorts.Length() == 0) {
1307 return NS_ERROR_UNEXPECTED;
1310 if (!mGuidToFirstIndexMap.IsInitialized()) {
1311 PRBool success = mGuidToFirstIndexMap.Init();
1312 NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
1315 if (!mViewItemUIDToIndexMap.IsInitialized()) {
1316 PRBool success = mViewItemUIDToIndexMap.Init();
1317 NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
1320 if (mValid == PR_TRUE) {
1323 rv = Invalidate(PR_FALSE);
1324 NS_ENSURE_SUCCESS(rv, rv);
1327 rv = mPropertyCache->Write();
1328 NS_ENSURE_SUCCESS(rv, rv);
1330 rv = UpdateQueries();
1331 NS_ENSURE_SUCCESS(rv, rv);
1333 rv = UpdateLength();
1334 NS_ENSURE_SUCCESS(rv, rv);
1342 NS_ENSURE_SUCCESS(rv, rv);
1345 nsCOMPtr<sbIPropertyInfo> info;
1346 rv = mPropMan->GetPropertyInfo(mSorts[0].property, getter_AddRefs(info));
1347 NS_ENSURE_SUCCESS(rv, rv);
1350 rv = info->GetNullSort(&nullSort);
1351 NS_ENSURE_SUCCESS(rv, rv);
1355 mNullsFirst = mSorts[0].ascending;
1358 mNullsFirst = !mSorts[0].ascending;
1361 mNullsFirst = PR_TRUE;
1364 mNullsFirst = PR_FALSE;
1369 mStatementX = mNullGuidRangeStatement;
1370 mStatementY = mFullGuidRangeStatement;
1371 mLengthX = mLength - mNonNullLength;
1374 mStatementX = mFullGuidRangeStatement;
1375 mStatementY = mNullGuidRangeStatement;
1376 mLengthX = mNonNullLength;
1381 mHasActiveSearch = PR_FALSE;
1382 PRUint32 filterCount = mFilters.Length();
1383 for (PRUint32 index = 0; index < filterCount; index++) {
1384 const FilterSpec& refSpec = mFilters.ElementAt(index);
1386 nsTArray<nsString>* stringArray =
1387 const_cast<nsTArray<nsString>*
>(&refSpec.values);
1388 NS_ENSURE_STATE(stringArray);
1390 if (refSpec.isSearch && stringArray->Length() > 0) {
1391 mHasActiveSearch = PR_TRUE;
1402 sbLocalDatabaseGUIDArray::UpdateLength()
1406 nsAutoMonitor mon(mCacheMonitor);
1414 mNonNullCountQuery.IsEmpty() && mNullGuidRangeQuery.IsEmpty())
1416 rv = ReadRowRange(mFullGuidRangeStatement,
1421 NS_ENSURE_SUCCESS(rv, rv);
1423 mLength = mCache.Length();
1424 mNonNullLength = mLength;
1428 if (mCachedLengthKey.IsEmpty() || mNeedNewKey) {
1429 GenerateCachedLengthKey();
1430 mNeedNewKey = PR_FALSE;
1433 rv = mLengthCache->GetCachedLength(mCachedLengthKey, &mLength);
1437 rv = RunLengthQuery(mFullCountStatement, &mLength);
1438 NS_ENSURE_SUCCESS(rv, rv);
1440 rv = mLengthCache->AddCachedLength(mCachedLengthKey, mLength);
1441 NS_ENSURE_SUCCESS(rv, rv);
1445 rv = RunLengthQuery(mFullCountStatement, &mLength);
1446 NS_ENSURE_SUCCESS(rv, rv);
1450 if (!mNonNullCountQuery.IsEmpty()) {
1452 rv = mLengthCache->GetCachedNonNullLength(mCachedLengthKey,
1456 rv = RunLengthQuery(mNonNullCountStatement, &mNonNullLength);
1457 NS_ENSURE_SUCCESS(rv, rv);
1459 rv = mLengthCache->AddCachedNonNullLength(mCachedLengthKey, mLength);
1460 NS_ENSURE_SUCCESS(rv, rv);
1464 rv = RunLengthQuery(mNonNullCountStatement, &mNonNullLength);
1465 NS_ENSURE_SUCCESS(rv, rv);
1469 mNonNullLength = mLength;
1483 nsCOMPtr<sbIDatabaseQuery> query;
1484 rv = MakeQuery(aStatement, getter_AddRefs(query));
1485 NS_ENSURE_SUCCESS(rv, rv);
1488 rv = query->Execute(&dbOk);
1489 NS_ENSURE_SUCCESS(rv, rv);
1490 NS_ENSURE_TRUE(dbOk == 0, NS_ERROR_FAILURE);
1492 nsCOMPtr<sbIDatabaseResult> result;
1493 rv = query->GetResultObject(getter_AddRefs(result));
1494 NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
1497 rv = result->GetRowCount(&rowCount);
1498 NS_ENSURE_SUCCESS(rv, rv);
1501 NS_ENSURE_TRUE(rowCount == 1, NS_ERROR_UNEXPECTED);
1503 nsAutoString countStr;
1504 rv = result->GetRowCell(0, 0, countStr);
1505 NS_ENSURE_SUCCESS(rv, rv);
1507 *_retval = countStr.ToInteger(&rv);
1508 NS_ENSURE_SUCCESS(rv, rv);
1514 sbLocalDatabaseGUIDArray::UpdateQueries()
1517 if (mQueriesValid) {
1530 nsCOMPtr<sbIDatabaseQuery> query =
1532 NS_ENSURE_SUCCESS(rv, rv);
1534 rv = query->SetDatabaseGUID(mDatabaseGUID);
1535 NS_ENSURE_SUCCESS(rv, rv);
1537 if (mDatabaseLocation) {
1538 rv = query->SetDatabaseLocation(mDatabaseLocation);
1539 NS_ENSURE_SUCCESS(rv, rv);
1554 nsAutoPtr<sbLocalDatabaseQuery> ldq;
1557 mBaseConstraintColumn,
1558 mBaseConstraintValue,
1559 NS_LITERAL_STRING(
"member_media_item_id"),
1563 mDistinctWithSortableValues,
1567 rv = ldq->GetFullCountQuery(mFullCountQuery);
1568 NS_ENSURE_SUCCESS(rv, rv);
1570 rv = query->PrepareQuery(mFullCountQuery,
1571 getter_AddRefs(mFullCountStatement));
1572 NS_ENSURE_SUCCESS(rv, rv);
1575 rv = ldq->GetFullGuidRangeQuery(mFullGuidRangeQuery);
1576 NS_ENSURE_SUCCESS(rv, rv);
1578 rv = query->PrepareQuery(mFullGuidRangeQuery,
1579 getter_AddRefs(mFullGuidRangeStatement));
1580 NS_ENSURE_SUCCESS(rv, rv);
1583 rv = ldq->GetNonNullCountQuery(mNonNullCountQuery);
1584 NS_ENSURE_SUCCESS(rv, rv);
1586 rv = query->PrepareQuery(mNonNullCountQuery,
1587 getter_AddRefs(mNonNullCountStatement));
1588 NS_ENSURE_SUCCESS(rv, rv);
1591 rv = ldq->GetNullGuidRangeQuery(mNullGuidRangeQuery);
1592 NS_ENSURE_SUCCESS(rv, rv);
1594 rv = query->PrepareQuery(mNullGuidRangeQuery,
1595 getter_AddRefs(mNullGuidRangeStatement));
1596 NS_ENSURE_SUCCESS(rv, rv);
1599 rv = ldq->GetPrefixSearchQuery(mPrefixSearchQuery);
1600 NS_ENSURE_SUCCESS(rv, rv);
1602 rv = query->PrepareQuery(mPrefixSearchQuery,
1603 getter_AddRefs(mPrefixSearchStatement));
1604 NS_ENSURE_SUCCESS(rv, rv);
1612 PRUint32 numSorts = mSorts.Length();
1613 if (numSorts > 1 && !mIsDistinct) {
1614 rv = ldq->GetResortQuery(mResortQuery);
1615 NS_ENSURE_SUCCESS(rv, rv);
1617 rv = query->PrepareQuery(mResortQuery,
1618 getter_AddRefs(mResortStatement));
1619 NS_ENSURE_SUCCESS(rv, rv);
1621 rv = ldq->GetNullResortQuery(mNullResortQuery);
1622 NS_ENSURE_SUCCESS(rv, rv);
1624 rv = query->PrepareQuery(mNullResortQuery,
1625 getter_AddRefs(mNullResortStatement));
1626 NS_ENSURE_SUCCESS(rv, rv);
1631 rv = ldq->GetPrefixSearchQuery(mPrimarySortKeyPositionQuery);
1632 NS_ENSURE_SUCCESS(rv, rv);
1634 rv = query->PrepareQuery(mPrimarySortKeyPositionQuery,
1635 getter_AddRefs(mPrimarySortKeyPositionStatement));
1636 NS_ENSURE_SUCCESS(rv, rv);
1639 mIsFullLibrary = ldq->GetIsFullLibrary();
1641 mQueriesValid = PR_TRUE;
1645 GenerateCachedLengthKey();
1654 NS_ENSURE_ARG_POINTER(_retval);
1659 nsString queryString;
1660 rv = aStatement->GetQueryString(queryString);
1661 if (NS_SUCCEEDED(rv)) {
1662 LOG((
"sbLocalDatabaseGUIDArray[0x%.8x] - MakeQuery: %s",
1663 this, NS_ConvertUTF16toUTF8(queryString).
get()));
1667 nsCOMPtr<sbIDatabaseQuery> query =
1669 NS_ENSURE_SUCCESS(rv, rv);
1671 rv = query->SetDatabaseGUID(mDatabaseGUID);
1672 NS_ENSURE_SUCCESS(rv, rv);
1674 if (mDatabaseLocation) {
1675 rv = query->SetDatabaseLocation(mDatabaseLocation);
1676 NS_ENSURE_SUCCESS(rv, rv);
1679 rv = query->AddPreparedStatement(aStatement);
1680 NS_ENSURE_SUCCESS(rv, rv);
1682 NS_ADDREF(*_retval = query);
1687 sbLocalDatabaseGUIDArray::FetchRows(PRUint32 aRequestedIndex,
1688 PRUint32 aFetchSize)
1698 if (mValid == PR_FALSE)
1731 PRUint32 indexB = mLengthX;
1732 PRUint32 indexC = mLength - 1;
1736 aFetchSize = mLength;
1744 PRUint32 cell = aRequestedIndex / aFetchSize;
1746 PRUint32 indexD = cell * aFetchSize;
1747 PRUint32 indexE = indexD + aFetchSize - 1;
1748 if (indexE > indexC) {
1751 PRUint32 lengthDE = indexE - indexD + 1;
1756 if (indexE < indexB) {
1757 rv = ReadRowRange(mStatementX,
1762 NS_ENSURE_SUCCESS(rv, rv);
1768 if (indexD >= indexB) {
1769 rv = ReadRowRange(mStatementY,
1774 NS_ENSURE_SUCCESS(rv, rv);
1781 rv = ReadRowRange(mStatementX,
1786 NS_ENSURE_SUCCESS(rv, rv);
1788 rv = ReadRowRange(mStatementY,
1790 indexE - indexB + 1,
1793 NS_ENSURE_SUCCESS(rv, rv);
1817 PRUint32 aStartIndex,
1819 PRUint32 aDestIndexOffset,
1825 NS_ENSURE_ARG_MIN(aStartIndex, 0);
1826 NS_ENSURE_ARG_MIN(aCount, 1);
1827 NS_ENSURE_ARG_MIN(aDestIndexOffset, 0);
1829 LOG((
"ReadRowRange start %d count %d dest offset %d isnull %d\n",
1841 nsCOMPtr<sbIDatabaseQuery> query;
1842 rv = MakeQuery(aStatement, getter_AddRefs(query));
1843 NS_ENSURE_SUCCESS(rv, rv);
1845 rv = query->BindInt64Parameter(0, aCount);
1846 NS_ENSURE_SUCCESS(rv, rv);
1848 rv = query->BindInt32Parameter(1, aStartIndex);
1849 NS_ENSURE_SUCCESS(rv, rv);
1851 rv = query->Execute(&dbOk);
1852 NS_ENSURE_SUCCESS(rv, rv);
1853 NS_ENSURE_TRUE(dbOk == 0, NS_ERROR_FAILURE);
1855 nsCOMPtr<sbIDatabaseResult> result;
1856 rv = query->GetResultObject(getter_AddRefs(result));
1857 NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
1860 rv = result->GetRowCount(&rowCount);
1861 NS_ENSURE_SUCCESS(rv, rv);
1879 PRBool needsSorting = (mPrimarySortsCount > 1) ||
1880 (mSorts.Length() > 1 && aIsNull);
1885 if (mCache.Length() < aDestIndexOffset +
aCount) {
1886 LOG((
"SetLength %d to %d", mCache.Length(), aDestIndexOffset +
aCount));
1887 PRBool success = mCache.SetLength(aDestIndexOffset + aCount);
1888 NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
1891 nsAutoString lastSortedValue;
1892 PRUint32 firstIndex = 0;
1893 PRBool isFirstValue = PR_TRUE;
1894 PRBool isFirstSort = PR_TRUE;
1895 for (PRUint32
i = 0;
i < rowCount;
i++) {
1896 PRUint32 index =
i + aDestIndexOffset;
1898 nsString mediaItemIdStr;
1899 rv = result->GetRowCell(
i, 0, mediaItemIdStr);
1900 NS_ENSURE_SUCCESS(rv, rv);
1902 PRUint32 mediaItemId = mediaItemIdStr.ToInteger(&rv);
1903 NS_ENSURE_SUCCESS(rv, rv);
1906 rv = result->GetRowCell(
i, 1, guid);
1907 NS_ENSURE_SUCCESS(rv, rv);
1910 rv = result->GetRowCell(
i, 2, value);
1911 NS_ENSURE_SUCCESS(rv, rv);
1914 rv = result->GetRowCell(
i, 3, ordinal);
1915 NS_ENSURE_SUCCESS(rv, rv);
1918 rv = result->GetRowCell(
i, 4, rowidStr);
1919 NS_ENSURE_SUCCESS(rv, rv);
1922 NS_ENSURE_SUCCESS(rv, rv);
1924 ArrayItem* item =
new ArrayItem(mediaItemId, guid, value, ordinal, rowid);
1925 NS_ENSURE_TRUE(item, NS_ERROR_OUT_OF_MEMORY);
1927 nsAutoPtr<ArrayItem>* success =
1928 mCache.ReplaceElementsAt(index, 1, item);
1929 NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
1931 TRACE((
"ReplaceElementsAt %d %s", index,
1932 NS_ConvertUTF16toUTF8(item->guid).get()));
1935 if (isFirstValue || !lastSortedValue.Equals(item->sortPropertyValue)) {
1936 if (!isFirstValue) {
1937 rv = SortRows(aDestIndexOffset + firstIndex,
1944 NS_ENSURE_SUCCESS(rv, rv);
1945 isFirstSort = PR_FALSE;
1947 lastSortedValue.Assign(item->sortPropertyValue);
1949 isFirstValue = PR_FALSE;
1954 LOG((
"Replaced Elements %d to %d",
1956 rowCount + aDestIndexOffset));
1959 rv = SortRows(aDestIndexOffset + firstIndex,
1960 aDestIndexOffset + rowCount - 1,
1964 isFirstSort == PR_TRUE,
1966 NS_ENSURE_SUCCESS(rv, rv);
1970 for (PRUint32
i = 0;
i < rowCount;
i++) {
1971 PRUint32 index =
i + aDestIndexOffset;
1973 ArrayItem* item = mCache[index];
1974 NS_ASSERTION(item,
"Null item in cache?");
1977 PRUint32 firstGuidIndex;
1978 PRBool found = mGuidToFirstIndexMap.Get(item->guid, &firstGuidIndex);
1979 if (!found || index < firstGuidIndex) {
1980 PRBool added = mGuidToFirstIndexMap.Put(item->guid, index);
1981 NS_ENSURE_TRUE(added, NS_ERROR_OUT_OF_MEMORY);
1986 nsAutoString viewItemUID;
1988 viewItemUID.Append(
'-');
1989 viewItemUID.AppendInt(item->mediaItemId);
1991 PRBool added = mViewItemUIDToIndexMap.Put(viewItemUID, index);
1992 NS_ENSURE_TRUE(added, NS_ERROR_OUT_OF_MEMORY);
1999 if (rowCount < aCount) {
2000 char*
message = PR_smprintf(
"Did not get the requested number of rows, "
2001 "requested %d got %d", aCount, rowCount);
2002 NS_WARNING(message);
2003 PR_smprintf_free(message);
2004 for (PRUint32
i = 0;
i < aCount - rowCount;
i++) {
2005 ArrayItem* item =
new ArrayItem(0,
2006 NS_LITERAL_STRING(
"error"),
2007 NS_LITERAL_STRING(
"error"),
2010 NS_ENSURE_TRUE(item, NS_ERROR_OUT_OF_MEMORY);
2012 nsAutoPtr<ArrayItem>* success =
2013 mCache.ReplaceElementsAt(
i + rowCount + aDestIndexOffset, 1, item);
2014 NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
2021 sbLocalDatabaseGUIDArray::SortBags(
const void* a,
const void* b,
void* closure)
2029 nsTArray<SortSpec>* sorts =
static_cast<nsTArray<SortSpec>*
>(closure);
2030 NS_ASSERTION(sorts->Length() > 1,
"Multisorting with single sort!");
2033 for (PRUint32
i = 1;
i < sorts->Length();
i++) {
2034 PRUint32 propertyId = sorts->ElementAt(
i).propertyId;
2035 PRBool ascending = sorts->ElementAt(
i).ascending;
2038 rv = bagA->GetSortablePropertyByID(propertyId, valueA);
2039 NS_ENSURE_SUCCESS(rv, rv);
2042 rv = bagB->GetSortablePropertyByID(propertyId, valueB);
2043 NS_ENSURE_SUCCESS(rv, rv);
2045 if (valueA == valueB) {
2050 return valueA > valueB ? 1 : -1;
2053 return valueA < valueB ? 1 : -1;
2060 PRUint32 mediaItemIdA;
2061 rv = bagA->GetMediaItemId(&mediaItemIdA);
2062 NS_ENSURE_SUCCESS(rv, rv);
2064 PRUint32 mediaItemIdB;
2065 rv = bagB->GetMediaItemId(&mediaItemIdB);
2066 NS_ENSURE_SUCCESS(rv, rv);
2068 return mediaItemIdA > mediaItemIdB ? 1 : -1;
2072 sbLocalDatabaseGUIDArray::SortRows(PRUint32 aStartIndex,
2074 const nsAString& aKey,
2083 LOG((
"Sorting rows %d to %d on %s, isfirst %d islast %d isonly %d isnull %d\n",
2086 NS_ConvertUTF16toUTF8(aKey).
get(),
2099 if (!aIsFirst && !aIsLast && !aIsOnly && aStartIndex == aEndIndex) {
2103 PRUint32 rangeLength = aEndIndex - aStartIndex + 1;
2113 if (mHasActiveSearch && !aIsFirst && !aIsLast && !aIsOnly && mPropertyCache) {
2114 nsTArray<const PRUnichar*> guids(rangeLength);
2115 for (PRUint32
i = aStartIndex;
i <= aEndIndex;
i++) {
2116 const PRUnichar** appended =
2117 guids.AppendElement(mCache[
i]->guid.get());
2118 NS_ENSURE_TRUE(appended, NS_ERROR_OUT_OF_MEMORY);
2123 PRUint32 bagsCount = 0;
2125 rv = mPropertyCache->GetProperties(guids.Elements(),
2129 NS_ENSURE_SUCCESS(rv, rv);
2143 nsClassHashtable<nsStringHashKey, ArrayItem> lookup;
2144 PRBool success = lookup.Init(bagsCount);
2145 NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
2147 for (PRUint32
i = aStartIndex;
i <= aEndIndex;
i++) {
2148 ArrayItem* item = mCache[
i];
2149 nsAutoPtr<ArrayItem> copy(
new ArrayItem(*item));
2150 NS_ENSURE_TRUE(copy, NS_ERROR_OUT_OF_MEMORY);
2151 success = lookup.Put(copy->guid, copy);
2152 NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
2156 for (PRUint32
i = 0;
i < bagsCount;
i++) {
2158 rv = bags[
i]->GetGuid(guid);
2159 NS_ENSURE_SUCCESS(rv, rv);
2162 PRBool found = lookup.Get(guid, &item);
2163 NS_ENSURE_TRUE(found, NS_ERROR_UNEXPECTED);
2164 nsAutoPtr<ArrayItem> copy(
new ArrayItem(*item));
2165 NS_ENSURE_TRUE(copy, NS_ERROR_OUT_OF_MEMORY);
2166 nsAutoPtr<ArrayItem>* replaced =
2167 mCache.ReplaceElementsAt(
i + aStartIndex,
2170 NS_ENSURE_TRUE(replaced, NS_ERROR_OUT_OF_MEMORY);
2177 nsCOMPtr<sbIDatabaseQuery> query;
2179 rv = MakeQuery(mNullResortStatement, getter_AddRefs(query));
2180 NS_ENSURE_SUCCESS(rv, rv);
2183 rv = MakeQuery(mResortStatement, getter_AddRefs(query));
2184 NS_ENSURE_SUCCESS(rv, rv);
2186 rv = query->BindStringParameter(0, aKey);
2187 NS_ENSURE_SUCCESS(rv, rv);
2190 rv = query->Execute(&dbOk);
2191 NS_ENSURE_SUCCESS(rv, rv);
2192 NS_ENSURE_TRUE(dbOk == 0, NS_ERROR_FAILURE);
2194 nsCOMPtr<sbIDatabaseResult> result;
2195 rv = query->GetResultObject(getter_AddRefs(result));
2196 NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
2199 rv = result->GetRowCount(&rowCount);
2200 NS_ENSURE_SUCCESS(rv, rv);
2206 if (rangeLength > rowCount) {
2207 return NS_ERROR_UNEXPECTED;
2216 if(rangeLength != mLength) {
2231 offset = aStartIndex - mNonNullLength;
2236 rv = GetPrimarySortKeyPosition(aKey, &position);
2237 NS_ENSURE_SUCCESS(rv, rv);
2247 offset = rowCount - rangeLength;
2260 for (PRUint32
i = 0;
i < rangeLength;
i++) {
2262 PRUint32 row = offset +
i;
2263 nsAutoPtr<ArrayItem>& item = mCache[i + aStartIndex];
2265 nsString mediaItemIdStr;
2266 rv = result->GetRowCell(row, 0, mediaItemIdStr);
2267 NS_ENSURE_SUCCESS(rv, rv);
2269 item->mediaItemId = mediaItemIdStr.ToInteger(&rv);
2270 NS_ENSURE_SUCCESS(rv, rv);
2272 rv = result->GetRowCell(row, 1, item->guid);
2273 NS_ENSURE_SUCCESS(rv, rv);
2275 rv = result->GetRowCell(row, 2, item->ordinal);
2276 NS_ENSURE_SUCCESS(rv, rv);
2279 rv = result->GetRowCell(row, 3, rowidStr);
2280 NS_ENSURE_SUCCESS(rv, rv);
2283 NS_ENSURE_SUCCESS(rv, rv);
2290 sbLocalDatabaseGUIDArray::GetPrimarySortKeyPosition(
const nsAString& aValue,
2298 if (!mPrimarySortKeyPositionCache.IsInitialized()) {
2299 mPrimarySortKeyPositionCache.Init(100);
2303 if (!mPrimarySortKeyPositionCache.Get(aValue, &position)) {
2306 nsCOMPtr<sbIDatabaseQuery> query;
2307 rv = MakeQuery(mPrimarySortKeyPositionStatement,
2308 getter_AddRefs(query));
2309 NS_ENSURE_SUCCESS(rv, rv);
2311 rv = query->BindStringParameter(0, aValue);
2312 NS_ENSURE_SUCCESS(rv, rv);
2314 rv = query->Execute(&dbOk);
2315 NS_ENSURE_SUCCESS(rv, rv);
2316 NS_ENSURE_TRUE(dbOk == 0, NS_ERROR_FAILURE);
2318 nsCOMPtr<sbIDatabaseResult> result;
2319 rv = query->GetResultObject(getter_AddRefs(result));
2320 NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
2323 rv = result->GetRowCount(&rowCount);
2324 NS_ENSURE_SUCCESS(rv, rv);
2326 NS_ENSURE_TRUE(rowCount == 1, NS_ERROR_UNEXPECTED);
2328 nsAutoString countStr;
2329 rv = result->GetRowCell(0, 0, countStr);
2330 NS_ENSURE_SUCCESS(rv, rv);
2332 position = countStr.ToInteger(&rv);
2333 NS_ENSURE_SUCCESS(rv, rv);
2335 mPrimarySortKeyPositionCache.Put(aValue, position);
2343 sbLocalDatabaseGUIDArray::GetByIndexInternal(PRUint32 aIndex,
2344 ArrayItem** _retval)
2348 TRACE((
"GetByIndexInternal %d %d", aIndex, mLength));
2350 nsAutoMonitor mon(mCacheMonitor);
2352 if (mValid == PR_FALSE) {
2354 NS_ENSURE_SUCCESS(rv, rv);
2357 NS_ENSURE_TRUE(aIndex < mLength, NS_ERROR_INVALID_ARG);
2362 if (aIndex < mCache.Length()) {
2363 ArrayItem* item = mCache[aIndex];
2365 TRACE((
"Cache hit, got %s", NS_ConvertUTF16toUTF8(item->guid).get()));
2373 #if defined(FORCE_FETCH_ALL_GUIDS_ASYNC)
2377 rv = FetchRows(aIndex, mFetchSize);
2378 NS_ENSURE_SUCCESS(rv, rv);
2379 NS_ENSURE_TRUE(aIndex < mCache.Length(), NS_ERROR_FAILURE);
2385 if (!mPrefetchedRows) {
2386 mPrefetchedRows = PR_TRUE;
2388 &sbLocalDatabaseGUIDArray::FetchRows,
2390 static_cast<PRUint32>(0),
2391 static_cast<PRUint32>(0));
2397 rv = FetchRows(0, 0);
2398 NS_ENSURE_SUCCESS(rv, rv);
2399 NS_ENSURE_TRUE(aIndex < mCache.Length(), NS_ERROR_FAILURE);
2402 *_retval = mCache[aIndex];
2408 sbLocalDatabaseGUIDArray::GetPropertyId(
const nsAString& aProperty)
2414 sbLocalDatabaseGUIDArray::GetMTListener(
2417 NS_ENSURE_ARG_POINTER(aListener);
2423 *aListener = nsnull;
2426 nsCOMPtr<nsIWeakReference> weak;
2427 nsCOMPtr<sbILocalDatabaseGUIDArrayListener>
listener;
2428 if (!NS_IsMainThread()) {
2429 nsCOMPtr<nsIThread> mainThread;
2430 rv = NS_GetMainThread(getter_AddRefs(mainThread));
2431 NS_ENSURE_SUCCESS(rv, rv);
2435 NS_PROXY_SYNC | NS_PROXY_ALWAYS,
2436 getter_AddRefs(weak));
2437 NS_ENSURE_SUCCESS(rv, rv);
2439 listener = do_QueryReferent(weak, &rv);
2440 NS_ENSURE_SUCCESS(rv, rv);
2443 *aListener = nsnull;
2446 nsCOMPtr<sbILocalDatabaseGUIDArrayListener> proxiedListener;
2449 NS_PROXY_SYNC | NS_PROXY_ALWAYS,
2450 getter_AddRefs(proxiedListener));
2451 NS_ENSURE_SUCCESS(rv, rv);
2452 proxiedListener.forget(aListener);
2456 listener = do_QueryReferent(mListener);
2458 listener.forget(aListener);
2463 sbLocalDatabaseGUIDArray::GenerateCachedLengthKey()
2465 nsAutoLock mon(mPropIdsLock);
2469 mPropIdsUsedInCacheKey.clear();
2471 if(mLengthCache && !mCachedLengthKey.IsEmpty()) {
2472 mLengthCache->RemoveCachedLength(mCachedLengthKey);
2473 mLengthCache->RemoveCachedNonNullLength(mCachedLengthKey);
2477 mCachedLengthKey.SetLength(2048);
2480 mCachedLengthKey.Truncate();
2483 mCachedLengthKey.Append(mDatabaseGUID);
2486 mCachedLengthKey.Append(mBaseTable);
2489 mCachedLengthKey.Append(mBaseConstraintColumn);
2492 mCachedLengthKey.AppendInt(mBaseConstraintValue);
2495 mCachedLengthKey.AppendInt(mIsDistinct);
2498 mCachedLengthKey.AppendInt(mDistinctWithSortableValues);
2501 mCachedLengthKey.AppendInt(mIsFullLibrary);
2507 PRUint32 filterCount = mFilters.Length();
2508 for (PRUint32 index = 0; index < filterCount; index++) {
2509 const FilterSpec& refSpec = mFilters.ElementAt(index);
2511 mCachedLengthKey.Append(refSpec.property);
2513 PRUint32 propId = 0;
2514 if(NS_SUCCEEDED(mPropertyCache->GetPropertyDBID(refSpec.property,
2516 mPropIdsUsedInCacheKey.insert(propId);
2519 mCachedLengthKey.AppendInt(refSpec.isSearch);
2521 PRUint32 valueCount = refSpec.values.Length();
2522 for(PRUint32 valueIndex = 0; valueIndex < valueCount; valueIndex++) {
2523 mCachedLengthKey.Append(refSpec.values.ElementAt(valueIndex));
2528 PRUint32 sortCount = mSorts.Length();
2529 for (PRUint32 index = 0; index < sortCount; index++) {
2530 const SortSpec& sortSpec = mSorts.ElementAt(index);
2531 mCachedLengthKey.AppendInt(sortSpec.propertyId);
2532 mPropIdsUsedInCacheKey.insert(sortSpec.propertyId);
2534 mCachedLengthKey.AppendInt(sortSpec.ascending);
2535 mCachedLengthKey.AppendInt(sortSpec.secondary);
2555 sbGUIDArrayEnumerator::HasMoreElements(PRBool *_retval)
2560 rv = mArray->GetLength(&length);
2561 NS_ENSURE_SUCCESS(rv, rv);
2566 if (length != mPreviousLength) {
2567 mPreviousLength = length;
2569 mNextGUID.Truncate();
2572 *_retval = mNextIndex < length;
2578 sbGUIDArrayEnumerator::GetNext(
nsISupports **_retval)
2580 nsresult rv = NS_ERROR_UNEXPECTED;
2583 rv = mArray->GetGuidByIndex(mNextIndex, guid);
2584 NS_ENSURE_SUCCESS(rv, rv);
2586 nsCOMPtr<sbIMediaItem> item;
2587 rv = mLibrary->GetMediaItem(guid, getter_AddRefs(item));
2588 NS_ENSURE_SUCCESS(rv, rv);
2590 nsCOMPtr<nsISupports> supports = do_QueryInterface(item, &rv);
2591 NS_ENSURE_SUCCESS(rv, rv);
2593 NS_ADDREF(*_retval = supports);
2606 NS_ASSERTION(aArray,
"Null value passed to ctor");
2614 sbGUIDArrayStringEnumerator::HasMore(PRBool *_retval)
2619 rv = mArray->GetLength(&length);
2620 NS_ENSURE_SUCCESS(rv, rv);
2622 *_retval = mNextIndex < length;
2627 sbGUIDArrayStringEnumerator::GetNext(nsAString& _retval)
2631 rv = mArray->GetGuidByIndex(mNextIndex, _retval);
2632 NS_ENSURE_SUCCESS(rv, rv);
#define SONGBIRD_DATABASEQUERY_CONTRACTID
[USER CODE SHOULD NOT REFERENCE THIS CLASS]
attribute sbILocalDatabaseGUIDArrayListener listener
NS_IMPL_ISUPPORTS1(sbDeviceCapabilitiesUtils, sbIDeviceCapabilitiesUtils) sbDeviceCapabilitiesUtils
PRUint64 nsString_ToUint64(const nsAString &str, nsresult *rv)
[USER CODE SHOULD NOT REFERENCE THIS CLASS]
#define SB_PROPERTY_ORDINAL
[USER CODE SHOULD NOT REFERENCE THIS CLASS]
const unsigned long SORT_NULL_LAST
Null values always last.
nsresult do_GetProxyForObject(nsIEventTarget *aTarget, REFNSIID aIID, nsISupports *aObj, PRInt32 aProxyType, void **aProxyObject)
static PRBool SB_IsTopLevelProperty(PRUint32 aPropertyDBID)
nsresult sbInvokeOnMainThread2Async(T &aObject, MT aMethod, RT aFailureReturnValue, A1 aArg1, A2 aArg2)
#define SB_PROPERTYMANAGER_CONTRACTID
#define SB_PROPERTY_CREATED
static PRInt32 SB_GetPropertyId(const nsAString &aProperty, sbILocalDatabasePropertyCache *aPropertyCache)
const unsigned long SORT_NULL_SMALL
Causes null values to be infinitely small. This is the default.
Songbird Thread Utilities Definitions.
#define DEFAULT_FETCH_SIZE
[USER CODE SHOULD NOT REFERENCE THIS CLASS]
StringArrayEnumerator prototype hasMore
[USER CODE SHOULD NOT REFERENCE THIS CLASS]
NS_IMPL_THREADSAFE_ISUPPORTS2(sbLocalDatabaseGUIDArray, sbILocalDatabaseGUIDArray, nsISupportsWeakReference) sbLocalDatabaseGUIDArray
An object responsible for executing SQL queries on the database.
restoreHistoryPrecursor aCount
const unsigned long SORT_NULL_FIRST
Null values always first.
const unsigned long SORT_NULL_BIG
Causes null values to be infinitely large.
An interface to carry around arrays of nsIProperty instances. Users of this interface should only QI ...
~sbGUIDArrayStringEnumerator()
_getSelectedPageStyle s i
A prepared database statement.
Songbird Database Object Definition.