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:
dietrich@mozilla.com 2008-03-19 14:08:10 -07:00
Родитель 703b6a2f0c
Коммит 1ee56dab8e
3 изменённых файлов: 322 добавлений и 170 удалений

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

@ -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;
}