2
2
This file is part of the Nepomuk KDE project.
3
Copyright (C) 2007-2010 Sebastian Trueg <trueg@kde.org>
3
Copyright (C) 2007-2011 Sebastian Trueg <trueg@kde.org>
5
5
This library is free software; you can redistribute it and/or
6
6
modify it under the terms of the GNU Library General Public
133
Soprano::LiteralValue createLiteral( const QString& s_, bool globbing ) {
134
bool hadQuotes = false;
135
QString s = stripQuotes( s_, &hadQuotes );
133
Soprano::LiteralValue createLiteral( const QString& s, bool globbing ) {
134
// 1. check if it is a number
135
QString clearString(s);
136
clearString.remove(QLatin1Char('\''));
137
clearString.remove(QLatin1Char('"'));
137
int i = s.toInt( &b );
139
int i = clearString.toInt( &b );
139
141
return Soprano::LiteralValue( i );
140
double d = s.toDouble( &b );
142
double d = clearString.toDouble( &b );
142
144
return Soprano::LiteralValue( d );
146
// 2. no number - continue with the original string
148
// no globbing if we have quotes or if there already is a wildcard
149
if ( s[0] == QLatin1Char('\'') ||
150
s[0] == QLatin1Char('\"') ) {
145
155
// we can only do query term globbing for strings longer than 3 chars
147
if( !hadQuotes && globbing && s.length() > 3 && !s.endsWith('*') && !s.endsWith('?') )
157
if( globbing && s.length() > 3 && !s.endsWith('*') && !s.endsWith('?') )
148
158
return QString(s + '*');
250
260
Nepomuk::Query::ComparisonTerm::Regexp );
264
* Merging literal terms is an optimization which is based on the assumption that most
265
* users want to search for the full text terms they enter in the value of the same
267
* Since merging two literals "foo" and "bar" into one term "foo AND bar" effectively
268
* changes the result set (the former allows that "foo" occurs in a property value
269
* different from "bar" while the latter forces them to occur in the same.)
270
* But the resulting query is much faster.
272
Nepomuk::Query::Term mergeLiteralTerms( const Nepomuk::Query::Term& term )
274
if( term.isAndTerm() ) {
276
QStringList fullTextTerms;
277
Q_FOREACH( const Term& st, term.toAndTerm().subTerms() ) {
278
if( st.isLiteralTerm() ) {
279
fullTextTerms << st.toLiteralTerm().value().toString();
282
mergedTerm.addSubTerm( st );
285
mergedTerm.addSubTerm( LiteralTerm( fullTextTerms.join( QString::fromLatin1(" AND ") ) ) );
286
return mergedTerm.optimized();
253
293
#ifndef Q_CC_MSVC
254
294
#warning Make the parser handle different data, time, and datetime encodings as well as suffixes like MB or GB
461
501
bool inAndBlock = false;
505
// create local copies of the regexps for thread safety purposes
506
const QRegExp resourceRx = s_resourceRx;
507
const QRegExp propertyRx = s_propertyRx;
508
const QRegExp fieldFieldRx = s_fieldFieldRx;
509
const QRegExp fieldRx = s_fieldRx;
510
const QRegExp plainTermRx = s_plainTermRx;
464
512
while ( pos < query.length() ) {
465
513
// skip whitespace
466
514
while ( pos < query.length() && query[pos].isSpace() ) {
473
521
if ( pos < query.length() ) {
474
if ( s_resourceRx.indexIn( query, pos ) == pos ) {
475
kDebug() << "matched resource term at" << pos << s_resourceRx.cap( 0 );
476
term = ComparisonTerm( tryToBeIntelligentAboutParsingUrl( s_resourceRx.cap( 2 ) ),
477
ResourceTerm( tryToBeIntelligentAboutParsingUrl( s_resourceRx.cap( 3 ) ) ),
522
if ( resourceRx.indexIn( query, pos ) == pos ) {
523
kDebug() << "matched resource term at" << pos << resourceRx.cap( 0 );
524
term = ComparisonTerm( tryToBeIntelligentAboutParsingUrl( resourceRx.cap( 2 ) ),
525
ResourceTerm( tryToBeIntelligentAboutParsingUrl( resourceRx.cap( 3 ) ) ),
478
526
ComparisonTerm::Equal );
479
if ( !positiveTerm(s_resourceRx.cap( 1 ) ) ) {
527
if ( !positiveTerm( resourceRx.cap( 1 ) ) ) {
480
528
term = NegationTerm::negateTerm( term );
482
pos += s_resourceRx.matchedLength();
530
pos += resourceRx.matchedLength();
485
else if ( s_propertyRx.indexIn( query, pos ) == pos ) {
486
kDebug() << "matched property term at" << pos << s_propertyRx.cap( 0 );
533
else if ( propertyRx.indexIn( query, pos ) == pos ) {
534
kDebug() << "matched property term at" << pos << propertyRx.cap( 0 );
487
535
ComparisonTerm ct;
488
ct.setProperty( tryToBeIntelligentAboutParsingUrl( s_propertyRx.cap( 2 ) ) );
489
ct.setSubTerm( LiteralTerm( createLiteral( s_propertyRx.cap( 4 ), flags&QueryTermGlobbing ) ) );
490
QString comparator = s_propertyRx.cap( 3 );
536
ct.setProperty( tryToBeIntelligentAboutParsingUrl( propertyRx.cap( 2 ) ) );
537
ct.setSubTerm( LiteralTerm( createLiteral( propertyRx.cap( 4 ), flags&QueryTermGlobbing ) ) );
538
QString comparator = propertyRx.cap( 3 );
491
539
ct.setComparator( fieldTypeRelationFromString( comparator ) );
492
pos += s_propertyRx.matchedLength();
540
pos += propertyRx.matchedLength();
494
if ( !positiveTerm(s_propertyRx.cap( 1 ) ) ) {
542
if ( !positiveTerm(propertyRx.cap( 1 ) ) ) {
495
543
term = NegationTerm::negateTerm( ct );
502
else if ( s_fieldFieldRx.indexIn( query, pos ) == pos ) {
550
else if ( fieldFieldRx.indexIn( query, pos ) == pos ) {
503
551
kDebug() << "matched field field term at" << pos
504
<< s_fieldFieldRx.cap( 0 )
505
<< s_fieldFieldRx.cap( 2 )
506
<< s_fieldFieldRx.cap( 4 )
507
<< s_fieldFieldRx.cap( 5 )
508
<< s_fieldFieldRx.cap( 7 )
509
<< s_fieldFieldRx.cap( 8 );
552
<< fieldFieldRx.cap( 0 )
553
<< fieldFieldRx.cap( 2 )
554
<< fieldFieldRx.cap( 4 )
555
<< fieldFieldRx.cap( 5 )
556
<< fieldFieldRx.cap( 7 )
557
<< fieldFieldRx.cap( 8 );
510
558
ComparisonTerm ct;
511
ct.setProperty( QUrl(stripQuotes( s_fieldFieldRx.cap( 2 ) )) );
512
QString comparator = s_fieldFieldRx.cap( 4 );
559
ct.setProperty( QUrl(stripQuotes( fieldFieldRx.cap( 2 ) )) );
560
QString comparator = fieldFieldRx.cap( 4 );
513
561
ct.setComparator( fieldTypeRelationFromString( comparator ) );
514
ct.setSubTerm( ComparisonTerm( QUrl(stripQuotes( s_fieldFieldRx.cap( 5 ) )),
515
LiteralTerm( createLiteral( s_fieldFieldRx.cap( 8 ), flags&QueryTermGlobbing ) ),
516
fieldTypeRelationFromString( s_fieldFieldRx.cap( 7 ) ) ) );
517
pos += s_fieldFieldRx.matchedLength();
562
ct.setSubTerm( ComparisonTerm( QUrl(stripQuotes( fieldFieldRx.cap( 5 ) )),
563
LiteralTerm( createLiteral( fieldFieldRx.cap( 8 ), flags&QueryTermGlobbing ) ),
564
fieldTypeRelationFromString( fieldFieldRx.cap( 7 ) ) ) );
565
pos += fieldFieldRx.matchedLength();
519
if ( !positiveTerm(s_fieldFieldRx.cap( 1 ) ) ) {
567
if ( !positiveTerm( fieldFieldRx.cap( 1 ) ) ) {
520
568
term = NegationTerm::negateTerm( ct );
527
else if ( s_fieldRx.indexIn( query, pos ) == pos ) {
528
kDebug() << "matched field term at" << pos << s_fieldRx.cap( 0 ) << s_fieldRx.cap( 2 ) << s_fieldRx.cap( 4 ) << s_fieldRx.cap( 5 );
529
if( stripQuotes ( s_fieldRx.cap( 2 ) ).compare( QString( "inFolder" ), Qt::CaseInsensitive ) == 0 ) {
530
KUrl url( s_fieldRx.cap( 5 ) );
575
else if ( fieldRx.indexIn( query, pos ) == pos ) {
576
kDebug() << "matched field term at" << pos << fieldRx.cap( 0 ) << fieldRx.cap( 2 ) << fieldRx.cap( 4 ) << fieldRx.cap( 5 );
577
if( stripQuotes ( fieldRx.cap( 2 ) ).compare( QString( "inFolder" ), Qt::CaseInsensitive ) == 0 ) {
578
KUrl url( fieldRx.cap( 5 ) );
531
579
kDebug() << "found include path" << url;
532
580
FileQuery fileQuery(final);
533
if ( positiveTerm( s_fieldRx.cap( 1 ) ) )
581
if ( positiveTerm( fieldRx.cap( 1 ) ) )
534
582
fileQuery.addIncludeFolder(url);
536
584
fileQuery.addExcludeFolder(url);
537
585
final = fileQuery;
538
pos += s_fieldRx.matchedLength();
586
pos += fieldRx.matchedLength();
541
589
ComparisonTerm ct;
542
ct.setProperty( QUrl( stripQuotes( s_fieldRx.cap( 2 ) ) ) );
543
ct.setSubTerm( LiteralTerm( createLiteral( s_fieldRx.cap( 5 ), flags&QueryTermGlobbing ) ) );
544
QString comparator = s_fieldRx.cap( 4 );
590
ct.setProperty( QUrl( stripQuotes( fieldRx.cap( 2 ) ) ) );
591
ct.setSubTerm( LiteralTerm( createLiteral( fieldRx.cap( 5 ), flags&QueryTermGlobbing ) ) );
592
QString comparator = fieldRx.cap( 4 );
545
593
ct.setComparator( fieldTypeRelationFromString( comparator ) );
546
pos += s_fieldRx.matchedLength();
547
if ( !positiveTerm(s_fieldRx.cap( 1 ) ) ) {
594
pos += fieldRx.matchedLength();
595
if ( !positiveTerm(fieldRx.cap( 1 ) ) ) {
549
597
nt.setSubTerm( ct );
558
else if ( s_plainTermRx.indexIn( query, pos ) == pos ) {
559
QString value = s_plainTermRx.cap( 2 );
606
else if ( plainTermRx.indexIn( query, pos ) == pos ) {
607
QString value = plainTermRx.cap( 2 );
560
608
if ( d->orKeywords.contains( value.toLower() ) ) {
561
609
inOrBlock = true;
572
620
term = LiteralTerm( createLiteral( value, flags&QueryTermGlobbing ) );
574
if ( !positiveTerm(s_plainTermRx.cap( 1 ) ) ) {
622
if ( !positiveTerm(plainTermRx.cap( 1 ) ) ) {
575
623
term = NegationTerm::negateTerm( term );
578
pos += s_plainTermRx.matchedLength();
626
pos += plainTermRx.matchedLength();