summaryrefslogtreecommitdiffstats
path: root/kexi/kexidb/expression.h
blob: 6ee98f326f6b9b9d86c06c49db07bd6118d279ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
/* This file is part of the KDE project
   Copyright (C) 2003-2007 Jaroslaw Staniek <js@iidea.pl>

   Design based on nexp.h : Parser module of Python-like language
   (C) 2001 Jaroslaw Staniek, MIMUW (www.mimuw.edu.pl)

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
*/

#ifndef KEXIDB_EXPRESSION_H
#define KEXIDB_EXPRESSION_H

#include "field.h"
#include "queryschema.h"

#include <kdebug.h>
#include "global.h"

namespace KexiDB {

//! classes
#define KexiDBExpr_Unknown 0
#define KexiDBExpr_Unary 1
#define KexiDBExpr_Arithm 2
#define KexiDBExpr_Logical 3
#define KexiDBExpr_Relational 4
#define KexiDBExpr_SpecialBinary 5
#define KexiDBExpr_Const 6
#define KexiDBExpr_Variable 7
#define KexiDBExpr_Function 8
#define KexiDBExpr_Aggregation 9
#define KexiDBExpr_TableList 10
#define KexiDBExpr_QueryParameter 11

//! Custom tokens are not used in parser but used as extension in expression classes.
//#define KEXIDB_CUSTOM_TOKEN 0x1000

//! \return class name of class \a c
KEXI_DB_EXPORT QString exprClassName(int c);

class ParseInfo;
class NArgExpr;
class UnaryExpr;
class BinaryExpr;
class ConstExpr;
class VariableExpr;
class FunctionExpr;
class QueryParameterExpr;
class QuerySchemaParameterValueListIterator;
//class QuerySchemaParameterList;

//! A base class for all expressions
class KEXI_DB_EXPORT BaseExpr
{
public:
	typedef QPtrList<BaseExpr> List;
	typedef QPtrListIterator<BaseExpr> ListIterator;

	BaseExpr(int token);
	virtual ~BaseExpr();

	//! \return a deep copy of this object.
//! @todo a nonpointer will be returned here when we move to implicit data sharing
	virtual BaseExpr* copy() const = 0;

	int token() const { return m_token; }
	
	virtual Field::Type type();
	
	BaseExpr* parent() const { return m_par; }
	
	virtual void setParent(BaseExpr *p) { m_par = p; }
	
	virtual bool validate(ParseInfo& parseInfo);

	/*! \return string as a representation of this expression element by running recursive calls. 
	 \a param, if not 0, points to a list item containing value of a query parameter
	 (used in QueryParameterExpr). */
	virtual QString toString(QuerySchemaParameterValueListIterator* params = 0) = 0;

	/*! Collects query parameters (messages and types) reculsively and saves them to params.
	 The leaf nodes are objects of QueryParameterExpr class. */
	virtual void getQueryParameters(QuerySchemaParameterList& params) = 0;
	
	inline void debug() { KexiDBDbg << debugString() << endl; }
	
	virtual QString debugString();
	
	/*! \return single character if the token is < 256 
	 or token name, e.g. LESS_OR_EQUAL (for debugging). */
	inline QString tokenToDebugString() { return tokenToDebugString(m_token); }

	static QString tokenToDebugString(int token);

	/*! \return string for token, like "<=" or ">" */
	virtual QString tokenToString();

	int exprClass() const { return m_cl; }

	/*! Convenience type casts. */
	NArgExpr* toNArg();
	UnaryExpr* toUnary();
	BinaryExpr* toBinary();
	ConstExpr* toConst();
	VariableExpr* toVariable();
	FunctionExpr* toFunction();
	QueryParameterExpr* toQueryParameter();

protected:
	int m_cl; //!< class
	BaseExpr *m_par; //!< parent expression
	int m_token;
};

//! A base class N-argument operation
class KEXI_DB_EXPORT NArgExpr : public BaseExpr
{
public:
	NArgExpr(int aClass, int token);
	NArgExpr(const NArgExpr& expr);
	virtual ~NArgExpr();
	//! \return a deep copy of this object.
	virtual NArgExpr* copy() const;
	void add(BaseExpr *expr);
	void prepend(BaseExpr *expr);
	BaseExpr *arg(int n);
	int args();
	virtual QString debugString();
	virtual QString toString(QuerySchemaParameterValueListIterator* params = 0);
	virtual void getQueryParameters(QuerySchemaParameterList& params);
	virtual bool validate(ParseInfo& parseInfo);
	BaseExpr::List list;
};

//! An unary argument operation: + - NOT (or !) ~ "IS NULL" "IS NOT NULL" 
class KEXI_DB_EXPORT UnaryExpr : public BaseExpr
{
public:
	UnaryExpr(int token, BaseExpr *arg);
	UnaryExpr(const UnaryExpr& expr);
	virtual ~UnaryExpr();
	//! \return a deep copy of this object.
	virtual UnaryExpr* copy() const;
	virtual Field::Type type();
	virtual QString debugString();
	virtual QString toString(QuerySchemaParameterValueListIterator* params = 0);
	virtual void getQueryParameters(QuerySchemaParameterList& params);
	BaseExpr *arg() const { return m_arg; }
	virtual bool validate(ParseInfo& parseInfo);

	BaseExpr *m_arg;
};

/*! A base class for binary operation
 - arithmetic operations: + - / * % << >> & | ||
 - relational operations: = (or ==) < > <= >= <> (or !=) LIKE IN 'SIMILAR TO' 'NOT SIMILAR TO'
 - logical operations: OR (or ||) AND (or &&) XOR
 - SpecialBinary "pseudo operators": 
    * e.g. "f1 f2" : token == 0
    * e.g. "f1 AS f2" : token == AS
*/
class KEXI_DB_EXPORT BinaryExpr : public BaseExpr
{
public:
	BinaryExpr(int aClass, BaseExpr *left_expr, int token, BaseExpr *right_expr);
	BinaryExpr(const BinaryExpr& expr);
	virtual ~BinaryExpr();
	//! \return a deep copy of this object.
	virtual BinaryExpr* copy() const;
	virtual Field::Type type();
	virtual QString debugString();
	virtual QString toString(QuerySchemaParameterValueListIterator* params = 0);
	virtual void getQueryParameters(QuerySchemaParameterList& params);
	BaseExpr *left() const { return m_larg; }
	BaseExpr *right() const { return m_rarg; }
	virtual bool validate(ParseInfo& parseInfo);
	virtual QString tokenToString();

	BaseExpr *m_larg;
	BaseExpr *m_rarg;
};

/*! String, integer, float constants also includes NULL value.
 token can be: IDENTIFIER, SQL_NULL, CHARACTER_STRING_LITERAL,
 INTEGER_CONST, REAL_CONST */
class KEXI_DB_EXPORT ConstExpr : public BaseExpr
{
public:
	ConstExpr(int token, const QVariant& val);
	ConstExpr(const ConstExpr& expr);
	virtual ~ConstExpr();
	//! \return a deep copy of this object.
	virtual ConstExpr* copy() const;
	virtual Field::Type type();
	virtual QString debugString();
	virtual QString toString(QuerySchemaParameterValueListIterator* params = 0);
	virtual void getQueryParameters(QuerySchemaParameterList& params);
	virtual bool validate(ParseInfo& parseInfo);
	QVariant value;
};

//! Query parameter used to getting user input of constant values.
//! It contains a message that is displayed to the user.
class KEXI_DB_EXPORT QueryParameterExpr : public ConstExpr
{
public:
	QueryParameterExpr(const QString& message);
	QueryParameterExpr(const QueryParameterExpr& expr);
	virtual ~QueryParameterExpr();
	//! \return a deep copy of this object.
	virtual QueryParameterExpr* copy() const;
	virtual Field::Type type();
	/*! Sets expected type of the parameter. The default is String.
	 This method is called from parent's expression validate().
	 This depends on the type of the related expression.
	 For instance: query "SELECT * FROM cars WHERE name=[enter name]",
	 "[enter name]" has parameter of the same type as "name" field.
	 "=" binary expression's validate() will be called for the left side
	 of the expression and then the right side will have type set to String.
	*/
	void setType(Field::Type type);
	virtual QString debugString();
	virtual QString toString(QuerySchemaParameterValueListIterator* params = 0);
	virtual void getQueryParameters(QuerySchemaParameterList& params);
	virtual bool validate(ParseInfo& parseInfo);
protected:
	Field::Type m_type;
};

//! Variables like <i>fieldname</i> or <i>tablename</i>.<i>fieldname</i>
class KEXI_DB_EXPORT VariableExpr : public BaseExpr
{
public:
	VariableExpr(const QString& _name);
	VariableExpr(const VariableExpr& expr);
	virtual ~VariableExpr();
	//! \return a deep copy of this object.
	virtual VariableExpr* copy() const;
	virtual Field::Type type();
	virtual QString debugString();
	virtual QString toString(QuerySchemaParameterValueListIterator* params = 0);
	virtual void getQueryParameters(QuerySchemaParameterList& params);

	/*! Validation. Sets field, tablePositionForField 
	 and tableForQueryAsterisk members. 
	 See addColumn() in parse.y to see how it's used on column adding. */
	virtual bool validate(ParseInfo& parseInfo);

	/*! Verbatim name as returned by scanner. */
	QString name;

	/* NULL by default. After successful validate() it will point to a field,
	 if the variable is of a form "tablename.fieldname" or "fieldname", 
	 otherwise (eg. for asterisks) -still NULL.
	 Only meaningful for column expressions within a query. */
	Field *field;

	/* -1 by default. After successful validate() it will contain a position of a table
	 within query that needs to be bound to the field. 
	 This value can be either be -1 if no binding is needed.
	 This value is used in the Parser to call 
	  QuerySchema::addField(Field* field, int bindToTable);
	 Only meaningful for column expressions within a query. */
	int tablePositionForField;

	/*! NULL by default. After successful validate() it will point to a table
	 that is referenced by asterisk, i.e. "*.tablename". 
	 This is set to NULL if this variable is not an asterisk of that form. */
	TableSchema *tableForQueryAsterisk;
};

//! - aggregation functions like SUM, COUNT, MAX, ...
//! - builtin functions like CURRENT_TIME()
//! - user defined functions
class KEXI_DB_EXPORT FunctionExpr : public BaseExpr
{
public:
	FunctionExpr(const QString& _name, NArgExpr* args_ = 0);
	FunctionExpr(const FunctionExpr& expr);
	virtual ~FunctionExpr();
	//! \return a deep copy of this object.
	virtual FunctionExpr* copy() const;
	virtual Field::Type type();
	virtual QString debugString();
	virtual QString toString(QuerySchemaParameterValueListIterator* params = 0);
	virtual void getQueryParameters(QuerySchemaParameterList& params);
	virtual bool validate(ParseInfo& parseInfo);

	static QValueList<QCString> builtInAggregates();
	static bool isBuiltInAggregate(const QCString& fname);

	QString name;
	NArgExpr* args;
};

} //namespace KexiDB

#endif