35TQPtrList<Field> fieldList;
41ParserPrivate::ParserPrivate()
42 : reservedKeywords(997, 997, false)
51ParserPrivate::~ParserPrivate()
57void ParserPrivate::clear()
59 operation = Parser::OP_None;
66 : repeatedTablesAndAliases(997, false)
69 repeatedTablesAndAliases.setAutoDelete(
true);
72ParseInfo::~ParseInfo()
79extern void tokenize(
const char *data);
81void yyerror(
const char *str)
83 KexiDBDbg <<
"error: " << str << endl;
84 KexiDBDbg <<
"at character " << current <<
" near tooken " << ctoken << endl;
87 const bool otherError = (tqstrnicmp(str,
"other error", 11)==0);
89 if (parser->error().type().isEmpty()
90 && (str==0 || strlen(str)==0
91 || tqstrnicmp(str,
"syntax error", 12)==0 || tqstrnicmp(str,
"parse error", 11)==0)
94 KexiDBDbg << parser->statement() << endl;
95 TQString ptrline =
"";
96 for(
int i=0; i < current; i++)
101 KexiDBDbg << ptrline << endl;
104 TQString lexerErr = parser->error().error();
106 TQString errtypestr(str);
107 if (lexerErr.isEmpty()) {
109 if (errtypestr.startsWith(
"parse error, unexpected ")) {
111 TQString e = errtypestr.mid(24);
112 KexiDBDbg << e <<endl;
113 TQString token =
"IDENTIFIER";
114 if (e.startsWith(token)) {
117 pos = re.search(e, pos);
118 TQStringList captured=re.capturedTexts();
119 if (captured.count()>=2) {
128 e = errtypestr.mid(47);
129 KexiDBDbg << e <<endl;
135 if (errtypestr.startsWith(
"parse error, expecting `IDENTIFIER'"))
136 lexerErr = i18n(
"identifier was expected");
140 if (!lexerErr.isEmpty())
141 lexerErr.prepend(
": ");
143 if (parser->isReservedKeyword(ctoken.latin1()))
144 parser->setError(
ParserError(i18n(
"Syntax Error"),
145 i18n(
"\"%1\" is a reserved keyword").arg(ctoken)+lexerErr, ctoken, current) );
147 parser->setError(
ParserError(i18n(
"Syntax Error"),
148 i18n(
"Syntax Error near \"%1\"").arg(ctoken)+lexerErr, ctoken, current) );
153void setError(
const TQString& errName,
const TQString& errDesc)
155 parser->setError(
ParserError(errName, errDesc, ctoken, current) );
156 yyerror(errName.latin1());
159void setError(
const TQString& errDesc)
161 setError(
"other error", errDesc);
165#define IMPL_ERROR(errmsg) setError("Implementation error", errmsg)
167bool parseData(
Parser *p,
const char *data)
177 ParserError err(i18n(
"Error"), i18n(
"No query specified"), ctoken, current);
178 parser->setError(err);
185 if (!parser->error().type().isEmpty()) {
194 KexiDBDbg <<
"parseData(): ok" << endl;
230bool addColumn( ParseInfo& parseInfo,
BaseExpr* columnExpr )
232 if (!columnExpr->validate(parseInfo)) {
233 setError(parseInfo.errMsg, parseInfo.errDescr);
238 if (columnExpr->exprClass() == KexiDBExpr_Variable && v_e) {
240 if (v_e->
name==
"*") {
241 if (parseInfo.querySchema->tables()->isEmpty()) {
242 setError(i18n(
"\"*\" could not be used if no tables are specified"));
245 parseInfo.querySchema->addAsterisk(
new QueryAsterisk(parseInfo.querySchema) );
248 parseInfo.querySchema->addAsterisk(
251 else if (v_e->field) {
252 parseInfo.querySchema->addField(v_e->field, v_e->tablePositionForField);
255 IMPL_ERROR(
"addColumn(): unknown case!");
262 parseInfo.querySchema->addExpression(columnExpr);
265 KexiDBDbg <<
"found variable name: " << varName << endl;
266 int dotPos = varName.find(
'.');
267 TQString tableName, fieldName;
270 tableName = varName.left(dotPos);
271 fieldName = varName.mid(dotPos+1);
273 if (tableName.isEmpty()) {
275 if (fieldName==
"*") {
276 parseInfo.querySchema->addAsterisk(
new QueryAsterisk(parseInfo.querySchema) );
280 Field *firstField = 0;
282 Field *f = it.current()->field(fieldName);
288 setError(i18n(
"Ambiguous field name"),
289 i18n(
"Both table \"%1\" and \"%2\" have defined \"%3\" field. "
290 "Use \"<tableName>.%4\" notation to specify table name.")
291 .arg(firstField->
table()->name()).arg(f->
table()->name())
292 .arg(fieldName).arg(fieldName));
298 setError(i18n(
"Field not found"),
299 i18n(
"Table containing \"%1\" field not found").arg(fieldName));
303 parseInfo.querySchema->addField(firstField);
307 tableName = tableName.lower();
308 TableSchema *ts = parseInfo.querySchema->table( tableName );
311 const TQValueList<int> tPositions = parseInfo.querySchema->tablePositions(tableName);
312 TQValueList<int>::ConstIterator it = tPositions.constBegin();
313 TQCString tableAlias;
315 for (; it!=tPositions.constEnd() && covered; ++it) {
316 tableAlias = parseInfo.querySchema->tableAlias(*it);
317 if (tableAlias.isEmpty() || tableAlias.lower()==tableName.latin1())
319 KexiDBDbg <<
" --" <<
"covered by " << tableAlias <<
" alias" << endl;
322 setError(i18n(
"Could not access the table directly using its name"),
323 i18n(
"Table \"%1\" is covered by aliases. Instead of \"%2\", "
324 "you can write \"%3\"").arg(tableName)
325 .arg(tableName+
"."+fieldName).arg(tableAlias+
"."+fieldName.latin1()));
330 int tablePosition = -1;
332 tablePosition = parseInfo.querySchema->tablePositionForAlias( tableName.latin1() );
333 if (tablePosition>=0) {
334 ts = parseInfo.querySchema->tables()->at(tablePosition);
343 TQValueList<int> *positionsList = repeatedTablesAndAliases[ tableName ];
344 if (!positionsList) {
345 IMPL_ERROR(tableName +
"." + fieldName +
", !positionsList ");
349 if (fieldName==
"*") {
350 if (positionsList->count()>1) {
351 setError(i18n(
"Ambiguous \"%1.*\" expression").arg(tableName),
352 i18n(
"More than one \"%1\" table or alias defined").arg(tableName));
355 parseInfo.querySchema->addAsterisk(
new QueryAsterisk(parseInfo.querySchema, ts) );
363 int numberOfTheSameFields = 0;
364 for (TQValueList<int>::iterator it = positionsList->begin();
365 it!=positionsList->end();++it)
367 TableSchema *otherTS = parseInfo.querySchema->tables()->at(*it);
368 if (otherTS->
field(fieldName))
369 numberOfTheSameFields++;
370 if (numberOfTheSameFields>1) {
371 setError(i18n(
"Ambiguous \"%1.%2\" expression").arg(tableName).arg(fieldName),
372 i18n(
"More than one \"%1\" table or alias defined containing \"%2\" field")
373 .arg(tableName).arg(fieldName));
378 parseInfo.querySchema->addField(realField, tablePosition);
381 setError(i18n(
"Field not found"), i18n(
"Table \"%1\" has no \"%2\" field")
382 .arg(tableName).arg(fieldName));
388 tableNotFoundError(tableName);
404 SelectOptionsInternal* options )
406 ParseInfo parseInfo(querySchema);
418 for (
int i=0; i<tablesList->args(); i++, columnNum++) {
421 TQCString aliasString;
422 if (e->exprClass() == KexiDBExpr_SpecialBinary) {
424 assert(t_with_alias);
425 assert(t_with_alias->left()->exprClass() == KexiDBExpr_Variable);
426 assert(t_with_alias->right()->exprClass() == KexiDBExpr_Variable
427 && (t_with_alias->token()==AS || t_with_alias->token()==0));
428 t_e = t_with_alias->left()->toVariable();
429 aliasString = t_with_alias->right()->toVariable()->
name.latin1();
432 t_e = e->toVariable();
435 TQCString tname = t_e->
name.latin1();
436 TableSchema *s = parser->db()->tableSchema(TQString(tname));
439 i18n(
"Table \"%1\" does not exist").arg(TQString(tname)));
444 TQCString tableOrAliasName;
445 if (!aliasString.isEmpty()) {
446 tableOrAliasName = aliasString;
449 tableOrAliasName = tname;
453 TQValueList<int> *list = parseInfo.repeatedTablesAndAliases[tableOrAliasName];
460 list =
new TQValueList<int>();
462 parseInfo.repeatedTablesAndAliases.insert( tableOrAliasName, list );
484 querySchema->
addTable( s, aliasString );
490 if (querySchema->
tables()->count()==1)
497 const uint colCount = colViews->list.count();
499 colViews->list.first();
500 for (; columnNum<colCount; columnNum++) {
501 e = colViews->list.current();
502 bool moveNext =
true;
505 if (e->exprClass() == KexiDBExpr_SpecialBinary && e->toBinary()
506 && (e->token()==AS || e->token()==0))
509 columnExpr = e->toBinary()->left();
511 aliasVariable = e->toBinary()->right()->toVariable();
512 if (!aliasVariable) {
513 setError(i18n(
"Invalid alias definition for column \"%1\"")
520 const int c = columnExpr->exprClass();
521 const bool isExpressionField =
522 c == KexiDBExpr_Const
523 || c == KexiDBExpr_Unary
524 || c == KexiDBExpr_Arithm
525 || c == KexiDBExpr_Logical
526 || c == KexiDBExpr_Relational
527 || c == KexiDBExpr_Const
528 || c == KexiDBExpr_Function
529 || c == KexiDBExpr_Aggregation;
531 if (c == KexiDBExpr_Variable) {
534 else if (isExpressionField) {
537 colViews->list.take();
540 else if (aliasVariable) {
542 e->toBinary()->m_larg = 0;
545 setError(i18n(
"Invalid \"%1\" column definition").arg(e->
toString()));
550 if (!addColumn( parseInfo, columnExpr )) {
576 colViews->list.next();
584 if (options->whereExpr) {
585 if (!options->whereExpr->validate(parseInfo)) {
586 setError(parseInfo.errMsg, parseInfo.errDescr);
593 if (options->orderByColumns) {
595 OrderByColumnInternal::ListConstIterator it = options->orderByColumns->constEnd();
596 uint count = options->orderByColumns->count();
598 for (;count>0; --it, --count)
604 orderByColumnList.
appendColumn( *columnInfo, (*it).ascending );
608 if ((*it).columnNumber != -1) {
610 (*it).ascending, (*it).columnNumber-1 ))
612 setError(i18n(
"Could not define sorting - no column at position %1")
613 .arg((*it).columnNumber));
621 setError(i18n(
"Could not define sorting - "
622 "column name or alias \"%1\" does not exist").arg((*it).aliasOrName));
626 orderByColumnList.
appendField( *f, (*it).ascending );
A base class for all expressions.
virtual TQString toString(QuerySchemaParameterValueListIterator *params=0)=0
virtual TableSchema * table() const
A base class N-argument operation.
KexiDB::OrderByColumnList provides list of sorted columns for a query schema.
void appendColumn(QueryColumnInfo &columnInfo, bool ascending=true)
void appendField(Field &field, bool ascending=true)
Provides detailed i18n'ed error description about the Parser .
Parser for SQL statements.
void clear()
rests results
@ OP_Select
Alter an existing table.
@ OP_Error
No statement parsed or reseted.
KexiDB::QueryAsterisk class encapsulates information about single asterisk in query definition.
Helper class that assigns additional information for the column in a query.
KexiDB::QuerySchema provides information about database query.
void addTable(TableSchema *table, const TQCString &alias=TQCString())
void setWhereExpression(BaseExpr *expr)
OrderByColumnList & orderByColumnList() const
void setMasterTable(TableSchema *table)
Field * findTableField(const TQString &tableOrTableAndFieldName) const
TableSchema::List * tables() const
QueryColumnInfo * columnInfo(const TQString &identifier, bool expanded=true)
void setColumnAlias(uint position, const TQCString &alias)
TQPtrListIterator< TableSchema > ListIterator
Iterator for tables list.
Variables like fieldname or tablename.fieldname.
TableSchema * tableForQueryAsterisk
High-level database connectivity library with database backend drivers.