2008-01-14 01:01:11 +01:00
|
|
|
/*
|
2012-11-26 01:22:01 +01:00
|
|
|
QUERY.hpp - interface for generic queries
|
2010-12-17 23:28:49 +01:00
|
|
|
|
2008-03-10 08:38:59 +01:00
|
|
|
Copyright (C) Lumiera.org
|
|
|
|
|
2008, Hermann Vosseler <Ichthyostega@web.de>
|
2010-12-17 23:28:49 +01:00
|
|
|
|
2008-01-14 01:01:11 +01:00
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
|
modify it under the terms of the GNU General Public License as
|
2010-12-17 23:28:49 +01:00
|
|
|
published by the Free Software Foundation; either version 2 of
|
|
|
|
|
the License, or (at your option) any later version.
|
|
|
|
|
|
2008-01-14 01:01:11 +01:00
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
2010-12-17 23:28:49 +01:00
|
|
|
|
2008-01-14 01:01:11 +01:00
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
2010-12-17 23:28:49 +01:00
|
|
|
|
2008-01-14 01:01:11 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
2013-01-02 03:32:49 +01:00
|
|
|
/** @file query.hpp
|
|
|
|
|
** Basic and generic representation of an internal query.
|
|
|
|
|
** This header provides the foundation for issuing queries instead of using hard wired
|
|
|
|
|
** logic and defaults. This is a fundamental architecture pattern within Lumiera, and serves
|
|
|
|
|
** to decouple the parts of the application and allows for a rules based configuration and
|
|
|
|
|
** orchestration of the internal workings.
|
|
|
|
|
**
|
|
|
|
|
** A Query is a request for just \em someone to come up with a solution, a preconfigured
|
|
|
|
|
** setup, some existing data object or contextual information. In order to be usable,
|
|
|
|
|
** a QueryResolver needs to be available for computing the solution and retrieving
|
|
|
|
|
** the results. As a common denominator, queries can be <i>generic queries</i> given
|
|
|
|
|
** in predicate logic syntax; in this case a generic query resolver (Planned feature
|
|
|
|
|
** as of 1/2013) will be able at least to determine a suitable facility for delegating
|
|
|
|
|
** the resolution. Besides, specific subsystems are using more specific kinds of
|
|
|
|
|
** queries and provide a specialised resolution mechanism, which in these cases
|
|
|
|
|
** can be addressed directly.
|
|
|
|
|
**
|
|
|
|
|
** \par General usage pattern
|
|
|
|
|
** Some parts of the application allow to issue queries -- typically these parts do
|
|
|
|
|
** also expose a service point for clients to issue similar queries. In any case, a
|
|
|
|
|
** query remains in the ownership of the issuer, which is also responsible to keep
|
|
|
|
|
** the storage alive during results retrieval. Queries can't be copied and are passed
|
|
|
|
|
** by reference, since #Query is an interface baseclass. Each query instance bears
|
|
|
|
|
** at least a type tag to indicate the type of the returned result, plus a classification
|
|
|
|
|
** tag indicate the kind of query. Generally, queries are also required to provide a
|
|
|
|
|
** syntactical representation, allowing to transform each query into a generic query.
|
|
|
|
|
**
|
|
|
|
|
** To resolve the query, a lumiera::QueryResolver instance is necessary, and this
|
|
|
|
|
** query resolver needs the ability to deal with this specific kind of query. Typically
|
|
|
|
|
** this is achieved by installing a resolution function into the resolver on application start.
|
|
|
|
|
** The QueryResolver returns a result set, actually a Query::Cursor, which can be used to
|
|
|
|
|
** enumerate multiple solutions, if any.
|
|
|
|
|
**
|
|
|
|
|
** Queries are \em immutable, but it is possible to re-build and remould a query using
|
|
|
|
|
** a Query<TY>::Builder, accessible via Query#build() and Query#rebuild().
|
|
|
|
|
**
|
|
|
|
|
** @note as of 1/2013 this is rather a concept draft, but some parts of the code base
|
|
|
|
|
** are already actively using some more specific queries
|
|
|
|
|
**
|
|
|
|
|
** @see lumiera::QueryResolver
|
|
|
|
|
** @see mobject::session::DefsManager
|
|
|
|
|
** @see asset::StructFactory
|
|
|
|
|
** @see config-resolver.hpp specialised setup for the Proc-Layer
|
|
|
|
|
** @see fake-configrules.hpp currently used dummy-implementation
|
|
|
|
|
** @see SessionServiceExploreScope
|
|
|
|
|
** @see PlacementIndexQueryResolver
|
|
|
|
|
**
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
2012-12-03 00:18:18 +01:00
|
|
|
#ifndef LUMIERA_QUERY_H
|
|
|
|
|
#define LUMIERA_QUERY_H
|
2008-01-14 01:01:11 +01:00
|
|
|
|
|
|
|
|
|
2012-11-26 01:22:01 +01:00
|
|
|
#include "lib/bool-checkable.hpp"
|
|
|
|
|
#include "lib/typed-counter.hpp"
|
|
|
|
|
#include "lib/iter-adapter.hpp"
|
2012-12-07 01:49:35 +01:00
|
|
|
#include "lib/query-text.hpp"
|
2012-12-09 02:42:36 +01:00
|
|
|
#include "lib/query-util.hpp"
|
2012-12-26 01:11:57 +01:00
|
|
|
#include "lib/hash-value.h"
|
2012-11-26 01:22:01 +01:00
|
|
|
#include "lib/nocopy.hpp"
|
2009-09-24 23:02:40 +02:00
|
|
|
#include "lib/symbol.hpp"
|
2012-11-26 01:22:01 +01:00
|
|
|
#include "lib/util.hpp"
|
2008-11-30 06:46:32 +01:00
|
|
|
|
2012-11-26 01:22:01 +01:00
|
|
|
#include <boost/lexical_cast.hpp>
|
2012-12-17 23:17:32 +01:00
|
|
|
#include <boost/operators.hpp>
|
2012-11-26 01:22:01 +01:00
|
|
|
#include <tr1/memory>
|
|
|
|
|
#include <typeinfo>
|
|
|
|
|
#include <cctype>
|
|
|
|
|
#include <string>
|
2008-11-30 06:46:32 +01:00
|
|
|
|
2012-11-26 01:22:01 +01:00
|
|
|
|
2012-12-01 08:44:07 +01:00
|
|
|
namespace lumiera {
|
2009-09-24 23:02:40 +02:00
|
|
|
|
2012-11-26 01:22:01 +01:00
|
|
|
using lib::IxID;
|
2009-09-24 23:02:40 +02:00
|
|
|
using lib::Symbol;
|
|
|
|
|
using lib::Literal;
|
2012-11-26 01:22:01 +01:00
|
|
|
using util::unConst;
|
|
|
|
|
using boost::lexical_cast;
|
2008-01-14 01:01:11 +01:00
|
|
|
using std::string;
|
2010-04-04 06:38:22 +02:00
|
|
|
|
2012-11-26 01:22:01 +01:00
|
|
|
|
2008-11-30 06:46:32 +01:00
|
|
|
/* ==== common definitions for rule based queries ==== */
|
2008-01-14 01:01:11 +01:00
|
|
|
|
2012-11-26 01:22:01 +01:00
|
|
|
class Goal;
|
|
|
|
|
class Resolution;
|
2012-12-17 23:17:32 +01:00
|
|
|
class QueryResolver;
|
|
|
|
|
class QueryKey;
|
|
|
|
|
|
2012-11-26 01:22:01 +01:00
|
|
|
|
|
|
|
|
/** Allow for taking ownership of a result set */
|
|
|
|
|
typedef std::tr1::shared_ptr<Resolution> PReso;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Query ABC: unspecific goal for resolution or retrieval.
|
|
|
|
|
* Goal elements are used within the backbone of a generic query system
|
|
|
|
|
* to access individual resolution mechanisms based on an internal classification
|
|
|
|
|
* of the type of query.
|
|
|
|
|
*/
|
|
|
|
|
class Goal
|
|
|
|
|
: util::no_copy_by_client
|
|
|
|
|
{
|
|
|
|
|
public:
|
2012-12-07 01:49:35 +01:00
|
|
|
virtual ~Goal(); ///< this is a marker baseclass
|
2012-11-26 01:22:01 +01:00
|
|
|
|
|
|
|
|
enum Kind
|
2012-12-07 01:49:35 +01:00
|
|
|
{ EMPTY = 0
|
|
|
|
|
, GENERIC = 1
|
2012-11-26 01:22:01 +01:00
|
|
|
, DISCOVERY
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct QueryID
|
|
|
|
|
{
|
|
|
|
|
Kind kind;
|
|
|
|
|
IxID type;
|
2012-12-25 01:16:19 +01:00
|
|
|
|
|
|
|
|
explicit
|
|
|
|
|
QueryID(Kind k =EMPTY, IxID t=1)
|
|
|
|
|
: kind(k)
|
|
|
|
|
, type(t)
|
|
|
|
|
{ }
|
2012-11-26 01:22:01 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
QueryID const&
|
|
|
|
|
getQID() const
|
|
|
|
|
{
|
|
|
|
|
return id_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Single Solution, possibly part of a result set.
|
|
|
|
|
* A pointer-like object, usually to be down-casted
|
|
|
|
|
* to a specifically typed Query::Cursor
|
|
|
|
|
* @see Resolution
|
|
|
|
|
*/
|
|
|
|
|
class Result
|
|
|
|
|
: public lib::BoolCheckable<Result>
|
|
|
|
|
{
|
|
|
|
|
void* cur_;
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
void point_at(void* p) { cur_ = p; }
|
|
|
|
|
|
|
|
|
|
template<typename RES>
|
|
|
|
|
RES&
|
|
|
|
|
access()
|
|
|
|
|
{
|
|
|
|
|
REQUIRE (cur_);
|
|
|
|
|
return *reinterpret_cast<RES*> (cur_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
bool isValid() const { return bool(cur_); }
|
|
|
|
|
|
|
|
|
|
Result() : cur_(0) { } ///< create an NIL result
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
QueryID id_;
|
|
|
|
|
|
|
|
|
|
Goal (QueryID qid)
|
|
|
|
|
: id_(qid)
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2012-12-26 01:11:57 +01:00
|
|
|
inline bool
|
|
|
|
|
operator< (Goal::QueryID const& id1, Goal::QueryID const& id2)
|
|
|
|
|
{
|
|
|
|
|
return id1.kind < id2.kind
|
|
|
|
|
||(id1.kind == id2.kind && id1.type < id2.type);
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-26 01:22:01 +01:00
|
|
|
inline bool
|
|
|
|
|
operator== (Goal::QueryID const& id1, Goal::QueryID const& id2)
|
|
|
|
|
{
|
|
|
|
|
return id1.kind == id2.kind
|
|
|
|
|
&& id1.type == id2.type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline bool
|
|
|
|
|
operator!= (Goal::QueryID const& id1, Goal::QueryID const& id2)
|
|
|
|
|
{
|
|
|
|
|
return ! (id1 == id2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-12-25 01:16:19 +01:00
|
|
|
namespace {
|
|
|
|
|
/** Context used for generating type-IDs to denote
|
|
|
|
|
* the specific result types of issued queries */
|
|
|
|
|
typedef lib::TypedContext<Goal::Result> ResultType;
|
|
|
|
|
|
|
|
|
|
template<typename RES>
|
|
|
|
|
inline IxID
|
|
|
|
|
getResultTypeID() ///< @return unique ID denoting result type RES
|
|
|
|
|
{
|
|
|
|
|
return ResultType::ID<RES>::get();
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-26 01:11:57 +01:00
|
|
|
/** includes the QueryID type distinction into the given hash value */
|
|
|
|
|
inline size_t
|
|
|
|
|
taggedHash (size_t hash, Goal::QueryID typeID)
|
|
|
|
|
{
|
|
|
|
|
lib::hash::combine (hash, typeID.kind);
|
|
|
|
|
lib::hash::combine (hash, typeID.type);
|
|
|
|
|
return hash;
|
|
|
|
|
}
|
2012-11-26 01:22:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-04-04 06:38:22 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2012-11-26 01:22:01 +01:00
|
|
|
* Generic interface to express a query
|
|
|
|
|
* for specifically typed result elements
|
|
|
|
|
* providing some capabilities or fulfilling
|
|
|
|
|
* some properties. This is a generic umbrella
|
|
|
|
|
* for several kinds of queries and provides a
|
|
|
|
|
* mechanism for uniform usage of various
|
|
|
|
|
* resolution mechanisms.
|
|
|
|
|
*
|
|
|
|
|
* Any query bears an internal type classification and can be
|
|
|
|
|
* represented in a common syntactical form based on predicate logic.
|
|
|
|
|
* Query instances are created by some facilities allowing to query for objects.
|
|
|
|
|
* These query providers \em do know the specific kind (type) of query to expose.
|
|
|
|
|
* While client code uses these queries only by reference, there is the possibility
|
|
|
|
|
* to involve a generic QueryResolver, which -- behind the scenes -- manages a registry
|
|
|
|
|
* of specific resolution mechanisms. This way, clients may retrieve a set of results,
|
|
|
|
|
* each representing a possible solution to the posed query.
|
|
|
|
|
*
|
2010-11-27 03:59:07 +01:00
|
|
|
* @note until really integrating a rules based system
|
2012-11-26 01:22:01 +01:00
|
|
|
* this is largely dummy placeholder implementation.
|
|
|
|
|
* Some more specific query resolvers are available already,
|
|
|
|
|
* so, depending on the circumstances the actual resolution might be
|
|
|
|
|
* substantial or just a fake.
|
|
|
|
|
* @warning especially the classical resolution-type queries are just
|
|
|
|
|
* faked and use the given query-string as-is, without any normalisation.
|
|
|
|
|
* Moreover, as especially the fake-configrules match by string comparison,
|
2010-11-27 03:59:07 +01:00
|
|
|
* this may led to unexpected mis-matches.
|
2008-01-14 01:01:11 +01:00
|
|
|
*/
|
2012-11-26 01:22:01 +01:00
|
|
|
template<class RES>
|
2012-11-25 02:04:19 +01:00
|
|
|
class Query
|
2012-11-26 01:22:01 +01:00
|
|
|
: public Goal
|
2008-01-14 01:01:11 +01:00
|
|
|
{
|
2012-12-07 01:49:35 +01:00
|
|
|
/** generic syntactical definition */
|
|
|
|
|
lib::QueryText def_;
|
|
|
|
|
|
2012-11-26 01:22:01 +01:00
|
|
|
protected:
|
|
|
|
|
static QueryID
|
|
|
|
|
defineQueryTypeID (Kind queryType = Goal::GENERIC)
|
|
|
|
|
{
|
2012-12-25 01:16:19 +01:00
|
|
|
QueryID id(queryType, getResultTypeID<RES>());
|
2012-11-26 01:22:01 +01:00
|
|
|
return id;
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-07 01:49:35 +01:00
|
|
|
|
2012-11-26 01:22:01 +01:00
|
|
|
class Builder;
|
2012-12-11 04:45:18 +01:00
|
|
|
|
2012-12-29 00:31:24 +01:00
|
|
|
Query (QueryID typeID, lib::QueryText const& genericQuerySpec)
|
2012-12-11 04:45:18 +01:00
|
|
|
: Goal (typeID)
|
2012-12-29 00:31:24 +01:00
|
|
|
, def_(genericQuerySpec)
|
2012-12-07 01:49:35 +01:00
|
|
|
{ }
|
|
|
|
|
|
2012-12-11 04:45:18 +01:00
|
|
|
Query (QueryID typeID, string querySpec)
|
|
|
|
|
: Goal (defineQueryTypeID(typeID.kind))
|
|
|
|
|
, def_(querySpec)
|
|
|
|
|
{
|
|
|
|
|
REQUIRE (this->getQID().type == typeID.type);
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-07 01:49:35 +01:00
|
|
|
friend class Builder;
|
|
|
|
|
|
2012-11-26 01:22:01 +01:00
|
|
|
|
2008-01-14 01:01:11 +01:00
|
|
|
public:
|
2012-11-26 01:22:01 +01:00
|
|
|
Query()
|
2012-12-07 01:49:35 +01:00
|
|
|
: Goal (defineQueryTypeID(Goal::EMPTY))
|
2012-11-25 02:04:19 +01:00
|
|
|
{ }
|
2008-02-18 04:16:53 +01:00
|
|
|
|
2012-11-26 01:22:01 +01:00
|
|
|
explicit
|
|
|
|
|
Query (string querySpec)
|
|
|
|
|
: Goal (defineQueryTypeID(Goal::GENERIC))
|
2012-12-07 01:49:35 +01:00
|
|
|
, def_(querySpec)
|
|
|
|
|
{ }
|
2008-04-07 03:19:24 +02:00
|
|
|
|
2012-12-25 01:16:19 +01:00
|
|
|
operator QueryKey() const;
|
2012-12-07 01:49:35 +01:00
|
|
|
|
2012-12-25 01:16:19 +01:00
|
|
|
static Builder build (Kind queryType = Goal::GENERIC);
|
|
|
|
|
Builder rebuild() const;
|
2012-12-17 23:17:32 +01:00
|
|
|
|
2012-12-25 01:16:19 +01:00
|
|
|
string extractID (Symbol predicate) const;
|
|
|
|
|
bool usesPredicate (Symbol predicate) const;
|
2012-12-17 23:17:32 +01:00
|
|
|
|
2012-12-09 02:42:36 +01:00
|
|
|
|
2012-11-26 01:22:01 +01:00
|
|
|
|
|
|
|
|
/* results retrieval */
|
|
|
|
|
class Cursor
|
|
|
|
|
: public Goal::Result
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
typedef RES value_type;
|
|
|
|
|
typedef RES& reference;
|
|
|
|
|
typedef RES* pointer;
|
|
|
|
|
|
|
|
|
|
RES& operator* () { return access<RES>(); }
|
|
|
|
|
RES* operator->() { return & access<RES>(); }
|
|
|
|
|
|
|
|
|
|
void point_at(RES* r){ Goal::Result::point_at(r);}
|
|
|
|
|
void point_at(RES& r){ Goal::Result::point_at(&r);}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef lib::IterAdapter<Cursor,PReso> iterator;
|
2012-11-25 02:04:19 +01:00
|
|
|
|
2012-11-26 01:22:01 +01:00
|
|
|
iterator operator() (QueryResolver const& resolver) const;
|
|
|
|
|
iterator resolveBy (QueryResolver const& resolver) const;
|
|
|
|
|
|
2012-12-09 02:42:36 +01:00
|
|
|
|
2012-11-26 01:22:01 +01:00
|
|
|
friend size_t
|
|
|
|
|
hash_value (Query const& q)
|
|
|
|
|
{
|
2012-12-26 01:11:57 +01:00
|
|
|
return taggedHash (hash_value(q.def_), q.id_);
|
2012-11-26 01:22:01 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-12-17 23:17:32 +01:00
|
|
|
/**
|
|
|
|
|
* Wrapper for indexing and ordering.
|
|
|
|
|
* Defines a synthetic totally ordered index value.
|
|
|
|
|
* Implicitly convertible to and from Query instances.
|
|
|
|
|
*/
|
|
|
|
|
class QueryKey
|
2012-12-22 00:39:23 +01:00
|
|
|
: boost::totally_ordered<QueryKey>
|
2012-12-17 23:17:32 +01:00
|
|
|
{
|
|
|
|
|
Goal::QueryID id_;
|
|
|
|
|
lib::QueryText def_;
|
|
|
|
|
|
|
|
|
|
public:
|
2012-12-22 00:39:23 +01:00
|
|
|
QueryKey (Goal::QueryID id, lib::QueryText q)
|
2012-12-17 23:17:32 +01:00
|
|
|
: id_(id)
|
|
|
|
|
, def_(q)
|
|
|
|
|
{ }
|
|
|
|
|
|
2012-12-25 01:16:19 +01:00
|
|
|
/** the empty or bottom query key */
|
|
|
|
|
QueryKey()
|
|
|
|
|
: id_()
|
|
|
|
|
, def_("NIL")
|
|
|
|
|
{ }
|
|
|
|
|
|
2012-12-17 23:17:32 +01:00
|
|
|
// default copyable
|
|
|
|
|
|
|
|
|
|
template<class RES>
|
|
|
|
|
operator Query<RES>() const
|
|
|
|
|
{
|
2012-12-22 00:39:23 +01:00
|
|
|
REQUIRE (getResultTypeID<RES>() == id_.type);
|
2012-12-24 03:20:52 +01:00
|
|
|
return Query<RES>::build(id_.kind).fromText(def_);
|
2012-12-17 23:17:32 +01:00
|
|
|
}
|
|
|
|
|
|
2012-12-22 22:01:51 +01:00
|
|
|
string
|
|
|
|
|
display() const
|
2012-12-22 00:39:23 +01:00
|
|
|
{
|
|
|
|
|
return "kind=" + lexical_cast<string>(id_.kind)
|
|
|
|
|
+",type=" + lexical_cast<string>(id_.type)
|
|
|
|
|
+",def=" + string(def_);
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-24 03:20:52 +01:00
|
|
|
string
|
|
|
|
|
getQueryString() const
|
|
|
|
|
{
|
|
|
|
|
return string(def_);
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-22 00:39:23 +01:00
|
|
|
|
2012-12-17 23:17:32 +01:00
|
|
|
uint
|
|
|
|
|
degree() const
|
|
|
|
|
{
|
2012-12-22 00:39:23 +01:00
|
|
|
return def_.degree_of_constriction();
|
2012-12-17 23:17:32 +01:00
|
|
|
}
|
|
|
|
|
|
2012-12-25 01:16:19 +01:00
|
|
|
bool
|
|
|
|
|
empty() const
|
|
|
|
|
{
|
|
|
|
|
return Goal::EMPTY == id_.kind;
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-17 23:17:32 +01:00
|
|
|
|
|
|
|
|
friend bool
|
|
|
|
|
operator< (QueryKey const& q1, QueryKey const& q2)
|
|
|
|
|
{
|
2012-12-22 00:39:23 +01:00
|
|
|
uint d1 = q1.degree();
|
|
|
|
|
uint d2 = q2.degree();
|
|
|
|
|
return d1 < d2
|
2012-12-26 01:11:57 +01:00
|
|
|
||(d1 == d2 && ( q1.def_ < q2.def_
|
|
|
|
|
||(q1.def_ == q2.def_ && q1.id_ < q2.id_)));
|
2012-12-17 23:17:32 +01:00
|
|
|
}
|
|
|
|
|
|
2012-12-25 01:16:19 +01:00
|
|
|
friend bool
|
|
|
|
|
operator== (QueryKey const& q1, QueryKey const& q2)
|
|
|
|
|
{
|
|
|
|
|
return q1.def_ == q2.def_;
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-17 23:17:32 +01:00
|
|
|
friend size_t
|
|
|
|
|
hash_value (QueryKey const& q)
|
|
|
|
|
{
|
2012-12-26 01:11:57 +01:00
|
|
|
return taggedHash (hash_value(q.def_), q.id_);
|
2012-12-17 23:17:32 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-12-09 02:42:36 +01:00
|
|
|
/**
|
|
|
|
|
* Helper for establishing,
|
|
|
|
|
* reworking and remolding queries.
|
|
|
|
|
*/
|
|
|
|
|
template<class RES>
|
|
|
|
|
class Query<RES>::Builder
|
|
|
|
|
{
|
|
|
|
|
QueryID typeID_;
|
|
|
|
|
string predicateForm_;
|
|
|
|
|
|
|
|
|
|
Builder (QueryID kind, string baseDef ="")
|
|
|
|
|
: typeID_(kind)
|
|
|
|
|
, predicateForm_(baseDef)
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
friend class Query<RES>;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
2012-12-11 04:45:18 +01:00
|
|
|
/** when done with defining or reworking the query,
|
|
|
|
|
* the result may be retrieved by type conversion */
|
|
|
|
|
operator Query<RES>()
|
|
|
|
|
{
|
|
|
|
|
return Query<RES>(typeID_, predicateForm_);
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-09 02:42:36 +01:00
|
|
|
|
2012-12-11 04:45:18 +01:00
|
|
|
/** @return a string representation usable for hashing
|
|
|
|
|
* @note includes the type parameter of the underlying query
|
|
|
|
|
*/
|
2012-12-09 02:42:36 +01:00
|
|
|
string
|
2012-11-26 01:22:01 +01:00
|
|
|
asKey() const
|
|
|
|
|
{
|
|
|
|
|
return "type("
|
|
|
|
|
+ lexical_cast<string> (getResultTypeID<RES>())
|
|
|
|
|
+ "), "+predicateForm_;
|
|
|
|
|
}
|
2012-12-09 02:42:36 +01:00
|
|
|
|
|
|
|
|
|
2012-12-11 04:45:18 +01:00
|
|
|
/** extract an ID term defined as (single) parameter for the given predicate.
|
|
|
|
|
* E.g. when using the query "foo(a), bar(b)", \c extractID("bar") returns "b"
|
|
|
|
|
* @param predicate symbol of the predicate to investigate
|
|
|
|
|
* @warning preliminary implementation
|
|
|
|
|
*/
|
2012-12-09 02:42:36 +01:00
|
|
|
string
|
|
|
|
|
extractID (Symbol predicate) const
|
|
|
|
|
{
|
|
|
|
|
return lib::query::extractID (predicate, this->predicateForm_);
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-11 04:45:18 +01:00
|
|
|
|
|
|
|
|
/** remove the first term from this query definition,
|
|
|
|
|
* which matches the given predicate symbol
|
|
|
|
|
* @warning preliminary implementation
|
|
|
|
|
*/
|
|
|
|
|
Builder&
|
|
|
|
|
removeTerm (Symbol termPredicate)
|
|
|
|
|
{
|
|
|
|
|
lib::query::removeTerm(termPredicate, this->predicateForm_);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-17 23:17:32 +01:00
|
|
|
Builder&
|
|
|
|
|
withConditions (string additionalQueryPredicates)
|
|
|
|
|
{
|
2012-12-24 03:20:52 +01:00
|
|
|
this->predicateForm_ =
|
|
|
|
|
lib::query::appendTerms(this->predicateForm_, additionalQueryPredicates);
|
2012-12-17 23:17:32 +01:00
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-25 01:16:19 +01:00
|
|
|
Builder&
|
|
|
|
|
prependConditions (string additionalQueryPredicates)
|
|
|
|
|
{
|
|
|
|
|
this->predicateForm_ =
|
|
|
|
|
lib::query::appendTerms(additionalQueryPredicates, this->predicateForm_);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-22 22:01:51 +01:00
|
|
|
Builder&
|
|
|
|
|
fromText (string queryPredicates)
|
|
|
|
|
{
|
|
|
|
|
this->predicateForm_ = queryPredicates;
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-09 02:42:36 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2012-12-11 04:45:18 +01:00
|
|
|
|
|
|
|
|
|
2012-12-22 00:39:23 +01:00
|
|
|
template<class RES>
|
|
|
|
|
inline typename Query<RES>::Builder
|
|
|
|
|
Query<RES>::build (Kind queryType)
|
|
|
|
|
{
|
|
|
|
|
return Builder(defineQueryTypeID (queryType));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-12-09 02:42:36 +01:00
|
|
|
template<class RES>
|
2012-12-17 23:17:32 +01:00
|
|
|
inline typename Query<RES>::Builder
|
2012-12-09 02:42:36 +01:00
|
|
|
Query<RES>::rebuild() const
|
|
|
|
|
{
|
|
|
|
|
return Builder(this->id_, this->def_);
|
|
|
|
|
}
|
2012-11-26 01:22:01 +01:00
|
|
|
|
|
|
|
|
|
2012-12-17 23:17:32 +01:00
|
|
|
/** convenience shortcut to extract a desired name-ID.
|
|
|
|
|
* @todo used extensively for the mock implementation of query resolution.
|
|
|
|
|
* For real resolution queries, such a function is quite nonsensical.
|
|
|
|
|
* To be revisited and (likely) to be removed on the long run
|
|
|
|
|
* @see Query::Builder#extractID
|
|
|
|
|
*/
|
|
|
|
|
template<class RES>
|
|
|
|
|
inline string
|
|
|
|
|
Query<RES>::extractID (Symbol predicate) const
|
|
|
|
|
{
|
|
|
|
|
return this->rebuild().extractID (predicate);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-12-25 01:16:19 +01:00
|
|
|
template<class RES>
|
|
|
|
|
inline bool
|
|
|
|
|
Query<RES>::usesPredicate (Symbol predicate) const
|
|
|
|
|
{
|
|
|
|
|
return lib::query::hasTerm(predicate, this->def_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-12-17 23:17:32 +01:00
|
|
|
/** automatic conversion from Query to QueryKey for indexing and ordering.
|
|
|
|
|
* By defining a parameter of type QueryKey, any provided Query will be
|
|
|
|
|
* automatically transformed into an generic representation usable for
|
|
|
|
|
* ordered storage in sets, maps and for generation of metrics.
|
|
|
|
|
*/
|
|
|
|
|
template<class RES>
|
2012-12-22 00:39:23 +01:00
|
|
|
inline
|
2012-12-17 23:17:32 +01:00
|
|
|
Query<RES>::operator QueryKey() const
|
|
|
|
|
{
|
|
|
|
|
return QueryKey (this->id_, this->def_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-11-26 01:22:01 +01:00
|
|
|
|
2012-12-03 00:18:18 +01:00
|
|
|
} // namespace lumiera
|
2008-01-14 01:01:11 +01:00
|
|
|
#endif
|