зеркало из https://github.com/mozilla/pjs.git
Bug 420354 ? History not shown in sidebar when sorted by date or by date and site (for ondrej@allpeers.com, r=dietrich)
This commit is contained in:
Родитель
703b6a2f0c
Коммит
1ee56dab8e
|
@ -241,11 +241,6 @@ inline void ReverseString(const nsString& aInput, nsAString& aReversed)
|
|||
for (PRInt32 i = aInput.Length() - 1; i >= 0; i --)
|
||||
aReversed.Append(aInput[i]);
|
||||
}
|
||||
inline void parameterString(PRInt32 paramIndex, nsACString& aParamString)
|
||||
{
|
||||
aParamString = nsPrintfCString("?%d", paramIndex + 1);
|
||||
}
|
||||
|
||||
|
||||
// UpdateBatchScoper
|
||||
//
|
||||
|
@ -2725,12 +2720,15 @@ PRBool NeedToFilterResultSet(const nsCOMArray<nsNavHistoryQuery>& aQueries,
|
|||
|
||||
// ** Helper class for ConstructQueryString **/
|
||||
|
||||
static const PRInt32 MAX_HISTORY_DAYS = 6;
|
||||
|
||||
class PlacesSQLQueryBuilder
|
||||
{
|
||||
public:
|
||||
PlacesSQLQueryBuilder(const nsCString& aConditions,
|
||||
nsNavHistoryQueryOptions* aOptions,
|
||||
PRBool aUseLimit);
|
||||
PRBool aUseLimit,
|
||||
nsNavHistory::StringHash& aAddParams);
|
||||
|
||||
nsresult GetQueryString(nsCString& aQueryString);
|
||||
|
||||
|
@ -2764,12 +2762,14 @@ private:
|
|||
nsCString mGroupBy;
|
||||
PRBool mHasDateColumns;
|
||||
PRBool mSkipOrderBy;
|
||||
nsNavHistory::StringHash& mAddParams;
|
||||
};
|
||||
|
||||
PlacesSQLQueryBuilder::PlacesSQLQueryBuilder(
|
||||
const nsCString& aConditions,
|
||||
nsNavHistoryQueryOptions* aOptions,
|
||||
PRBool aUseLimit) :
|
||||
PRBool aUseLimit,
|
||||
nsNavHistory::StringHash& aAddParams) :
|
||||
mConditions(aConditions),
|
||||
mResultType(aOptions->ResultType()),
|
||||
mQueryType(aOptions->QueryType()),
|
||||
|
@ -2777,7 +2777,8 @@ PlacesSQLQueryBuilder::PlacesSQLQueryBuilder(
|
|||
mSortingMode(aOptions->SortingMode()),
|
||||
mMaxResults(aOptions->MaxResults()),
|
||||
mUseLimit(aUseLimit),
|
||||
mSkipOrderBy(PR_FALSE)
|
||||
mSkipOrderBy(PR_FALSE),
|
||||
mAddParams(aAddParams)
|
||||
{
|
||||
mHasDateColumns = (mQueryType == nsINavHistoryQueryOptions::QUERY_TYPE_BOOKMARKS);
|
||||
}
|
||||
|
@ -2930,11 +2931,11 @@ PlacesSQLQueryBuilder::SelectAsDay()
|
|||
PRTime mNow;
|
||||
} midnight;
|
||||
|
||||
nsCAutoString dateParam;
|
||||
nsCAutoString dateName;
|
||||
|
||||
const PRInt32 MAX_DAYS = 6;
|
||||
|
||||
for (PRInt32 i = 0; i <= MAX_DAYS; i++) {
|
||||
for (PRInt32 i = 0; i <= MAX_HISTORY_DAYS; i++) {
|
||||
dateParam = nsPrintfCString(":dayTitle%d", i);
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
|
@ -2951,6 +2952,8 @@ PlacesSQLQueryBuilder::SelectAsDay()
|
|||
break;
|
||||
}
|
||||
|
||||
mAddParams.Put(dateParam, dateName);
|
||||
|
||||
PRInt32 fromDayAgo = -i;
|
||||
PRInt32 toDayAgo = -i + 1;
|
||||
|
||||
|
@ -2958,14 +2961,14 @@ PlacesSQLQueryBuilder::SelectAsDay()
|
|||
"SELECT * "
|
||||
"FROM (SELECT %d dayOrder, "
|
||||
"'%d' dayRange, "
|
||||
"'%s' dayTitle, "
|
||||
"%s dayTitle, " // This will be bound
|
||||
"%llu beginTime, "
|
||||
"%llu endTime "
|
||||
"FROM moz_historyvisits "
|
||||
"WHERE visit_date >= %llu AND visit_date < %llu "
|
||||
" AND visit_type NOT IN (0,4) "
|
||||
"LIMIT 1) TUNION%d UNION ",
|
||||
i, i, dateName.get(),
|
||||
i, i, dateParam.get(),
|
||||
midnight.Get(fromDayAgo),
|
||||
midnight.Get(toDayAgo),
|
||||
midnight.Get(fromDayAgo),
|
||||
|
@ -2975,14 +2978,17 @@ PlacesSQLQueryBuilder::SelectAsDay()
|
|||
mQueryString.Append( dayRange );
|
||||
}
|
||||
|
||||
history->GetAgeInDaysString(MAX_DAYS,
|
||||
dateParam = nsPrintfCString(":dayTitle%d", MAX_HISTORY_DAYS+1);
|
||||
history->GetAgeInDaysString(MAX_HISTORY_DAYS,
|
||||
NS_LITERAL_STRING("finduri-AgeInDays-isgreater").get(), dateName);
|
||||
|
||||
mAddParams.Put(dateParam, dateName);
|
||||
|
||||
mQueryString.Append(nsPrintfCString(1024,
|
||||
"SELECT * "
|
||||
"FROM (SELECT %d dayOrder, "
|
||||
"'%d+' dayRange, "
|
||||
"'%s' dayTitle, "
|
||||
"%s dayTitle, " // This will be bound
|
||||
"1 beginTime, "
|
||||
"%llu endTime "
|
||||
"FROM moz_historyvisits "
|
||||
|
@ -2991,11 +2997,11 @@ PlacesSQLQueryBuilder::SelectAsDay()
|
|||
"LIMIT 1) TUNIONLAST "
|
||||
") TOUTER " // TOUTER END
|
||||
"ORDER BY dayOrder ASC",
|
||||
MAX_DAYS+1,
|
||||
MAX_DAYS+1,
|
||||
dateName.get(),
|
||||
midnight.Get(-MAX_DAYS),
|
||||
midnight.Get(-MAX_DAYS)
|
||||
MAX_HISTORY_DAYS+1,
|
||||
MAX_HISTORY_DAYS+1,
|
||||
dateParam.get(),
|
||||
midnight.Get(-MAX_HISTORY_DAYS),
|
||||
midnight.Get(-MAX_HISTORY_DAYS)
|
||||
));
|
||||
|
||||
return NS_OK;
|
||||
|
@ -3010,6 +3016,7 @@ PlacesSQLQueryBuilder::SelectAsSite()
|
|||
NS_ENSURE_STATE(history);
|
||||
|
||||
history->GetStringFromName(NS_LITERAL_STRING("localhost").get(), localFiles);
|
||||
mAddParams.Put(NS_LITERAL_CSTRING(":localhost"), localFiles);
|
||||
|
||||
// We want just sites, but from whole database - we omit join with visits,
|
||||
// it could happen, that we get later empty host, when we click on it, but
|
||||
|
@ -3019,7 +3026,7 @@ PlacesSQLQueryBuilder::SelectAsSite()
|
|||
mQueryString = nsPrintfCString(2048,
|
||||
"SELECT DISTINCT null, "
|
||||
"'place:type=%ld&sort=%ld&domain=&domainIsHost=true', "
|
||||
"'%s', '%s', null, null, null, null, null "
|
||||
":localhost, :localhost, null, null, null, null, null "
|
||||
"WHERE EXISTS(SELECT '*' "
|
||||
"FROM moz_places "
|
||||
"WHERE hidden <> 1 AND rev_host = '.' "
|
||||
|
@ -3035,8 +3042,6 @@ PlacesSQLQueryBuilder::SelectAsSite()
|
|||
"ORDER BY 1 ASC) inner1",
|
||||
nsINavHistoryQueryOptions::RESULTS_AS_URI,
|
||||
nsINavHistoryQueryOptions::SORT_BY_TITLE_ASCENDING,
|
||||
localFiles.get(),
|
||||
localFiles.get(),
|
||||
nsINavHistoryQueryOptions::RESULTS_AS_URI,
|
||||
nsINavHistoryQueryOptions::SORT_BY_TITLE_ASCENDING);
|
||||
// Now we need to use the filters - we need them all
|
||||
|
@ -3045,8 +3050,8 @@ PlacesSQLQueryBuilder::SelectAsSite()
|
|||
mQueryString = nsPrintfCString(4096,
|
||||
"SELECT DISTINCT null, "
|
||||
"'place:type=%ld&sort=%ld&domain=&domainIsHost=true"
|
||||
"&beginTime='||?1||'&endTime='||?2, "
|
||||
"'%s', '%s', null, null, null, null, null "
|
||||
"&beginTime='||:begin_time||'&endTime='||:end_time, "
|
||||
":localhost, :localhost, null, null, null, null, null "
|
||||
"WHERE EXISTS(SELECT '*' "
|
||||
"FROM moz_places h "
|
||||
"JOIN moz_historyvisits v ON h.id = v.place_id "
|
||||
|
@ -3056,7 +3061,7 @@ PlacesSQLQueryBuilder::SelectAsSite()
|
|||
"UNION ALL "
|
||||
"SELECT DISTINCT null, "
|
||||
"'place:type=%ld&sort=%ld&domain='||host||'&domainIsHost=true"
|
||||
"&beginTime='||?1||'&endTime='||?2, "
|
||||
"&beginTime='||:begin_time||'&endTime='||:end_time, "
|
||||
"host, host, null, null, null, null, null "
|
||||
"FROM (SELECT get_unreversed_host(rev_host) host "
|
||||
"FROM (SELECT DISTINCT rev_host "
|
||||
|
@ -3068,8 +3073,6 @@ PlacesSQLQueryBuilder::SelectAsSite()
|
|||
"ORDER BY 1 ASC) inner1",
|
||||
nsINavHistoryQueryOptions::RESULTS_AS_URI,
|
||||
nsINavHistoryQueryOptions::SORT_BY_TITLE_ASCENDING,
|
||||
localFiles.get(),
|
||||
localFiles.get(),
|
||||
nsINavHistoryQueryOptions::RESULTS_AS_URI,
|
||||
nsINavHistoryQueryOptions::SORT_BY_TITLE_ASCENDING);
|
||||
}
|
||||
|
@ -3111,10 +3114,11 @@ PlacesSQLQueryBuilder::Where()
|
|||
nsCAutoString innerCondition;
|
||||
// If we have condition AND it
|
||||
if (!mConditions.IsEmpty()) {
|
||||
innerCondition = " AND ";
|
||||
innerCondition = " AND (";
|
||||
innerCondition += mConditions;
|
||||
innerCondition += ")";
|
||||
}
|
||||
mQueryString.ReplaceSubstring("{ADDITIONAL_CONDITIONS}",
|
||||
mQueryString.ReplaceSubstring("{ADDITIONAL_CONDITIONS}",
|
||||
innerCondition.get());
|
||||
|
||||
} else if (!mConditions.IsEmpty()) {
|
||||
|
@ -3222,7 +3226,9 @@ nsresult
|
|||
nsNavHistory::ConstructQueryString(
|
||||
const nsCOMArray<nsNavHistoryQuery>& aQueries,
|
||||
nsNavHistoryQueryOptions* aOptions,
|
||||
nsCString& queryString, PRBool& aParamsPresent)
|
||||
nsCString& queryString,
|
||||
PRBool& aParamsPresent,
|
||||
nsNavHistory::StringHash& aAddParams)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
|
@ -3285,19 +3291,11 @@ nsNavHistory::ConstructQueryString(
|
|||
|
||||
nsCAutoString conditions;
|
||||
|
||||
// Query string: Output parameters should be in order of kGetInfoIndex_*
|
||||
// WATCH OUT: nsNavBookmarks::Init also creates some statements that share
|
||||
// these same indices for passing to RowToResult. If you add something to
|
||||
// this, you also need to update the bookmark statements to keep them in
|
||||
// sync!
|
||||
|
||||
PRInt32 numParameters = 0;
|
||||
PRInt32 i;
|
||||
for (i = 0; i < aQueries.Count(); i ++) {
|
||||
nsCString queryClause;
|
||||
PRInt32 clauseParameters = 0;
|
||||
rv = QueryToSelectClause(aQueries[i], aOptions, numParameters,
|
||||
&queryClause, &clauseParameters);
|
||||
rv = QueryToSelectClause(aQueries[i], aOptions, i, &queryClause);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (! queryClause.IsEmpty()) {
|
||||
aParamsPresent = PR_TRUE;
|
||||
|
@ -3305,7 +3303,6 @@ nsNavHistory::ConstructQueryString(
|
|||
conditions += NS_LITERAL_CSTRING(" OR ");
|
||||
conditions += NS_LITERAL_CSTRING("(") + queryClause +
|
||||
NS_LITERAL_CSTRING(")");
|
||||
numParameters += clauseParameters;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3315,13 +3312,32 @@ nsNavHistory::ConstructQueryString(
|
|||
PRBool useLimitClause = !NeedToFilterResultSet(aQueries, aOptions);
|
||||
|
||||
PlacesSQLQueryBuilder queryStringBuilder(conditions, aOptions,
|
||||
useLimitClause);
|
||||
useLimitClause, aAddParams);
|
||||
rv = queryStringBuilder.GetQueryString(queryString);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PLDHashOperator BindAdditionalParameter(nsNavHistory::StringHash::KeyType aParamName,
|
||||
nsCString aParamValue,
|
||||
void* aStatement)
|
||||
{
|
||||
mozIStorageStatement* stmt = static_cast<mozIStorageStatement*>(aStatement);
|
||||
|
||||
PRUint32 index;
|
||||
nsresult rv = stmt->GetParameterIndex(aParamName, &index);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return PL_DHASH_STOP;
|
||||
|
||||
rv = stmt->BindUTF8StringParameter(index, aParamValue);
|
||||
if (NS_FAILED(rv))
|
||||
return PL_DHASH_STOP;
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
// nsNavHistory::GetQueryResults
|
||||
//
|
||||
// Call this to get the results from a complex query. This is used by
|
||||
|
@ -3349,8 +3365,10 @@ nsNavHistory::GetQueryResults(nsNavHistoryQueryResultNode *aResultNode,
|
|||
|
||||
nsCString queryString;
|
||||
PRBool paramsPresent = PR_FALSE;
|
||||
nsNavHistory::StringHash addParams;
|
||||
addParams.Init(MAX_HISTORY_DAYS+1);
|
||||
nsresult rv = ConstructQueryString(aQueries, aOptions, queryString,
|
||||
paramsPresent);
|
||||
paramsPresent, addParams);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
#ifdef DEBUG_thunder
|
||||
|
@ -3369,17 +3387,15 @@ nsNavHistory::GetQueryResults(nsNavHistoryQueryResultNode *aResultNode,
|
|||
|
||||
if (paramsPresent) {
|
||||
// bind parameters
|
||||
PRInt32 numParameters = 0;
|
||||
PRInt32 i;
|
||||
for (i = 0; i < aQueries.Count(); i++) {
|
||||
PRInt32 clauseParameters = 0;
|
||||
rv = BindQueryClauseParameters(statement, numParameters,
|
||||
aQueries[i], aOptions, &clauseParameters);
|
||||
rv = BindQueryClauseParameters(statement, i, aQueries[i], aOptions);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
numParameters += clauseParameters;
|
||||
}
|
||||
}
|
||||
|
||||
addParams.EnumerateRead(BindAdditionalParameter, statement.get());
|
||||
|
||||
// optimize the case where we just use the results as is
|
||||
// and we don't need to do any post-query filtering
|
||||
if (NeedToFilterResultSet(aQueries, aOptions)) {
|
||||
|
@ -4641,10 +4657,63 @@ nsNavHistory::CommitLazyMessages()
|
|||
|
||||
// Query stuff *****************************************************************
|
||||
|
||||
// Helper class for QueryToSelectClause
|
||||
//
|
||||
// This class helps to build part of the WHERE clause. It supports
|
||||
// multiple queries by appending the query index to the parameter name.
|
||||
// For the query with index 0 the parameter name is not altered what
|
||||
// allows using this parameter in other situations (see SelectAsSite).
|
||||
|
||||
class ConditionBuilder
|
||||
{
|
||||
public:
|
||||
|
||||
ConditionBuilder(PRInt32 aQueryIndex): mQueryIndex(aQueryIndex)
|
||||
{ }
|
||||
|
||||
ConditionBuilder& Condition(const char* aStr)
|
||||
{
|
||||
if (!mClause.IsEmpty())
|
||||
mClause.AppendLiteral(" AND ");
|
||||
Str(aStr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ConditionBuilder& Str(const char* aStr)
|
||||
{
|
||||
mClause.Append(' ');
|
||||
mClause.Append(aStr);
|
||||
mClause.Append(' ');
|
||||
return *this;
|
||||
}
|
||||
|
||||
ConditionBuilder& Param(const char* aParam)
|
||||
{
|
||||
mClause.Append(' ');
|
||||
if (!mQueryIndex)
|
||||
mClause.Append(aParam);
|
||||
else
|
||||
mClause += nsPrintfCString("%s%d", aParam, mQueryIndex);
|
||||
|
||||
mClause.Append(' ');
|
||||
return *this;
|
||||
}
|
||||
|
||||
void GetClauseString(nsCString& aResult)
|
||||
{
|
||||
aResult = mClause;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
PRInt32 mQueryIndex;
|
||||
nsCString mClause;
|
||||
};
|
||||
|
||||
|
||||
// nsNavHistory::QueryToSelectClause
|
||||
//
|
||||
// THE ORDER AND BEHAVIOR SHOULD BE IN SYNC WITH BindQueryClauseParameters
|
||||
// THE BEHAVIOR SHOULD BE IN SYNC WITH BindQueryClauseParameters
|
||||
//
|
||||
// I don't check return values from the query object getters because there's
|
||||
// no way for those to fail.
|
||||
|
@ -4652,86 +4721,47 @@ nsNavHistory::CommitLazyMessages()
|
|||
nsresult
|
||||
nsNavHistory::QueryToSelectClause(nsNavHistoryQuery* aQuery, // const
|
||||
nsNavHistoryQueryOptions* aOptions,
|
||||
PRInt32 aStartParameter,
|
||||
nsCString* aClause,
|
||||
PRInt32* aParamCount)
|
||||
PRInt32 aQueryIndex,
|
||||
nsCString* aClause)
|
||||
{
|
||||
PRBool hasIt;
|
||||
|
||||
aClause->Truncate();
|
||||
*aParamCount = 0;
|
||||
nsCAutoString paramString;
|
||||
ConditionBuilder clause(aQueryIndex);
|
||||
|
||||
// begin time
|
||||
if (NS_SUCCEEDED(aQuery->GetHasBeginTime(&hasIt)) && hasIt) {
|
||||
parameterString(aStartParameter + *aParamCount, paramString);
|
||||
*aClause += NS_LITERAL_CSTRING("v.visit_date >= ") + paramString;
|
||||
(*aParamCount) ++;
|
||||
}
|
||||
if (NS_SUCCEEDED(aQuery->GetHasBeginTime(&hasIt)) && hasIt)
|
||||
clause.Condition("v.visit_date >=").Param(":begin_time");
|
||||
|
||||
// end time
|
||||
if (NS_SUCCEEDED(aQuery->GetHasEndTime(&hasIt)) && hasIt) {
|
||||
if (! aClause->IsEmpty())
|
||||
*aClause += NS_LITERAL_CSTRING(" AND ");
|
||||
parameterString(aStartParameter + *aParamCount, paramString);
|
||||
*aClause += NS_LITERAL_CSTRING("v.visit_date <= ") + paramString;
|
||||
(*aParamCount) ++;
|
||||
}
|
||||
if (NS_SUCCEEDED(aQuery->GetHasEndTime(&hasIt)) && hasIt)
|
||||
clause.Condition("v.visit_date <=").Param(":end_time");
|
||||
|
||||
// search terms FIXME
|
||||
|
||||
// min and max visit count
|
||||
if (aQuery->MinVisits() >= 0) {
|
||||
if (! aClause->IsEmpty())
|
||||
*aClause += NS_LITERAL_CSTRING(" AND ");
|
||||
parameterString(aStartParameter + *aParamCount, paramString);
|
||||
*aClause += NS_LITERAL_CSTRING("h.visit_count >= ") + paramString;
|
||||
(*aParamCount) ++;
|
||||
}
|
||||
|
||||
if (aQuery->MaxVisits() >= 0) {
|
||||
if (! aClause->IsEmpty())
|
||||
*aClause += NS_LITERAL_CSTRING(" AND ");
|
||||
parameterString(aStartParameter + *aParamCount, paramString);
|
||||
*aClause += NS_LITERAL_CSTRING("h.visit_count <= ") + paramString;
|
||||
(*aParamCount) ++;
|
||||
}
|
||||
if (aQuery->MinVisits() >= 0)
|
||||
clause.Condition("h.visit_count >=").Param(":min_visits");
|
||||
|
||||
if (aQuery->MaxVisits() >= 0)
|
||||
clause.Condition("h.visit_count <=").Param(":max_visits");
|
||||
|
||||
// only bookmarked, has no affect on bookmarks-only queries
|
||||
if (aOptions->QueryType() != nsINavHistoryQueryOptions::QUERY_TYPE_BOOKMARKS &&
|
||||
aQuery->OnlyBookmarked()) {
|
||||
// only bookmarked, has no affect on bookmarks-only queries
|
||||
if (!aClause->IsEmpty())
|
||||
*aClause += NS_LITERAL_CSTRING(" AND ");
|
||||
|
||||
*aClause += NS_LITERAL_CSTRING("EXISTS (SELECT b.fk FROM moz_bookmarks b WHERE b.type = ") +
|
||||
nsPrintfCString("%d", nsNavBookmarks::TYPE_BOOKMARK) +
|
||||
NS_LITERAL_CSTRING(" AND b.fk = h.id)");
|
||||
}
|
||||
aQuery->OnlyBookmarked())
|
||||
clause.Condition("EXISTS (SELECT b.fk FROM moz_bookmarks b WHERE b.type = ")
|
||||
.Str(nsPrintfCString("%d", nsNavBookmarks::TYPE_BOOKMARK).get())
|
||||
.Str("AND b.fk = h.id)");
|
||||
|
||||
// domain
|
||||
if (NS_SUCCEEDED(aQuery->GetHasDomain(&hasIt)) && hasIt) {
|
||||
if (! aClause->IsEmpty())
|
||||
*aClause += NS_LITERAL_CSTRING(" AND ");
|
||||
|
||||
PRBool domainIsHost = PR_FALSE;
|
||||
aQuery->GetDomainIsHost(&domainIsHost);
|
||||
if (domainIsHost) {
|
||||
parameterString(aStartParameter + *aParamCount, paramString);
|
||||
*aClause += NS_LITERAL_CSTRING("h.rev_host = ") + paramString;
|
||||
aClause->Append(' ');
|
||||
(*aParamCount) ++;
|
||||
} else {
|
||||
if (domainIsHost)
|
||||
clause.Condition("h.rev_host =").Param(":domain_lower");
|
||||
else
|
||||
// see domain setting in BindQueryClauseParameters for why we do this
|
||||
parameterString(aStartParameter + *aParamCount, paramString);
|
||||
*aClause += NS_LITERAL_CSTRING("h.rev_host >= ") + paramString;
|
||||
(*aParamCount) ++;
|
||||
|
||||
parameterString(aStartParameter + *aParamCount, paramString);
|
||||
*aClause += NS_LITERAL_CSTRING(" AND h.rev_host < ") + paramString;
|
||||
aClause->Append(' ');
|
||||
(*aParamCount) ++;
|
||||
}
|
||||
clause.Condition("h.rev_host >=").Param(":domain_lower")
|
||||
.Condition("h.rev_host <").Param(":domain_upper");
|
||||
}
|
||||
|
||||
// URI
|
||||
|
@ -4742,79 +4772,110 @@ nsNavHistory::QueryToSelectClause(nsNavHistoryQuery* aQuery, // const
|
|||
// In the future, we could do a >=,<= thing like we do for domain names to
|
||||
// make it use the index.
|
||||
if (NS_SUCCEEDED(aQuery->GetHasUri(&hasIt)) && hasIt) {
|
||||
if (! aClause->IsEmpty())
|
||||
*aClause += NS_LITERAL_CSTRING(" AND ");
|
||||
|
||||
nsCAutoString paramString;
|
||||
parameterString(aStartParameter + *aParamCount, paramString);
|
||||
(*aParamCount) ++;
|
||||
|
||||
nsCAutoString match;
|
||||
if (aQuery->UriIsPrefix()) {
|
||||
// Prefix: want something of the form SUBSTR(h.url, 0, length(?1)) = ?1
|
||||
*aClause += NS_LITERAL_CSTRING("SUBSTR(h.url, 0, LENGTH(") +
|
||||
paramString + NS_LITERAL_CSTRING(")) = ") + paramString;
|
||||
} else {
|
||||
*aClause += NS_LITERAL_CSTRING("h.url = ") + paramString;
|
||||
}
|
||||
aClause->Append(' ');
|
||||
if (aQuery->UriIsPrefix())
|
||||
clause.Condition("SUBSTR(h.url, 0, LENGTH(").Param(":uri").Str(")) =")
|
||||
.Param(":uri");
|
||||
else
|
||||
clause.Condition("h.url =").Param(":uri");
|
||||
}
|
||||
|
||||
// annotation
|
||||
aQuery->GetHasAnnotation(&hasIt);
|
||||
if (hasIt) {
|
||||
if (! aClause->IsEmpty())
|
||||
*aClause += NS_LITERAL_CSTRING(" AND ");
|
||||
|
||||
nsCAutoString paramString;
|
||||
parameterString(aStartParameter + *aParamCount, paramString);
|
||||
(*aParamCount) ++;
|
||||
|
||||
clause.Condition("");
|
||||
if (aQuery->AnnotationIsNot())
|
||||
aClause->AppendLiteral("NOT ");
|
||||
aClause->AppendLiteral("EXISTS (SELECT h.id FROM moz_annos anno JOIN moz_anno_attributes annoname ON anno.anno_attribute_id = annoname.id WHERE anno.place_id = h.id AND annoname.name = ");
|
||||
aClause->Append(paramString);
|
||||
aClause->AppendLiteral(") ");
|
||||
clause.Str("NOT");
|
||||
clause.Str(
|
||||
"EXISTS "
|
||||
"(SELECT h.id "
|
||||
"FROM moz_annos anno "
|
||||
"JOIN moz_anno_attributes annoname "
|
||||
"ON anno.anno_attribute_id = annoname.id "
|
||||
"WHERE anno.place_id = h.id "
|
||||
"AND annoname.name = ").Param(":anno").Str(")");
|
||||
// annotation-based queries don't get the common conditions, so you get
|
||||
// all URLs with that annotation
|
||||
}
|
||||
|
||||
clause.GetClauseString(*aClause);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Helper class for BindQueryClauseParameters
|
||||
//
|
||||
// This class converts parameter names to parameter indexes. It supports
|
||||
// multiple queries by appending the query index to the parameter name.
|
||||
// For the query with index 0 the parameter name is not altered what
|
||||
// allows using this parameter in other situations (see SelectAsSite).
|
||||
|
||||
class IndexGetter
|
||||
{
|
||||
public:
|
||||
IndexGetter(PRInt32 aQueryIndex, mozIStorageStatement* aStatement) :
|
||||
mQueryIndex(aQueryIndex), mStatement(aStatement)
|
||||
{
|
||||
mResult = NS_OK;
|
||||
}
|
||||
|
||||
PRUint32 For(const char* aName)
|
||||
{
|
||||
PRUint32 index;
|
||||
|
||||
// Do not execute if we already had an error
|
||||
if (NS_SUCCEEDED(mResult)) {
|
||||
if (!mQueryIndex)
|
||||
mResult = mStatement->GetParameterIndex(nsCAutoString(aName), &index);
|
||||
else
|
||||
mResult = mStatement->GetParameterIndex(
|
||||
nsPrintfCString("%s%d", aName, mQueryIndex), &index);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(mResult))
|
||||
return index;
|
||||
|
||||
return -1; // Invalid index
|
||||
}
|
||||
|
||||
nsresult Result()
|
||||
{
|
||||
return mResult;
|
||||
}
|
||||
|
||||
private:
|
||||
PRInt32 mQueryIndex;
|
||||
mozIStorageStatement* mStatement;
|
||||
nsresult mResult;
|
||||
};
|
||||
|
||||
// nsNavHistory::BindQueryClauseParameters
|
||||
//
|
||||
// THE ORDER AND BEHAVIOR SHOULD BE IN SYNC WITH QueryToSelectClause
|
||||
// THE BEHAVIOR SHOULD BE IN SYNC WITH QueryToSelectClause
|
||||
|
||||
nsresult
|
||||
nsNavHistory::BindQueryClauseParameters(mozIStorageStatement* statement,
|
||||
PRInt32 aStartParameter,
|
||||
PRInt32 aQueryIndex,
|
||||
nsNavHistoryQuery* aQuery, // const
|
||||
nsNavHistoryQueryOptions* aOptions,
|
||||
PRInt32* aParamCount)
|
||||
nsNavHistoryQueryOptions* aOptions)
|
||||
{
|
||||
nsresult rv;
|
||||
(*aParamCount) = 0;
|
||||
|
||||
PRBool hasIt;
|
||||
IndexGetter index(aQueryIndex, statement);
|
||||
|
||||
// begin time
|
||||
if (NS_SUCCEEDED(aQuery->GetHasBeginTime(&hasIt)) && hasIt) {
|
||||
PRTime time = NormalizeTime(aQuery->BeginTimeReference(),
|
||||
aQuery->BeginTime());
|
||||
rv = statement->BindInt64Parameter(aStartParameter + *aParamCount, time);
|
||||
rv = statement->BindInt64Parameter(index.For(":begin_time"), time);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
(*aParamCount) ++;
|
||||
}
|
||||
|
||||
// end time
|
||||
if (NS_SUCCEEDED(aQuery->GetHasEndTime(&hasIt)) && hasIt) {
|
||||
PRTime time = NormalizeTime(aQuery->EndTimeReference(),
|
||||
aQuery->EndTime());
|
||||
rv = statement->BindInt64Parameter(aStartParameter + *aParamCount, time);
|
||||
rv = statement->BindInt64Parameter(index.For(":end_time"), time);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
(*aParamCount) ++;
|
||||
}
|
||||
|
||||
// search terms FIXME
|
||||
|
@ -4822,16 +4883,14 @@ nsNavHistory::BindQueryClauseParameters(mozIStorageStatement* statement,
|
|||
// min and max visit count
|
||||
PRInt32 visits = aQuery->MinVisits();
|
||||
if (visits >= 0) {
|
||||
rv = statement->BindInt32Parameter(aStartParameter + *aParamCount, visits);
|
||||
rv = statement->BindInt32Parameter(index.For(":min_visits"), visits);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
(*aParamCount) ++;
|
||||
}
|
||||
|
||||
visits = aQuery->MaxVisits();
|
||||
if (visits >= 0) {
|
||||
rv = statement->BindInt32Parameter(aStartParameter + *aParamCount, visits);
|
||||
rv = statement->BindInt32Parameter(index.For(":max_visits"), visits);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
(*aParamCount) ++;
|
||||
}
|
||||
|
||||
// domain (see GetReversedHostname for more info on reversed host names)
|
||||
|
@ -4840,39 +4899,35 @@ nsNavHistory::BindQueryClauseParameters(mozIStorageStatement* statement,
|
|||
GetReversedHostname(NS_ConvertUTF8toUTF16(aQuery->Domain()), revDomain);
|
||||
|
||||
if (aQuery->DomainIsHost()) {
|
||||
rv = statement->BindStringParameter(aStartParameter + *aParamCount, revDomain);
|
||||
rv = statement->BindStringParameter(index.For(":domain_lower"), revDomain);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
(*aParamCount) ++;
|
||||
} else {
|
||||
// for "mozilla.org" do query >= "gro.allizom." AND < "gro.allizom/"
|
||||
// which will get everything starting with "gro.allizom." while using the
|
||||
// index (using SUBSTRING() causes indexes to be discarded).
|
||||
NS_ASSERTION(revDomain[revDomain.Length() - 1] == '.', "Invalid rev. host");
|
||||
rv = statement->BindStringParameter(aStartParameter + *aParamCount, revDomain);
|
||||
rv = statement->BindStringParameter(index.For(":domain_lower"), revDomain);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
(*aParamCount) ++;
|
||||
revDomain.Truncate(revDomain.Length() - 1);
|
||||
revDomain.Append(PRUnichar('/'));
|
||||
rv = statement->BindStringParameter(aStartParameter + *aParamCount, revDomain);
|
||||
rv = statement->BindStringParameter(index.For(":domain_upper"), revDomain);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
(*aParamCount) ++;
|
||||
}
|
||||
}
|
||||
|
||||
// URI
|
||||
if (NS_SUCCEEDED(aQuery->GetHasUri(&hasIt)) && hasIt) {
|
||||
BindStatementURI(statement, aStartParameter + *aParamCount, aQuery->Uri());
|
||||
(*aParamCount) ++;
|
||||
}
|
||||
if (NS_SUCCEEDED(aQuery->GetHasUri(&hasIt)) && hasIt)
|
||||
BindStatementURI(statement, index.For(":uri"), aQuery->Uri());
|
||||
|
||||
// annotation
|
||||
aQuery->GetHasAnnotation(&hasIt);
|
||||
if (hasIt) {
|
||||
rv = statement->BindUTF8StringParameter(aStartParameter + *aParamCount,
|
||||
if (NS_SUCCEEDED(aQuery->GetHasAnnotation(&hasIt)) && hasIt) {
|
||||
rv = statement->BindUTF8StringParameter(index.For(":anno"),
|
||||
aQuery->Annotation());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
NS_ENSURE_SUCCESS(index.Result(), index.Result());
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -369,6 +369,8 @@ public:
|
|||
// sets the schema version in the database to match SCHEMA_VERSION
|
||||
nsresult UpdateSchemaVersion();
|
||||
|
||||
typedef nsDataHashtable<nsCStringHashKey, nsCString> StringHash;
|
||||
|
||||
private:
|
||||
~nsNavHistory();
|
||||
|
||||
|
@ -566,20 +568,19 @@ protected:
|
|||
#endif
|
||||
|
||||
nsresult ConstructQueryString(const nsCOMArray<nsNavHistoryQuery>& aQueries,
|
||||
nsNavHistoryQueryOptions *aOptions,
|
||||
nsNavHistoryQueryOptions* aOptions,
|
||||
nsCString& queryString,
|
||||
PRBool& aParamsPresent);
|
||||
PRBool& aParamsPresent,
|
||||
StringHash& aAddParams);
|
||||
|
||||
nsresult QueryToSelectClause(nsNavHistoryQuery* aQuery,
|
||||
nsNavHistoryQueryOptions* aOptions,
|
||||
PRInt32 aStartParameter,
|
||||
nsCString* aClause,
|
||||
PRInt32* aParamCount);
|
||||
PRInt32 aQueryIndex,
|
||||
nsCString* aClause);
|
||||
nsresult BindQueryClauseParameters(mozIStorageStatement* statement,
|
||||
PRInt32 aStartParameter,
|
||||
PRInt32 aQueryIndex,
|
||||
nsNavHistoryQuery* aQuery,
|
||||
nsNavHistoryQueryOptions* aOptions,
|
||||
PRInt32* aParamCount);
|
||||
nsNavHistoryQueryOptions* aOptions);
|
||||
|
||||
nsresult ResultsAsList(mozIStorageStatement* statement,
|
||||
nsNavHistoryQueryOptions* aOptions,
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Google Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2005
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ondrej Brablc <ondrej@allpeers.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// Get history service
|
||||
try {
|
||||
var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].getService(Ci.nsINavHistoryService);
|
||||
} catch(ex) {
|
||||
do_throw("Could not get history service\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a test URI visit to the database, and checks for a valid place ID.
|
||||
*
|
||||
* @param aURI
|
||||
* The URI to add a visit for.
|
||||
* @param aReferrer
|
||||
* The referring URI for the given URI. This can be null.
|
||||
* @returns the place id for aURI.
|
||||
*/
|
||||
function add_visit(aURI, aDayOffset, aEmbedded) {
|
||||
var placeID = histsvc.addVisit(aURI,
|
||||
(Date.now() + aDayOffset*86400000) * 1000,
|
||||
null,
|
||||
aEmbedded?histsvc.TRANSITION_EMBED
|
||||
:histsvc.TRANSITION_TYPED,
|
||||
false, // not redirect
|
||||
0);
|
||||
do_check_true(placeID > 0);
|
||||
return placeID;
|
||||
}
|
||||
|
||||
// main
|
||||
function run_test() {
|
||||
|
||||
var testURI = uri("http://mirror1.mozilla.com/a");
|
||||
add_visit(testURI, -1);
|
||||
testURI = uri("http://mirror2.mozilla.com/b");
|
||||
add_visit(testURI, -2);
|
||||
testURI = uri("http://mirror1.google.com/b");
|
||||
add_visit(testURI, -1, true);
|
||||
testURI = uri("http://mirror2.google.com/a");
|
||||
add_visit(testURI, -2);
|
||||
testURI = uri("http://mirror1.apache.org/b");
|
||||
add_visit(testURI, -3);
|
||||
testURI = uri("http://mirror2.apache.org/a");
|
||||
add_visit(testURI, -4, true);
|
||||
|
||||
var options = histsvc.getNewQueryOptions();
|
||||
var queries = [];
|
||||
queries.push(histsvc.getNewQuery());
|
||||
queries.push(histsvc.getNewQuery());
|
||||
|
||||
queries[0].domain = "mozilla.com";
|
||||
queries[1].domain = "google.com";
|
||||
|
||||
var result = histsvc.executeQueries(queries, queries.length, options);
|
||||
var root = result.root;
|
||||
root.containerOpen = true;
|
||||
do_check_eq(root.childCount, 3);
|
||||
root.containerOpen = false;
|
||||
}
|
Загрузка…
Ссылка в новой задаче