diff options
Diffstat (limited to 'connectivity/source/parse')
-rw-r--r-- | connectivity/source/parse/PColumn.cxx | 134 | ||||
-rw-r--r-- | connectivity/source/parse/internalnode.cxx | 127 | ||||
-rw-r--r-- | connectivity/source/parse/makefile.mk | 114 | ||||
-rw-r--r-- | connectivity/source/parse/sqlbison.y | 4232 | ||||
-rw-r--r-- | connectivity/source/parse/sqlflex.l | 592 | ||||
-rw-r--r-- | connectivity/source/parse/sqliterator.cxx | 1583 | ||||
-rw-r--r-- | connectivity/source/parse/sqlnode.cxx | 1399 |
7 files changed, 8181 insertions, 0 deletions
diff --git a/connectivity/source/parse/PColumn.cxx b/connectivity/source/parse/PColumn.cxx new file mode 100644 index 000000000000..2644abc2c6f6 --- /dev/null +++ b/connectivity/source/parse/PColumn.cxx @@ -0,0 +1,134 @@ +/************************************************************************* + * + * $RCSfile: PColumn.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:14:28 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source 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.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifndef _CONNECTIVITY_SDBCX_COLUMN_HXX_ +#include "connectivity/PColumn.hxx" +#endif +#ifndef _CONNECTIVITY_PROPERTYIDS_HXX_ +#include "propertyids.hxx" +#endif + +using namespace connectivity; +using namespace connectivity::parse; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +// ------------------------------------------------------------------------- +OParseColumn::OParseColumn(const Reference<XFastPropertySet>& _xColumn,sal_Bool _bCase) + : connectivity::sdbcx::OColumn( getString(_xColumn->getFastPropertyValue(PROPERTY_ID_NAME)) + , getString(_xColumn->getFastPropertyValue(PROPERTY_ID_TYPENAME)) + , getString(_xColumn->getFastPropertyValue(PROPERTY_ID_DEFAULTVALUE)) + , getINT32(_xColumn->getFastPropertyValue(PROPERTY_ID_ISNULLABLE)) + , getINT32(_xColumn->getFastPropertyValue(PROPERTY_ID_PRECISION)) + , getINT32(_xColumn->getFastPropertyValue(PROPERTY_ID_SCALE)) + , getINT32(_xColumn->getFastPropertyValue(PROPERTY_ID_TYPE)) + , getBOOL(_xColumn->getFastPropertyValue(PROPERTY_ID_ISAUTOINCREMENT)) + , sal_False + , getBOOL(_xColumn->getFastPropertyValue(PROPERTY_ID_ISCURRENCY)) + , _bCase + ) + , m_bFunction(sal_False) + , m_bDbasePrecisionChanged(sal_False) +{ + construct(); +} +// ------------------------------------------------------------------------- +OParseColumn::OParseColumn( const ::rtl::OUString& _Name, + const ::rtl::OUString& _TypeName, + const ::rtl::OUString& _DefaultValue, + sal_Int32 _IsNullable, + sal_Int32 _Precision, + sal_Int32 _Scale, + sal_Int32 _Type, + sal_Bool _IsAutoIncrement, + sal_Bool _IsCurrency, + sal_Bool _bCase + ) : connectivity::sdbcx::OColumn(_Name, + _TypeName, + _DefaultValue, + _IsNullable, + _Precision, + _Scale, + _Type, + _IsAutoIncrement, + sal_False, + _IsCurrency, + _bCase) + , m_bFunction(sal_False) + , m_bDbasePrecisionChanged(sal_False) +{ + construct(); +} +// ------------------------------------------------------------------------- +OParseColumn::~OParseColumn() +{ +} +// ------------------------------------------------------------------------- +void OParseColumn::construct() +{ + sal_Int32 nAttrib = isNew() ? 0 : PropertyAttribute::READONLY; + + registerProperty(connectivity::PROPERTY_FUNCTION, PROPERTY_ID_FUNCTION, nAttrib,&m_bFunction, ::getCppuType(reinterpret_cast< sal_Bool*>(NULL))); + registerProperty(connectivity::PROPERTY_TABLENAME, PROPERTY_ID_TABLENAME, nAttrib,&m_aTableName, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerProperty(connectivity::PROPERTY_REALNAME, PROPERTY_ID_REALNAME, nAttrib,&m_aRealName, ::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL))); + registerProperty(connectivity::PROPERTY_DBASEPRECISIONCHANGED, PROPERTY_ID_DBASEPRECISIONCHANGED, nAttrib,&m_bDbasePrecisionChanged, ::getCppuType(reinterpret_cast<sal_Bool*>(NULL))); + +} + diff --git a/connectivity/source/parse/internalnode.cxx b/connectivity/source/parse/internalnode.cxx new file mode 100644 index 000000000000..57d5dbd6d7e6 --- /dev/null +++ b/connectivity/source/parse/internalnode.cxx @@ -0,0 +1,127 @@ +/************************************************************************* + * + * $RCSfile: internalnode.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:14:28 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source 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.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ +#ifndef _CONNECTIVITY_SQLINTERNALNODE_HXX +#include "internalnode.hxx" +#endif + +#include <stl_algo.h> +#ifndef _CONNECTIVITY_SQLPARSE_HXX +#include <connectivity/sqlparse.hxx> +#endif +#ifndef _DEBUG_HXX //autogen +#include <tools/debug.hxx> +#endif + +using namespace connectivity; + +//----------------------------------------------------------------------------- +OSQLInternalNode::OSQLInternalNode(const sal_Char* pNewValue, + SQLNodeType eNodeType, + sal_uInt32 nNodeID) + :OSQLParseNode(pNewValue,eNodeType,nNodeID) +{ + DBG_ASSERT(OSQLParser::s_pGarbageCollector, "Collector not initialized") + OSQLParser::s_pGarbageCollector->push_back(this); +} + +//----------------------------------------------------------------------------- +OSQLInternalNode::OSQLInternalNode(const ByteString &_NewValue, + SQLNodeType eNodeType, + sal_uInt32 nNodeID) + :OSQLParseNode(_NewValue,eNodeType,nNodeID) +{ + DBG_ASSERT(OSQLParser::s_pGarbageCollector, "Collector not initialized") + OSQLParser::s_pGarbageCollector->push_back(this); +} + +//----------------------------------------------------------------------------- +OSQLInternalNode::OSQLInternalNode(const sal_Unicode* pNewValue, + SQLNodeType eNodeType, + sal_uInt32 nNodeID) + :OSQLParseNode(pNewValue,eNodeType,nNodeID) +{ + DBG_ASSERT(OSQLParser::s_pGarbageCollector, "Collector not initialized") + OSQLParser::s_pGarbageCollector->push_back(this); +} + +//----------------------------------------------------------------------------- +OSQLInternalNode::OSQLInternalNode(const String &_NewValue, + SQLNodeType eNodeType, + sal_uInt32 nNodeID) + :OSQLParseNode(_NewValue,eNodeType,nNodeID) +{ + DBG_ASSERT(OSQLParser::s_pGarbageCollector, "Collector not initialized") + OSQLParser::s_pGarbageCollector->push_back(this); +} + + +//----------------------------------------------------------------------------- +OSQLInternalNode::~OSQLInternalNode() +{ + // remove the node from the garbage list + DBG_ASSERT(OSQLParser::s_pGarbageCollector, "Collector not initialized") + if (!OSQLParser::s_pGarbageCollector->empty()) + { + OSQLParser::s_pGarbageCollector->erase( + ::std::find(OSQLParser::s_pGarbageCollector->begin(), OSQLParser::s_pGarbageCollector->end(), + this)); + } +} diff --git a/connectivity/source/parse/makefile.mk b/connectivity/source/parse/makefile.mk new file mode 100644 index 000000000000..4d33aac1f973 --- /dev/null +++ b/connectivity/source/parse/makefile.mk @@ -0,0 +1,114 @@ +#************************************************************************* +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.1.1.1 $ +# +# last change: $Author: hr $ $Date: 2000-09-18 16:14:28 $ +# +# The Contents of this file are made available subject to the terms of +# either of the following licenses +# +# - GNU Lesser General Public License Version 2.1 +# - Sun Industry Standards Source License Version 1.1 +# +# Sun Microsystems Inc., October, 2000 +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2000 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +# +# Sun Industry Standards Source License Version 1.1 +# ================================================= +# The contents of this file are subject to the Sun Industry Standards +# Source 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.openoffice.org/license.html. +# +# Software provided under this License is provided on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, +# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, +# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. +# See the License for the specific provisions governing your rights and +# obligations concerning the Software. +# +# The Initial Developer of the Original Code is: Sun Microsystems, Inc. +# +# Copyright: 2000 by Sun Microsystems, Inc. +# +# All Rights Reserved. +# +# Contributor(s): _______________________________________ +# +# +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=connectivity +TARGET=sql + +# --- Settings ----------------------------------------------------- + +.INCLUDE : svpre.mk +.INCLUDE : settings.mk +.INCLUDE : sv.mk + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/sqlbison.obj \ + $(SLO)$/sqlflex.obj \ + $(SLO)$/PColumn.obj \ + $(SLO)$/sqliterator.obj \ + $(SLO)$/sqlnode.obj \ + $(SLO)$/fcode.obj \ + $(SLO)$/fcomp.obj \ + $(SLO)$/fanalyzer.obj \ + $(SLO)$/internalnode.obj + + +EXCEPTIONSFILES= \ + $(SLO)$/sqlbison.obj \ + $(SLO)$/PColumn.obj \ + $(SLO)$/sqliterator.obj \ + $(SLO)$/internalnode.obj \ + $(SLO)$/fcode.obj \ + $(SLO)$/fcomp.obj \ + $(SLO)$/fanalyzer.obj \ + $(SLO)$/sqlnode.obj + +all: \ + $(MISC)$/sqlflex.cxx \ + $(MISC)$/sqlbison.cxx \ + ALLTAR +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk + + +$(MISC)$/sqlflex.cxx: sqlflex.l + +flex -i -8 -PSQLyy -L -o$(MISC)$/sqlflex.cxx sqlflex.l + +$(MISC)$/sqlbison.cxx: sqlbison.y + +bison -v -d -pSQLyy -l -bsql -o$(MISC)$/sqlbison.cxx sqlbison.y + -$(MKDIR) $(OUT)$/inc$/connectivity + +$(COPY) $(MISC)$/sqlbison.cxx.h $(OUT)$/inc$/connectivity$/sqlbison.hxx + diff --git a/connectivity/source/parse/sqlbison.y b/connectivity/source/parse/sqlbison.y new file mode 100644 index 000000000000..f8aa3daf6254 --- /dev/null +++ b/connectivity/source/parse/sqlbison.y @@ -0,0 +1,4232 @@ +%{ +//-------------------------------------------------------------------------- +// +// $Header: /zpool/svn/migration/cvs_rep_09_09_08/code/connectivity/source/parse/sqlbison.y,v 1.1.1.1 2000-09-18 16:14:28 hr Exp $ +// +// Copyright 2000 Sun Microsystems, Inc. All Rights Reserved. +// +// First creation: +// OJ +// +// Last change: +// $Author: hr $ $Date: 2000-09-18 16:14:28 $ $Revision: 1.1.1.1 $ +// +// Description: +// +// +//-------------------------------------------------------------------------- + +#ifndef _VECTOR_ +#include <vector> +#endif + +#ifndef _SOLAR_H +#include <tools/solar.h> +#endif + +#ifndef _CONNECTIVITY_SQLNODE_HXX +#include <connectivity/sqlnode.hxx> +#endif +#ifndef _CONNECTIVITY_SQLPARSE_HXX +#include <connectivity/sqlparse.hxx> +#endif +#ifndef _CONNECTIVITY_SQLINTERNALNODE_HXX +#include <internalnode.hxx> +#endif +#ifndef _COM_SUN_STAR_LANG_LOCALE_HPP_ +#include <com/sun/star/lang/Locale.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_DATATYPE_HPP_ +#include <com/sun/star/sdbc/DataType.hpp> +#endif +#ifndef _COM_SUN_STAR_UTIL_DATE_HPP_ +#include <com/sun/star/util/Date.hpp> +#endif +#ifndef _COM_SUN_STAR_UTIL_XNUMBERFORMATTER_HPP_ +#include <com/sun/star/util/XNumberFormatter.hpp> +#endif +#ifndef _COM_SUN_STAR_UTIL_XNUMBERFORMATSSUPPLIER_HPP_ +#include <com/sun/star/util/XNumberFormatsSupplier.hpp> +#endif +#ifndef _COM_SUN_STAR_UTIL_XNUMBERFORMATS_HPP_ +#include <com/sun/star/util/XNumberFormats.hpp> +#endif +#ifndef _COM_SUN_STAR_UTIL_NUMBERFORMAT_HPP_ +#include <com/sun/star/util/NumberFormat.hpp> +#endif +#ifndef _COM_SUN_STAR_UTIL_XNUMBERFORMATTYPES_HPP_ +#include <com/sun/star/util/XNumberFormatTypes.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ +#include <com/sun/star/beans/XPropertySet.hpp> +#endif +#ifndef _TOOLS_SOLMATH_HXX //autogen wg. SolarMath +#include <tools/solmath.hxx> +#endif +#ifndef _ISOLANG_HXX +#include <tools/isolang.hxx> +#endif +#ifndef _DATETIME_HXX +#include <tools/datetime.hxx> +#endif +#ifndef _TOOLS_INTN_HXX //autogen wg. International +#include <tools/intn.hxx> +#endif +#ifndef _CONNECTIVITY_SQLSCAN_HXX +#include "sqlscan.hxx" +#endif +#ifndef _OSL_DIAGNOSE_H_ +#include <osl/diagnose.h> +#endif + +static String aEmptyString; + +static connectivity::OSQLInternalNode* newNode(const sal_Char* pNewValue, + const connectivity::SQLNodeType eNodeType, + const UINT16 nNodeID = 0) +{ + + return new connectivity::OSQLInternalNode(pNewValue, eNodeType, nNodeID); +} + +static connectivity::OSQLInternalNode* newNode(const ByteString& _NewValue, + const connectivity::SQLNodeType eNodeType, + const UINT16 nNodeID = 0) +{ + + return new connectivity::OSQLInternalNode(_NewValue, eNodeType, nNodeID); +} + +static connectivity::OSQLInternalNode* newNode(const String& _NewValue, + const connectivity::SQLNodeType eNodeType, + const UINT16 nNodeID = 0) +{ + + return new connectivity::OSQLInternalNode(_NewValue, eNodeType, nNodeID); +} + + +// yyi ist die interne Nr. der Regel, die gerade reduziert wird. +// Ueber die Mapping-Tabelle yyrmap wird daraus eine externe Regel-Nr. +#define SQL_NEW_RULE newNode(aEmptyString, SQL_NODE_RULE, yyr1[yyn]) +#define SQL_NEW_LISTRULE newNode(aEmptyString, SQL_NODE_LISTRULE, yyr1[yyn]) +#define SQL_NEW_COMMALISTRULE newNode(aEmptyString, SQL_NODE_COMMALISTRULE, yyr1[yyn]) + + +connectivity::OSQLParser* xxx_pGLOBAL_SQLPARSER; + +#define YYERROR_VERBOSE + +#define SQLyyerror(s) \ +{ \ + xxx_pGLOBAL_SQLPARSER->error(s); \ +} + +using namespace connectivity; +#define SQLyylex xxx_pGLOBAL_SQLPARSER->SQLlex +%} + /* symbolic tokens */ + +%union { + connectivity::OSQLParseNode * pParseNode; +} +%type <pParseNode> '(' ')' ',' ':' ';' '?' '[' ']' '{' '}' '.' + +%token <pParseNode> SQL_TOKEN_STRING SQL_TOKEN_ACCESS_DATE SQL_TOKEN_INT SQL_TOKEN_REAL_NUM +%token <pParseNode> SQL_TOKEN_INTNUM SQL_TOKEN_APPROXNUM SQL_TOKEN_NOT SQL_TOKEN_NAME + + /* operators */ +%left <pParseNode> SQL_TOKEN_NAME +%left <pParseNode> SQL_TOKEN_OR +%left <pParseNode> SQL_TOKEN_AND + +%left <pParseNode> LESSEQ GREATEQ NOTEQUAL LESS GREAT EQUAL /* '<' '>' = <> < > <= >= != */ +%left <pParseNode> '+' '-' +%left <pParseNode> '*' '/' +%left <pParseNode> SQL_TOKEN_NATURAL SQL_TOKEN_CROSS SQL_TOKEN_FULL SQL_TOKEN_LEFT SQL_TOKEN_RIGHT +%left <pParseNode> ')' +%right <pParseNode> '=' +%right <pParseNode> '.' +%right <pParseNode> '(' + + +%nonassoc <pParseNode> SQL_TOKEN_UMINUS + + + + /* literal keyword tokens */ + +%token <pParseNode> SQL_TOKEN_ALL SQL_TOKEN_ALTER SQL_TOKEN_AMMSC SQL_TOKEN_ANY SQL_TOKEN_AS SQL_TOKEN_ASC SQL_TOKEN_AT SQL_TOKEN_AUTHORIZATION SQL_TOKEN_AVG + +%token <pParseNode> SQL_TOKEN_BETWEEN SQL_TOKEN_BIT SQL_TOKEN_BIT_LENGTH SQL_TOKEN_BOTH SQL_TOKEN_BY + +%token <pParseNode> SQL_TOKEN_CAST SQL_TOKEN_CHARACTER SQL_TOKEN_CHAR_LENGTH SQL_TOKEN_CHECK SQL_TOKEN_COLLATE SQL_TOKEN_COMMIT SQL_TOKEN_CONTINUE SQL_TOKEN_CONVERT SQL_TOKEN_COUNT SQL_TOKEN_CREATE SQL_TOKEN_CROSS +%token <pParseNode> SQL_TOKEN_CURRENT SQL_TOKEN_CURRENT_DATE SQL_TOKEN_CURRENT_TIME SQL_TOKEN_CURRENT_TIMESTAMP SQL_TOKEN_CURSOR + +%token <pParseNode> SQL_TOKEN_DATE SQL_TOKEN_DAY SQL_TOKEN_DEC SQL_TOKEN_DECIMAL SQL_TOKEN_DECLARE SQL_TOKEN_DEFAULT SQL_TOKEN_DELETE SQL_TOKEN_DESC +%token <pParseNode> SQL_TOKEN_DISTINCT SQL_TOKEN_DOUBLE SQL_TOKEN_DROP + +%token <pParseNode> SQL_TOKEN_ESCAPE SQL_TOKEN_EXCEPT SQL_TOKEN_EXISTS SQL_TOKEN_EXTRACT SQL_TOKEN_FALSE SQL_TOKEN_FETCH SQL_TOKEN_FLOAT SQL_TOKEN_FOR SQL_TOKEN_FOREIGN SQL_TOKEN_FOUND SQL_TOKEN_FROM SQL_TOKEN_FULL + +%token <pParseNode> SQL_TOKEN_GRANT SQL_TOKEN_GROUP SQL_TOKEN_HAVING SQL_TOKEN_HOUR SQL_TOKEN_IN SQL_TOKEN_INDICATOR SQL_TOKEN_INNER SQL_TOKEN_INSERT SQL_TOKEN_INTEGER SQL_TOKEN_INTO SQL_TOKEN_IS SQL_TOKEN_INTERSECT + +%token <pParseNode> SQL_TOKEN_JOIN SQL_TOKEN_KEY SQL_TOKEN_LEADING SQL_TOKEN_LEFT SQL_TOKEN_LIKE SQL_TOKEN_LOCAL SQL_TOKEN_LOWER SQL_TOKEN_MINUTE SQL_TOKEN_MONTH +%token <pParseNode> SQL_TOKEN_MAX SQL_TOKEN_MIN SQL_TOKEN_NATURAL SQL_TOKEN_NCHAR SQL_TOKEN_NULL SQL_TOKEN_NUMERIC + +%token <pParseNode> SQL_TOKEN_OCTECT_LENGTH SQL_TOKEN_OF SQL_TOKEN_ON SQL_TOKEN_OPTION SQL_TOKEN_ORDER SQL_TOKEN_OUTER + +%token <pParseNode> SQL_TOKEN_POSITION SQL_TOKEN_PRECISION SQL_TOKEN_PRIMARY SQL_TOKEN_PRIVILEGES SQL_TOKEN_PROCEDURE SQL_TOKEN_PUBLIC +%token <pParseNode> SQL_TOKEN_REAL SQL_TOKEN_REFERENCES SQL_TOKEN_ROLLBACK SQL_TOKEN_RIGHT + +%token <pParseNode> SQL_TOKEN_SCHEMA SQL_TOKEN_SECOND SQL_TOKEN_SELECT SQL_TOKEN_SET SQL_TOKEN_SIZE SQL_TOKEN_SMALLINT SQL_TOKEN_SOME SQL_TOKEN_SQLCODE SQL_TOKEN_SQLERROR SQL_TOKEN_SUBSTRING SQL_TOKEN_SUM + +%token <pParseNode> SQL_TOKEN_TABLE SQL_TOKEN_TIME SQL_TOKEN_TIMESTAMP SQL_TOKEN_TIMEZONE_HOUR SQL_TOKEN_TIMEZONE_MINUTE SQL_TOKEN_TO SQL_TOKEN_TRAILING SQL_TOKEN_TRANSLATE SQL_TOKEN_TRIM SQL_TOKEN_TRUE SQL_TOKEN_UNION +%token <pParseNode> SQL_TOKEN_UNIQUE SQL_TOKEN_UNKNOWN SQL_TOKEN_UPDATE SQL_TOKEN_UPPER SQL_TOKEN_USAGE SQL_TOKEN_USER SQL_TOKEN_USING SQL_TOKEN_VALUES SQL_TOKEN_VIEW +%token <pParseNode> SQL_TOKEN_WHERE SQL_TOKEN_WITH SQL_TOKEN_WORK SQL_TOKEN_YEAR SQL_TOKEN_ZONE + +/* ODBC KEYWORDS */ +%token <pParseNode> SQL_TOKEN_CALL SQL_TOKEN_D SQL_TOKEN_FN SQL_TOKEN_T SQL_TOKEN_TS SQL_TOKEN_OJ + + +%token <pParseNode> SQL_TOKEN_INVALIDSYMBOL + +/*%type <pParseNode> sql_single_statement */ + +%type <pParseNode> sql /*schema */ +%type <pParseNode> column_def_opt_list column_def_opt table_constraint_def column_commalist +%type <pParseNode> view_def opt_with_check_option opt_column_commalist privilege_def +%type <pParseNode> opt_with_grant_option privileges operation_commalist operation +%type <pParseNode> grantee_commalist grantee opt_order_by_clause ordering_spec_commalist +%type <pParseNode> ordering_spec opt_asc_desc manipulative_statement commit_statement +%type <pParseNode> /*delete_statement_positioned*/ delete_statement_searched fetch_statement +%type <pParseNode> insert_statement values_or_query_spec +%type <pParseNode> rollback_statement select_statement_into opt_all_distinct +%type <pParseNode> /*update_statement_positioned*/ assignment_commalist assignment +%type <pParseNode> update_statement_searched target_commalist target opt_where_clause +%type <pParseNode> select_statement selection table_exp from_clause table_ref_commalist table_ref +%type <pParseNode> where_clause opt_group_by_clause column_ref_commalist opt_having_clause +%type <pParseNode> search_condition predicate comparison_predicate between_predicate +%type <pParseNode> like_predicate opt_escape test_for_null in_predicate +%type <pParseNode> all_or_any_predicate any_all_some existence_test subquery +%type <pParseNode> scalar_exp_commalist parameter_ref literal +%type <pParseNode> column_ref data_type column cursor parameter range_variable user /*like_check*/ +/* neue Regeln bei OJ */ +%type <pParseNode> derived_column as_clause table_name num_primary term num_value_exp +%type <pParseNode> value_exp_primary num_value_fct unsigned_value_spec cast_spec set_fct_spec scalar_subquery +%type <pParseNode> position_exp extract_exp length_exp general_value_spec +%type <pParseNode> general_set_fct set_fct_type query_exp non_join_query_exp joined_table +%type <pParseNode> non_join_query_term non_join_query_primary simple_table +%type <pParseNode> table_value_const_list row_value_constructor row_value_const_list row_value_constructor_elem +%type <pParseNode> qualified_join value_exp query_term join_type outer_join_type join_condition boolean_term +%type <pParseNode> boolean_factor truth_value boolean_test boolean_primary named_columns_join join_spec +%type <pParseNode> cast_operand cast_target factor datetime_value_exp /*interval_value_exp*/ datetime_term datetime_factor +%type <pParseNode> datetime_primary datetime_value_fct time_zone time_zone_specifier /*interval_term*/ /*interval_qualifier*/ +%type <pParseNode> /*start_field*/ non_second_datetime_field /*end_field*/ /*single_datetime_field*/ extract_field datetime_field time_zone_field +%type <pParseNode> extract_source char_length_exp octet_length_exp bit_length_exp select_sublist string_value_exp +%type <pParseNode> char_value_exp concatenation char_factor char_primary string_value_fct char_substring_fct fold +%type <pParseNode> form_conversion char_translation trim_fct trim_operands trim_spec bit_value_fct bit_substring_fct op_column_commalist +%type <pParseNode> /*bit_concatenation*/ bit_value_exp bit_factor bit_primary collate_clause char_value_fct unique_spec value_exp_commalist in_predicate_value unique_test update_source +%type <pParseNode> all query_primary as not for_length upper_lower comparison column_val cross_union /*opt_schema_element_list*/ +%type <pParseNode> /*op_authorization op_schema*/ nil_fkt schema_element base_table_def base_table_element base_table_element_commalist +%type <pParseNode> column_def odbc_fct_spec odbc_call_spec odbc_fct_type op_parameter union_statement +%type <pParseNode> op_odbc_call_parameter odbc_parameter_commalist odbc_parameter +%% + +/* Parse Tree an OSQLParser zurueckliefern + * (der Zugriff ueber yyval nach Aufruf des Parsers scheitert, + * + */ +sql_single_statement: + sql + { xxx_pGLOBAL_SQLPARSER->setParseTree( $1 ); } + | sql ';' + { xxx_pGLOBAL_SQLPARSER->setParseTree( $1 ); } + ; +/* +sql_list: + sql_ ';' + {$$ = SQL_NEW_LISTRULE; + $$->append($1); + pSqlParseTreeRoot = $1; -- obsolete - Ergebnis in yyval! rdm } + | sql_list sql ';' + {$1->append($2); + $$ = $1;} + ; +*/ + + + /* schema definition language */ + /* Note: other ``sql:'' rules appear later in the grammar */ +/*** +sql: + schema + ; + +op_authorization: + {$$ = SQL_NEW_RULE;} + | SQL_TOKEN_AUTHORIZATION user + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + } + ; +op_schema: + {$$ = SQL_NEW_RULE;} + | SQL_TOKEN_NAME + | SQL_TOKEN_NAME '.' SQL_TOKEN_NAME + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode(".", SQL_NODE_PUNCTUATION)); + $$->append($3); + } + ; + +schema: + SQL_TOKEN_CREATE SQL_TOKEN_SCHEMA op_schema op_authorization opt_schema_element_list + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + $$->append($5); + } + ; + +opt_schema_element_list: + /* empty * / {$$ = SQL_NEW_RULE;} + | schema_glement_list + ; + +schema_element_list: + schema_element + {$$ = SQL_NEW_LISTRULE; + $$->append($1);} + | schema_element_list schema_element + {$1->append($2); + $$ = $1;} + ; +*/ +sql: + schema_element + {$$ = SQL_NEW_RULE; + $$->append($1); + } + ; + +schema_element: + base_table_def + | view_def + | privilege_def + ; + +base_table_def: + SQL_TOKEN_CREATE SQL_TOKEN_TABLE table_name '(' base_table_element_commalist ')' + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($5); + $$->append($6 = newNode(")", SQL_NODE_PUNCTUATION));} + ; + +base_table_element_commalist: + base_table_element + {$$ = SQL_NEW_COMMALISTRULE; + $$->append($1);} + | base_table_element_commalist ',' base_table_element + {$1->append($3); + $$ = $1;} + ; + +base_table_element: + column_def + | table_constraint_def + ; + +column_def: + column data_type column_def_opt_list + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + } + ; + +column_def_opt_list: + /* empty */ {$$ = SQL_NEW_LISTRULE;} + | column_def_opt_list column_def_opt + {$1->append($2); + $$ = $1;} + ; + +nil_fkt: + datetime_value_fct + ; +unique_spec: + SQL_TOKEN_UNIQUE + | SQL_TOKEN_PRIMARY SQL_TOKEN_KEY + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + } + ; +column_def_opt: + SQL_TOKEN_NOT SQL_TOKEN_NULL + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2);} + | unique_spec + | SQL_TOKEN_DEFAULT literal + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2);} + | SQL_TOKEN_DEFAULT SQL_TOKEN_NULL + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2);} + | SQL_TOKEN_DEFAULT SQL_TOKEN_USER + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2);} + | SQL_TOKEN_DEFAULT nil_fkt + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + } + | SQL_TOKEN_CHECK + | SQL_TOKEN_CHECK '(' search_condition ')' + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(")", SQL_NODE_PUNCTUATION));} + | SQL_TOKEN_REFERENCES table_name + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2);} + | SQL_TOKEN_REFERENCES table_name '(' column_commalist ')' + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($4); + $$->append($5 = newNode(")", SQL_NODE_PUNCTUATION));} + ; + +table_constraint_def: + unique_spec '(' column_commalist ')' + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(")", SQL_NODE_PUNCTUATION));} + | SQL_TOKEN_FOREIGN SQL_TOKEN_KEY '(' column_commalist ')' SQL_TOKEN_REFERENCES table_name + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($4); + $$->append($5 = newNode(")", SQL_NODE_PUNCTUATION)); + $$->append($6); + $$->append($7);} + | SQL_TOKEN_FOREIGN SQL_TOKEN_KEY '(' column_commalist ')' SQL_TOKEN_REFERENCES table_name '(' column_commalist ')' + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($4); + $$->append($5 = newNode(")", SQL_NODE_PUNCTUATION)); + $$->append($6); + $$->append($7); + $$->append($8 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($9); + $$->append($10 = newNode(")", SQL_NODE_PUNCTUATION));} + | SQL_TOKEN_CHECK '(' search_condition ')' + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(")", SQL_NODE_PUNCTUATION));} + ; +op_column_commalist: + /* empty */ {$$ = SQL_NEW_RULE;} + | '(' column_commalist ')' + {$$ = SQL_NEW_RULE; + $$->append($1 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($2); + $$->append($3 = newNode(")", SQL_NODE_PUNCTUATION)); + } + ; +column_commalist: + column_commalist ',' column + {$1->append($3); + $$ = $1;} + | column + {$$ = SQL_NEW_COMMALISTRULE; + $$->append($1);} + ; + +view_def: + SQL_TOKEN_CREATE SQL_TOKEN_VIEW table_name opt_column_commalist SQL_TOKEN_AS select_statement opt_with_check_option + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + $$->append($5); + $$->append($6); + $$->append($7);} + ; + +opt_with_check_option: + /* empty */ {$$ = SQL_NEW_RULE;} + | SQL_TOKEN_WITH SQL_TOKEN_CHECK SQL_TOKEN_OPTION + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3);} + ; + +opt_column_commalist: + /* empty */ {$$ = SQL_NEW_RULE;} + | '(' column_commalist ')' + {$$ = SQL_NEW_RULE; + $$->append($1 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($2); + $$->append($3 = newNode(")", SQL_NODE_PUNCTUATION));} + ; + +privilege_def: + SQL_TOKEN_GRANT privileges SQL_TOKEN_ON table_name SQL_TOKEN_TO grantee_commalist + opt_with_grant_option + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + $$->append($5); + $$->append($6); + $$->append($7);} + ; + +opt_with_grant_option: + /* empty */ {$$ = SQL_NEW_RULE;} + | SQL_TOKEN_WITH SQL_TOKEN_GRANT SQL_TOKEN_OPTION + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3);} + ; + +privileges: + SQL_TOKEN_ALL SQL_TOKEN_PRIVILEGES + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2);} + | operation_commalist + ; + +operation_commalist: + operation + {$$ = SQL_NEW_COMMALISTRULE; + $$->append($1);} + | operation_commalist ',' operation + {$1->append($3); + $$ = $1;} + ; + +operation: + SQL_TOKEN_SELECT + | SQL_TOKEN_INSERT opt_column_commalist + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2);} + | SQL_TOKEN_DELETE + | SQL_TOKEN_UPDATE opt_column_commalist + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2);} + | SQL_TOKEN_REFERENCES opt_column_commalist + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2);} + | SQL_TOKEN_USAGE + ; + + +grantee_commalist: + grantee + {$$ = SQL_NEW_COMMALISTRULE; + $$->append($1);} + | grantee_commalist ',' grantee + {$1->append($3); + $$ = $1;} + ; + +grantee: + SQL_TOKEN_PUBLIC + | user + ; + + /* module language */ + +opt_order_by_clause: + /* empty */ {$$ = SQL_NEW_RULE;} + | SQL_TOKEN_ORDER SQL_TOKEN_BY ordering_spec_commalist + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3);} + ; + +ordering_spec_commalist: + ordering_spec + {$$ = SQL_NEW_COMMALISTRULE; + $$->append($1);} + | ordering_spec_commalist ',' ordering_spec + {$1->append($3); + $$ = $1;} + ; + +ordering_spec: +/* SQL_TOKEN_INTNUM opt_asc_desc + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2);} +*/ + predicate opt_asc_desc + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2);} + + | row_value_constructor_elem opt_asc_desc + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2);} + ; + +opt_asc_desc: + {$$ = SQL_NEW_RULE;} + | SQL_TOKEN_ASC + | SQL_TOKEN_DESC + ; + + +/*** +manipulative_statement_list: + manipulative_statement + {$$ = SQL_NEW_LISTRULE; + $$->append($1);} + | manipulative_statement_list manipulative_statement + {$1->append($2); + $$ = $1;} + ; +***/ + +sql: + {$$ = SQL_NEW_LISTRULE;} + ; +not: + {$$ = SQL_NEW_RULE;} + | SQL_TOKEN_NOT + ; + /* manipulative statements */ + +sql: manipulative_statement + ; + +manipulative_statement: + commit_statement +/* | delete_statement_positioned*/ + | delete_statement_searched + | fetch_statement + | insert_statement + | rollback_statement + | select_statement_into +/* | update_statement_positioned*/ + | update_statement_searched + | union_statement + | '{' odbc_call_spec '}' + { + $$ = SQL_NEW_RULE; + $$->append($1 = newNode("{", SQL_NODE_PUNCTUATION)); + $$->append($2); + $$->append($3 = newNode("}", SQL_NODE_PUNCTUATION)); + } + ; + +union_statement: + select_statement + | union_statement SQL_TOKEN_UNION all select_statement + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + } + ; +commit_statement: + SQL_TOKEN_COMMIT SQL_TOKEN_WORK + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2);} + ; +/* +delete_statement_positioned: + SQL_TOKEN_DELETE SQL_TOKEN_FROM table_name SQL_TOKEN_WHERE SQL_TOKEN_CURRENT SQL_TOKEN_OF cursor + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + $$->append($5); + $$->append($6); + $$->append($7);} + ; +*/ +delete_statement_searched: + SQL_TOKEN_DELETE SQL_TOKEN_FROM table_name opt_where_clause + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4);} + ; + +fetch_statement: + SQL_TOKEN_FETCH cursor SQL_TOKEN_INTO target_commalist + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4);} + ; + +insert_statement: + SQL_TOKEN_INSERT SQL_TOKEN_INTO table_name opt_column_commalist values_or_query_spec + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + $$->append($5);} + ; +values_or_query_spec: + SQL_TOKEN_VALUES table_value_const_list + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + } + ; + +table_value_const_list: + row_value_constructor + {$$ = SQL_NEW_COMMALISTRULE; + $$->append($1);} + | table_value_const_list ',' row_value_constructor + {$1->append($3); + $$ = $1;} + ; +row_value_const_list: + row_value_constructor_elem + {$$ = SQL_NEW_COMMALISTRULE; + $$->append($1);} + | row_value_const_list ',' row_value_constructor_elem + {$1->append($3); + $$ = $1;} + ; +row_value_constructor: + row_value_constructor_elem + | '(' row_value_const_list ')' + { + $$ = SQL_NEW_RULE; + $$->append($1 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($2); + $$->append($3 = newNode(")", SQL_NODE_PUNCTUATION)); + } +/* | subquery + { + $$ = SQL_NEW_RULE; + $$->append($1); + }*/ + ; +row_value_constructor_elem: + value_exp /*[^')']*/ + | SQL_TOKEN_NULL + | SQL_TOKEN_DEFAULT + ; + + +rollback_statement: + SQL_TOKEN_ROLLBACK SQL_TOKEN_WORK + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2);} + ; + + + /* INTO target_commalist herausgenommen */ +select_statement_into: + SQL_TOKEN_SELECT opt_all_distinct selection SQL_TOKEN_INTO target_commalist table_exp + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + $$->append($5); + $$->append($6); } + ; + +opt_all_distinct: + {$$ = SQL_NEW_RULE;} + | SQL_TOKEN_ALL + | SQL_TOKEN_DISTINCT + + ; +/* +update_statement_positioned: + SQL_TOKEN_UPDATE table_name SQL_TOKEN_SET assignment_commalist + SQL_TOKEN_WHERE SQL_TOKEN_CURRENT SQL_TOKEN_OF cursor + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + $$->append($5); + $$->append($6); + $$->append($7); + $$->append($8);} + ; +*/ +assignment_commalist: + assignment + {$$ = SQL_NEW_COMMALISTRULE; + $$->append($1);} + | assignment_commalist ',' assignment + {$1->append($3); + $$ = $1;} + ; + +assignment: + column EQUAL update_source + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3);} + ; +update_source: + value_exp + | SQL_TOKEN_NULL + | SQL_TOKEN_DEFAULT + ; +update_statement_searched: + SQL_TOKEN_UPDATE table_name SQL_TOKEN_SET assignment_commalist opt_where_clause + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + $$->append($5);} + ; + +target_commalist: + target + {$$ = SQL_NEW_COMMALISTRULE; + $$->append($1);} + | target_commalist ',' target + {$1->append($3); + $$ = $1;} + ; + +target: + parameter_ref + ; + +opt_where_clause: + /* empty */ {$$ = SQL_NEW_RULE;} + | where_clause + ; + + /* query expressions */ + +query_term: + non_join_query_term + { + $$ = SQL_NEW_RULE; + $$->append($1); + } +/* | joined_table + { + $$ = SQL_NEW_RULE; + $$->append($1); + } +*/ ; +/* SELECT STATEMENT */ +select_statement: + SQL_TOKEN_SELECT opt_all_distinct selection table_exp + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + } + ; + +selection: + '*' + { + $$ = SQL_NEW_RULE; + $$->append($1 = newNode("*", SQL_NODE_PUNCTUATION)); + } + | scalar_exp_commalist + ; + +table_exp: + from_clause + opt_where_clause + opt_group_by_clause + opt_having_clause + opt_order_by_clause + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + $$->append($5);} + ; + +from_clause: + SQL_TOKEN_FROM table_ref_commalist + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2);} + ; + +table_ref_commalist: + table_ref + {$$ = SQL_NEW_COMMALISTRULE; + $$->append($1);} + | table_ref_commalist ',' table_ref /*[^SQL_TOKEN_CROSS SQL_TOKEN_FULL SQL_TOKEN_UNION SQL_TOKEN_LEFT SQL_TOKEN_RIGHT SQL_TOKEN_INNER SQL_TOKEN_NATURAL]*/ + {$1->append($3); + $$ = $1;} + ; +as: + {$$ = SQL_NEW_RULE;} + | SQL_TOKEN_AS + { + $$ = SQL_NEW_RULE; + } + ; +table_ref: + table_name + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | table_name as range_variable op_column_commalist + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + } + | '(' joined_table ')' as range_variable op_column_commalist + { + $$ = SQL_NEW_RULE; + $$->append($1 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($2); + $$->append($3 = newNode(")", SQL_NODE_PUNCTUATION)); + $$->append($4); + $$->append($5); + $$->append($6); + } + | joined_table + | '{' SQL_TOKEN_OJ joined_table '}' + { + $$ = SQL_NEW_RULE; + $$->append($1 = newNode("{", SQL_NODE_PUNCTUATION)); + $$->append($2); + $$->append($3); + $$->append($4 = newNode("}", SQL_NODE_PUNCTUATION)); + } + ; +where_clause: + SQL_TOKEN_WHERE search_condition + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2);} + ; + +opt_group_by_clause: + /* empty */ {$$ = SQL_NEW_RULE;} + | SQL_TOKEN_GROUP SQL_TOKEN_BY column_ref_commalist + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3);} + ; + +column_ref_commalist: + column_ref + {$$ = SQL_NEW_COMMALISTRULE; + $$->append($1);} + | column_ref_commalist ',' column_ref + {$1->append($3); + $$ = $1;} + ; + +opt_having_clause: + /* empty */ {$$ = SQL_NEW_RULE;} + | SQL_TOKEN_HAVING search_condition + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2);} + ; + + /* search conditions */ +truth_value: + SQL_TOKEN_TRUE + | SQL_TOKEN_FALSE + | SQL_TOKEN_UNKNOWN + ; +boolean_primary: + predicate + | '(' search_condition ')' + { + $$ = SQL_NEW_RULE; + $$->append($1 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($2); + $$->append($3 = newNode(")", SQL_NODE_PUNCTUATION)); + } + ; +subroutine: + { + if(!xxx_pGLOBAL_SQLPARSER->inPredicateCheck()) + YYERROR; + } + ; +boolean_test: + boolean_primary + | boolean_primary SQL_TOKEN_IS truth_value + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + } + | boolean_primary SQL_TOKEN_IS SQL_TOKEN_NOT truth_value %prec SQL_TOKEN_IS + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + } + | subroutine SQL_TOKEN_NOT SQL_TOKEN_LIKE string_value_exp opt_escape + { + if (xxx_pGLOBAL_SQLPARSER->inPredicateCheck()) + { + OSQLParseNode* pColumnRef = newNode(aEmptyString, SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::column_ref)); + pColumnRef->append(newNode(xxx_pGLOBAL_SQLPARSER->getFieldName(),SQL_NODE_NAME)); + + $$ = SQL_NEW_RULE; + $$->append(pColumnRef); + $$->append($2); + $$->append($3); + if (xxx_pGLOBAL_SQLPARSER->buildLikeRule($$,$4,$5)) + $$->append($5); + else + { + delete $$; + YYABORT; + } + } + else + YYERROR; + } + ; +boolean_factor: + boolean_test + | SQL_TOKEN_NOT boolean_test + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + } + ; +boolean_term: + boolean_factor + | boolean_term SQL_TOKEN_AND boolean_factor + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + } + | row_value_constructor_elem '\n' /*[^')' ',']*/ + { + $$ = SQL_NEW_RULE; + INT16 nErg = xxx_pGLOBAL_SQLPARSER->buildComparsionRule($$,$1); + if(nErg == 1) + { + OSQLParseNode* pTemp = $$; + $$ = pTemp->removeAt((ULONG)0); + delete pTemp; + } + else + { + delete $$; + if(nErg) + YYERROR; + else + YYABORT; + } + } + | boolean_term SQL_TOKEN_AND literal + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + INT16 nErg = xxx_pGLOBAL_SQLPARSER->buildComparsionRule($$,$3); + if(nErg < 1) + { + delete $$; + if(nErg) + YYERROR; + else + YYABORT; + } + + } + | boolean_term SQL_TOKEN_AND SQL_TOKEN_STRING + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + INT16 nErg = xxx_pGLOBAL_SQLPARSER->buildComparsionRule($$,$3); + if(nErg < 1) + { + delete $$; + if(nErg) + YYERROR; + else + YYABORT; + } + + } + ; +search_condition: + boolean_term + | search_condition SQL_TOKEN_OR boolean_term + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + } + ; +predicate: + comparison_predicate + | between_predicate + | all_or_any_predicate + | existence_test + | unique_test + | test_for_null + | in_predicate + | like_predicate + ; + +comparison_predicate: + row_value_constructor comparison row_value_constructor + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + } + | comparison row_value_constructor + { + $$ = SQL_NEW_RULE; + INT16 nErg = xxx_pGLOBAL_SQLPARSER->buildComparsionRule($$,$2,$1); + if(nErg == 1) + { + OSQLParseNode* pTemp = $$; + $$ = pTemp->removeAt((ULONG)0); + delete pTemp; + } + else + { + delete $$; + YYABORT; + } + } + ; +comparison: + LESS + | NOTEQUAL + | EQUAL + | GREAT + | LESSEQ + | GREATEQ + ; +between_predicate: + row_value_constructor SQL_TOKEN_BETWEEN row_value_constructor SQL_TOKEN_AND row_value_constructor + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + $$->append($5); + } + | row_value_constructor SQL_TOKEN_NOT SQL_TOKEN_BETWEEN row_value_constructor SQL_TOKEN_AND row_value_constructor + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + $$->append($5); + $$->append($6); + } + | subroutine SQL_TOKEN_NOT SQL_TOKEN_BETWEEN row_value_constructor SQL_TOKEN_AND row_value_constructor + { + if (xxx_pGLOBAL_SQLPARSER->inPredicateCheck()) + { + OSQLParseNode* pColumnRef = newNode(aEmptyString, SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::column_ref)); + pColumnRef->append(newNode(xxx_pGLOBAL_SQLPARSER->getFieldName(),SQL_NODE_NAME)); + + $$ = SQL_NEW_RULE; + $$->append(pColumnRef); + $$->append($2); + $$->append($3); + $$->append($4); + $$->append($5); + $$->append($6); + } + else + YYERROR; + } + | subroutine SQL_TOKEN_BETWEEN row_value_constructor SQL_TOKEN_AND row_value_constructor + { + if (xxx_pGLOBAL_SQLPARSER->inPredicateCheck()) + { + OSQLParseNode* pColumnRef = newNode(aEmptyString, SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::column_ref)); + pColumnRef->append(newNode(xxx_pGLOBAL_SQLPARSER->getFieldName(),SQL_NODE_NAME)); + + $$ = SQL_NEW_RULE; + $$->append(pColumnRef); + $$->append($2); + $$->append($3); + $$->append($4); + $$->append($5); + } + else + YYERROR; + } + ; + +like_predicate: + row_value_constructor SQL_TOKEN_NOT SQL_TOKEN_LIKE string_value_exp opt_escape + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + $$->append($5); + } + | row_value_constructor SQL_TOKEN_LIKE string_value_exp opt_escape + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + } + | row_value_constructor SQL_TOKEN_NOT SQL_TOKEN_LIKE value_exp_primary opt_escape + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + $$->append($5); + } + | row_value_constructor SQL_TOKEN_LIKE value_exp_primary opt_escape + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + } + /*| SQL_TOKEN_NOT + { + if(!xxx_pGLOBAL_SQLPARSER->inPredicateCheck()) + YYERROR; + } SQL_TOKEN_LIKE string_value_exp opt_escape + { + if (xxx_pGLOBAL_SQLPARSER->inPredicateCheck()) + { + OSQLParseNode* pColumnRef = newNode(aEmptyString, SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::column_ref)); + pColumnRef->append(newNode(xxx_pGLOBAL_SQLPARSER->getFieldName(),SQL_NODE_NAME)); + + $$ = SQL_NEW_RULE; + $$->append(pColumnRef); + $$->append($1); + $$->append($3); + if (xxx_pGLOBAL_SQLPARSER->buildLikeRule($$,$4,$5)) + $$->append($5); + else + { + delete $$; + YYABORT; + } + } + else + YYERROR; + } + */| SQL_TOKEN_LIKE string_value_exp opt_escape + { + if (xxx_pGLOBAL_SQLPARSER->inPredicateCheck()) + { + OSQLParseNode* pColumnRef = newNode(aEmptyString, SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::column_ref)); + pColumnRef->append(newNode(xxx_pGLOBAL_SQLPARSER->getFieldName(),SQL_NODE_NAME)); + + $$ = SQL_NEW_RULE; + $$->append(pColumnRef); + $$->append($1); + if (xxx_pGLOBAL_SQLPARSER->buildLikeRule($$,$2,$3)) + $$->append($3); + else + { + delete $$; + YYABORT; + } + } + else + YYERROR; + } + | SQL_TOKEN_LIKE value_exp_primary opt_escape + { + if (xxx_pGLOBAL_SQLPARSER->inPredicateCheck()) + { + OSQLParseNode* pColumnRef = newNode(aEmptyString, SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::column_ref)); + pColumnRef->append(newNode(xxx_pGLOBAL_SQLPARSER->getFieldName(),SQL_NODE_NAME)); + + $$ = SQL_NEW_RULE; + $$->append(pColumnRef); + $$->append($1); + if (xxx_pGLOBAL_SQLPARSER->buildLikeRule($$,$2,$3)) + $$->append($3); + else + { + delete $$; + YYABORT; + } + } + else + YYERROR; + } + | subroutine SQL_TOKEN_NOT SQL_TOKEN_LIKE value_exp_primary opt_escape + { + if (xxx_pGLOBAL_SQLPARSER->inPredicateCheck()) + { + OSQLParseNode* pColumnRef = newNode(aEmptyString, SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::column_ref)); + pColumnRef->append(newNode(xxx_pGLOBAL_SQLPARSER->getFieldName(),SQL_NODE_NAME)); + + $$ = SQL_NEW_RULE; + $$->append(pColumnRef); + $$->append($2); + $$->append($3); + if (xxx_pGLOBAL_SQLPARSER->buildLikeRule($$,$4,$5)) + $$->append($5); + else + { + delete $$; + YYABORT; + } + } + else + YYERROR; + } + ; + +opt_escape: + /* empty */ {$$ = SQL_NEW_RULE;} + | SQL_TOKEN_ESCAPE string_value_exp + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2);} + | '{' SQL_TOKEN_ESCAPE SQL_TOKEN_STRING '}' + { + $$ = SQL_NEW_RULE; + $$->append($1 = newNode("{", SQL_NODE_PUNCTUATION)); + $$->append($2); + $$->append($3); + $$->append($4 = newNode("}", SQL_NODE_PUNCTUATION)); + } + ; + +test_for_null: + row_value_constructor SQL_TOKEN_IS not SQL_TOKEN_NULL + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + } + | SQL_TOKEN_IS not SQL_TOKEN_NULL + { + if (xxx_pGLOBAL_SQLPARSER->inPredicateCheck()) + { + OSQLParseNode* pColumnRef = newNode(aEmptyString, SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::column_ref)); + pColumnRef->append(newNode(xxx_pGLOBAL_SQLPARSER->getFieldName(),SQL_NODE_NAME)); + + $$ = SQL_NEW_RULE; + $$->append(pColumnRef); + $$->append($1); + $$->append($2); + $$->append($3); + } + else + YYERROR; + } + ; +in_predicate_value: + subquery + {$$ = SQL_NEW_RULE; + $$->append($1); + } + | '(' value_exp_commalist ')' + {$$ = SQL_NEW_RULE; + $$->append($1 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($2); + $$->append($3 = newNode(")", SQL_NODE_PUNCTUATION)); + } + ; +in_predicate: + row_value_constructor not SQL_TOKEN_IN in_predicate_value + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + } + | subroutine SQL_TOKEN_IN in_predicate_value + { + if (xxx_pGLOBAL_SQLPARSER->inPredicateCheck()) + { + OSQLParseNode* pColumnRef = newNode(aEmptyString, SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::column_ref)); + pColumnRef->append(newNode(xxx_pGLOBAL_SQLPARSER->getFieldName(),SQL_NODE_NAME)); + + $$ = SQL_NEW_RULE; + $$->append(pColumnRef); + $$->append($2); + $$->append($3); + /*$$->append($3);*/ + } + else + YYERROR; + } + ; +all_or_any_predicate: + row_value_constructor comparison any_all_some subquery + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + } + | comparison any_all_some subquery + { + if(xxx_pGLOBAL_SQLPARSER->inPredicateCheck()) + { + OSQLParseNode* pColumnRef = newNode(aEmptyString, SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::column_ref)); + pColumnRef->append(newNode(xxx_pGLOBAL_SQLPARSER->getFieldName(),SQL_NODE_NAME)); + + $$ = SQL_NEW_RULE; + $$->append(pColumnRef); + $$->append($1); + $$->append($2); + $$->append($3); + } + else + YYERROR; + } + ; + +any_all_some: + SQL_TOKEN_ANY + | SQL_TOKEN_ALL + | SQL_TOKEN_SOME + ; + +existence_test: + SQL_TOKEN_EXISTS subquery + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2);} + ; +unique_test: + SQL_TOKEN_UNIQUE subquery + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2);} + ; +subquery: + '(' query_exp ')' + {$$ = SQL_NEW_RULE; + $$->append($1 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($2); + $$->append($3 = newNode(")", SQL_NODE_PUNCTUATION));} + ; + + /* scalar expressions */ +scalar_exp_commalist: + select_sublist + { + $$ = SQL_NEW_COMMALISTRULE; + $$->append($1); + } + | scalar_exp_commalist ',' select_sublist + { + $1->append($3); + $$ = $1; + } + ; +select_sublist: + table_name '.' '*' + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode(".", SQL_NODE_PUNCTUATION)); + $$->append($3 = newNode("*", SQL_NODE_PUNCTUATION)); + } + | derived_column + + ; + +parameter_ref: + parameter + ; + +/* +op_like: + '*' + { + $$ = newNode("*", SQL_NODE_PUNCTUATION); + } + | '?' + { + $$ = newNode("?", SQL_NODE_PUNCTUATION); + } + | op_like '*' + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("*", SQL_NODE_PUNCTUATION)); + xxx_pGLOBAL_SQLPARSER->reduceLiteral($$, FALSE); + } + | op_like '?' + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("?", SQL_NODE_PUNCTUATION)); + xxx_pGLOBAL_SQLPARSER->reduceLiteral($$, FALSE); + } + ; +*/ + +literal: +/* SQL_TOKEN_STRING + | */SQL_TOKEN_INT + | SQL_TOKEN_REAL_NUM + | SQL_TOKEN_INTNUM + | SQL_TOKEN_APPROXNUM + | SQL_TOKEN_ACCESS_DATE +/* rules for predicate check */ + | literal SQL_TOKEN_STRING + { + if (xxx_pGLOBAL_SQLPARSER->inPredicateCheck()) + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + xxx_pGLOBAL_SQLPARSER->reduceLiteral($$, TRUE); + } + else + YYERROR; + } + | literal SQL_TOKEN_INT + { + if (xxx_pGLOBAL_SQLPARSER->inPredicateCheck()) + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + xxx_pGLOBAL_SQLPARSER->reduceLiteral($$, TRUE); + } + else + YYERROR; + } + | literal SQL_TOKEN_REAL_NUM + { + if (xxx_pGLOBAL_SQLPARSER->inPredicateCheck()) + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + xxx_pGLOBAL_SQLPARSER->reduceLiteral($$, TRUE); + } + else + YYERROR; + } + | literal SQL_TOKEN_APPROXNUM + { + if (xxx_pGLOBAL_SQLPARSER->inPredicateCheck()) + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + xxx_pGLOBAL_SQLPARSER->reduceLiteral($$, TRUE); + } + else + YYERROR; + } + ; + + /* miscellaneous */ +as_clause: + /* empty */ {$$ = SQL_NEW_RULE;} + | SQL_TOKEN_AS column + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + } + | column + ; +position_exp: + SQL_TOKEN_POSITION '(' string_value_exp SQL_TOKEN_IN string_value_exp ')' + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4); + $$->append($5); + $$->append($6 = newNode(")", SQL_NODE_PUNCTUATION)); + } + ; +num_value_fct: + position_exp + | extract_exp + | length_exp + ; +char_length_exp: + SQL_TOKEN_CHAR_LENGTH '(' string_value_exp ')' + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(")", SQL_NODE_PUNCTUATION)); + } + ; +octet_length_exp: + SQL_TOKEN_OCTECT_LENGTH '(' string_value_exp ')' + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(")", SQL_NODE_PUNCTUATION)); + } + ; +bit_length_exp: + SQL_TOKEN_BIT_LENGTH '(' string_value_exp ')' + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(")", SQL_NODE_PUNCTUATION)); + } + ; +length_exp: + char_length_exp + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | octet_length_exp + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | bit_length_exp + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + ; +datetime_field: + non_second_datetime_field + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | SQL_TOKEN_SECOND + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + ; +extract_field: + datetime_field + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | time_zone_field + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + ; +time_zone_field: + SQL_TOKEN_TIMEZONE_HOUR + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | SQL_TOKEN_TIMEZONE_MINUTE + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + ; +extract_source: + datetime_value_exp + { + $$ = SQL_NEW_RULE; + $$->append($1); + } +/* | interval_value_exp + { + $$ = SQL_NEW_RULE; + $$->append($1); + } */ + ; +extract_exp: + SQL_TOKEN_EXTRACT '(' extract_field SQL_TOKEN_FROM extract_source ')' + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4); + $$->append($5); + $$->append($6 = newNode(")", SQL_NODE_PUNCTUATION)); + } + ; +unsigned_value_spec: + literal + | general_value_spec + ; +general_value_spec: + parameter + | SQL_TOKEN_USER + ; +set_fct_spec: + general_set_fct + | '{' odbc_fct_spec '}' + { + $$ = SQL_NEW_RULE; + $$->append($1 = newNode("{", SQL_NODE_PUNCTUATION)); + $$->append($2); + $$->append($3 = newNode("}", SQL_NODE_PUNCTUATION)); + } + | SQL_TOKEN_NAME '(' value_exp_commalist ')' + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(")", SQL_NODE_PUNCTUATION)); + } + ; +op_parameter: + {$$ = SQL_NEW_RULE;} + | '?' EQUAL + { + $$ = SQL_NEW_RULE; + $$->append($1 = newNode("?", SQL_NODE_PUNCTUATION)); + $$->append($2); + } + ; +odbc_call_spec: + op_parameter SQL_TOKEN_CALL table_name op_odbc_call_parameter + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + } + ; + +op_odbc_call_parameter: + {$$ = SQL_NEW_RULE;} + | '(' odbc_parameter_commalist ')' + { + $$ = SQL_NEW_RULE; + $$->append($1 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($2); + $$->append($3 = newNode(")", SQL_NODE_PUNCTUATION)); + } + ; + +odbc_parameter_commalist: + odbc_parameter + {$$ = SQL_NEW_COMMALISTRULE; + $$->append($1);} + | odbc_parameter_commalist ',' odbc_parameter + { + $1->append($3); + $$ = $1; + } + ; +odbc_parameter: + /* empty */ {$$ = SQL_NEW_RULE;} + | literal + | parameter + ; + +odbc_fct_spec: + odbc_fct_type SQL_TOKEN_STRING + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + } + ; + +odbc_fct_type: + SQL_TOKEN_FN + | SQL_TOKEN_D + | SQL_TOKEN_T + | SQL_TOKEN_TS + ; + +general_set_fct: + set_fct_type '(' opt_all_distinct value_exp ')' + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4); + $$->append($5 = newNode(")", SQL_NODE_PUNCTUATION)); + } + | SQL_TOKEN_COUNT '(' '*' ')' + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3 = newNode("*", SQL_NODE_PUNCTUATION)); + $$->append($4 = newNode(")", SQL_NODE_PUNCTUATION)); + } + | SQL_TOKEN_COUNT '(' opt_all_distinct value_exp ')' + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4); + $$->append($5 = newNode(")", SQL_NODE_PUNCTUATION)); + } + ; +set_fct_type: + SQL_TOKEN_AVG + | SQL_TOKEN_MAX + | SQL_TOKEN_MIN + | SQL_TOKEN_SUM + ; + +outer_join_type: + SQL_TOKEN_LEFT %prec SQL_TOKEN_LEFT + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | SQL_TOKEN_RIGHT %prec SQL_TOKEN_RIGHT + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | SQL_TOKEN_FULL %prec SQL_TOKEN_FULL + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + ; +join_condition: + SQL_TOKEN_ON search_condition + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + } + ; +join_spec: + join_condition + | named_columns_join + ; +join_type: + SQL_TOKEN_INNER + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | outer_join_type + | outer_join_type SQL_TOKEN_OUTER + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + } + ; +cross_union: + table_ref /*[SQL_TOKEN_CROSS]*/ SQL_TOKEN_CROSS SQL_TOKEN_JOIN table_ref %prec SQL_TOKEN_CROSS + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + } + ; + +qualified_join: + /* wenn SQL_TOKEN_NATURAL, dann keine join_spec */ + table_ref /*[SQL_TOKEN_NATURAL]*/ SQL_TOKEN_NATURAL join_type SQL_TOKEN_JOIN table_ref %prec SQL_TOKEN_NATURAL + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + $$->append($5); + } + | table_ref join_type SQL_TOKEN_JOIN table_ref join_spec + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + $$->append($5); + } + | cross_union + ; +joined_table: + qualified_join +/* | query_exp*/ + | '(' joined_table ')' + { + $$ = SQL_NEW_RULE; + $$->append($1 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($2); + $$->append($3 = newNode(")", SQL_NODE_PUNCTUATION)); + } + + ; +named_columns_join: + SQL_TOKEN_USING '(' column_commalist ')' + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(")", SQL_NODE_PUNCTUATION)); + } + ; +simple_table: + select_statement + | values_or_query_spec + ; + +non_join_query_primary: + simple_table + | '(' non_join_query_exp ')' + { + $$ = SQL_NEW_RULE; + $$->append($1 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($2); + $$->append($3 = newNode(")", SQL_NODE_PUNCTUATION)); + } + ; +non_join_query_term: + non_join_query_primary + | query_term SQL_TOKEN_INTERSECT all query_primary + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + } + ; +query_primary: + non_join_query_primary + /*| joined_table*/ + ; +non_join_query_exp: + non_join_query_term + | query_exp SQL_TOKEN_UNION all query_term + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + } + | query_exp SQL_TOKEN_EXCEPT all query_term + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + } + ; +all: + /* empty*/ {$$ = SQL_NEW_RULE;} + | SQL_TOKEN_ALL + ; +query_exp: + non_join_query_exp /*[^')']*/ + ; +scalar_subquery: + subquery + ; +cast_operand: + value_exp + | SQL_TOKEN_NULL + ; +cast_target: + table_name + | data_type + ; +cast_spec: + SQL_TOKEN_CAST '(' cast_operand SQL_TOKEN_AS cast_target ')' + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4); + $$->append($5); + $$->append($6 = newNode(")", SQL_NODE_PUNCTUATION)); + } + ; +value_exp_primary: + unsigned_value_spec + | column_ref + | set_fct_spec + | scalar_subquery + | '(' value_exp ')' + { + $$ = SQL_NEW_RULE; + $$->append($1 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($2); + $$->append($3 = newNode(")", SQL_NODE_PUNCTUATION)); + } + | cast_spec + ; + +num_primary: + value_exp_primary + | num_value_fct + ; +factor: + num_primary + | '-' num_primary %prec SQL_TOKEN_UMINUS + { + $$ = SQL_NEW_RULE; + $$->append($1 = newNode("-", SQL_NODE_PUNCTUATION)); + $$->append($2); + } + | '+' num_primary %prec SQL_TOKEN_UMINUS + { + $$ = SQL_NEW_RULE; + $$->append($1 = newNode("+", SQL_NODE_PUNCTUATION)); + $$->append($2); + } + ; + +term: + factor + | term '*' factor + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("*", SQL_NODE_PUNCTUATION)); + $$->append($3); + } + | term '/' factor + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("/", SQL_NODE_PUNCTUATION)); + $$->append($3); + } + ; + +num_value_exp: + term + | num_value_exp '+' term + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("+", SQL_NODE_PUNCTUATION)); + $$->append($3); + } + | num_value_exp '-' term + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("-", SQL_NODE_PUNCTUATION)); + $$->append($3); + } + ; +datetime_primary: +/* value_exp_primary + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + |*/ datetime_value_fct + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + ; +datetime_value_fct: + SQL_TOKEN_CURRENT_DATE + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | SQL_TOKEN_CURRENT_TIME + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | SQL_TOKEN_CURRENT_TIMESTAMP + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + ; +time_zone: + SQL_TOKEN_AT time_zone_specifier + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + } + ; +time_zone_specifier: + SQL_TOKEN_LOCAL + { + $$ = SQL_NEW_RULE; + $$->append($1); + } +/* | SQL_TOKEN_TIME SQL_TOKEN_ZONE interval_value_exp + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + }*/ + ; +datetime_factor: + datetime_primary + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | datetime_primary time_zone + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + } + ; +datetime_term: + datetime_factor + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + ; +/* +interval_term: + literal + | interval_term '*' factor + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("*", SQL_NODE_PUNCTUATION)); + $$->append($3); + } + | interval_term '/' factor + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("/", SQL_NODE_PUNCTUATION)); + $$->append($3); + } + ; +*/ +datetime_value_exp: + datetime_term + { + $$ = SQL_NEW_RULE; + $$->append($1); + } +/* | interval_value_exp '+' datetime_term + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("+", SQL_NODE_PUNCTUATION)); + $$->append($3); + } + | datetime_value_exp '+' interval_term + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("+", SQL_NODE_PUNCTUATION)); + $$->append($3); + } + | datetime_value_exp '-' interval_term + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("-", SQL_NODE_PUNCTUATION)); + $$->append($3); + } +*/ ; +/* +interval_value_exp: + interval_term + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | interval_value_exp '+' interval_term + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("+", SQL_NODE_PUNCTUATION)); + $$->append($3); + } + | interval_value_exp '-' interval_term + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("-", SQL_NODE_PUNCTUATION)); + $$->append($3); + } + | '(' datetime_value_exp '-' datetime_term ')' interval_qualifier + { + $$ = SQL_NEW_RULE; + $$->append($1 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($2); + $$->append($3 = newNode("-", SQL_NODE_PUNCTUATION)); + $$->append($4); + $$->append($5 = newNode(")", SQL_NODE_PUNCTUATION)); + $$->append($6); + } + ; +*/ +non_second_datetime_field: + SQL_TOKEN_YEAR + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | SQL_TOKEN_MONTH + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | SQL_TOKEN_DAY + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | SQL_TOKEN_HOUR + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | SQL_TOKEN_MINUTE + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + ; +/*start_field: + non_second_datetime_field + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | non_second_datetime_field '(' SQL_TOKEN_INTNUM ')' + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(")", SQL_NODE_PUNCTUATION)); + } + ; +end_field: + non_second_datetime_field + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | SQL_TOKEN_SECOND + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | SQL_TOKEN_SECOND '(' SQL_TOKEN_INTNUM ')' + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(")", SQL_NODE_PUNCTUATION)); + } + ; +*/ +/* +single_datetime_field: + non_second_datetime_field + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | non_second_datetime_field '(' SQL_TOKEN_INTNUM ')' + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(")", SQL_NODE_PUNCTUATION)); + } + | SQL_TOKEN_SECOND + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | SQL_TOKEN_SECOND '(' SQL_TOKEN_INTNUM ')' + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(")", SQL_NODE_PUNCTUATION)); + } + | SQL_TOKEN_SECOND '(' SQL_TOKEN_INTNUM ',' SQL_TOKEN_INTNUM ')' + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(",", SQL_NODE_PUNCTUATION)); + $$->append($5); + $$->append($6 = newNode(")", SQL_NODE_PUNCTUATION)); + } + ; +*/ +/* +interval_qualifier: + start_field SQL_TOKEN_TO end_field + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + } + | single_datetime_field + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + ; +*/ +value_exp_commalist: + value_exp + {$$ = SQL_NEW_COMMALISTRULE; + $$->append($1);} + | value_exp_commalist ',' value_exp + {$1->append($3); + $$ = $1;} + /* this rule is only valid if we check predicates */ + | value_exp_commalist ';' value_exp + { + if (xxx_pGLOBAL_SQLPARSER->inPredicateCheck()) + { + $1->append($3); + $$ = $1; + } + else + YYERROR; + } + ; +value_exp: + num_value_exp /*[^')']*/ + | string_value_exp + | datetime_value_exp + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + ; +string_value_exp: + char_value_exp +/* | bit_value_exp + { + $$ = SQL_NEW_RULE; + $$->append($1); + } +*/ ; +char_value_exp: + char_factor + | concatenation + ; +concatenation: + char_value_exp '+' char_factor + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("+", SQL_NODE_PUNCTUATION)); + $$->append($3); + } + ; + +char_primary: + SQL_TOKEN_STRING + | string_value_fct + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + ; +collate_clause: + SQL_TOKEN_COLLATE table_name + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + } + ; +char_factor: + char_primary + | char_primary collate_clause + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + } + ; +string_value_fct: + char_value_fct + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | bit_value_fct + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + ; +bit_value_fct: + bit_substring_fct + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + ; +bit_substring_fct: + SQL_TOKEN_SUBSTRING '(' bit_value_exp SQL_TOKEN_FROM string_value_exp for_length ')' + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4); + $$->append($5); + $$->append($6); + $$->append($7 = newNode(")", SQL_NODE_PUNCTUATION)); + } + ; +bit_value_exp: + bit_factor + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + ; +/* + bit_concatenation + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | +bit_concatenation: + bit_value_exp '+' bit_factor + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("+", SQL_NODE_PUNCTUATION)); + $$->append($3); + } + ; +*/ +bit_factor: + bit_primary + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + ; +bit_primary: + {$$ = SQL_NEW_RULE;} +/* value_exp_primary + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | string_value_fct + { + $$ = SQL_NEW_RULE; + $$->append($1); + }*/ + ; +char_value_fct: + char_substring_fct + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | fold + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | form_conversion + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | char_translation + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + | trim_fct + { + $$ = SQL_NEW_RULE; + $$->append($1); + } + ; +for_length: + {$$ = SQL_NEW_RULE;} + | SQL_TOKEN_FOR string_value_exp + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + } + ; +char_substring_fct: + SQL_TOKEN_SUBSTRING '(' string_value_exp SQL_TOKEN_FROM string_value_exp for_length ')' + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4); + $$->append($5); + $$->append($6); + $$->append($7 = newNode(")", SQL_NODE_PUNCTUATION)); + } + ; +upper_lower: + SQL_TOKEN_UPPER + | SQL_TOKEN_LOWER + ; +fold: + upper_lower '(' string_value_exp ')' + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(")", SQL_NODE_PUNCTUATION)); + } + ; +form_conversion: + SQL_TOKEN_CONVERT '(' string_value_exp SQL_TOKEN_USING table_name ')' + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4); + $$->append($5); + $$->append($6 = newNode(")", SQL_NODE_PUNCTUATION)); + } + ; +char_translation: + SQL_TOKEN_TRANSLATE '(' string_value_exp SQL_TOKEN_USING table_name ')' + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4); + $$->append($5); + $$->append($6 = newNode(")", SQL_NODE_PUNCTUATION)); + } + ; +trim_fct: + SQL_TOKEN_TRIM '(' trim_operands ')' + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(")", SQL_NODE_PUNCTUATION)); + } + ; +trim_operands: + string_value_exp + | trim_spec string_value_exp SQL_TOKEN_FROM string_value_exp + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + $$->append($4); + } + | trim_spec SQL_TOKEN_FROM string_value_exp + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + $$->append($3); + } + ; +trim_spec: + SQL_TOKEN_BOTH + | SQL_TOKEN_LEADING + | SQL_TOKEN_TRAILING + ; + +derived_column: + value_exp as_clause + { + $$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2); + } + ; +/* Tabellenname */ +table_name: + SQL_TOKEN_NAME + {$$ = SQL_NEW_RULE; + $$->append($1);} + | SQL_TOKEN_NAME '.' SQL_TOKEN_NAME %prec SQL_TOKEN_NAME + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode(".", SQL_NODE_PUNCTUATION)); + $$->append($3);} + | SQL_TOKEN_NAME '.' SQL_TOKEN_NAME '.' SQL_TOKEN_NAME %prec SQL_TOKEN_NAME + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2= newNode(".", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(".", SQL_NODE_PUNCTUATION)); + $$->append($5);} + | SQL_TOKEN_NAME ':' SQL_TOKEN_NAME '.' SQL_TOKEN_NAME + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2= newNode(":", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(".", SQL_NODE_PUNCTUATION)); + $$->append($5);} +/* | SQL_TOKEN_NAME ';' SQL_TOKEN_NAME '.' SQL_TOKEN_NAME + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2= newNode(";", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(".", SQL_NODE_PUNCTUATION)); + $$->append($5);} +*/ ; +column_ref: + column + {$$ = SQL_NEW_RULE; + $$->append($1);} + | SQL_TOKEN_NAME '.' column_val %prec '.' + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode(".", SQL_NODE_PUNCTUATION)); + $$->append($3);} + | SQL_TOKEN_NAME '.' SQL_TOKEN_NAME '.' column_val %prec '.' + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode(".", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(".", SQL_NODE_PUNCTUATION)); + $$->append($5);} + | SQL_TOKEN_NAME '.' SQL_TOKEN_NAME '.' SQL_TOKEN_NAME '.' column_val %prec '.' + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2= newNode(".", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(".", SQL_NODE_PUNCTUATION)); + $$->append($5); + $$->append($6 = newNode(".", SQL_NODE_PUNCTUATION)); + $$->append($7); + } + | SQL_TOKEN_NAME ':' SQL_TOKEN_NAME '.' SQL_TOKEN_NAME '.' column_val %prec '.' + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2= newNode(":", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(".", SQL_NODE_PUNCTUATION)); + $$->append($5); + $$->append($6 = newNode(".", SQL_NODE_PUNCTUATION)); + $$->append($7); + } +/* | SQL_TOKEN_NAME ';' SQL_TOKEN_NAME '.' SQL_TOKEN_NAME '.' column_val + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2= newNode(";", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(".", SQL_NODE_PUNCTUATION)); + $$->append($5); + $$->append($6 = newNode(".", SQL_NODE_PUNCTUATION)); + $$->append($7); + } +*/ ; + + /* data types */ +column_val: + column + {$$ = SQL_NEW_RULE; + $$->append($1);} + | '*' + { + $$ = SQL_NEW_RULE; + $$->append($1 = newNode("*", SQL_NODE_PUNCTUATION)); + } + ; +data_type: + SQL_TOKEN_CHARACTER + | SQL_TOKEN_CHARACTER '(' SQL_TOKEN_INTNUM ')' + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(")", SQL_NODE_PUNCTUATION));} + | SQL_TOKEN_NUMERIC + | SQL_TOKEN_NUMERIC '(' SQL_TOKEN_INTNUM ')' + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(")", SQL_NODE_PUNCTUATION));} + | SQL_TOKEN_NUMERIC '(' SQL_TOKEN_INTNUM ',' SQL_TOKEN_INTNUM ')' + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(",", SQL_NODE_PUNCTUATION)); + $$->append($5); + $$->append($6 = newNode(")", SQL_NODE_PUNCTUATION));} + | SQL_TOKEN_DECIMAL + | SQL_TOKEN_DECIMAL '(' SQL_TOKEN_INTNUM ')' + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(")", SQL_NODE_PUNCTUATION));} + | SQL_TOKEN_DECIMAL '(' SQL_TOKEN_INTNUM ',' SQL_TOKEN_INTNUM ')' + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(",", SQL_NODE_PUNCTUATION)); + $$->append($5); + $$->append($6 = newNode(")", SQL_NODE_PUNCTUATION));} + | SQL_TOKEN_INTEGER + | SQL_TOKEN_SMALLINT + | SQL_TOKEN_FLOAT + | SQL_TOKEN_FLOAT '(' SQL_TOKEN_INTNUM ')' + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2 = newNode("(", SQL_NODE_PUNCTUATION)); + $$->append($3); + $$->append($4 = newNode(")", SQL_NODE_PUNCTUATION));} + | SQL_TOKEN_REAL + | SQL_TOKEN_DOUBLE SQL_TOKEN_PRECISION + {$$ = SQL_NEW_RULE; + $$->append($1); + $$->append($2);} + ; + + /* the various things you can name */ + +column: + SQL_TOKEN_NAME + | SQL_TOKEN_POSITION + { + UINT16 nNod = $$->getRuleID(); + delete $$; + $$ = newNode(xxx_pGLOBAL_SQLPARSER->TokenIDToStr(nNod), SQL_NODE_NAME); + } + | SQL_TOKEN_CHAR_LENGTH + { + UINT16 nNod = $$->getRuleID(); + delete $$; + $$ = newNode(xxx_pGLOBAL_SQLPARSER->TokenIDToStr(nNod), SQL_NODE_NAME); + } + | SQL_TOKEN_EXTRACT + { + UINT16 nNod = $$->getRuleID(); + delete $$; + $$ = newNode(xxx_pGLOBAL_SQLPARSER->TokenIDToStr(nNod), SQL_NODE_NAME); + } + ; + +cursor: SQL_TOKEN_NAME + {$$ = SQL_NEW_RULE; + $$->append($1);} + ; + +/*** +module: SQL_TOKEN_NAME + {$$ = SQL_NEW_RULE; + $$->append($1);} + ; +***/ + +parameter: + ':' SQL_TOKEN_NAME + {$$ = SQL_NEW_RULE; + $$->append($1 = newNode(":", SQL_NODE_PUNCTUATION)); + $$->append($2);} + | '?' + {$$ = SQL_NEW_RULE; + $$->append($1 = newNode("?", SQL_NODE_PUNCTUATION));} + | '[' SQL_TOKEN_NAME ']' + {$$ = SQL_NEW_RULE; + $$->append($1 = newNode("[", SQL_NODE_PUNCTUATION)); + $$->append($2); + $$->append($3 = newNode("]", SQL_NODE_PUNCTUATION));} + ; + +/*** +procedure: SQL_TOKEN_NAME + {$$ = SQL_NEW_RULE; + $$->append($1);} + ; +***/ + +range_variable: SQL_TOKEN_NAME + ; + +user: SQL_TOKEN_NAME + ; + +/* PREDICATECHECK RULES */ +sql: + search_condition /* checking predicats */ + { + if (xxx_pGLOBAL_SQLPARSER->inPredicateCheck()) + { + $$ = $1; + } + else + YYERROR; + } +%% + + +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::osl; +// using namespace connectivity; + +//============================================================ +//= a helper for static ascii pseudo-unicode strings +//============================================================ +// string constants +struct _ConstAsciiString_ +{ + sal_Int32 length; + sal_Char const* str; + + operator rtl::OUString () const { return rtl::OUString(str, length, RTL_TEXTENCODING_ASCII_US); } +// operator String () const { return String(str, length, RTL_TEXTENCODING_ASCII_US); } + operator const sal_Char * () const { return str; } +}; + +#define IMPLEMENT_CONSTASCII_STRING( name, string ) \ + _ConstAsciiString_ const name = { sizeof(string)-1, string } + +IMPLEMENT_CONSTASCII_STRING(ERROR_STR_GENERAL, "Syntax error in SQL expression"); +IMPLEMENT_CONSTASCII_STRING(ERROR_STR_GENERAL_HINT, "before \"#\" expression." ); +IMPLEMENT_CONSTASCII_STRING(ERROR_STR_VALUE_NO_LIKE, "The value # can not be used with LIKE!"); +IMPLEMENT_CONSTASCII_STRING(ERROR_STR_FIELD_NO_LIKE, "LIKE can not be used with this field!"); +IMPLEMENT_CONSTASCII_STRING(ERROR_STR_INVALID_COMPARE, "The entered criterion can not be compared with this field!"); +IMPLEMENT_CONSTASCII_STRING(ERROR_STR_INVALID_STRING_COMPARE, "The field can not be compared with a string!"); +IMPLEMENT_CONSTASCII_STRING(ERROR_STR_INVALID_DATE_COMPARE, "The field can not be compared with a date!"); +IMPLEMENT_CONSTASCII_STRING(ERROR_STR_INVALID_REAL_COMPARE, "The field can not be compared with a floating point number!"); +IMPLEMENT_CONSTASCII_STRING(ERROR_STR_INVALID_INT_COMPARE, "The field can not be compared with a number!"); + +IMPLEMENT_CONSTASCII_STRING(KEY_STR_LIKE, "LIKE"); +IMPLEMENT_CONSTASCII_STRING(KEY_STR_NOT, "NOT"); +IMPLEMENT_CONSTASCII_STRING(KEY_STR_NULL, "NULL"); +IMPLEMENT_CONSTASCII_STRING(KEY_STR_TRUE, "TRUE"); +IMPLEMENT_CONSTASCII_STRING(KEY_STR_FALSE, "FALSE"); +IMPLEMENT_CONSTASCII_STRING(KEY_STR_IS, "IS"); +IMPLEMENT_CONSTASCII_STRING(KEY_STR_BETWEEN, "BETWEEN"); +IMPLEMENT_CONSTASCII_STRING(KEY_STR_OR, "OR"); +IMPLEMENT_CONSTASCII_STRING(KEY_STR_AND, "AND"); +IMPLEMENT_CONSTASCII_STRING(KEY_STR_AVG, "AVG"); +IMPLEMENT_CONSTASCII_STRING(KEY_STR_COUNT, "COUNT"); +IMPLEMENT_CONSTASCII_STRING(KEY_STR_MAX, "MAX"); +IMPLEMENT_CONSTASCII_STRING(KEY_STR_MIN, "MIN"); +IMPLEMENT_CONSTASCII_STRING(KEY_STR_SUM, "SUM"); + +IMPLEMENT_CONSTASCII_STRING(FIELD_STR_LOCALE, "Locale"); +IMPLEMENT_CONSTASCII_STRING(FIELD_STR_REALNAME, "RealName"); +IMPLEMENT_CONSTASCII_STRING(FIELD_STR_FORMATKEY, "FormatKey"); +IMPLEMENT_CONSTASCII_STRING(FIELD_STR_NAME, "Name"); +IMPLEMENT_CONSTASCII_STRING(FIELD_STR_TYPE, "Type"); +IMPLEMENT_CONSTASCII_STRING(FIELD_STR_NULLDATE, "NullDate"); + +IMPLEMENT_CONSTASCII_STRING(STR_SQL_TOKEN, "SQL_TOKEN_"); + +//========================================================================== +//= OParseContext +//========================================================================== +DBG_NAME(OParseContext); +//----------------------------------------------------------------------------- +OParseContext::OParseContext() +{ + DBG_CTOR(OParseContext,NULL); +} + +//----------------------------------------------------------------------------- +OParseContext::~OParseContext() +{ + DBG_DTOR(OParseContext,NULL); +} + +//----------------------------------------------------------------------------- +String OParseContext::getErrorMessage(ErrorCode _eCode) const +{ + String aMsg; + switch (_eCode) + { + case ERROR_GENERAL: aMsg = ERROR_STR_GENERAL; break; + case ERROR_GENERAL_HINT: aMsg = ERROR_STR_GENERAL_HINT; break; + case ERROR_VALUE_NO_LIKE: aMsg = ERROR_STR_VALUE_NO_LIKE; break; + case ERROR_FIELD_NO_LIKE: aMsg = ERROR_STR_FIELD_NO_LIKE; break; + case ERROR_INVALID_COMPARE: aMsg = ERROR_STR_INVALID_COMPARE; break; + case ERROR_INVALID_INT_COMPARE: aMsg = ERROR_STR_INVALID_INT_COMPARE; break; + case ERROR_INVALID_STRING_COMPARE: aMsg = ERROR_STR_INVALID_STRING_COMPARE; break; + case ERROR_INVALID_DATE_COMPARE: aMsg = ERROR_STR_INVALID_DATE_COMPARE; break; + case ERROR_INVALID_REAL_COMPARE: aMsg = ERROR_STR_INVALID_REAL_COMPARE; break; + } + return aMsg; +} + +//----------------------------------------------------------------------------- +ByteString OParseContext::getIntlKeywordAscii(InternationalKeyCode _eKey) const +{ + ByteString aKeyword; + switch (_eKey) + { + case KEY_LIKE: aKeyword = KEY_STR_LIKE; break; + case KEY_NOT: aKeyword = KEY_STR_NOT; break; + case KEY_NULL: aKeyword = KEY_STR_NULL; break; + case KEY_TRUE: aKeyword = KEY_STR_TRUE; break; + case KEY_FALSE: aKeyword = KEY_STR_FALSE; break; + case KEY_IS: aKeyword = KEY_STR_IS; break; + case KEY_BETWEEN: aKeyword = KEY_STR_BETWEEN; break; + case KEY_OR: aKeyword = KEY_STR_OR; break; + case KEY_AND: aKeyword = KEY_STR_AND; break; + case KEY_AVG: aKeyword = KEY_STR_AVG; break; + case KEY_COUNT: aKeyword = KEY_STR_COUNT; break; + case KEY_MAX: aKeyword = KEY_STR_MAX; break; + case KEY_MIN: aKeyword = KEY_STR_MIN; break; + case KEY_SUM: aKeyword = KEY_STR_SUM; break; + } + return aKeyword; +} + +//----------------------------------------------------------------------------- +OParseContext::InternationalKeyCode OParseContext::getIntlKeyCode(const ByteString& rToken) const +{ + static OParseContext::InternationalKeyCode Intl_TokenID[] = + { + KEY_LIKE, KEY_NOT, KEY_NULL, KEY_TRUE, + KEY_FALSE, KEY_IS, KEY_BETWEEN, KEY_OR, + KEY_AND, KEY_AVG, KEY_COUNT, KEY_MAX, + KEY_MIN, KEY_SUM + }; + + sal_uInt32 nCount = sizeof Intl_TokenID / sizeof Intl_TokenID[0]; + for (sal_uInt32 i = 0; i < nCount; i++) + { + ByteString aKey = getIntlKeywordAscii(Intl_TokenID[i]); + if (rToken.EqualsIgnoreCaseAscii(aKey)) + return Intl_TokenID[i]; + } + + return KEY_NONE; +} + +//------------------------------------------------------------------------------ +const International& OParseContext::getDefaultInternational() +{ + static International aIntl(LANGUAGE_ENGLISH_US); + static BOOL bInitialized = FALSE; + if (!bInitialized) + { // ensure that the two members we're interested in are really set + // (if the system doesn't know the locale en_US aIntl would be initialized with the + // system language which may be anything - which we don't want ...) + // 74342 - 21.03.00 - FS + aIntl.SetNumThousandSep(','); + aIntl.SetNumDecimalSep('.'); + bInitialized = TRUE; + } + return aIntl; +} + +//========================================================================== +//= misc +//========================================================================== +// Der (leider globale) yylval fuer die Uebergabe von +// Werten vom Scanner an den Parser. Die globale Variable +// wird nur kurzzeitig verwendet, der Parser liest die Variable +// sofort nach dem Scanner-Aufruf in eine gleichnamige eigene +// Member-Variable. + +const double fMilliSecondsPerDay = 86400000.0; + +//------------------------------------------------------------------------------ +Date getNULLDate(const Reference< ::com::sun::star::util::XNumberFormatsSupplier > &xSupplier) +{ + DBG_ASSERT(xSupplier.is(), "getNULLDate : the formatter doesn't implement a supplier !"); + if (xSupplier.is()) + { + try + { + // get the null date + ::com::sun::star::util::Date aDate; + xSupplier->getNumberFormatSettings()->getPropertyValue(FIELD_STR_NULLDATE) >>= aDate; + return Date(aDate.Day, aDate.Month, aDate.Year); + } + catch ( ... ) + { + } + } + + return Date(1,1,1900); +} + +//------------------------------------------------------------------------------ +Any getNumberFormatProperty(const Reference< ::com::sun::star::util::XNumberFormatsSupplier > &xSupplier, + sal_Int32 nKey, + const rtl::OUString& aPropertyName) +{ + DBG_ASSERT(xSupplier.is(), "getNumberFormatProperty : the formatter doesn't implement a supplier !"); + Reference< ::com::sun::star::util::XNumberFormats > xFormats = xSupplier->getNumberFormats(); + + if (xFormats.is()) + { + try + { + Reference< XPropertySet > xProperties(xFormats->getByKey(nKey)); + return xProperties->getPropertyValue(aPropertyName); + } + catch( ... ) + { + } + } + return Any(); +} + +// date time conversion +//------------------------------------------------------------------ +DateTime ToDateTime(const Reference< ::com::sun::star::util::XNumberFormatsSupplier > & xSupplier, + const double& fSbxDate) +{ + + long nDays = (long)fSbxDate; + long nMSeconds = long((fSbxDate - (double)nDays) * fMilliSecondsPerDay + 0.5); + + // Datum: + DateTime x(getNULLDate(xSupplier)); + + if (nDays >= 0) + x += (sal_uInt32)nDays; + else + x -= (sal_uInt32)(-nDays); + + // Zeit: + x.MakeTimeFromMS(nMSeconds); + if (x.GetTime() < 0) + x += Time(23,59,59,99); + return x; +} + +//------------------------------------------------------------------ +double ToDouble(const Reference< ::com::sun::star::util::XNumberFormatsSupplier > & xSupplier, const Date& rDate) +{ + long nDays = 0; + Date aNullDate(getNULLDate(xSupplier)); + if (aNullDate >= rDate) + { + nDays = (long)(aNullDate - rDate); + nDays *= -1; + } + else + nDays = (long)(rDate - aNullDate); + + return (double)nDays; +} + +//------------------------------------------------------------------ +double ToDouble(const Time& rTime) +{ + return (double)rTime.GetMSFromTime() / fMilliSecondsPerDay; +} + +//------------------------------------------------------------------ +Date ToDate(const Reference< ::com::sun::star::util::XNumberFormatsSupplier > & xSupplier, const double& fSbxDate) +{ + // count the days + long nDays = (long)fSbxDate; + Date aNullDate(getNULLDate(xSupplier)); + + if (nDays >= 0) + aNullDate += (sal_uInt32)nDays; + else + aNullDate -= (sal_uInt32)(-nDays); + + return aNullDate; +} + +//------------------------------------------------------------------ +Time ToTime(const double& fSbxDate) +{ + long nDays = (long)fSbxDate; + long nMSeconds = long((fSbxDate - (double)nDays) * fMilliSecondsPerDay + 0.5); + + Time x; + x.MakeTimeFromMS(nMSeconds); + if (x.GetTime() < 0) + x += Time(23,59,59,99); + return x; +} + +//------------------------------------------------------------------ +String ToDateString(const Date& rDate) +{ + sal_Char s[11]; + sprintf(s,"%04d-%02d-%02d", + (int)rDate.GetYear(), + (int)rDate.GetMonth(), + (int)rDate.GetDay()); + s[10] = 0; + return String::CreateFromAscii(s); +} + +//------------------------------------------------------------------ +String ToTimeString(const Time& rTime) +{ + sal_Char s[9]; + sprintf(s,"%02d:%02d:%02d", + (int)rTime.GetHour(), + (int)rTime.GetMin(), + (int)rTime.GetSec()); + s[8] = 0; + return String::CreateFromAscii(s); +} + +//------------------------------------------------------------------ +String ToDateTimeString(const DateTime& rDateTime) +{ + String aTemp(ToDateString(rDateTime)); + aTemp += String::CreateFromAscii(" "); + aTemp += ToTimeString(rDateTime); + return aTemp; +} + + +//------------------------------------------------------------------ +String ConvertLikeToken(const OSQLParseNode* pTokenNode, const OSQLParseNode* pEscapeNode, sal_Bool bInternational) +{ + String aMatchStr; + if (pTokenNode->isToken()) + { + char cEscape = 0; + if (pEscapeNode->count()) + cEscape = pEscapeNode->getChild(1)->getTokenValue().GetChar(0); + + // Platzhalter austauschen + aMatchStr = pTokenNode->getTokenValue(); + sal_uInt16 nLen = aMatchStr.Len(); + const char* sSearch = bInternational ? "%_" : "*?"; + const char* sReplace = bInternational ? "*?" : "%_"; + for (sal_uInt16 i = 0; i < nLen; i++) + { + char c = aMatchStr.GetChar(i); + if (c == sSearch[0] || c == sSearch[1]) + { + if (i > 0 && aMatchStr.GetChar(i-1) == cEscape) + continue; + else if (c == sSearch[0]) + aMatchStr.SetChar(i,sReplace[0]); + else + aMatchStr.SetChar(i,sReplace[1]); + } + } + } + return aMatchStr; +} + +//========================================================================== +//= OSQLParser +//========================================================================== +DBG_NAME(OSQLParser); + +sal_uInt32 OSQLParser::s_nRuleIDs[OSQLParseNode::rule_count + 1]; +OParseContext OSQLParser::s_aDefaultContext; + +sal_Int32 OSQLParser::s_nRefCount = 0; +::osl::Mutex OSQLParser::s_aMutex; +OSQLScanner* OSQLParser::s_pScanner = 0; +OSQLParseNodes* OSQLParser::s_pGarbageCollector = 0; + +//----------------------------------------------------------------------------- +OSQLParser::OSQLParser(OParseContext* _pContext) + :m_pContext(_pContext) + ,m_pParseTree(NULL) + ,m_pIntl(NULL) + ,m_nFormatKey(0) +{ + DBG_CTOR(OSQLParser,NULL); + + xxx_pGLOBAL_SQLPARSER = this; + +#ifdef SQLYYDEBUG +#ifdef SQLYYDEBUG_ON + SQLyydebug = 1; +#endif +#endif + + ::osl::MutexGuard aGuard(s_aMutex); + // do we have to initialize the data + if (s_nRefCount == 0) + { + s_pScanner = new OSQLScanner(); + s_pScanner->setScanner(); + s_pGarbageCollector = new OSQLParseNodes(); + + // auf 0 zuruecksetzen + memset(OSQLParser::s_nRuleIDs,0,sizeof(sal_uInt16) * OSQLParseNode::rule_count+1); + } + ++s_nRefCount; + + if (m_pContext == NULL) + // take the default context + m_pContext = &s_aDefaultContext; +} + +//----------------------------------------------------------------------------- +OSQLParser::~OSQLParser() +{ + { + ::osl::MutexGuard aGuard(s_aMutex); + DBG_ASSERT(s_nRefCount > 0, "OSQLParser::~OSQLParser() : suspicious call : have a refcount of 0 !"); + if (!--s_nRefCount) + { + s_pScanner->setScanner(sal_True); + delete s_pScanner; + s_pScanner = NULL; + + delete s_pGarbageCollector; + s_pGarbageCollector = NULL; + } + } + + delete m_pIntl; + + DBG_DTOR(OSQLParser,NULL); +} + +//----------------------------------------------------------------------------- +OSQLParseNode* OSQLParser::parseTree(String& rErrorMessage, + const String& rStatement, + sal_Bool bInternational) +{ + DBG_CHKTHIS(OSQLParser,NULL); + + // Guard the parsing + ::osl::MutexGuard aGuard(s_aMutex); + + // defines how to scan + s_pScanner->SetRule(s_pScanner->GetSQLRule()); // initial + s_pScanner->prepareScan(rStatement, m_pContext, bInternational); + + SQLyylval.pParseNode = NULL; + // SQLyypvt = NULL; + m_pParseTree = NULL; + m_sErrorMessage.Erase(); + + // ... und den Parser anwerfen ... + if (SQLyyparse() != 0) + { + // only set the error message, if it's not already set + if (!m_sErrorMessage.Len()) + m_sErrorMessage = s_pScanner->getErrorMessage(); + if (!m_sErrorMessage.Len()) + m_sErrorMessage = m_pContext->getErrorMessage(OParseContext::ERROR_GENERAL); + + rErrorMessage = m_sErrorMessage; + + // clear the garbage collector + while (!s_pGarbageCollector->empty()) + { + OSQLParseNode* pNode = *s_pGarbageCollector->begin(); + while (pNode->getParent()) + pNode = pNode->getParent(); + delete pNode; + } + return NULL; + } + else + { + s_pGarbageCollector->clear(); + + // Das Ergebnis liefern (den Root Parse Node): + + // DBG_ASSERT(Sdbyyval.pParseNode != NULL,"OSQLParser: Parser hat keinen ParseNode geliefert"); + // return Sdbyyval.pParseNode; + // geht nicht wegen Bug in MKS YACC-erzeugtem Code (es wird ein falscher ParseNode + // geliefert). + + // Stattdessen setzt die Parse-Routine jetzt den Member pParseTree + // - einfach diesen zurueckliefern: + DBG_ASSERT(m_pParseTree != NULL,"OSQLParser: Parser hat keinen ParseTree geliefert"); + return m_pParseTree; + } +} + +static char* __READONLY_DATA PREDICATE_CHECK = "PREDICATE "; +//----------------------------------------------------------------------------- +OSQLParseNode* OSQLParser::predicateTree(String& rErrorMessage, const String& rStatement, + const Reference< ::com::sun::star::util::XNumberFormatter > & xFormatter, + const Reference< XPropertySet > & xField) +{ + DBG_CHKTHIS(OSQLParser,NULL); + + // mutex for parsing + static ::osl::Mutex aMutex; + + // Guard the parsing + ::osl::MutexGuard aGuard(s_aMutex); + + // reset the parser + if (!m_pIntl) + m_pIntl = new International(m_pContext->getDefaultInternational()); + + m_xField = xField; + m_xFormatter = xFormatter; + + if (m_xField.is()) + { + sal_Int32 nType=0; + try + { + // get the field name + rtl::OUString aString; + + // retrieve the fields name + // #75243# use the RealName of the column if there is any otherwise the name which could be the alias + // of the field + if (m_xField->getPropertySetInfo()->hasPropertyByName(FIELD_STR_REALNAME)) + m_xField->getPropertyValue(FIELD_STR_REALNAME) >>= aString; + else + m_xField->getPropertyValue(FIELD_STR_NAME) >>= aString; + + m_sFieldName = aString; + + // get the field format key + m_xField->getPropertyValue(FIELD_STR_FORMATKEY) >>= m_nFormatKey; + + // get the field type + m_xField->getPropertyValue(FIELD_STR_TYPE) >>= nType; + } + catch ( ... ) + { + } + + if (m_nFormatKey && m_xFormatter.is()) + { + Any aValue = getNumberFormatProperty(m_xFormatter->getNumberFormatsSupplier(), m_nFormatKey, FIELD_STR_LOCALE); + DBG_ASSERT(aValue.getValueType() == ::getCppuType((const ::com::sun::star::lang::Locale*)0), "OSQLParser::PredicateTree : invalid language property !"); + + if (aValue.getValueType() == ::getCppuType((const ::com::sun::star::lang::Locale*)0)) + { + com::sun::star::lang::Locale aLocale; + aValue >>= aLocale; + *m_pIntl = International(ConvertIsoNamesToLanguage(aLocale.Language.getStr(), + aLocale.Country.getStr())); + } + } + else + *m_pIntl = m_pContext->getDefaultInternational(); + + switch (nType) + { + case DataType::DATE: + case DataType::TIME: + case DataType::TIMESTAMP: + s_pScanner->SetRule(s_pScanner->GetDATERule()); + break; + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::LONGVARCHAR: + s_pScanner->SetRule(s_pScanner->GetSTRINGRule()); + break; + default: + if (m_pIntl->GetNumDecimalSep() == ',') + s_pScanner->SetRule(s_pScanner->GetGERRule()); + else + s_pScanner->SetRule(s_pScanner->GetENGRule()); + } + + } + else + s_pScanner->SetRule(s_pScanner->GetSQLRule()); + + s_pScanner->prepareScan(rStatement, m_pContext, sal_True); + + SQLyylval.pParseNode = NULL; + // SQLyypvt = NULL; + m_pParseTree = NULL; + m_sErrorMessage.Erase(); + + // ... und den Parser anwerfen ... + if (SQLyyparse() != 0) + { + m_sFieldName.Erase(); + m_xField = NULL; + m_xFormatter = NULL; + m_nFormatKey = 0; + + if (!m_sErrorMessage.Len()) + m_sErrorMessage = s_pScanner->getErrorMessage(); + if (!m_sErrorMessage.Len()) + m_sErrorMessage = m_pContext->getErrorMessage(OParseContext::ERROR_GENERAL); + + rErrorMessage = m_sErrorMessage; + + // clear the garbage collector + while (!s_pGarbageCollector->empty()) + { + OSQLParseNode* pNode = *s_pGarbageCollector->begin(); + while (pNode->getParent()) + pNode = pNode->getParent(); + delete pNode; + } + return NULL; + } + else + { + s_pGarbageCollector->clear(); + + m_sFieldName.Erase(); + m_xField = NULL; + m_xFormatter = NULL; + m_nFormatKey = 0; + + // Das Ergebnis liefern (den Root Parse Node): + + // Stattdessen setzt die Parse-Routine jetzt den Member pParseTree + // - einfach diesen zurueckliefern: + DBG_ASSERT(m_pParseTree != NULL,"OSQLParser: Parser hat keinen ParseTree geliefert"); + return m_pParseTree; + } +} + +//----------------------------------------------------------------------------- +ByteString OSQLParser::TokenIDToStr(sal_uInt32 nTokenID, OParseContext* pContext) +{ + ByteString aStr; + if (pContext) + aStr = pContext->getIntlKeywordAscii((OParseContext::InternationalKeyCode)nTokenID); + + if (!aStr.Len()) + { + aStr = yytname[YYTRANSLATE(nTokenID)]; + if(aStr.EqualsIgnoreCaseAscii("SQL_TOKEN_",0,10)) + aStr.Erase(0,10); + } + return aStr; +} + +//----------------------------------------------------------------------------- +/*sal_uInt32 OSQLParser::StrToTokenID(const ByteString & rName) +{ + ByteString aName; + if (rName.IsAlphaNumericAscii()) + aName = rName; + else + { + aName = "'"; + aName += rName; + aName += "'"; + } + + // Gewuenschten Token-Namen suchen: + for (sal_uInt32 i = 0; i < SQLyyntoken; i++) + { + if (aName == TokenTypes[i].name) + return TokenTypes[i].token; + } + + // Nicht gefunden + return 0; +}*/ + +//----------------------------------------------------------------------------- +String OSQLParser::RuleIDToStr(sal_uInt32 nRuleID) +{ + OSL_ENSHURE(nRuleID >= (sizeof yytname/sizeof yytname[0]), "Invalid nRuleId!"); + return String::CreateFromAscii(yytname[nRuleID]); +} + +//----------------------------------------------------------------------------- +sal_uInt32 OSQLParser::StrToRuleID(const ByteString & rValue) +{ + // In yysvar nach dem angegebenen Namen suchen, den ::com::sun::star::sdbcx::Index zurueckliefern + // (oder 0, wenn nicht gefunden) + static sal_Int32 nLen = sizeof(yytname)/sizeof(yytname[0]); + for (sal_uInt32 i = YYTRANSLATE(SQL_TOKEN_INVALIDSYMBOL); i < (nLen-1); i++) + { + if (yytname && rValue == yytname[i]) + return i; + } + + // Nicht gefunden + return 0; +} + +//----------------------------------------------------------------------------- +sal_uInt32 OSQLParser::RuleID(OSQLParseNode::Rule eRule) +{ + if (!s_nRuleIDs[eRule]) + { + switch (eRule) + { + case OSQLParseNode::select_statement: + s_nRuleIDs[eRule] = StrToRuleID("select_statement"); break; + case OSQLParseNode::from_clause: + s_nRuleIDs[eRule] = StrToRuleID("from_clause"); break; + case OSQLParseNode::table_ref_commalist: + s_nRuleIDs[eRule] = StrToRuleID("table_ref_commalist"); break; + case OSQLParseNode::table_exp: + s_nRuleIDs[eRule] = StrToRuleID("table_exp"); break; + case OSQLParseNode::table_ref: + s_nRuleIDs[eRule] = StrToRuleID("table_ref"); break; + case OSQLParseNode::table_name: + s_nRuleIDs[eRule] = StrToRuleID("table_name"); break; + case OSQLParseNode::opt_column_commalist: + s_nRuleIDs[eRule] = StrToRuleID("opt_column_commalist"); break; + case OSQLParseNode::column_commalist: + s_nRuleIDs[eRule] = StrToRuleID("column_commalist"); break; + case OSQLParseNode::column_ref_commalist: + s_nRuleIDs[eRule] = StrToRuleID("column_ref_commalist"); break; + case OSQLParseNode::column_ref: + s_nRuleIDs[eRule] = StrToRuleID("column_ref"); break; + case OSQLParseNode::opt_order_by_clause: + s_nRuleIDs[eRule] = StrToRuleID("opt_order_by_clause"); break; + case OSQLParseNode::ordering_spec_commalist: + s_nRuleIDs[eRule] = StrToRuleID("ordering_spec_commalist"); break; + case OSQLParseNode::ordering_spec: + s_nRuleIDs[eRule] = StrToRuleID("ordering_spec"); break; + case OSQLParseNode::opt_asc_desc: + s_nRuleIDs[eRule] = StrToRuleID("opt_asc_desc"); break; + case OSQLParseNode::where_clause: + s_nRuleIDs[eRule] = StrToRuleID("where_clause"); break; + case OSQLParseNode::opt_where_clause: + s_nRuleIDs[eRule] = StrToRuleID("opt_where_clause"); break; + case OSQLParseNode::search_condition: + s_nRuleIDs[eRule] = StrToRuleID("search_condition"); break; + case OSQLParseNode::comparison_predicate: + s_nRuleIDs[eRule] = StrToRuleID("comparison_predicate"); break; + case OSQLParseNode::between_predicate: + s_nRuleIDs[eRule] = StrToRuleID("between_predicate"); break; + case OSQLParseNode::like_predicate: + s_nRuleIDs[eRule] = StrToRuleID("like_predicate"); break; + case OSQLParseNode::opt_escape: + s_nRuleIDs[eRule] = StrToRuleID("opt_escape"); break; + case OSQLParseNode::test_for_null: + s_nRuleIDs[eRule] = StrToRuleID("test_for_null"); break; + case OSQLParseNode::scalar_exp_commalist: + s_nRuleIDs[eRule] = StrToRuleID("scalar_exp_commalist"); break; + case OSQLParseNode::scalar_exp: + s_nRuleIDs[eRule] = StrToRuleID("scalar_exp"); break; + case OSQLParseNode::parameter_ref: + s_nRuleIDs[eRule] = StrToRuleID("parameter_ref"); break; + case OSQLParseNode::parameter: + s_nRuleIDs[eRule] = StrToRuleID("parameter"); break; + case OSQLParseNode::general_set_fct: + s_nRuleIDs[eRule] = StrToRuleID("general_set_fct"); break; + case OSQLParseNode::range_variable: + s_nRuleIDs[eRule] = StrToRuleID("range_variable"); break; + case OSQLParseNode::column: + s_nRuleIDs[eRule] = StrToRuleID("column"); break; + case OSQLParseNode::delete_statement_positioned: + s_nRuleIDs[eRule] = StrToRuleID("delete_statement_positioned"); break; + case OSQLParseNode::delete_statement_searched: + s_nRuleIDs[eRule] = StrToRuleID("delete_statement_searched"); break; + case OSQLParseNode::update_statement_positioned: + s_nRuleIDs[eRule] = StrToRuleID("update_statement_positioned"); break; + case OSQLParseNode::update_statement_searched: + s_nRuleIDs[eRule] = StrToRuleID("update_statement_searched"); break; + case OSQLParseNode::assignment_commalist: + s_nRuleIDs[eRule] = StrToRuleID("assignment_commalist"); break; + case OSQLParseNode::assignment: + s_nRuleIDs[eRule] = StrToRuleID("assignment"); break; + case OSQLParseNode::values_or_query_spec: + s_nRuleIDs[eRule] = StrToRuleID("values_or_query_spec"); break; + case OSQLParseNode::insert_statement: + s_nRuleIDs[eRule] = StrToRuleID("insert_statement"); break; + case OSQLParseNode::insert_atom_commalist: + s_nRuleIDs[eRule] = StrToRuleID("insert_atom_commalist"); break; + case OSQLParseNode::insert_atom: + s_nRuleIDs[eRule] = StrToRuleID("insert_atom"); break; + case OSQLParseNode::predicate_check: + s_nRuleIDs[eRule] = StrToRuleID("predicate_check"); break; + case OSQLParseNode::qualified_join: + s_nRuleIDs[eRule] = StrToRuleID("qualified_join"); break; + case OSQLParseNode::cross_union: + s_nRuleIDs[eRule] = StrToRuleID("cross_union"); break; + case OSQLParseNode::select_sublist: + s_nRuleIDs[eRule] = StrToRuleID("select_sublist"); break; + case OSQLParseNode::derived_column: + s_nRuleIDs[eRule] = StrToRuleID("derived_column"); break; + case OSQLParseNode::column_val: + s_nRuleIDs[eRule] = StrToRuleID("column_val"); break; + case OSQLParseNode::set_fct_spec: + s_nRuleIDs[eRule] = StrToRuleID("set_fct_spec"); break; + case OSQLParseNode::boolean_term: + s_nRuleIDs[eRule] = StrToRuleID("boolean_term"); break; + case OSQLParseNode::boolean_primary: + s_nRuleIDs[eRule] = StrToRuleID("boolean_primary"); break; + case OSQLParseNode::num_value_exp: + s_nRuleIDs[eRule] = StrToRuleID("num_value_exp"); break; + case OSQLParseNode::join_type: + s_nRuleIDs[eRule] = StrToRuleID("join_type"); break; + case OSQLParseNode::position_exp: + s_nRuleIDs[eRule] = StrToRuleID("position_exp"); break; + case OSQLParseNode::extract_exp: + s_nRuleIDs[eRule] = StrToRuleID("extract_exp"); break; + case OSQLParseNode::length_exp: + s_nRuleIDs[eRule] = StrToRuleID("length_exp"); break; + case OSQLParseNode::char_value_fct: + s_nRuleIDs[eRule] = StrToRuleID("char_value_fct"); break; + case OSQLParseNode::odbc_call_spec: + s_nRuleIDs[eRule] = StrToRuleID("odbc_call_spec"); break; + case OSQLParseNode::in_predicate: + s_nRuleIDs[eRule] = StrToRuleID("in_predicate"); break; + case OSQLParseNode::existence_test: + s_nRuleIDs[eRule] = StrToRuleID("existence_test"); break; + case OSQLParseNode::unique_test: + s_nRuleIDs[eRule] = StrToRuleID("unique_test"); break; + case OSQLParseNode::all_or_any_predicate: + s_nRuleIDs[eRule] = StrToRuleID("all_or_any_predicate"); break; + case OSQLParseNode::named_columns_join: + s_nRuleIDs[eRule] = StrToRuleID("named_columns_join"); break; + case OSQLParseNode::join_condition: + s_nRuleIDs[eRule] = StrToRuleID("join_condition"); break; + case OSQLParseNode::joined_table: + s_nRuleIDs[eRule] = StrToRuleID("joined_table"); break; + case OSQLParseNode::boolean_factor: + s_nRuleIDs[eRule] = StrToRuleID("boolean_factor"); break; + case OSQLParseNode::not: + s_nRuleIDs[eRule] = StrToRuleID("not"); break; + case OSQLParseNode::boolean_test: + s_nRuleIDs[eRule] = StrToRuleID("boolean_test"); break; + case OSQLParseNode::manipulative_statement: + s_nRuleIDs[eRule] = StrToRuleID("manipulative_statement"); break; + case OSQLParseNode::subquery: + s_nRuleIDs[eRule] = StrToRuleID("subquery"); break; + case OSQLParseNode::value_exp_commalist: + s_nRuleIDs[eRule] = StrToRuleID("value_exp_commalist"); break; + case OSQLParseNode::odbc_fct_spec: + s_nRuleIDs[eRule] = StrToRuleID("odbc_fct_spec"); break; + case OSQLParseNode::union_statement: + s_nRuleIDs[eRule] = StrToRuleID("union_statement"); break; + case OSQLParseNode::outer_join_type: + s_nRuleIDs[eRule] = StrToRuleID("outer_join_type"); break; + case OSQLParseNode::char_value_exp: + s_nRuleIDs[eRule] = StrToRuleID("char_value_exp"); break; + case OSQLParseNode::term: + s_nRuleIDs[eRule] = StrToRuleID("term"); break; + case OSQLParseNode::value_exp_primary: + s_nRuleIDs[eRule] = StrToRuleID("value_exp_primary"); break; + case OSQLParseNode::value_exp: + s_nRuleIDs[eRule] = StrToRuleID("value_exp"); break; + default: + DBG_ERROR("interner Fehler: Regel nicht bekannt, in OSQLParser::RuleID nachtragen!"); + } + } + return s_nRuleIDs[(sal_uInt16)eRule]; +} + +//----------------------------------------------------------------------------- +sal_Int16 OSQLParser::buildNode(OSQLParseNode*& pAppend,OSQLParseNode* pLiteral,OSQLParseNode*& pCompare) +{ + OSQLParseNode* pColumnRef = new OSQLInternalNode(aEmptyString, SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::column_ref)); + pColumnRef->append(new OSQLInternalNode(m_sFieldName,SQL_NODE_NAME)); + OSQLParseNode* pComp = new OSQLInternalNode(aEmptyString, SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::comparison_predicate)); + pComp->append(pColumnRef); + pComp->append(pCompare); + pComp->append(pLiteral); + pAppend->append(pComp); + return 1; +} + +//----------------------------------------------------------------------------- +sal_Int16 OSQLParser::buildNode_STR_NUM(OSQLParseNode*& pAppend,OSQLParseNode*& pLiteral,OSQLParseNode*& pCompare) +{ + OSQLParseNode* pColumnRef = new OSQLInternalNode(aEmptyString, SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::column_ref)); + pColumnRef->append(new OSQLInternalNode(m_sFieldName,SQL_NODE_NAME)); + OSQLParseNode* pComp = new OSQLInternalNode(aEmptyString, SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::comparison_predicate)); + pComp->append(pColumnRef); + pComp->append(pCompare); + + if (m_nFormatKey) + { + sal_Int16 nScale = 0; + try + { + Any aValue = getNumberFormatProperty(m_xFormatter->getNumberFormatsSupplier(), + m_nFormatKey, rtl::OUString::createFromAscii("Decimals")); + aValue >>= nScale; + } + catch ( ... ) + { + } + + int nErrno=0; + double dValue = SolarMath::StringToDouble(pLiteral->getTokenValue().GetBuffer(), *m_pIntl, nErrno); + String aValue; + SolarMath::DoubleToString(aValue, dValue, 'F', nScale, m_pIntl->GetNumDecimalSep(), sal_True); + pComp->append(new OSQLInternalNode(aValue,SQL_NODE_STRING)); + } + else + pComp->append(new OSQLInternalNode(pLiteral->getTokenValue(),SQL_NODE_STRING)); + + pAppend->append(pComp); + + delete pLiteral; + pLiteral = NULL; + + return 1; +} + +//----------------------------------------------------------------------------- +sal_Int16 OSQLParser::buildNode_Date(const double& fValue, sal_Int16 nType, OSQLParseNode*& pAppend,OSQLParseNode* pLiteral,OSQLParseNode*& pCompare) +{ + OSQLParseNode* pColumnRef = new OSQLInternalNode(aEmptyString, SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::column_ref)); + pColumnRef->append(new OSQLInternalNode(m_sFieldName,SQL_NODE_NAME)); + OSQLParseNode* pComp = new OSQLInternalNode(aEmptyString, SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::comparison_predicate)); + pComp->append(pColumnRef); + pComp->append(pCompare); + + OSQLParseNode* pNewNode = new OSQLInternalNode(aEmptyString, SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::set_fct_spec)); + pNewNode->append(new OSQLInternalNode(String::CreateFromAscii("{"), SQL_NODE_PUNCTUATION)); + OSQLParseNode* pDateNode = new OSQLInternalNode(aEmptyString, SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::odbc_fct_spec)); + pNewNode->append(pDateNode); + pNewNode->append(new OSQLInternalNode(String::CreateFromAscii("}"), SQL_NODE_PUNCTUATION)); + + switch (nType) + { + case DataType::DATE: + { + Date aDate = ToDate(m_xFormatter->getNumberFormatsSupplier(), fValue); + String aString = ToDateString(aDate); + pDateNode->append(new OSQLInternalNode(aEmptyString, SQL_NODE_KEYWORD, SQL_TOKEN_D)); + pDateNode->append(new OSQLInternalNode(aString, SQL_NODE_STRING)); + break; + } + case DataType::TIME: + { + Time aTime = ToTime(fValue); + String aString = ToTimeString(aTime); + pDateNode->append(new OSQLInternalNode(aEmptyString, SQL_NODE_KEYWORD, SQL_TOKEN_T)); + pDateNode->append(new OSQLInternalNode(aString, SQL_NODE_STRING)); + break; + } + case DataType::TIMESTAMP: + { + DateTime aDateTime = ToDateTime(m_xFormatter->getNumberFormatsSupplier(), fValue); + if (aDateTime.GetMSFromTime() / fMilliSecondsPerDay) + { + String aString = ToDateTimeString(aDateTime); + pDateNode->append(new OSQLInternalNode(aEmptyString, SQL_NODE_KEYWORD, SQL_TOKEN_TS)); + pDateNode->append(new OSQLInternalNode(aString, SQL_NODE_STRING)); + } + else + { + pDateNode->append(new OSQLInternalNode(aEmptyString, SQL_NODE_KEYWORD, SQL_TOKEN_D)); + pDateNode->append(new OSQLInternalNode(ToDateString(aDateTime), SQL_NODE_STRING)); + } + break; + } + } + + pComp->append(pNewNode); + pAppend->append(pComp); + + delete pLiteral; + pLiteral = NULL; + + return 1; +} + +//----------------------------------------------------------------------------- +sal_Int16 OSQLParser::buildLikeRule(OSQLParseNode*& pAppend, OSQLParseNode*& pLiteral, const OSQLParseNode* pEscape) +{ + sal_Int16 nErg = 0; + sal_Int32 nType = 0; + + if (!m_xField.is()) + return nErg; + try + { + Any aValue; + { + aValue = m_xField->getPropertyValue(FIELD_STR_TYPE); + aValue >>= nType; + } + } + catch ( ... ) + { + return nErg; + } + + switch (nType) + { + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::LONGVARCHAR: + if(pLiteral->isRule()) + { + pAppend->append(pLiteral); + nErg = 1; + } + else + { + switch(pLiteral->getNodeType()) + { + case SQL_NODE_STRING: + pLiteral->m_aNodeValue = ConvertLikeToken(pLiteral, pEscape, sal_False); + pAppend->append(pLiteral); + nErg = 1; + break; + case SQL_NODE_APPROXNUM: + if (m_xFormatter.is() && m_nFormatKey) + { + sal_Int16 nScale = 0; + try + { + Any aValue = getNumberFormatProperty(m_xFormatter->getNumberFormatsSupplier(), + m_nFormatKey, rtl::OUString::createFromAscii("Decimals")); + aValue >>= nScale; + } + catch ( ... ) + { + } + + int nErrno=0; + String aValue; + double dValue = SolarMath::StringToDouble(pLiteral->getTokenValue().GetBuffer(), OParseContext::getDefaultInternational(), nErrno); + SolarMath::DoubleToString(aValue, dValue, 'F', nScale, '.', sal_True); + pAppend->append(new OSQLInternalNode(aValue,SQL_NODE_STRING)); + } + else + pAppend->append(new OSQLInternalNode(pLiteral->getTokenValue(),SQL_NODE_STRING)); + + delete pLiteral; + nErg = 1; + break; + default: + { + m_sErrorMessage = m_pContext->getErrorMessage(OParseContext::ERROR_VALUE_NO_LIKE); + m_sErrorMessage.SearchAndReplace(String::CreateFromAscii("#1"),pLiteral->getTokenValue()); + } + } + } + break; + default: + m_sErrorMessage = m_pContext->getErrorMessage(OParseContext::ERROR_FIELD_NO_LIKE); + } + return nErg; +} +//----------------------------------------------------------------------------- +sal_Int16 OSQLParser::buildStringNodes(OSQLParseNode*& pLiteral) +{ + if(!pLiteral) + return 1; + + if(SQL_ISRULE(pLiteral,set_fct_spec) || SQL_ISRULE(pLiteral,general_set_fct) || SQL_ISRULE(pLiteral,column_ref) + || SQL_ISRULE(pLiteral,subquery)) + return 1; // here I have a function that I can't transform into a string + + if(pLiteral->getNodeType() == SQL_NODE_INTNUM || pLiteral->getNodeType() == SQL_NODE_APPROXNUM || pLiteral->getNodeType() == SQL_NODE_ACCESS_DATE) + { + OSQLParseNode* pParent = pLiteral->getParent(); + + OSQLParseNode* pNewNode = new OSQLInternalNode(pLiteral->getTokenValue(), SQL_NODE_STRING); + pParent->replace(pLiteral, pNewNode); + delete pLiteral; + pLiteral = NULL; + return 1; + } + + for(sal_uInt32 i=0;i<pLiteral->count();++i) + { + OSQLParseNode* pChild = pLiteral->getChild(i); + buildStringNodes(pChild); + } + if(SQL_ISRULE(pLiteral,term) || SQL_ISRULE(pLiteral,value_exp_primary)) + { + m_sErrorMessage = m_pContext->getErrorMessage(OParseContext::ERROR_INVALID_COMPARE); + return 0; + } + return 1; +} +//----------------------------------------------------------------------------- +sal_Int16 OSQLParser::buildComparsionRule(OSQLParseNode*& pAppend,OSQLParseNode* pLiteral) +{ + OSQLParseNode* pComp = new OSQLInternalNode(String('='), SQL_NODE_EQUAL); + return buildComparsionRule(pAppend,pLiteral,pComp); +} + +//----------------------------------------------------------------------------- +sal_Int16 OSQLParser::buildComparsionRule(OSQLParseNode*& pAppend,OSQLParseNode* pLiteral,OSQLParseNode*& pCompare) +{ + sal_Int16 nErg = 0; + if (m_xField.is()) + { + sal_Int32 nType = 0; + try + { + Any aValue; + { + aValue = m_xField->getPropertyValue(FIELD_STR_TYPE); + aValue >>= nType; + } + } + catch ( ... ) + { + return nErg; + } + + if (pLiteral->isRule() && !SQL_ISRULE(pLiteral,value_exp)) + { + switch(nType) + { + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::LONGVARCHAR: + if(!SQL_ISRULE(pLiteral,char_value_exp) && !buildStringNodes(pLiteral)) + break; + default: + nErg = buildNode(pAppend,pLiteral,pCompare); + } + } + else + { + switch(pLiteral->getNodeType()) + { + case SQL_NODE_STRING: + switch(nType) + { + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::LONGVARCHAR: + nErg = buildNode(pAppend,pLiteral,pCompare); + break; + case DataType::DATE: + case DataType::TIME: + case DataType::TIMESTAMP: + if (m_xFormatter.is()) + { + try + { + // do we have a date + double fValue = m_xFormatter->convertStringToNumber(m_nFormatKey, pLiteral->getTokenValue().GetBuffer()); + nErg = buildNode_Date(fValue, nType, pAppend,pLiteral,pCompare); + } + catch ( ... ) + { + try + { + Reference< ::com::sun::star::util::XNumberFormatsSupplier > xFormatSup = m_xFormatter->getNumberFormatsSupplier(); + Reference< ::com::sun::star::util::XNumberFormatTypes > xFormatTypes(xFormatSup->getNumberFormats(),UNO_QUERY); + if (xFormatTypes.is()) + { + String sLanguage, sCountry; + ConvertLanguageToIsoNames(m_pIntl->GetLanguage(), sLanguage, sCountry); + ::com::sun::star::lang::Locale aLocale(sLanguage.GetBuffer(), + sCountry.GetBuffer(), + rtl::OUString()); + + double fValue = m_xFormatter->convertStringToNumber( + xFormatTypes->getStandardFormat(::com::sun::star::util::NumberFormat::DATE, aLocale), + pLiteral->getTokenValue().GetBuffer()); + nErg = buildNode_Date(fValue, nType, pAppend,pLiteral,pCompare); + } + else + { + nErg = -1; + m_sErrorMessage = m_pContext->getErrorMessage(OParseContext::ERROR_INVALID_DATE_COMPARE); + } + + } + catch ( ... ) + { + nErg = -1; + m_sErrorMessage = m_pContext->getErrorMessage(OParseContext::ERROR_INVALID_DATE_COMPARE); + } + } + } + else + nErg = buildNode(pAppend,pLiteral,pCompare); + + break; + default: + m_sErrorMessage = m_pContext->getErrorMessage(OParseContext::ERROR_INVALID_DATE_COMPARE); + } + break; + case SQL_NODE_ACCESS_DATE: + switch(nType) + { + case DataType::DATE: + case DataType::TIME: + case DataType::TIMESTAMP: + if (m_xFormatter.is()) + { + try + { + // do we have a date + double fValue = m_xFormatter->convertStringToNumber(m_nFormatKey, pLiteral->getTokenValue().GetBuffer()); + nErg = buildNode_Date(fValue, nType, pAppend,pLiteral,pCompare); + } + catch ( ... ) + { + try + { + Reference< ::com::sun::star::util::XNumberFormatsSupplier > xFormatSup = m_xFormatter->getNumberFormatsSupplier(); + Reference< ::com::sun::star::util::XNumberFormatTypes > xFormatTypes(xFormatSup->getNumberFormats(),UNO_QUERY); + if (xFormatTypes.is()) + { + String sLanguage, sCountry; + ConvertLanguageToIsoNames(m_pIntl->GetLanguage(), sLanguage, sCountry); + ::com::sun::star::lang::Locale aLocale(sLanguage.GetBuffer(), + sCountry.GetBuffer(), + rtl::OUString()); + + double fValue = m_xFormatter->convertStringToNumber( + xFormatTypes->getStandardFormat(::com::sun::star::util::NumberFormat::DATE, aLocale), + pLiteral->getTokenValue().GetBuffer()); + nErg = buildNode_Date(fValue, nType, pAppend,pLiteral,pCompare); + } + else + { + nErg = -1; + m_sErrorMessage = m_pContext->getErrorMessage(OParseContext::ERROR_INVALID_DATE_COMPARE); + } + } + catch ( ... ) + { + nErg = -1; + m_sErrorMessage = m_pContext->getErrorMessage(OParseContext::ERROR_INVALID_DATE_COMPARE); + } + } + } + else + { + nErg = -1; + m_sErrorMessage = m_pContext->getErrorMessage(OParseContext::ERROR_INVALID_DATE_COMPARE); + } + break; + default: + m_sErrorMessage = m_pContext->getErrorMessage(OParseContext::ERROR_INVALID_DATE_COMPARE); + } + break; + case SQL_NODE_INTNUM: + switch(nType) + { + case DataType::BIT: + case DataType::DECIMAL: + case DataType::NUMERIC: + case DataType::TINYINT: + case DataType::SMALLINT: + case DataType::INTEGER: + case DataType::BIGINT: + case DataType::REAL: + case DataType::DOUBLE: + // kill thousand seperators if any + if (m_pIntl->GetNumDecimalSep() == ',' ) + { + pLiteral->m_aNodeValue.SearchAndReplaceAll('.', String()); + // and replace decimal + pLiteral->m_aNodeValue.SearchAndReplaceAll(',', '.'); + } + else + pLiteral->m_aNodeValue.SearchAndReplaceAll(',', String()); + nErg = buildNode(pAppend,pLiteral,pCompare); + break; + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::LONGVARCHAR: + nErg = buildNode_STR_NUM(pAppend,pLiteral,pCompare); + break; + default: + m_sErrorMessage = m_pContext->getErrorMessage(OParseContext::ERROR_INVALID_INT_COMPARE); + } + break; + case SQL_NODE_APPROXNUM: + switch(nType) + { + case DataType::DECIMAL: + case DataType::NUMERIC: + case DataType::REAL: + case DataType::DOUBLE: + if (inPredicateCheck()) + { + // kill thousand seperators if any + if (m_pIntl->GetNumDecimalSep() == ',' ) + { + pLiteral->m_aNodeValue.SearchAndReplaceAll('.', String()); + // and replace decimal + pLiteral->m_aNodeValue.SearchAndReplaceAll(',', '.'); + } + else + pLiteral->m_aNodeValue.SearchAndReplaceAll(',', String()); + } + nErg = buildNode(pAppend,pLiteral,pCompare); + break; + case DataType::CHAR: + case DataType::VARCHAR: + case DataType::LONGVARCHAR: + nErg = buildNode_STR_NUM(pAppend,pLiteral,pCompare); + break; + case DataType::INTEGER: + default: + m_sErrorMessage = m_pContext->getErrorMessage(OParseContext::ERROR_INVALID_REAL_COMPARE); + } + break; + } + } + if (!nErg) + --nErg; + } + if (!pCompare->getParent()) // I have no parent so I was not used and I must die :-) + delete pCompare; + return nErg; +} + +//----------------------------------------------------------------------------- +void OSQLParser::reduceLiteral(OSQLParseNode*& pLiteral, sal_Bool bAppendBlank) +{ + DBG_ASSERT(pLiteral->isRule(), "This is no ::com::sun::star::chaos::Rule"); + DBG_ASSERT(pLiteral->count() == 2, "OSQLParser::ReduceLiteral() Invalid count"); + OSQLParseNode* pTemp = pLiteral; + String aValue; + if (bAppendBlank) + { + ((aValue = pLiteral->getChild(0)->getTokenValue()) += String(' ')) += + pLiteral->getChild(1)->getTokenValue(); + } + else + (aValue = pLiteral->getChild(0)->getTokenValue()) += + pLiteral->getChild(1)->getTokenValue(); + + pLiteral = new OSQLInternalNode(aValue,SQL_NODE_STRING); + delete pTemp; +} +// ------------------------------------------------------------------------- +void OSQLParser::error(char *fmt) +{ + if(!m_sErrorMessage.Len()) + { + m_sErrorMessage = m_pContext->getErrorMessage(OParseContext::ERROR_GENERAL); + m_sErrorMessage.AppendAscii(": "); + m_sErrorMessage += m_pContext->getErrorMessage(OParseContext::ERROR_GENERAL_HINT); + m_sErrorMessage.SearchAndReplaceAscii("#",String::CreateFromAscii(fmt)); + } +} +// ------------------------------------------------------------------------- +int OSQLParser::SQLlex() +{ + return s_pScanner->SQLlex(); +} +/*------------------------------------------------------------------------ + + $Log: not supported by cvs2svn $ + Revision 1.1 2000/07/25 10:39:29 oj + new revision + + Revision 1.0 21.07.2000 12:27:34 oj +------------------------------------------------------------------------*/ + diff --git a/connectivity/source/parse/sqlflex.l b/connectivity/source/parse/sqlflex.l new file mode 100644 index 000000000000..446ec2454aea --- /dev/null +++ b/connectivity/source/parse/sqlflex.l @@ -0,0 +1,592 @@ +%{ + +//-------------------------------------------------------------------------- +// +// $Header: /zpool/svn/migration/cvs_rep_09_09_08/code/connectivity/source/parse/sqlflex.l,v 1.1.1.1 2000-09-18 16:14:28 hr Exp $ +// +// Copyright 2000 Sun Microsystems, Inc. All Rights Reserved. +// +// First creation: +// OJ +// +// Last change: +// $Author: hr $ $Date: 2000-09-18 16:14:28 $ $Revision: 1.1.1.1 $ +// +// Description: +// +// +//-------------------------------------------------------------------------- + +#define YY_EXIT 1 // YY_FATAL will not halt the application + +#ifndef _CSTDARG_ +#include <cstdarg> // std::va_list +#endif + +#ifndef _INC_STRING +#include <string.h> +#endif +#ifndef _SOLAR_H +#include <tools/solar.h> +#endif + +#ifndef _CONNECTIVITY_SQLINTERNALNODE_HXX +#include "internalnode.hxx" +#endif + +#ifndef _CONNECTIVITY_SQLYACC_HXX +#define _CONNECTIVITY_SQLYACC_HXX + +#ifndef SQLYYDEBUG +#define SQLYYDEBUG 1 +#endif + +#include "connectivity/sqlbison.hxx" +#endif +#ifndef _CONNECTIVITY_SQLSCAN_HXX +#include "sqlscan.hxx" +#endif +#ifndef _OSL_DIAGNOSE_H_ +#include <osl/diagnose.h> +#endif +#ifndef _CONNECTIVITY_SQLPARSE_HXX +#include <connectivity/sqlparse.hxx> +#endif +using namespace connectivity; + +//============================================================================= +// +// Erzeugung der Blaetter fuer die Token +// Blaetter werden generell vom Lexer erzeugt + +static String aEmptyString; + +static int gatherString(int delim, int nTyp); +static int gatherName(const char*); +static int gatherNamePre(const char* ); +// has to be set before the parser starts +OSQLScanner* xxx_pGLOBAL_SQLSCAN = NULL; + +#define SQL_NEW_NODE(text, token) \ + SQLyylval.pParseNode = new OSQLInternalNode(text, token); + +#define SQL_NEW_KEYWORD(token) \ + SQLyylval.pParseNode = new OSQLInternalNode(aEmptyString, SQL_NODE_KEYWORD, (token)); + +#define SQL_NEW_NAME SQL_NEW_NODE(String::CreateFromAscii(SQLyytext), SQL_NODE_NAME) +#define SQL_NEW_INTNUM SQL_NEW_NODE(String::CreateFromAscii(SQLyytext), SQL_NODE_INTNUM) +#define SQL_NEW_APPROXNUM SQL_NEW_NODE(String::CreateFromAscii(SQLyytext), SQL_NODE_APPROXNUM) +#define SQL_NEW_STRING SQL_NEW_NODE(String::CreateFromAscii(SQLyytext), SQL_NODE_STRING) +#define SQL_NEW_COMPARISON SQL_NEW_NODE(String::CreateFromAscii(SQLyytext), SQL_NODE_COMPARISON) +#define SQL_NEW_AMMSC SQL_NEW_NODE(String::CreateFromAscii(SQLyytext), SQL_NODE_AMMSC) +#define SQL_NEW_DATE SQL_NEW_NODE(String::CreateFromAscii(SQLyytext), SQL_NODE_ACCESS_DATE) + +#define YY_INPUT(buf,result,max_size) \ +{ \ + buf[0] = xxx_pGLOBAL_SQLSCAN->SQLyygetc(); \ + result = buf[0] != -1; \ +} + +#define YY_FATAL_ERROR(msg) \ +{ \ + xxx_pGLOBAL_SQLSCAN->SQLyyerror(msg); \ +} + +// +//============================================================================= + +%} +%e 2500 +%n 2900 +%p 8500 + +%s SQL +%s PREDICATE_ENG +%s PREDICATE_GER +%s DATE +%s STRING + +%option noyywrap +%option never-interactive +%% + +[Aa][Ll][Ll] {SQL_NEW_KEYWORD(SQL_TOKEN_ALL); return SQL_TOKEN_ALL; } +[Aa][Ll][Tt][Ee][Rr] {SQL_NEW_KEYWORD(SQL_TOKEN_ALTER); return SQL_TOKEN_ALTER; } +[Aa][Nn][Dd] {SQL_NEW_KEYWORD(SQL_TOKEN_AND); return SQL_TOKEN_AND; } +[Aa][Nn][Yy] {SQL_NEW_KEYWORD(SQL_TOKEN_ANY); return SQL_TOKEN_ANY; } +[Aa][Ss] {SQL_NEW_KEYWORD(SQL_TOKEN_AS); return SQL_TOKEN_AS; } +[Aa][Ss][Cc] {SQL_NEW_KEYWORD(SQL_TOKEN_ASC); return SQL_TOKEN_ASC; } +[Aa][Tt] {SQL_NEW_KEYWORD(SQL_TOKEN_AT); return SQL_TOKEN_AT; } +[Aa][Uu][Tt][Hh][Oo][Rr][Ii][Zz][Aa][Tt][Ii][Oo][Nn] {SQL_NEW_KEYWORD(SQL_TOKEN_AUTHORIZATION); return SQL_TOKEN_AUTHORIZATION; } +[Aa][Vv][Gg] {SQL_NEW_KEYWORD(SQL_TOKEN_AVG); return SQL_TOKEN_AVG; } + +[Bb][Ee][Tt][Ww][Ee][Ee][Nn] {SQL_NEW_KEYWORD(SQL_TOKEN_BETWEEN); return SQL_TOKEN_BETWEEN; } +[Bb][Ii][Tt] {SQL_NEW_KEYWORD(SQL_TOKEN_BIT); return SQL_TOKEN_BIT; } +[Bb][Ii][Tt]_[Ll][Ee][Nn][Gg][Tt][Hh] {SQL_NEW_KEYWORD(SQL_TOKEN_BIT_LENGTH); return SQL_TOKEN_BIT_LENGTH; } +[Bb][Oo][Tt][Hh] {SQL_NEW_KEYWORD(SQL_TOKEN_BOTH); return SQL_TOKEN_BOTH; } +[Bb][Yy] {SQL_NEW_KEYWORD(SQL_TOKEN_BY); return SQL_TOKEN_BY; } + +[Cc][Aa][Ll][Ll] {SQL_NEW_KEYWORD(SQL_TOKEN_CALL); return SQL_TOKEN_CALL; } +[Cc][Aa][Ss][Tt] {SQL_NEW_KEYWORD(SQL_TOKEN_CAST); return SQL_TOKEN_CAST; } +[Cc][Hh][Aa][Rr]([Aa][Cc][Tt][Ee][Rr])? {SQL_NEW_KEYWORD(SQL_TOKEN_CHARACTER); return SQL_TOKEN_CHARACTER; } +[Cc][Hh][Aa][Rr]([Aa][Cc][Tt][Ee][Rr])?_[Ll][Ee][Nn][Gg][Tt][Hh] {SQL_NEW_KEYWORD(SQL_TOKEN_CHAR_LENGTH); return SQL_TOKEN_CHAR_LENGTH; } +[Cc][Hh][Ee][Cc][Kk] {SQL_NEW_KEYWORD(SQL_TOKEN_CHECK); return SQL_TOKEN_CHECK; } +[Cc][Oo][Ll][Ll][Aa][Tt][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_COLLATE); return SQL_TOKEN_COLLATE; } +[Cc][Oo][Mm][Mm][Ii][Tt] {SQL_NEW_KEYWORD(SQL_TOKEN_COMMIT); return SQL_TOKEN_COMMIT; } +[Cc][Oo][Nn][Tt][Ii][Nn][Uu][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_CONTINUE); return SQL_TOKEN_CONTINUE; } +[Cc][Oo][Nn][Vv][Ee][Rr][Tt] {SQL_NEW_KEYWORD(SQL_TOKEN_CONVERT); return SQL_TOKEN_CONVERT; } +[Cc][Oo][Uu][Nn][Tt] {SQL_NEW_KEYWORD(SQL_TOKEN_COUNT); return SQL_TOKEN_COUNT; } +[Cc][Rr][Ee][Aa][Tt][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_CREATE); return SQL_TOKEN_CREATE; } +[Cc][Rr][Oo][Ss][Ss] {SQL_NEW_KEYWORD(SQL_TOKEN_CROSS); return SQL_TOKEN_CROSS; } +[Cc][Uu][Rr][Rr][Ee][Nn][Tt] {SQL_NEW_KEYWORD(SQL_TOKEN_CURRENT); return SQL_TOKEN_CURRENT; } +[Cc][Uu][Rr][Rr][Ee][Nn][Tt]_[Dd][Aa][Tt][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_CURRENT_DATE); return SQL_TOKEN_CURRENT_DATE; } +[Cc][Uu][Rr][Rr][Ee][Nn][Tt]_[Tt][Ii][Mm][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_CURRENT_TIME); return SQL_TOKEN_CURRENT_TIME; } +[Cc][Uu][Rr][Rr][Ee][Nn][Tt]_[Tt][Ii][Mm][Ee][Ss][Tt][Aa][Mm][Pp] {SQL_NEW_KEYWORD(SQL_TOKEN_CURRENT_TIMESTAMP); return SQL_TOKEN_CURRENT_TIMESTAMP; } +[Cc][Uu][Rr][Ss][Oo][Rr] {SQL_NEW_KEYWORD(SQL_TOKEN_CURSOR); return SQL_TOKEN_CURSOR; } + +[Dd] {SQL_NEW_KEYWORD(SQL_TOKEN_D); return SQL_TOKEN_D; } +[Dd][Aa][Tt][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_DATE); return SQL_TOKEN_DATE; } +[Dd][Aa][Yy] {SQL_NEW_KEYWORD(SQL_TOKEN_DAY); return SQL_TOKEN_DAY; } +[Dd][Ee][Cc] {SQL_NEW_KEYWORD(SQL_TOKEN_DEC); return SQL_TOKEN_DEC; } +[Dd][Ee][Cc][Ii][Mm][Aa][Ll] {SQL_NEW_KEYWORD(SQL_TOKEN_DECIMAL); return SQL_TOKEN_DECIMAL; } +[Dd][Ee][Cc][Ll][Aa][Rr][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_DECLARE); return SQL_TOKEN_DECLARE; } +[Dd][Ee][Ff][Aa][Uu][Ll][Tt] {SQL_NEW_KEYWORD(SQL_TOKEN_DEFAULT); return SQL_TOKEN_DEFAULT; } +[Dd][Ee][Ll][Ee][Tt][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_DELETE); return SQL_TOKEN_DELETE; } +[Dd][Ee][Ss][Cc] {SQL_NEW_KEYWORD(SQL_TOKEN_DESC); return SQL_TOKEN_DESC; } +[Dd][Ii][Ss][Tt][Ii][Nn][Cc][Tt] {SQL_NEW_KEYWORD(SQL_TOKEN_DISTINCT); return SQL_TOKEN_DISTINCT; } +[Dd][Oo][Uu][Bb][Ll][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_DOUBLE); return SQL_TOKEN_DOUBLE; } +[Dd][Rr][Oo][Pp] {SQL_NEW_KEYWORD(SQL_TOKEN_DROP); return SQL_TOKEN_DROP; } + +[Ee][Ss][Cc][Aa][Pp][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_ESCAPE); return SQL_TOKEN_ESCAPE; } +[Ee][Xx][Cc][Ee][Pp][Tt] {SQL_NEW_KEYWORD(SQL_TOKEN_EXCEPT); return SQL_TOKEN_EXCEPT; } +[Ee][Xx][Ii][Ss][Tt][Ss] {SQL_NEW_KEYWORD(SQL_TOKEN_EXISTS); return SQL_TOKEN_EXISTS; } +[Ee][Xx][Tt][Rr][Aa][Cc][Tt] {SQL_NEW_KEYWORD(SQL_TOKEN_EXTRACT); return SQL_TOKEN_EXTRACT; } + +[Ff][Aa][Ll][Ss][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_FALSE); return SQL_TOKEN_FALSE; } +[Ff][Ee][Tt][Cc][Hh] {SQL_NEW_KEYWORD(SQL_TOKEN_FETCH); return SQL_TOKEN_FETCH; } +[Ff][Ll][Oo][Aa][Tt] {SQL_NEW_KEYWORD(SQL_TOKEN_FLOAT); return SQL_TOKEN_FLOAT; } +[Ff][Nn] {SQL_NEW_KEYWORD(SQL_TOKEN_FN); return SQL_TOKEN_FN; } +[Ff][Oo][Rr] {SQL_NEW_KEYWORD(SQL_TOKEN_FOR); return SQL_TOKEN_FOR; } +[Ff][Oo][Rr][Ee][Ii][Gg][Nn] {SQL_NEW_KEYWORD(SQL_TOKEN_FOREIGN); return SQL_TOKEN_FOREIGN; } +[Ff][Oo][Uu][Nn][Dd] {SQL_NEW_KEYWORD(SQL_TOKEN_FOUND); return SQL_TOKEN_FOUND; } +[Ff][Rr][Oo][Mm] {SQL_NEW_KEYWORD(SQL_TOKEN_FROM); return SQL_TOKEN_FROM; } +[Ff][Uu][Ll][Ll] {SQL_NEW_KEYWORD(SQL_TOKEN_FULL); return SQL_TOKEN_FULL; } + +[Gg][Rr][Aa][Nn][Tt] {SQL_NEW_KEYWORD(SQL_TOKEN_GRANT); return SQL_TOKEN_GRANT; } +[Gg][Rr][Oo][Uu][Pp] {SQL_NEW_KEYWORD(SQL_TOKEN_GROUP); return SQL_TOKEN_GROUP; } + +[Hh][Aa][Vv][Ii][Nn][Gg] {SQL_NEW_KEYWORD(SQL_TOKEN_HAVING); return SQL_TOKEN_HAVING; } +[Hh][Oo][Uu][Rr] {SQL_NEW_KEYWORD(SQL_TOKEN_HOUR); return SQL_TOKEN_HOUR; } + +[Ii][Nn] {SQL_NEW_KEYWORD(SQL_TOKEN_IN); return SQL_TOKEN_IN; } +[Ii][Nn][Nn][Ee][Rr] {SQL_NEW_KEYWORD(SQL_TOKEN_INNER); return SQL_TOKEN_INNER; } +[Ii][Nn][Ss][Ee][Rr][Tt] {SQL_NEW_KEYWORD(SQL_TOKEN_INSERT); return SQL_TOKEN_INSERT; } +[Ii][Nn][Tt]([Ee][Gg][Ee][Rr])? {SQL_NEW_KEYWORD(SQL_TOKEN_INTEGER); return SQL_TOKEN_INTEGER; } +[Ii][Nn][Tt][Ee][Rr][Ss][Ee][Cc][Tt] {SQL_NEW_KEYWORD(SQL_TOKEN_INTERSECT); return SQL_TOKEN_INTERSECT; } +[Ii][Nn][Tt][Oo] {SQL_NEW_KEYWORD(SQL_TOKEN_INTO); return SQL_TOKEN_INTO; } +[Ii][Ss] {SQL_NEW_KEYWORD(SQL_TOKEN_IS); return SQL_TOKEN_IS; } + +[Jj][Oo][Ii][Nn] {SQL_NEW_KEYWORD(SQL_TOKEN_JOIN); return SQL_TOKEN_JOIN; } + +[Kk][Ee][Yy] {SQL_NEW_KEYWORD(SQL_TOKEN_KEY); return SQL_TOKEN_KEY; } + +[Ll][Ee][Aa][Dd][Ii][Nn][Gg] {SQL_NEW_KEYWORD(SQL_TOKEN_LEADING); return SQL_TOKEN_LEADING; } +[Ll][Ee][Ff][Tt] {SQL_NEW_KEYWORD(SQL_TOKEN_LEFT); return SQL_TOKEN_LEFT; } +[Ll][Ii][Kk][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_LIKE); return SQL_TOKEN_LIKE; } +[Ll][Oo][Cc][Aa][Ll] {SQL_NEW_KEYWORD(SQL_TOKEN_LOCAL); return SQL_TOKEN_LOCAL; } +[Ll][Oo][Ww][Ee][Rr] {SQL_NEW_KEYWORD(SQL_TOKEN_LOWER); return SQL_TOKEN_LOWER; } + +[Mm][Aa][Xx] {SQL_NEW_KEYWORD(SQL_TOKEN_MAX); return SQL_TOKEN_MAX; } +[Mm][Ii][Nn] {SQL_NEW_KEYWORD(SQL_TOKEN_MIN); return SQL_TOKEN_MIN; } +[Mm][Ii][Nn][Uu][Tt][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_MINUTE); return SQL_TOKEN_MINUTE; } +[Mm][Oo][Nn][Tt][Hh] {SQL_NEW_KEYWORD(SQL_TOKEN_MONTH); return SQL_TOKEN_MONTH; } + +[Nn][Aa][Tt][Uu][Rr][Aa][LL] {SQL_NEW_KEYWORD(SQL_TOKEN_NATURAL); return SQL_TOKEN_NATURAL; } +[Nn][Cc][Hh][Aa][Rr] {SQL_NEW_KEYWORD(SQL_TOKEN_NCHAR); return SQL_TOKEN_NCHAR; } +[Nn][Oo][Tt] {SQL_NEW_KEYWORD(SQL_TOKEN_NOT); return SQL_TOKEN_NOT; } +[Nn][Uu][Ll][Ll] {SQL_NEW_KEYWORD(SQL_TOKEN_NULL); return SQL_TOKEN_NULL; } +[Nn][Uu][Mm][Ee][Rr][Ii][Cc] {SQL_NEW_KEYWORD(SQL_TOKEN_NUMERIC); return SQL_TOKEN_NUMERIC; } + +[Oo][Cc][Tt][Ee][Tt]_[Ll][Ee][Nn][Gg][Tt][Hh] {SQL_NEW_KEYWORD(SQL_TOKEN_OCTECT_LENGTH); return SQL_TOKEN_OCTECT_LENGTH; } +[Oo][Ff] {SQL_NEW_KEYWORD(SQL_TOKEN_OF); return SQL_TOKEN_OF; } +[Oo][Jj] {SQL_NEW_KEYWORD(SQL_TOKEN_OJ); return SQL_TOKEN_OJ; } +[Oo][Nn] {SQL_NEW_KEYWORD(SQL_TOKEN_ON); return SQL_TOKEN_ON; } +[Oo][Pp][Tt][Ii][Oo][Nn] {SQL_NEW_KEYWORD(SQL_TOKEN_OPTION); return SQL_TOKEN_OPTION; } +[Oo][Rr] {SQL_NEW_KEYWORD(SQL_TOKEN_OR); return SQL_TOKEN_OR; } +[Oo][Rr][Dd][Ee][Rr] {SQL_NEW_KEYWORD(SQL_TOKEN_ORDER); return SQL_TOKEN_ORDER; } +[Oo][Uu][Tt][Ee][Rr] {SQL_NEW_KEYWORD(SQL_TOKEN_OUTER); return SQL_TOKEN_OUTER; } + +[Pp][Oo][Ss][Ii][Tt][Ii][Oo][Nn] {SQL_NEW_KEYWORD(SQL_TOKEN_POSITION); return SQL_TOKEN_POSITION; } +[Pp][Rr][Ee][Cc][Ii][Ss][Ii][Oo][Nn] {SQL_NEW_KEYWORD(SQL_TOKEN_PRECISION); return SQL_TOKEN_PRECISION; } +[Pp][Rr][Ii][Mm][Aa][Rr][Yy] {SQL_NEW_KEYWORD(SQL_TOKEN_PRIMARY); return SQL_TOKEN_PRIMARY; } +[Pp][Rr][Ii][Vv][Ii][Ll][Ee][Gg][Ee][Ss] {SQL_NEW_KEYWORD(SQL_TOKEN_PRIVILEGES); return SQL_TOKEN_PRIVILEGES; } +[Pp][Rr][Oo][Cc][Ee][Dd][Uu][Rr][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_PROCEDURE); return SQL_TOKEN_PROCEDURE; } +[Pp][Uu][Bb][Ll][Ii][Cc] {SQL_NEW_KEYWORD(SQL_TOKEN_PUBLIC); return SQL_TOKEN_PUBLIC; } + +[Rr][Ee][Aa][Ll] {SQL_NEW_KEYWORD(SQL_TOKEN_REAL); return SQL_TOKEN_REAL; } +[Rr][Ee][Ff][Ee][Rr][Ee][Nn][Cc][Ee][Ss] {SQL_NEW_KEYWORD(SQL_TOKEN_REFERENCES); return SQL_TOKEN_REFERENCES; } +[Rr][Oo][Ll][Ll][Bb][Aa][Cc][Kk] {SQL_NEW_KEYWORD(SQL_TOKEN_ROLLBACK); return SQL_TOKEN_ROLLBACK; } +[Rr][Ii][Gg][Hh][Tt] {SQL_NEW_KEYWORD(SQL_TOKEN_RIGHT); return SQL_TOKEN_RIGHT; } + +[Ss][Cc][Hh][Ee][Mm][Aa] {SQL_NEW_KEYWORD(SQL_TOKEN_SCHEMA); return SQL_TOKEN_SCHEMA; } +[Ss][Ee][Cc][Ee][Oo][Nn][Dd] {SQL_NEW_KEYWORD(SQL_TOKEN_SECOND); return SQL_TOKEN_SECOND; } +[Ss][Ee][Ll][Ee][Cc][Tt] {SQL_NEW_KEYWORD(SQL_TOKEN_SELECT); return SQL_TOKEN_SELECT; } +[Ss][Ee][Tt] {SQL_NEW_KEYWORD(SQL_TOKEN_SET); return SQL_TOKEN_SET; } +[Ss][Ii][Zz][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_SIZE); return SQL_TOKEN_SIZE; } +[Ss][Mm][Aa][Ll][Ll][Ii][Nn][Tt] {SQL_NEW_KEYWORD(SQL_TOKEN_SMALLINT); return SQL_TOKEN_SMALLINT; } +[Ss][Oo][Mm][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_SOME); return SQL_TOKEN_SOME; } +[Ss][Uu][Bb][Ss][Tt][Rr][Ii][Nn][Gg] {SQL_NEW_KEYWORD(SQL_TOKEN_SUBSTRING); return SQL_TOKEN_SUBSTRING; } +[Ss][Uu][Mm] {SQL_NEW_KEYWORD(SQL_TOKEN_SUM); return SQL_TOKEN_SUM; } + +[Tt] {SQL_NEW_KEYWORD(SQL_TOKEN_T); return SQL_TOKEN_T; } +[Tt][Aa][Bb][Ll][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_TABLE); return SQL_TOKEN_TABLE; } +[Tt][Ii][Mm][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_TIME); return SQL_TOKEN_TIME; } +[Tt][Ii][Mm][Ee][Ss][Tt][Aa][Mm][Pp] {SQL_NEW_KEYWORD(SQL_TOKEN_TIMESTAMP); return SQL_TOKEN_TIMESTAMP; } +[Tt][Ii][Mm][Ee][Zz][Oo][Nn][Ee]_[Hh][Oo][Uu][Rr] {SQL_NEW_KEYWORD(SQL_TOKEN_TIMEZONE_HOUR); return SQL_TOKEN_TIMEZONE_HOUR; } +[Tt][Ii][Mm][Ee][Zz][Oo][Nn][Ee]_[Mm][Ii][Nn][Uu][Tt][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_TIMEZONE_MINUTE); return SQL_TOKEN_TIMEZONE_MINUTE; } +[Tt][Oo] {SQL_NEW_KEYWORD(SQL_TOKEN_TO); return SQL_TOKEN_TO; } +[Tt][Rr][Aa][Ii][Ll][Ii][Nn][Gg] {SQL_NEW_KEYWORD(SQL_TOKEN_TRAILING); return SQL_TOKEN_TRAILING; } +[Tt][Rr][Aa][Nn][Ss][Ll][Aa][Tt][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_TRANSLATE); return SQL_TOKEN_TRANSLATE; } +[Tt][Rr][Ii][Mm] {SQL_NEW_KEYWORD(SQL_TOKEN_TRIM); return SQL_TOKEN_TRIM; } +[Tt][Rr][Uu][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_TRUE); return SQL_TOKEN_TRUE; } +[Tt][Ss] {SQL_NEW_KEYWORD(SQL_TOKEN_TS); return SQL_TOKEN_TS; } + +[Uu][Nn][Ii][Oo][Nn] {SQL_NEW_KEYWORD(SQL_TOKEN_UNION); return SQL_TOKEN_UNION; } +[Uu][Nn][Ii][Qq][Uu][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_UNIQUE); return SQL_TOKEN_UNIQUE; } +[Uu][Nn][Kk][Nn][Oo][Ww][Nn] {SQL_NEW_KEYWORD(SQL_TOKEN_UNKNOWN); return SQL_TOKEN_UNKNOWN; } +[Uu][Pp][Pp][Ee][Rr] {SQL_NEW_KEYWORD(SQL_TOKEN_UPPER); return SQL_TOKEN_UPPER; } +[Uu][Pp][Dd][Aa][Tt][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_UPDATE); return SQL_TOKEN_UPDATE; } +[Uu][Ss][Aa][Gg][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_USAGE); return SQL_TOKEN_USAGE; } +[Uu][Ss][Ee][Rr] {SQL_NEW_KEYWORD(SQL_TOKEN_USER); return SQL_TOKEN_USER; } +[Uu][Ss][Ii][Nn][Gg] {SQL_NEW_KEYWORD(SQL_TOKEN_USING); return SQL_TOKEN_USING; } + +[Vv][Aa][Ll][Uu][Ee][Ss] {SQL_NEW_KEYWORD(SQL_TOKEN_VALUES); return SQL_TOKEN_VALUES; } +[Vv][Ii][Ee][Ww] {SQL_NEW_KEYWORD(SQL_TOKEN_VIEW); return SQL_TOKEN_VIEW; } + +[Ww][Hh][Ee][Rr][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_WHERE); return SQL_TOKEN_WHERE; } +[Ww][Ii][Tt][Hh] {SQL_NEW_KEYWORD(SQL_TOKEN_WITH); return SQL_TOKEN_WITH; } +[Ww][Oo][Rr][Kk] {SQL_NEW_KEYWORD(SQL_TOKEN_WORK); return SQL_TOKEN_WORK; } + +[Yy][Ee][Aa][Rr] {SQL_NEW_KEYWORD(SQL_TOKEN_YEAR); return SQL_TOKEN_YEAR; } + +[Zz][Oo][Nn][Ee] {SQL_NEW_KEYWORD(SQL_TOKEN_ZONE); return SQL_TOKEN_ZONE; } + +"<" { SQL_NEW_NODE(String::CreateFromAscii(SQLyytext), SQL_NODE_LESS);return LESS;} +">" { SQL_NEW_NODE(String::CreateFromAscii(SQLyytext), SQL_NODE_GREAT);return GREAT;} +"=" { SQL_NEW_NODE(String::CreateFromAscii(SQLyytext), SQL_NODE_EQUAL);return EQUAL;} +"<=" { SQL_NEW_NODE(String::CreateFromAscii(SQLyytext), SQL_NODE_LESSEQ);return LESSEQ;} +">=" { SQL_NEW_NODE(String::CreateFromAscii(SQLyytext), SQL_NODE_GREATEQ);return GREATEQ;} +"<>" { SQL_NEW_NODE(String::CreateFromAscii(SQLyytext), SQL_NODE_NOTEQUAL);return NOTEQUAL;} +"!=" { SQL_NEW_NODE(String::CreateFromAscii(SQLyytext), SQL_NODE_NOTEQUAL);return NOTEQUAL;} + + +[-+*/:(),.;?{}] { return SQLyytext[0]; } + +<SQL>[A-Za-z][A-Za-z0-9_]* {return gatherName( SQLyytext);} + +<SQL>([0-9]+) | +<SQL>([0-9]+"."[0-9]*) | +<SQL>("."[0-9]*) {SQL_NEW_INTNUM; return SQL_TOKEN_INTNUM;} + +<SQL>[0-9]+[eE][+-]?[0-9]+ | +<SQL>[0-9]+"."[0-9]*[eE][+-]?[0-9]+ | +<SQL>"."[0-9]*[eE][+-]?[0-9]+ {SQL_NEW_APPROXNUM; return SQL_TOKEN_APPROXNUM; } + +<PREDICATE_GER,PREDICATE_ENG,DATE>[A-Za-z][A-Za-z0-9_%.,*?]* {return gatherNamePre(SQLyytext);} + +<PREDICATE_GER,PREDICATE_ENG>([0-9]+) {SQL_NEW_INTNUM; return SQL_TOKEN_INTNUM;} +<PREDICATE_ENG>([0-9]{1,3}(","[0-9]{3})+) {SQL_NEW_INTNUM; return SQL_TOKEN_INTNUM;} +<PREDICATE_GER>([0-9]{1,3}("."[0-9]{3})+) {SQL_NEW_INTNUM; return SQL_TOKEN_INTNUM;} + +<PREDICATE_ENG>([0-9]+"."[0-9]+) | +<PREDICATE_ENG>([0-9]{1,3}(","[0-9]{3})+"."[0-9]+) | +<PREDICATE_ENG>("."[0-9]+) {SQL_NEW_APPROXNUM; return SQL_TOKEN_APPROXNUM; } +<PREDICATE_ENG>[0-9]+[eE][+-]?[0-9]+ | +<PREDICATE_ENG>[0-9]+"."[0-9]*[eE][+-]?[0-9]+ | +<PREDICATE_ENG>"."[0-9]*[eE][+-]?[0-9]+ {SQL_NEW_APPROXNUM; return SQL_TOKEN_APPROXNUM; } + +<PREDICATE_GER>([0-9]+","[0-9]+) | +<PREDICATE_GER>([0-9]{1,3}("."[0-9]{3})+","[0-9]+) | +<PREDICATE_GER>(","[0-9]+) {SQL_NEW_APPROXNUM; return SQL_TOKEN_APPROXNUM; } +<PREDICATE_GER>[0-9]+[eE][+-]?[0-9]+ | +<PREDICATE_GER>[0-9]+","[0-9]*[eE][+-]?[0-9]+ | +<PREDICATE_GER>","[0-9]*[eE][+-]?[0-9]+ {SQL_NEW_APPROXNUM; return SQL_TOKEN_APPROXNUM; } + +<PREDICATE_GER,PREDICATE_ENG>[0-9.,][A-Za-z0-9_.,%]* {return gatherNamePre(SQLyytext);} + +<SQL>\" { return gatherString('\"',0); } +<SQL>` { return gatherString('`' ,0); } + +<PREDICATE_GER,PREDICATE_ENG,DATE>"[" { return gatherString(']' ,0);} + +\' { return gatherString('\'',1); } + +<PREDICATE_GER,PREDICATE_ENG,DATE># { return gatherString('#' ,2); } + +<DATE>[0-9]{1,4}[^ ]*[0-9] | +<DATE>[0-9]{1,4}[^ ]*[0-9][ ][0-9]{1,4}[^ ]*[0-9] { SQL_NEW_DATE; return SQL_TOKEN_ACCESS_DATE;} + +<STRING>["-""+""*""/"":""("")"",""."";""?""{""}"] { return SQLyytext[0]; } /* */ +<STRING>"[" { return gatherString(']' ,0); } +<STRING>[^ ':[]* { return gatherNamePre(SQLyytext); } + +\n {} + +[ \t\r]+ ; + +"--".*$ ; + +. {YY_FATAL_ERROR("Invalid symbol"); return SQL_TOKEN_INVALIDSYMBOL;} + +%% + +/* + * Read SQL string literal + * Valid strings: + * '' 'a string' 'quote '' within string' + * "" "a string" "quote "" within string" + * nTyp == 0 -> SQL_NODE_NAME + * nTyp == 1 -> SQL_NODE_STRING + * nTyp == 2 -> SQL_NODE_ACCESS_DATE + */ +int gatherString( int delim, int nTyp) +{ + int ch; + static sal_Int32 BUFFERSIZE = 256; + static char* Buffer = new char[BUFFERSIZE]; + + char *s = Buffer; + int nPos = 0; + + while ((ch = yyinput()) != EOF) + { + if (ch == delim) + { + if ((ch = yyinput()) != delim) + { + if (ch != EOF) + unput(ch); + + *s = '\0'; + + switch(nTyp) + { + case 0: + SQL_NEW_NODE(String(Buffer,RTL_TEXTENCODING_UTF8), SQL_NODE_NAME); + return SQL_TOKEN_NAME; + case 1: + SQL_NEW_NODE(String(Buffer,RTL_TEXTENCODING_UTF8), SQL_NODE_STRING); + return SQL_TOKEN_STRING; + case 2: + SQL_NEW_NODE(String(Buffer,RTL_TEXTENCODING_UTF8), SQL_NODE_ACCESS_DATE); + return SQL_TOKEN_ACCESS_DATE; + } + } + else + { + *s++ = ch; + if (++nPos == BUFFERSIZE) + { + ByteString aBuf(Buffer); + delete Buffer; + BUFFERSIZE *=2; + Buffer = new char[BUFFERSIZE]; + for(xub_StrLen i=0;i<aBuf.Len();++i,++Buffer) + *Buffer = aBuf.GetChar(i); + s = &Buffer[nPos]; + } + } + + } + else if (ch == '\r' || ch == '\n') + break; + else + { + *s++ = ch; + if (++nPos == BUFFERSIZE) + { + ByteString aBuf(Buffer); + delete Buffer; + BUFFERSIZE *=2; + Buffer = new char[BUFFERSIZE]; + for(xub_StrLen i=0;i<aBuf.Len();++i,++Buffer) + *Buffer = aBuf.GetChar(i); + s = &Buffer[nPos]; + } + } + } + *s = '\0'; + YY_FATAL_ERROR("Unterminated name string"); + return SQL_TOKEN_INVALIDSYMBOL; +} + +/* + * Read SQL Name literal + * Valid Names or internatioanl keywords: + * As we have international keywords, we test first on them + */ +int gatherName(const char* text) +{ + OSL_ENSHURE(xxx_pGLOBAL_SQLSCAN,"You forgot to set the scanner!"); + int nToken = xxx_pGLOBAL_SQLSCAN->getInternationalTokenID(text); + switch (nToken) + { + case SQL_TOKEN_LIKE: + case SQL_TOKEN_NOT: + case SQL_TOKEN_NULL: + case SQL_TOKEN_TRUE: + case SQL_TOKEN_FALSE: + case SQL_TOKEN_IS: + case SQL_TOKEN_BETWEEN: + case SQL_TOKEN_OR: + case SQL_TOKEN_AND: + case SQL_TOKEN_COUNT: + case SQL_TOKEN_AVG: + case SQL_TOKEN_MAX: + case SQL_TOKEN_MIN: + case SQL_TOKEN_SUM: + SQL_NEW_KEYWORD(nToken); + return nToken; + default: + SQL_NEW_NODE(String::CreateFromAscii(text), SQL_NODE_NAME); + return SQL_TOKEN_NAME; + } +} +/** + Read SQL Name literal for predicate check + Valid Names or internatioanl keywords: + As we have international keywords, we test first on them +*/ +int gatherNamePre(const char* text) +{ + OSL_ENSHURE(xxx_pGLOBAL_SQLSCAN,"You forgot to set the scanner!"); + int nToken = xxx_pGLOBAL_SQLSCAN->getInternationalTokenID(text); + switch (nToken) + { + case SQL_TOKEN_LIKE: + case SQL_TOKEN_NOT: + case SQL_TOKEN_NULL: + case SQL_TOKEN_TRUE: + case SQL_TOKEN_FALSE: + case SQL_TOKEN_IS: + case SQL_TOKEN_BETWEEN: + case SQL_TOKEN_OR: + case SQL_TOKEN_AND: + case SQL_TOKEN_COUNT: + case SQL_TOKEN_AVG: + case SQL_TOKEN_MAX: + case SQL_TOKEN_MIN: + case SQL_TOKEN_SUM: + SQL_NEW_KEYWORD(nToken); + return nToken; + default: + // we need a special handling for parameter + if (yy_hold_char == ':') + { + SQL_NEW_NODE(String::CreateFromAscii(text), SQL_NODE_NAME); + return SQL_TOKEN_NAME; + } + else + { + SQL_NEW_NODE(String::CreateFromAscii(text), SQL_NODE_STRING); + return SQL_TOKEN_STRING; + } + } +} + +using namespace connectivity; + +static sal_uInt32 Intl_TokenID[] = +{ + SQL_TOKEN_LIKE, SQL_TOKEN_NOT, SQL_TOKEN_NULL, SQL_TOKEN_TRUE, + SQL_TOKEN_FALSE, SQL_TOKEN_IS, SQL_TOKEN_BETWEEN, SQL_TOKEN_OR, + SQL_TOKEN_AND, SQL_TOKEN_AVG, SQL_TOKEN_COUNT, SQL_TOKEN_MAX, + SQL_TOKEN_MIN, SQL_TOKEN_SUM +}; + +DBG_NAME(OSQLScanner); + +//------------------------------------------------------------------------------ +OSQLScanner::OSQLScanner() + : m_nCurrentPos(0) + , m_bInternational(sal_False) + , m_pContext(NULL) + , m_nRule(0) // 0 is INITIAL +{ + DBG_CTOR(OSQLScanner,NULL); +} + +//------------------------------------------------------------------------------ +OSQLScanner::~OSQLScanner() +{ + DBG_DTOR(OSQLScanner,NULL); +} + +//------------------------------------------------------------------------------ +void OSQLScanner::SQLyyerror(char *fmt) +{ + DBG_ASSERT(m_pContext, "OSQLScanner::SQLyyerror: No Context set"); + m_sErrorMessage = m_pContext->getErrorMessage(OParseContext::ERROR_GENERAL); + if (m_nCurrentPos < m_sStatement.Len()) + { + m_sErrorMessage.AppendAscii(": "); + m_sErrorMessage += m_pContext->getErrorMessage(OParseContext::ERROR_GENERAL_HINT); + m_sErrorMessage.SearchAndReplaceAscii("#",String::CreateFromAscii(SQLyytext)); + } +} + +//------------------------------------------------------------------------------ +void OSQLScanner::prepareScan(const String & rNewStatement, OParseContext* pContext, sal_Bool bInternational) +{ + DBG_CHKTHIS(OSQLScanner,NULL); + + BEGIN(m_nRule); + + m_sErrorMessage.Erase(); + m_sStatement = ByteString(rNewStatement, RTL_TEXTENCODING_UTF8); + m_nCurrentPos = 0; + m_bInternational = bInternational; + m_pContext = pContext; +} + +//------------------------------------------------------------------------------ +int OSQLScanner::SQLyygetc(void) +{ + return (m_nCurrentPos >= m_sStatement.Len()) ? -1 : m_sStatement.GetChar(m_nCurrentPos++); +} + +//------------------------------------------------------------------------------ +int OSQLScanner::getInternationalTokenID(const char* sToken) const +{ + DBG_ASSERT(m_pContext, "OSQLScanner::getInternationalTokenID: No Context set"); + return (m_bInternational) ? m_pContext->getIntlKeyCode(ByteString(sToken, RTL_TEXTENCODING_ASCII_US)) : 0; +} +// ------------------------------------------------------------------------- +int OSQLScanner::GetCurrentRule() const { return m_nRule; } +int OSQLScanner::GetGERRule() const { return PREDICATE_GER; } +int OSQLScanner::GetENGRule() const { return PREDICATE_ENG; } +int OSQLScanner::GetSQLRule() const { return SQL; } +int OSQLScanner::GetDATERule() const { return DATE; } +int OSQLScanner::GetSTRINGRule() const { return STRING; } +// ------------------------------------------------------------------------- +void OSQLScanner::setScanner(sal_Bool _bNull) +{ + xxx_pGLOBAL_SQLSCAN = _bNull ? NULL : this; +} +// ------------------------------------------------------------------------- +int OSQLScanner::SQLlex() +{ + return SQLyylex(); +} +/*------------------------------------------------------------------------ + + $Log: not supported by cvs2svn $ + Revision 1.2 2000/08/01 14:26:02 oj + modified + + Revision 1.1 2000/07/25 10:39:47 oj + new revision + + Revision 1.0 21.07.2000 10:54:08 oj +------------------------------------------------------------------------*/ + diff --git a/connectivity/source/parse/sqliterator.cxx b/connectivity/source/parse/sqliterator.cxx new file mode 100644 index 000000000000..88e98fa418a7 --- /dev/null +++ b/connectivity/source/parse/sqliterator.cxx @@ -0,0 +1,1583 @@ +/************************************************************************* + * + * $RCSfile: sqliterator.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:14:28 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source 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.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifndef _CONNECTIVITY_PARSE_SQLITERATOR_HXX_ +#include "connectivity/sqliterator.hxx" +#endif + +#ifndef _CONNECTIVITY_SQLPARSE_HXX +#include <connectivity/sqlparse.hxx> +#endif +#ifndef _COM_SUN_STAR_SDBC_COLUMNVALUE_HPP_ +#include <com/sun/star/sdbc/ColumnValue.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_DATATYPE_HPP_ +#include <com/sun/star/sdbc/DataType.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_ +#include <com/sun/star/sdbc/XRow.hpp> +#endif +#ifdef SQL_TEST_PARSETREEITERATOR +#include <iostream.h> +#endif +#ifndef _CONNECTIVITY_SDBCX_COLUMN_HXX_ +#include "connectivity/PColumn.hxx" +#endif +#ifndef _CONNECTIVITY_SDBCX_COLLECTION_HXX_ +#include "connectivity/sdbcx/VCollection.hxx" +#endif +#ifndef _CONNECTIVITY_PROPERTYIDS_HXX_ +#include "propertyids.hxx" +#endif + +using namespace connectivity; +using namespace connectivity::parse; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; + +DBG_NAME(OSQLParseTreeIterator); +static String aEmptyString; + +class OPrivateColumns : public sdbcx::OCollection +{ + OSQLColumns m_aColumns; +protected: + virtual Reference< XNamed > createObject(const ::rtl::OUString& _rName); + virtual void impl_refresh() throw(RuntimeException) {} + virtual Reference< XPropertySet > createEmptyObject() + { + return NULL; + } +public: + OPrivateColumns(const OSQLColumns& _rColumns, + ::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex, + const ::std::vector< ::rtl::OUString> &_rVector + ) : sdbcx::OCollection(_rParent,sal_True,_rMutex,_rVector) + ,m_aColumns(_rColumns) + {} + ~OPrivateColumns() + { + disposing(); + } +}; +// ------------------------------------------------------------------------- +Reference< XNamed > OPrivateColumns::createObject(const ::rtl::OUString& _rName) +{ + return Reference< XNamed >(*find(m_aColumns.begin(),m_aColumns.end(),_rName,isCaseSensitive()),UNO_QUERY); +} +// ------------------------------------------------------------------------- +class OPrivateTables : public sdbcx::OCollection +{ + OSQLTables m_aTables; +protected: + virtual Reference< XNamed > createObject(const ::rtl::OUString& _rName); + virtual void impl_refresh() throw(RuntimeException) {} + virtual Reference< XPropertySet > createEmptyObject() + { + return NULL; + } +public: + OPrivateTables(const OSQLTables& _rColumns, + ::cppu::OWeakObject& _rParent, + ::osl::Mutex& _rMutex, + const ::std::vector< ::rtl::OUString> &_rVector + ) : sdbcx::OCollection(_rParent,sal_True,_rMutex,_rVector) + ,m_aTables(_rColumns) + {} +}; +// ------------------------------------------------------------------------- +Reference< XNamed > OPrivateTables::createObject(const ::rtl::OUString& _rName) +{ + return Reference< XNamed >(m_aTables.find(_rName)->second,UNO_QUERY); +} + +//----------------------------------------------------------------------------- +OSQLParseTreeIterator::OSQLParseTreeIterator() + : m_pParseTree(NULL) + , m_xTables(NULL) + , m_xDatabaseMetaData(NULL) +{ + DBG_CTOR(OSQLParseTreeIterator,NULL); + m_aSelectColumns = new OSQLColumns(); +} +//----------------------------------------------------------------------------- +OSQLParseTreeIterator::OSQLParseTreeIterator(const Reference< XNameAccess>& _xTables , + const Reference< XDatabaseMetaData>& _xDatabaseMetaData, + const OSQLParseNode* pRoot) + : m_xTables(_xTables) + , m_xDatabaseMetaData(_xDatabaseMetaData) + , m_aTables(_xDatabaseMetaData->storesMixedCaseQuotedIdentifiers()) + , m_aCaseEqual(_xDatabaseMetaData->storesMixedCaseQuotedIdentifiers()) +{ + DBG_CTOR(OSQLParseTreeIterator,NULL); + m_aSelectColumns = new OSQLColumns();// must be done because we need an empty column at zero + setParseTree(pRoot); +} +//----------------------------------------------------------------------------- +OSQLParseTreeIterator::OSQLParseTreeIterator(const OSQLParseTreeIterator & rIter) + :m_xTables(NULL) + ,m_pParseTree(NULL) + , m_xDatabaseMetaData(NULL) +{ + DBG_CTOR(OSQLParseTreeIterator,NULL); + + DBG_ERROR("OSQLParseTreeIterator: Copy-Konstruktor nicht implementiert!"); +} + +//----------------------------------------------------------------------------- +OSQLParseTreeIterator::~OSQLParseTreeIterator() +{ + DBG_DTOR(OSQLParseTreeIterator,NULL); + m_aTables.clear(); +} +// ------------------------------------------------------------------------- +Reference< XNameAccess > OSQLParseTreeIterator::getSelectAsNameAccess(::cppu::OWeakObject& _rParent,::osl::Mutex& _rMutex) const +{ + ::std::vector< ::rtl::OUString> aNames; + for(OSQLColumns::const_iterator aIter = m_aSelectColumns->begin(); aIter != m_aSelectColumns->end();++aIter) + aNames.push_back(getString((*aIter)->getFastPropertyValue(PROPERTY_ID_NAME))); + OPrivateColumns* pCols = new OPrivateColumns(*m_aSelectColumns,_rParent,_rMutex,aNames); + return pCols; +} +// ------------------------------------------------------------------------- +Reference< XNameAccess > OSQLParseTreeIterator::getTablesAsNameAccess(::cppu::OWeakObject& _rParent,::osl::Mutex& _rMutex) const +{ + ::std::vector< ::rtl::OUString> aNames; + for(OSQLTables::const_iterator aIter = m_aTables.begin(); aIter != m_aTables.end();++aIter) + { + Reference<XNamed> xName(aIter->second,UNO_QUERY); + aNames.push_back(xName->getName()); + } + OPrivateTables* pTabs = new OPrivateTables(m_aTables,_rParent,_rMutex,aNames); + return pTabs; +} +//----------------------------------------------------------------------------- +void OSQLParseTreeIterator::setParseTree(const OSQLParseNode * pNewParseTree) +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + // alle Eingaben zur"uck setzen + // aIteratorStatus.Clear(); +// for(ULONG i=0; i< m_aTables.count();i++) +// delete m_aTables.getObject(i); + m_aTables.clear(); + + m_aSelectColumns->clear(); + + m_pParseTree = pNewParseTree; + if (!m_pParseTree) + { + m_eStatementType = SQL_STATEMENT_UNKNOWN; + return; + } + + // falls m_pParseTree aber keine Connection, dann Fehler + if(!m_xTables.is()) + { + //aIteratorStatus.setInvalidStatement(); + CallError(RET_BREAK); + return; + } + + // m_aTables.setCaseSensitive(TablesAreSensitive()); + + + // Statement-Typ ermitteln ... + if (SQL_ISRULE(m_pParseTree,select_statement) || SQL_ISRULE(m_pParseTree,union_statement) ) + { + m_eStatementType = SQL_STATEMENT_SELECT; + } + else if (SQL_ISRULE(m_pParseTree,insert_statement)) + { + m_eStatementType = SQL_STATEMENT_INSERT; + } + else if (SQL_ISRULE(m_pParseTree,update_statement_positioned)) + { + m_eStatementType = SQL_STATEMENT_UPDATE; + } + else if (SQL_ISRULE(m_pParseTree,update_statement_searched)) + { + m_eStatementType = SQL_STATEMENT_UPDATE; + } + else if (SQL_ISRULE(m_pParseTree,delete_statement_positioned)) + { + m_eStatementType = SQL_STATEMENT_DELETE; + } + else if (SQL_ISRULE(m_pParseTree,delete_statement_searched)) + { + m_eStatementType = SQL_STATEMENT_DELETE; + } + else if (m_pParseTree->count() == 3 && SQL_ISRULE(m_pParseTree->getChild(1),odbc_call_spec)) + { + m_eStatementType = SQL_STATEMENT_ODBC_CALL; + } + else + { + m_eStatementType = SQL_STATEMENT_UNKNOWN; + //aIteratorStatus.setInvalidStatement(); + CallError(RET_BREAK); + return; + } +} + +//----------------------------------------------------------------------------- +void OSQLParseTreeIterator::traverseOneTableName(const OSQLParseNode * pTableName, const String & rTableRange) +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + + DBG_ASSERT(pTableName != NULL,"OSQLParseTreeIterator::traverseOneTableName: pTableName == NULL"); + + String aTableName; + String aTableRange(rTableRange); + + // Tabellenname abholen + pTableName->parseNodeToStr(aTableName,m_xDatabaseMetaData,NULL,FALSE,FALSE); + // Wenn keine Range Variable angegeben, dann den Tabellennamen verwenden. + if (!aTableRange.Len()) + aTableRange = aTableName; + + if(aTableName.Len()) + { + try + { + if(!m_xTables->hasByName(aTableName)) // name not in XNameAccess + { + const ::rtl::OUString sAll = ::rtl::OUString::createFromAscii("%"); + Sequence< ::rtl::OUString > aSeq; + Reference< XResultSet> xRes = m_xDatabaseMetaData->getTables(Any(),sAll,aTableName,aSeq); + if(xRes.is() && xRes->next()) + { + ::rtl::OUString sCatalog, sSchema, sName; + Reference< XRow > xCurrentRow(xRes, UNO_QUERY); + sCatalog = xCurrentRow->getString(1); + sSchema = xCurrentRow->getString(2); + sName = xCurrentRow->getString(3); + + if(sCatalog.getLength()) + { + aTableName = sCatalog; + aTableName += m_xDatabaseMetaData->getCatalogSeparator().getStr(); + } + if(sSchema.getLength()) + { + aTableName += sSchema.getStr(); + aTableName += ::rtl::OUString::createFromAscii(".").getStr(); + } + aTableName += sName.getStr(); + } + } + Any aTable(m_xTables->getByName(aTableName)); + OSQLTable xSet; + + if(aTable >>= xSet) + m_aTables[aTableRange] = xSet; + }catch(...) + { + if (CallError(RET_CONTINUE)) + m_aTables[aTableRange] = NULL; // ich soll den Fehler ignorieren + } + + } + else + CallError(RET_BREAK,rTableRange); +} +//----------------------------------------------------------------------------- +OSQLParseNode * OSQLParseTreeIterator::getQualified_join(OSQLParseNode *pTableRef,String& aTableRange) +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + aTableRange.Erase(); + + OSQLParseNode *pNode = getTableRef(pTableRef->getChild(0),aTableRange); + if(pNode) + traverseOneTableName(pNode,aTableRange); + ULONG nPos = 4; + if(SQL_ISRULE(pTableRef,cross_union) || pTableRef->getChild(1)->getTokenID() != SQL_TOKEN_NATURAL) + nPos = 3; + + + pNode = getTableRef(pTableRef->getChild(nPos),aTableRange); + if(pNode) + traverseOneTableName(pNode,aTableRange); + return pNode; +} +//----------------------------------------------------------------------------- +OSQLParseNode * OSQLParseTreeIterator::getTableRef(OSQLParseNode *pTableRef,String& aTableRange) +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + OSQLParseNode *pTableName = pTableRef; + if (pTableName->count() == 4 ) + { + if(SQL_ISPUNCTUATION(pTableName->getChild(0),"{")) + { // { OJ joined_table } + getQualified_join(pTableName->getChild(2),aTableRange); + pTableName = NULL; + } + else + { + // Tabellennamen gefunden + if(!SQL_ISRULE(pTableName,table_name)) + pTableName = pTableRef->getChild(0); + aTableRange.Erase(); + if(pTableRef->count() == 4) + aTableRange = pTableRef->getChild(2)->getTokenValue(); // Tabellenrange an Pos 2 + } + } + else if(SQL_ISRULE(pTableName,qualified_join) || SQL_ISRULE(pTableName,cross_union)) + { + getQualified_join(pTableRef,aTableRange); + pTableName = NULL; + } + else if (SQL_ISRULE(pTableName,joined_table)) + { + // '(' qualified_join ')' + getQualified_join(pTableName->getChild(1),aTableRange); + pTableName = NULL; + } + else if(pTableRef->count() == 6) + { + // '(' joined_table ')' as range_variable op_column_commalist + if(SQL_ISRULE(pTableRef->getChild(1),qualified_join) || SQL_ISRULE(pTableRef->getChild(1),cross_union)) + getQualified_join(pTableRef->getChild(1),aTableRange); + else if(SQL_ISRULE(pTableRef->getChild(1),select_statement)) // Unterabfrage + getSelect_statement(pTableRef->getChild(1)); + else if(pTableRef->getChild(1)->count() == 4) + // pTableRef->getChild(1) ->> non_join_query_exp + getSelect_statement(pTableRef->getChild(0)); // query_exp SQL_TOKEN_UNION all query_term + else + {// nyi: tiefere Verschachtelung m"oglch + CallError(4); + } + } + return pTableName; +} +//----------------------------------------------------------------------------- +void OSQLParseTreeIterator::getSelect_statement(OSQLParseNode *pSelect) +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + if(SQL_ISRULE(pSelect,union_statement)) + { + getSelect_statement(pSelect->getChild(0)); + //getSelect_statement(pSelect->getChild(3)); + return; + } + OSQLParseNode * pTableRefCommalist = pSelect->getChild(3)->getChild(0)->getChild(1); + + DBG_ASSERT(pTableRefCommalist != NULL,"OSQLParseTreeIterator: Fehler im Parse Tree"); + DBG_ASSERT(SQL_ISRULE(pTableRefCommalist,table_ref_commalist),"OSQLParseTreeIterator: Fehler im Parse Tree"); + + OSQLParseNode * pTableName = NULL; + String aTableRange; + for (ULONG i = 0; i < pTableRefCommalist->count(); i++) + { // from clause durchlaufen + aTableRange.Erase(); + + if (SQL_ISRULE(pTableRefCommalist->getChild(i),table_name)) + { + pTableName = pTableRefCommalist->getChild(i); + traverseOneTableName(pTableName,aTableRange);// Keine Range Variable + } + else if (SQL_ISRULE(pTableRefCommalist->getChild(i),table_ref)) + { + // Tabellenreferenz kann aus Tabellennamen, Tabellennamen (+),'('joined_table')'(+) bestehen + pTableName = pTableRefCommalist->getChild(i)->getChild(0); + if (SQL_ISRULE(pTableName,table_name)) + { // Tabellennamen gefunden + if(pTableRefCommalist->getChild(i)->count() == 4) // Tabellenrange an Pos 2 + aTableRange = pTableRefCommalist->getChild(i)->getChild(2)->getTokenValue(); + traverseOneTableName(pTableName,aTableRange); + } + else if(SQL_ISPUNCTUATION(pTableName,"{")) + getQualified_join(pTableRefCommalist->getChild(i)->getChild(2),aTableRange); + else // '(' joined_table ')' as range_variable op_column_commalist + getTableRef(pTableRefCommalist->getChild(i),aTableRange); + } + else if (SQL_ISRULE(pTableRefCommalist->getChild(i),qualified_join) || SQL_ISRULE(pTableRefCommalist->getChild(i),cross_union) ) + { + // qualified_join oder cross_union vorhanden + getQualified_join(pTableRefCommalist->getChild(i),aTableRange); + } + else if (SQL_ISRULE(pTableRefCommalist->getChild(i),joined_table)) + { + // '(' qualified_join ')' + getQualified_join(pTableRefCommalist->getChild(i)->getChild(1),aTableRange); + } + else + { + CallError(3,aTableRange); + } + + // if (! aIteratorStatus.IsSuccessful()) break; + } +} +//----------------------------------------------------------------------------- +void OSQLParseTreeIterator::traverseTableNames() +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + // aIteratorStatus.Clear(); + + if (m_pParseTree == NULL) { + //aIteratorStatus.setInvalidStatement(); + CallError(3); + return; + } + + OSQLParseNode * pTableName = NULL; + String aTableRange; + + // pTableName auf den (einzigen) Tabellennamen im Statement setzen. + // Je nach Statement (SELECT, INSERT, UPDATE, DELETE) an anderer Position. + // Bei Select koennen mehrere Tabellennamen auftreten, bei den uebrigen Statements + // ist ohnehin immer nur einer moeglich. + + if (m_eStatementType == SQL_STATEMENT_SELECT) + { + OSQLParseNode *pTmp = (OSQLParseNode *)m_pParseTree; + getSelect_statement(pTmp); + } + else if (m_eStatementType == SQL_STATEMENT_INSERT) + { + pTableName = m_pParseTree->getChild(2); + traverseOneTableName(pTableName,aTableRange); + } + else if (m_eStatementType == SQL_STATEMENT_UPDATE) + { + pTableName = m_pParseTree->getChild(1); + traverseOneTableName(pTableName,aTableRange); + } + else if (m_eStatementType == SQL_STATEMENT_DELETE) + { + pTableName = m_pParseTree->getChild(2); + traverseOneTableName(pTableName,aTableRange); + } else + { + CallError(5,aTableRange); + } +} +//----------------------------------------------------------------------------- +String OSQLParseTreeIterator::getColumnAlias(const OSQLParseNode* pDerivedColumn) const +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + String aColumnAlias; + if(pDerivedColumn->getChild(1)->count() == 2) + aColumnAlias = pDerivedColumn->getChild(1)->getChild(1)->getTokenValue(); + else if(!pDerivedColumn->getChild(1)->isRule()) + aColumnAlias = pDerivedColumn->getChild(1)->getTokenValue(); + return aColumnAlias; +} + +//----------------------------------------------------------------------------- +void OSQLParseTreeIterator::getColumnRange(const OSQLParseNode* pColumnRef,String &rColumnName,String &rTableRange) const +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + rColumnName.Erase(); + rTableRange.Erase(); + if(SQL_ISRULE(pColumnRef,column_ref))// ab hier ist es sicher eine Columnref + { + if(pColumnRef->count() > 1) + { + for(INT32 i=0;i<((INT32)pColumnRef->count())-2;i++) // mu"s signed sein, falls count == 1 + pColumnRef->getChild(i)->parseNodeToStr(rTableRange,m_xDatabaseMetaData,NULL,FALSE,FALSE); + // Spaltenname + rColumnName = pColumnRef->getChild(pColumnRef->count()-1)->getChild(0)->getTokenValue(); + } + else + rColumnName = pColumnRef->getChild(0)->getTokenValue(); + } + else if(SQL_ISRULE(pColumnRef,general_set_fct) || SQL_ISRULE(pColumnRef,set_fct_spec)) + { // Funktion + pColumnRef->parseNodeToStr(rColumnName,m_xDatabaseMetaData); + } + else if(pColumnRef->getNodeType() == SQL_NODE_NAME) + rColumnName = pColumnRef->getTokenValue(); +} + +//----------------------------------------------------------------------------- +BOOL OSQLParseTreeIterator::getColumnTableRange(const OSQLParseNode* pNode, String &rTableRange) const +{ + // Ermitteln ob alle Spalten zu einer Tabelle gehoeren + if (SQL_ISRULE(pNode,column_ref)) + { + String aColName, aTableRange; + getColumnRange(pNode, aColName, aTableRange); + if (!aTableRange.Len()) // keinen gefunden + { + // dann die Spalte in den Tabellen suchen + for (ConstOSQLTablesIterator aIter = m_aTables.begin(); aIter != m_aTables.end(); ++aIter) + { + if (aIter->second.is()) + { + try + { + Reference< XNameAccess > xColumns = aIter->second->getColumns(); + Any aColumn(xColumns->getByName(aColName)); + Reference< XFastPropertySet > xColumn; + + if (aColumn >>= xColumn) + { + aTableRange = aIter->first; + break; + } + } + catch(...) + { + } + } + } + if (!aTableRange.Len()) + return FALSE; + } + + + if (!rTableRange.Len()) + rTableRange = aTableRange; + else if (rTableRange != aTableRange) + return FALSE; + } + else + { + for (UINT32 i = 0, ncount = pNode->count(); i < ncount; i++) + { + if (!getColumnTableRange(pNode->getChild(i), rTableRange)) + return FALSE; + } + } + return TRUE; +} + +//----------------------------------------------------------------------------- +void OSQLParseTreeIterator::traverseSelectColumnNames(const OSQLParseNode* pSelectNode) +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + // aIteratorStatus.Clear(); + + if (!pSelectNode || m_eStatementType != SQL_STATEMENT_SELECT || !m_aTables.size()) + { + //aIteratorStatus.setInvalidStatement(); + CallError(3); + return; + } + + if(SQL_ISRULE(pSelectNode,union_statement)) + { + traverseSelectColumnNames(pSelectNode->getChild(0)); +// traverseSelectColumnNames(pSelectNode->getChild(3)); + return; + } + + // nyi: mehr Pruefung auf korrekte Struktur! + if (pSelectNode->getChild(2)->isRule() && SQL_ISPUNCTUATION(pSelectNode->getChild(2)->getChild(0),"*")) + { + // SELECT * ... + setSelectColumnName(String::CreateFromAscii("*"), aEmptyString,aEmptyString); + } + else if (SQL_ISRULE(pSelectNode->getChild(2),scalar_exp_commalist)) + { + // SELECT column(,column) oder SELECT COUNT(*) ... + OSQLParseNode * pSelection = pSelectNode->getChild(2); + + for (ULONG i = 0; i < pSelection->count(); i++) + { + OSQLParseNode *pColumnRef = pSelection->getChild(i); + + if (SQL_ISRULE(pColumnRef,select_sublist)) + { + // alle Spalten der Tabelle + String aTableRange; + pColumnRef->getChild(0)->parseNodeToStr(aTableRange,m_xDatabaseMetaData,NULL,FALSE,FALSE); + setSelectColumnName(String::CreateFromAscii("*"), aEmptyString,aTableRange); + continue; + }else if (SQL_ISRULE(pColumnRef,derived_column)) + { + String aColumnAlias(getColumnAlias(pColumnRef)); // kann leer sein + String aColumnName; + String aTableRange; + BOOL bFkt(FALSE); + pColumnRef = pColumnRef->getChild(0); + if (SQL_ISRULE(pColumnRef,column_ref)) + { + getColumnRange(pColumnRef,aColumnName,aTableRange); + DBG_ASSERT(aColumnName.Len(),"Columnname darf nicht leer sein"); + } + else /*if (SQL_ISRULE(pColumnRef,general_set_fct) || SQL_ISRULE(pColumnRef,set_fct_spec) || + SQL_ISRULE(pColumnRef,position_exp) || SQL_ISRULE(pColumnRef,extract_exp) || + SQL_ISRULE(pColumnRef,length_exp) || SQL_ISRULE(pColumnRef,char_value_fct)|| + SQL_ISRULE(pColumnRef,num_value_exp) || SQL_ISRULE(pColumnRef,term))*/ + { + /* Funktionsaufruf vorhanden */ + pColumnRef->parseNodeToStr(aColumnName,m_xDatabaseMetaData,NULL,FALSE,TRUE); + + // gehoeren alle beteiligten Spalten der Funktion zu einer Tabelle + if (m_aTables.size() == 1) + { + aTableRange = m_aTables.begin()->first; + } + else + { + getColumnTableRange(pColumnRef,aTableRange); + } + bFkt = TRUE; + } + /* + else + { + aIteratorStatus.setStatementTooComplex(); + return; + } + */ + if(!aColumnAlias.Len()) + aColumnAlias = aColumnName; + setSelectColumnName(aColumnName,aColumnAlias,aTableRange,bFkt); + } + } + + } else + { + //aIteratorStatus.setInvalidStatement(); + CallError(3); + } +} + + +//----------------------------------------------------------------------------- +void OSQLParseTreeIterator::traverseOrderByColumnNames(const OSQLParseNode* pSelectNode) +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + // aIteratorStatus.Clear(); + + if (pSelectNode == NULL) + { + //aIteratorStatus.setInvalidStatement(); + CallError(3); + return; + } + + if (m_eStatementType != SQL_STATEMENT_SELECT) + { + CallError(3); + //aIteratorStatus.setInvalidStatement(); + return; + } + + if(SQL_ISRULE(pSelectNode,union_statement)) + { + traverseOrderByColumnNames(pSelectNode->getChild(0)); + //traverseOrderByColumnNames(pSelectNode->getChild(3)); + return; + } + + DBG_ASSERT(pSelectNode->count() >= 4,"OSQLParseTreeIterator: Fehler im Parse Tree"); + + OSQLParseNode * pTableExp = pSelectNode->getChild(3); + DBG_ASSERT(pTableExp != NULL,"OSQLParseTreeIterator: Fehler im Parse Tree"); + DBG_ASSERT(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: Fehler im Parse Tree"); + DBG_ASSERT(pTableExp->count() == 5,"OSQLParseTreeIterator: Fehler im Parse Tree"); + + OSQLParseNode * pOptOrderByClause = pTableExp->getChild(4); + DBG_ASSERT(pOptOrderByClause != NULL,"OSQLParseTreeIterator: Fehler im Parse Tree"); + DBG_ASSERT(SQL_ISRULE(pOptOrderByClause,opt_order_by_clause),"OSQLParseTreeIterator: Fehler im Parse Tree"); + if (pOptOrderByClause->count() == 0) + return; + + DBG_ASSERT(pOptOrderByClause->count() == 3,"OSQLParseTreeIterator: Fehler im Parse Tree"); + + OSQLParseNode * pOrderingSpecCommalist = pOptOrderByClause->getChild(2); + DBG_ASSERT(pOrderingSpecCommalist != NULL,"OSQLParseTreeIterator: Fehler im Parse Tree"); + DBG_ASSERT(SQL_ISRULE(pOrderingSpecCommalist,ordering_spec_commalist),"OSQLParseTreeIterator: Fehler im Parse Tree"); + DBG_ASSERT(pOrderingSpecCommalist->count() > 0,"OSQLParseTreeIterator: Fehler im Parse Tree"); + + String aColumnName,aColumnAlias; + String aTableRange; + for (UINT32 i = 0; i < pOrderingSpecCommalist->count(); i++) + { + OSQLParseNode * pOrderingSpec = pOrderingSpecCommalist->getChild(i); + DBG_ASSERT(pOrderingSpec != NULL,"OSQLParseTreeIterator: Fehler im Parse Tree"); + DBG_ASSERT(SQL_ISRULE(pOrderingSpec,ordering_spec),"OSQLParseTreeIterator: Fehler im Parse Tree"); + DBG_ASSERT(pOrderingSpec->count() == 2,"OSQLParseTreeIterator: Fehler im Parse Tree"); + + OSQLParseNode * pColumnRef = pOrderingSpec->getChild(0); + aTableRange.Erase(); + aColumnName.Erase(); + if(SQL_ISRULE(pColumnRef,column_ref)) + { + // Column-Name (und TableRange): + if(SQL_ISRULE(pColumnRef,column_ref)) + getColumnRange(pColumnRef,aColumnName,aTableRange); + else // eine Expression + pColumnRef->parseNodeToStr(aColumnName,m_xDatabaseMetaData,NULL,FALSE,FALSE); + + DBG_ASSERT(aColumnName.Len(),"aColumnName darf nicht leer sein"); + } + else + { // here I found a predicate + pColumnRef->parseNodeToStr(aColumnName,m_xDatabaseMetaData,NULL,FALSE,FALSE); + } + DBG_ASSERT(pColumnRef != NULL,"OSQLParseTreeIterator: Fehler im Parse Tree"); + // Ascending/Descending + OSQLParseNode * pOptAscDesc = pOrderingSpec->getChild(1); + DBG_ASSERT(pOptAscDesc != NULL,"OSQLParseTreeIterator: Fehler im Parse Tree"); + + BOOL bAscending = TRUE; + if(pOptAscDesc) + { + if (SQL_ISTOKEN(pOptAscDesc,ASC)) + bAscending = TRUE; + else if (SQL_ISTOKEN(pOptAscDesc,DESC)) + bAscending = FALSE; + } + + setOrderByColumnName(aColumnName, aTableRange,bAscending); +// if (! aIteratorStatus.IsSuccessful()) +// return; + + } +} + +//----------------------------------------------------------------------------- +void OSQLParseTreeIterator::traverseSelectionCriteria(const OSQLParseNode* pSelectNode) +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + // aIteratorStatus.Clear(); + + if (pSelectNode == NULL) + { + CallError(3); + //aIteratorStatus.setInvalidStatement(); + return; + } + + + // Parse Tree analysieren (je nach Statement-Typ) + // und Zeiger auf WHERE-Klausel setzen: + OSQLParseNode * pWhereClause = NULL; + + if (m_eStatementType == SQL_STATEMENT_SELECT) + { + if(SQL_ISRULE(pSelectNode,union_statement)) + { + traverseSelectionCriteria(pSelectNode->getChild(0)); + traverseSelectionCriteria(pSelectNode->getChild(3)); + return; + } + DBG_ASSERT(pSelectNode->count() >= 4,"OSQLParseTreeIterator: Fehler im Parse Tree"); + + OSQLParseNode * pTableExp = pSelectNode->getChild(3); + DBG_ASSERT(pTableExp != NULL,"OSQLParseTreeIterator: Fehler im Parse Tree"); + DBG_ASSERT(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: Fehler im Parse Tree"); + DBG_ASSERT(pTableExp->count() == 5,"OSQLParseTreeIterator: Fehler im Parse Tree"); + + pWhereClause = pTableExp->getChild(1); + } else if (SQL_ISRULE(pSelectNode,update_statement_searched)) { + DBG_ASSERT(pSelectNode->count() == 5,"OSQLParseTreeIterator: Fehler im Parse Tree"); + pWhereClause = pSelectNode->getChild(4); + } else if (SQL_ISRULE(pSelectNode,update_statement_positioned)) { + // nyi + DBG_ERROR("OSQLParseTreeIterator::getSelectionCriteria: positioned nyi"); + } else if (SQL_ISRULE(pSelectNode,delete_statement_searched)) { + DBG_ASSERT(pSelectNode->count() == 4,"OSQLParseTreeIterator: Fehler im Parse Tree"); + pWhereClause = pSelectNode->getChild(3); + } else if (SQL_ISRULE(pSelectNode,delete_statement_positioned)) { + // nyi + DBG_ERROR("OSQLParseTreeIterator::getSelectionCriteria: positioned nyi"); + } else { + // Anderes Statement. Keine Selektionskriterien. + return; + } + + if (! SQL_ISRULE(pWhereClause,where_clause)) { + // Die Where Clause ist meistens optional, d. h. es koennte sich auch + // um "optional_where_clause" handeln. + DBG_ASSERT(SQL_ISRULE(pWhereClause,opt_where_clause),"OSQLParseTreeIterator: Fehler im Parse Tree"); + return; + } + + // Wenn es aber eine where_clause ist, dann darf sie nicht leer sein: + DBG_ASSERT(pWhereClause->count() == 2,"OSQLParseTreeIterator: Fehler im Parse Tree"); + + OSQLParseNode * pComparisonPredicate = pWhereClause->getChild(1); + DBG_ASSERT(pComparisonPredicate != NULL,"OSQLParseTreeIterator: Fehler im Parse Tree"); + + + // + // Und nun die Vergleichskriterien abarbeiten (rekursiv, alles ist erstmal ein OR-Kriterium): + // + setORCriteriaPre(); + // if (! aIteratorStatus.IsSuccessful()) return; + + traverseORCriteria(pComparisonPredicate); + // if (! aIteratorStatus.IsSuccessful()) return; + + setORCriteriaPost(); + + // Fehler wird ggf. einfach weitergereicht. +} + +//----------------------------------------------------------------------------- +void OSQLParseTreeIterator::traverseORCriteria(OSQLParseNode * pSearchCondition) +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + + if ( + pSearchCondition->count() == 3 && + SQL_ISPUNCTUATION(pSearchCondition->getChild(0),"(") && + SQL_ISPUNCTUATION(pSearchCondition->getChild(2),")") + ) + { + // Runde Klammern um den Ausdruck + traverseORCriteria(pSearchCondition->getChild(1)); + } else if (SQL_ISRULE(pSearchCondition,search_condition) && + pSearchCondition->count() == 3 && + SQL_ISTOKEN(pSearchCondition->getChild(1),OR)) + { + // OR-Verknuepfung: + + for (int i = 0; i < 3; i++) { + if (i == 1) continue; // Schluesselwort OR ueberspringen + + // Ist das erste Element wieder eine OR-Verknuepfung? + if (i == 0 && + SQL_ISRULE(pSearchCondition->getChild(0),search_condition) && + pSearchCondition->getChild(0)->count() == 3 && + SQL_ISTOKEN(pSearchCondition->getChild(0)->getChild(1),OR)) + { + // Dann rekursiv absteigen ... + traverseORCriteria(pSearchCondition->getChild(0)); + + } else { + // AND-Kriterien ... + setANDCriteriaPre(); + // if (! aIteratorStatus.IsSuccessful()) break; + + traverseANDCriteria(pSearchCondition->getChild(i)); + // if (! aIteratorStatus.IsSuccessful()) break; + + setANDCriteriaPost(); + } + + // if (! aIteratorStatus.IsSuccessful()) break; + } + } else { + // Nur *ein* Kriterium oder eine AND-Verknuepfung von Kriterien. + // Direkt die AND-Kriterien behandeln. + setANDCriteriaPre(); + // if (! aIteratorStatus.IsSuccessful()) return; + + traverseANDCriteria(pSearchCondition); + // if (! aIteratorStatus.IsSuccessful()) return; + + setANDCriteriaPost(); + } + + // Fehler einfach weiterreichen. +} + +//----------------------------------------------------------------------------- +void OSQLParseTreeIterator::traverseANDCriteria(OSQLParseNode * pSearchCondition) +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + + if ( + SQL_ISRULE(pSearchCondition,boolean_primary) && + pSearchCondition->count() == 3 && + SQL_ISPUNCTUATION(pSearchCondition->getChild(0),"(") && + SQL_ISPUNCTUATION(pSearchCondition->getChild(2),")") + ) + { + // Runde Klammern + traverseANDCriteria(pSearchCondition->getChild(1)); + } + // Das erste Element ist eine OR-Verknuepfung + else if ( SQL_ISRULE(pSearchCondition,search_condition) && pSearchCondition->count() == 3 ) + { + // Dann rekursiv absteigen (dieselbe Row benutzen) ... + traverseORCriteria(pSearchCondition->getChild(0)); +// if (! aIteratorStatus.IsSuccessful()) +// return; + + // Und mit dem rechten Child weitermachen: + traverseANDCriteria(pSearchCondition->getChild(2)); + } + // Das erste Element ist (wieder) eine AND-Verknuepfung + else if ( SQL_ISRULE(pSearchCondition,boolean_term) && pSearchCondition->count() == 3 ) + { + // Dann rekursiv absteigen (dieselbe Row benutzen) ... + traverseANDCriteria(pSearchCondition->getChild(0)); +// if (! aIteratorStatus.IsSuccessful()) +// return; + + // Und mit dem rechten Child weitermachen: + traverseANDCriteria(pSearchCondition->getChild(2)); + } + // Sonst einzelne Suchkriterien wie =, !=, ..., LIKE, IS NULL usw. behandeln: + else if (SQL_ISRULE(pSearchCondition,comparison_predicate) ) + { + OSQLPredicateType ePredicateType; + OSQLParseNode *pPrec = pSearchCondition->getChild(1); + if (pPrec->getNodeType() == SQL_NODE_EQUAL) + ePredicateType = SQL_PRED_EQUAL; + else if (pPrec->getNodeType() == SQL_NODE_NOTEQUAL) + ePredicateType = SQL_PRED_NOTEQUAL; + else if (pPrec->getNodeType() == SQL_NODE_LESS) + ePredicateType = SQL_PRED_LESS; + else if (pPrec->getNodeType() == SQL_NODE_LESSEQ) + ePredicateType = SQL_PRED_LESSOREQUAL; + else if (pPrec->getNodeType() == SQL_NODE_GREATEQ) + ePredicateType = SQL_PRED_GREATEROREQUAL; + else if (pPrec->getNodeType() == SQL_NODE_GREAT) + ePredicateType = SQL_PRED_GREATER; + + String aValue; + pSearchCondition->getChild(2)->parseNodeToStr(aValue,m_xDatabaseMetaData,NULL,FALSE,FALSE); + traverseOnePredicate(pSearchCondition->getChild(0),ePredicateType,aValue,FALSE,pSearchCondition->getChild(2)); +// if (! aIteratorStatus.IsSuccessful()) +// return; + } + else if (SQL_ISRULE(pSearchCondition,like_predicate) /*&& SQL_ISRULE(pSearchCondition->getChild(0),column_ref)*/) + { + OSQLPredicateType ePredicateType; + + DBG_ASSERT(pSearchCondition->count() >= 5,"OSQLParseTreeIterator: Fehler im Parse Tree"); + + OSQLParseNode * pNum_value_exp = pSearchCondition->getChild(3); + OSQLParseNode * pOptEscape = pSearchCondition->getChild(4); + + if (pSearchCondition->getChild(1)->getTokenID() == SQL_TOKEN_NOT) + ePredicateType = SQL_PRED_NOTLIKE; + else + ePredicateType = SQL_PRED_LIKE; + + DBG_ASSERT(pNum_value_exp != NULL,"OSQLParseTreeIterator: Fehler im Parse Tree"); + DBG_ASSERT(pOptEscape != NULL,"OSQLParseTreeIterator: Fehler im Parse Tree"); + + if (pOptEscape->count() != 0) + { + // aIteratorStatus.setStatementTooComplex(); + return; + } + + String aValue; + OSQLParseNode * pParam = NULL; + if (SQL_ISRULE(pNum_value_exp,parameter)) + pParam = pNum_value_exp; + else if(pNum_value_exp->isToken()) + // Normaler Wert + aValue = pNum_value_exp->getTokenValue(); + else + { + pNum_value_exp->parseNodeToStr(aValue,m_xDatabaseMetaData,NULL,FALSE,FALSE); + pParam = pNum_value_exp; + } + + traverseOnePredicate(pSearchCondition->getChild(0),ePredicateType,aValue,FALSE,pParam); +// if (! aIteratorStatus.IsSuccessful()) +// return; + } + else if (SQL_ISRULE(pSearchCondition,test_for_null) /*&& SQL_ISRULE(pSearchCondition->getChild(0),column_ref)*/) + { + OSQLPredicateType ePredicateType; + + DBG_ASSERT(pSearchCondition->count() >= 3,"OSQLParseTreeIterator: Fehler im Parse Tree"); + DBG_ASSERT(SQL_ISTOKEN(pSearchCondition->getChild(1),IS),"OSQLParseTreeIterator: Fehler im Parse Tree") + + if (SQL_ISTOKEN(pSearchCondition->getChild(2),NOT) ) + ePredicateType = SQL_PRED_ISNOTNULL; + else + ePredicateType = SQL_PRED_ISNULL; + + String aString; + traverseOnePredicate(pSearchCondition->getChild(0),ePredicateType,aString,TRUE,NULL); + // if (! aIteratorStatus.IsSuccessful()) return; + } else { + // Etwas anderes unterstuetzen wir (noch) nicht. Basta! + // aIteratorStatus.setStatementTooComplex(); + } + // Fehler einfach weiterreichen. +} + +//----------------------------------------------------------------------------- +void OSQLParseTreeIterator::traverseOnePredicate( + OSQLParseNode * pColumnRef, + OSQLPredicateType ePredicateType, + String& rValue, + BOOL bCompareNull, + OSQLParseNode * pParseNode) +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + + // Column-Name (und TableRange): + String aColumnName; + String aTableRange; + getColumnRange(pColumnRef,aColumnName,aTableRange); + + String aName; + if (pParseNode) //event. Parameter, oder Columnref oder + { + if (SQL_ISRULE(pParseNode,parameter)) + { + DBG_ASSERT(pParseNode->count() > 0,"OSQLParseTreeIterator: Fehler im Parse Tree"); + OSQLParseNode * pMark = pParseNode->getChild(0); + + String aParameterName; + if (SQL_ISPUNCTUATION(pMark,"?")) + { + // Name = "?", da kein Parametername verfuegbar (z. B. bei Native SQL) + rValue = '?'; + aName = '?'; + } + else if (SQL_ISPUNCTUATION(pMark,":")) + { + rValue = pParseNode->getChild(1)->getTokenValue(); + aName = ':'; + } + else if (SQL_ISPUNCTUATION(pMark,"[")) + { + rValue = pParseNode->getChild(1)->getTokenValue(); + aName = '['; + } + else + { + DBG_ERROR("OSQLParseTreeIterator: Fehler im Parse Tree"); + } + } + else if (SQL_ISRULE(pParseNode,column_ref))// Column-Name (und TableRange): + getColumnRange(pParseNode,aName,rValue); + } + + // "set"-Routine aufrufen ... + if (bCompareNull) { + // nyi: was soll das? Vergleich auf NULL geht nur ueber IS NULL oder IS NOT NULL! + setPredicate(aColumnName, aTableRange,ePredicateType, String(), String()); + } else { + setPredicate(aColumnName, aTableRange, ePredicateType, rValue, aName); + } + + // Fehler einfach weiterreichen ... +} + +//----------------------------------------------------------------------------- +void OSQLParseTreeIterator::traverseAssignments() +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + + DBG_ERROR("OSQLParseTreeIterator::traverseAssignments: noch nicht implementiert"); +} + +//----------------------------------------------------------------------------- +void OSQLParseTreeIterator::traverseAll() +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + + traverseTableNames(); + // if (! aIteratorStatus.IsSuccessful()) return; + + if (m_eStatementType == SQL_STATEMENT_SELECT) + { + const OSQLParseNode* pSelectNode = m_pParseTree; + traverseSelectColumnNames(pSelectNode); +// if (! aIteratorStatus.IsSuccessful()) +// return; + traverseOrderByColumnNames(pSelectNode); +// if (! aIteratorStatus.IsSuccessful()) +// return; + traverseSelectionCriteria(pSelectNode); + // if (! aIteratorStatus.IsSuccessful()) + // return; + } + else if (m_eStatementType == SQL_STATEMENT_INSERT || m_eStatementType == SQL_STATEMENT_UPDATE) + { + traverseAssignments(); + // if (! aIteratorStatus.IsSuccessful()) + // return; + } else if (m_eStatementType == SQL_STATEMENT_INSERT) { + // schon alles erledigt + } else { + CallError(3); + //aIteratorStatus.setInvalidStatement(); + } +} + +// Dummy-Implementationen: + +//----------------------------------------------------------------------------- +void OSQLParseTreeIterator::setTableName(const String & rTableName, const String & rDBName, const String& rOwner, + const String & rTableRange) +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + // nichts zu tun ... + +#ifdef SQL_TEST_PARSETREEITERATOR + cout << "OSQLParseTreeIterator::setTableName" + << (const char *) rTableName << ", " + << (const char *) rSchemaName << ", " + << (const char *) rTableRange + << "\n"; +#endif +} +//----------------------------------------------------------------------------- +void OSQLParseTreeIterator::appendColumns(const OSQLTable& _rTable) +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + if (!_rTable.is()) + return; + + Reference<XNameAccess> xColumns = _rTable->getColumns(); + + Sequence< ::rtl::OUString > aColNames = xColumns->getElementNames(); + const ::rtl::OUString* pBegin = aColNames.getConstArray(); + const ::rtl::OUString* pEnd = pBegin + aColNames.getLength(); + + for(;pBegin != pEnd;++pBegin) + { + OSQLColumns::const_iterator aIter = find(m_aSelectColumns->begin(),m_aSelectColumns->end(),*pBegin,m_aCaseEqual); + ::rtl::OUString aName(*pBegin); + sal_Int32 i=1; + while(aIter != m_aSelectColumns->end()) + { + aName = *pBegin + ::rtl::OUString::valueOf(i++); + aIter = find(m_aSelectColumns->begin(),m_aSelectColumns->end(),aName,m_aCaseEqual); + } + Reference< XFastPropertySet > xColumn; + if(xColumns->getByName(*pBegin) >>= xColumn) + { + OParseColumn* pColumn = new OParseColumn(xColumn,m_xDatabaseMetaData->storesMixedCaseQuotedIdentifiers()); + // pColumn->setTableName(aIter->first); + pColumn->setRealName(aName); + Reference< XFastPropertySet> xCol = pColumn; + m_aSelectColumns->push_back(xCol); + } + } +} +//----------------------------------------------------------------------------- +void OSQLParseTreeIterator::setSelectColumnName(const String & rColumnName,const String & rColumnAlias, const String & rTableRange,BOOL bFkt) +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + if(rColumnName.GetChar(0) == '*' && !rTableRange.Len()) + { // Suche "uber alle vorkommenden Tabellen + for(ConstOSQLTablesIterator aIter = m_aTables.begin(); aIter != m_aTables.end();++aIter) + appendColumns(aIter->second); + } + else if(rColumnName.GetChar(0) == '*' && rTableRange.Len()) // alle Columns aus dieser Tabelle + { + ConstOSQLTablesIterator aFind = m_aTables.find(rTableRange); + + if(aFind == m_aTables.end()) + { + String strExpression = rTableRange; + strExpression += '.'; + strExpression += rColumnName; + CallError(2, strExpression); + } + else + appendColumns(aFind->second); + } + else if(!rTableRange.Len())// ein Columnname existiert + { + if(!bFkt) + { + + UINT32 ncount = m_aSelectColumns->size(); + for(OSQLTablesIterator aIter = m_aTables.begin(); aIter != m_aTables.end(); ++aIter) + { + if (aIter->second.is()) + { + Reference<XNameAccess> xColumns = aIter->second->getColumns(); + + Reference< XFastPropertySet > xColumn; + if(xColumns->getByName(rColumnName) >>= xColumn) + { + String aNewColName(getUniqueColumnName(rColumnAlias)); + + OParseColumn* pColumn = new OParseColumn(xColumn,m_xDatabaseMetaData->storesMixedCaseQuotedIdentifiers()); + pColumn->setTableName(aIter->first); + pColumn->setName(aNewColName); + pColumn->setRealName(rColumnName); + + Reference< XFastPropertySet> xCol = pColumn; + m_aSelectColumns->push_back(xCol); + continue; // diese Column darf nur einmal vorkommen + } + } + } + if (ncount == m_aSelectColumns->size()) + { + String strExpression = rTableRange; + if (strExpression.Len()) + strExpression += '.'; + strExpression += rColumnName; + CallError(2, strExpression); + } + } + else + { + String aNewColName(getUniqueColumnName(rColumnAlias)); + + OParseColumn* pColumn = new OParseColumn(aNewColName,::rtl::OUString(),::rtl::OUString(), + ColumnValue::NULLABLE_UNKNOWN,0,0,DataType::VARCHAR,sal_False,sal_False,m_xDatabaseMetaData->storesMixedCaseQuotedIdentifiers()); + pColumn->setFunction(bFkt); + pColumn->setRealName(rColumnName); + + Reference< XFastPropertySet> xCol = pColumn; + m_aSelectColumns->push_back(xCol); + } + } + else // ColumnName und Tablename vorhanden + { + ConstOSQLTablesIterator aFind = m_aTables.find(rTableRange); + + BOOL bError = FALSE; + if (aFind->second.is()) + { + + if (bFkt) + { + String aNewColName(getUniqueColumnName(rColumnAlias)); + + OParseColumn* pColumn = new OParseColumn(aNewColName,::rtl::OUString(),::rtl::OUString(), + ColumnValue::NULLABLE_UNKNOWN,0,0,DataType::VARCHAR,sal_False,sal_False,m_xDatabaseMetaData->storesMixedCaseQuotedIdentifiers()); + pColumn->setFunction(sal_True); + pColumn->setRealName(rColumnName); + pColumn->setTableName(aFind->first); + + Reference< XFastPropertySet> xCol = pColumn; + m_aSelectColumns->push_back(xCol); + } + else + { + Reference< XFastPropertySet > xColumn; + if (aFind->second->getColumns()->getByName(rColumnName) >>= xColumn) + { + String aNewColName(getUniqueColumnName(rColumnAlias)); + + OParseColumn* pColumn = new OParseColumn(xColumn,m_xDatabaseMetaData->storesMixedCaseQuotedIdentifiers()); + pColumn->setName(aNewColName); + pColumn->setRealName(rColumnName); + pColumn->setTableName(aFind->first); + + Reference< XFastPropertySet> xCol = pColumn; + m_aSelectColumns->push_back(xCol); + } + else + bError = TRUE; + } + } + else + bError = TRUE; + + // Tabelle existiert nicht oder Feld nicht vorhanden + if (bError) + { + String strExpression = rTableRange; + if (strExpression.Len()) + strExpression += '.'; + strExpression += rColumnName; + if (!CallError(2, strExpression)) + return; + + String aNewColName(getUniqueColumnName(rColumnAlias)); + + OParseColumn* pColumn = new OParseColumn(aNewColName,::rtl::OUString(),::rtl::OUString(), + ColumnValue::NULLABLE_UNKNOWN,0,0,DataType::VARCHAR,sal_False,sal_False,m_xDatabaseMetaData->storesMixedCaseQuotedIdentifiers()); + pColumn->setFunction(sal_True); + + + Reference< XFastPropertySet> xCol = pColumn; + m_aSelectColumns->push_back(xCol); + } + } +} +//----------------------------------------------------------------------------- +String OSQLParseTreeIterator::getUniqueColumnName(const String & rColumnName) const +{ + ::rtl::OUString aAlias(rColumnName); + + OSQLColumns::const_iterator aIter = find(m_aSelectColumns->begin(),m_aSelectColumns->end(),aAlias,m_aCaseEqual); + sal_Int32 i=1; + while(aIter != m_aSelectColumns->end()) + { + (aAlias = rColumnName) += ::rtl::OUString::valueOf(i++); + aIter = find(m_aSelectColumns->begin(),m_aSelectColumns->end(),aAlias,m_aCaseEqual); + } + return aAlias; +} +//----------------------------------------------------------------------------- +void OSQLParseTreeIterator::setOrderByColumnName(const String & rColumnName, const String & rTableRange,BOOL bAscending) +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + // nichts zu tun ... + +#ifdef SQL_TEST_PARSETREEITERATOR + cout << "OSQLParseTreeIterator::setOrderByColumnName: " + << (const char *) rColumnName << ", " + << (const char *) rTableRange << ", " + << (bAscending ? "TRUE" : "FALSE") + << "\n"; +#endif +} + +//----------------------------------------------------------------------------- +void OSQLParseTreeIterator::setORCriteriaPre() +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + // nichts zu tun ... + +#ifdef SQL_TEST_PARSETREEITERATOR + cout << "OSQLParseTreeIterator::setORCriteriaPre\n"; +#endif +} + +//----------------------------------------------------------------------------- +void OSQLParseTreeIterator::setORCriteriaPost() +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + // nichts zu tun ... + +#ifdef SQL_TEST_PARSETREEITERATOR + cout << "OSQLParseTreeIterator::setORCriteriaPost\n"; +#endif +} + +//----------------------------------------------------------------------------- +void OSQLParseTreeIterator::setANDCriteriaPre() +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + // nichts zu tun ... + +#ifdef SQL_TEST_PARSETREEITERATOR + cout << "OSQLParseTreeIterator::setANDCriteriaPre\n"; +#endif +} + +//----------------------------------------------------------------------------- +void OSQLParseTreeIterator::setANDCriteriaPost() +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + // nichts zu tun ... + +#ifdef SQL_TEST_PARSETREEITERATOR + cout << "OSQLParseTreeIterator::setANDCriteriaPost\n"; +#endif +} + +//----------------------------------------------------------------------------- +void OSQLParseTreeIterator::setPredicate(const String & rColumnName, + const String & rTableRange, + OSQLPredicateType ePredicateType, + const String & rValue, + const String & rParameterName) +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + // nichts zu tun ... + +#ifdef SQL_TEST_PARSETREEITERATOR + cout << "OSQLParseTreeIterator::setPredicate: " + << (const char *) rColumnName << ", " + << (const char *) rTableRange << ", " + << (char) ePredicateType << ", " + << (const char *) rValue << ", " + << (const char *) rParameterName + << "\n"; +#endif +} + + +//----------------------------------------------------------------------------- +void OSQLParseTreeIterator::setAssign(const String & rColumnName, + const String & rValue, BOOL bsetNull, + const String & rParameterName) +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + // nichts zu tun ... + +#ifdef SQL_TEST_PARSETREEITERATOR + cout << "OSQLParseTreeIterator::setAssign: " + << (const char *) rColumnName << ", " + << (const char *) rValue << ", " + << (bsetNull ? "TRUE" : "FALSE") << ", " + << (const char *) rParameterName + << "\n"; +#endif +} + +//----------------------------------------------------------------------------- +const OSQLParseNode* OSQLParseTreeIterator::getWhereTree() const +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + + if (!m_pParseTree) + return NULL; + + // Parse Tree analysieren (je nach Statement-Typ) + // und Zeiger auf WHERE-Klausel setzen: + OSQLParseNode * pWhereClause = NULL; + if(getStatementType() == SQL_STATEMENT_SELECT) + { + DBG_ASSERT(m_pParseTree->count() >= 4,"ParseTreeIterator: Fehler im Parse Tree"); + OSQLParseNode * pTableExp = m_pParseTree->getChild(3); + DBG_ASSERT(pTableExp != NULL,"OSQLParseTreeIterator: Fehler im Parse Tree"); + DBG_ASSERT(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: Fehler im Parse Tree"); + DBG_ASSERT(pTableExp->count() == 5,"OSQLParseTreeIterator: Fehler im Parse Tree"); + + pWhereClause = pTableExp->getChild(1); + } + else if (SQL_ISRULE(m_pParseTree,update_statement_searched) || + SQL_ISRULE(m_pParseTree,delete_statement_searched)) + { + pWhereClause = m_pParseTree->getChild(m_pParseTree->count()-1); + } + if(pWhereClause->count() != 2) + pWhereClause = NULL; + return pWhereClause; +} + +//----------------------------------------------------------------------------- +const OSQLParseNode* OSQLParseTreeIterator::getOrderTree() const +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + + if (!m_pParseTree || getStatementType() != SQL_STATEMENT_SELECT) + return NULL; + + // Parse Tree analysieren (je nach Statement-Typ) + // und Zeiger auf ORDER-Klausel setzen: + OSQLParseNode * pOrderClause = NULL; + DBG_ASSERT(m_pParseTree->count() >= 4,"ParseTreeIterator: Fehler im Parse Tree"); + OSQLParseNode * pTableExp = m_pParseTree->getChild(3); + DBG_ASSERT(pTableExp != NULL,"OSQLParseTreeIterator: Fehler im Parse Tree"); + DBG_ASSERT(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: Fehler im Parse Tree"); + DBG_ASSERT(pTableExp->count() == 5,"OSQLParseTreeIterator: Fehler im Parse Tree"); + + pOrderClause = pTableExp->getChild(4); + // Wenn es aber eine order_by ist, dann darf sie nicht leer sein: + if(pOrderClause->count() != 3) + pOrderClause = NULL; + return pOrderClause; +} +//----------------------------------------------------------------------------- +const OSQLParseNode* OSQLParseTreeIterator::getGroupByTree() const +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + + if (!m_pParseTree || getStatementType() != SQL_STATEMENT_SELECT) + return NULL; + + // Parse Tree analysieren (je nach Statement-Typ) + // und Zeiger auf ORDER-Klausel setzen: + OSQLParseNode * pGroupClause = NULL; + DBG_ASSERT(m_pParseTree->count() >= 4,"ParseTreeIterator: Fehler im Parse Tree"); + OSQLParseNode * pTableExp = m_pParseTree->getChild(3); + DBG_ASSERT(pTableExp != NULL,"OSQLParseTreeIterator: Fehler im Parse Tree"); + DBG_ASSERT(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: Fehler im Parse Tree"); + DBG_ASSERT(pTableExp->count() == 5,"OSQLParseTreeIterator: Fehler im Parse Tree"); + + pGroupClause = pTableExp->getChild(3); + // Wenn es aber eine order_by ist, dann darf sie nicht leer sein: + if(pGroupClause->count() != 3) + pGroupClause = NULL; + return pGroupClause; +} +//----------------------------------------------------------------------------- +const OSQLParseNode* OSQLParseTreeIterator::getHavingTree() const +{ + DBG_CHKTHIS(OSQLParseTreeIterator,NULL); + + if (!m_pParseTree || getStatementType() != SQL_STATEMENT_SELECT) + return NULL; + + // Parse Tree analysieren (je nach Statement-Typ) + // und Zeiger auf ORDER-Klausel setzen: + OSQLParseNode * pHavingClause = NULL; + DBG_ASSERT(m_pParseTree->count() >= 4,"ParseTreeIterator: Fehler im Parse Tree"); + OSQLParseNode * pTableExp = m_pParseTree->getChild(3); + DBG_ASSERT(pTableExp != NULL,"OSQLParseTreeIterator: Fehler im Parse Tree"); + DBG_ASSERT(SQL_ISRULE(pTableExp,table_exp),"OSQLParseTreeIterator: Fehler im Parse Tree"); + DBG_ASSERT(pTableExp->count() == 5,"OSQLParseTreeIterator: Fehler im Parse Tree"); + + pHavingClause = pTableExp->getChild(3); + // Wenn es aber eine order_by ist, dann darf sie nicht leer sein: + if(pHavingClause->count() < 1) + pHavingClause = NULL; + return pHavingClause; +} +//----------------------------------------------------------------------------- +BOOL OSQLParseTreeIterator::CallError(USHORT nError,const String& rExpression) +{ +// SdbParseIteratorErrorInfo aErrorInfo; +// aErrorInfo.aStatus = rStatus; +// aErrorInfo.nErrorCode = nError; +// aErrorInfo.aExpression = rExpression; +// +// long nResult = aErrorHdl.Call(&aErrorInfo); +// if (nResult == RET_CONTINUE) + return TRUE; + +// if (nResult == RET_HANDLED) +// { +// // aIteratorStatus.set(SQL_STAT_SUCCESS); +// return FALSE; +// } +// +// aIteratorStatus = rStatus; +// return FALSE; +// +} + diff --git a/connectivity/source/parse/sqlnode.cxx b/connectivity/source/parse/sqlnode.cxx new file mode 100644 index 000000000000..f35c06bf8f25 --- /dev/null +++ b/connectivity/source/parse/sqlnode.cxx @@ -0,0 +1,1399 @@ +/************************************************************************* + * + * $RCSfile: sqlnode.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-18 16:14:28 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source 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.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ +#ifndef _CONNECTIVITY_SQLNODE_HXX +#include <connectivity/sqlnode.hxx> +#endif +#ifndef _CONNECTIVITY_SQLPARSE_HXX +#include <connectivity/sqlparse.hxx> +#endif +#ifndef _COM_SUN_STAR_LANG_LOCALE_HPP_ +#include <com/sun/star/lang/Locale.hpp> +#endif +#ifndef _COM_SUN_STAR_UTIL_XNUMBERFORMATTER_HPP_ +#include <com/sun/star/util/XNumberFormatter.hpp> +#endif +#ifndef _COM_SUN_STAR_UTIL_XNUMBERFORMATTYPES_HPP_ +#include <com/sun/star/util/XNumberFormatTypes.hpp> +#endif +#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ +#include <com/sun/star/beans/XPropertySet.hpp> +#endif +#ifndef _COM_SUN_STAR_SDBC_XDATABASEMETADATA_HPP_ +#include <com/sun/star/sdbc/XDatabaseMetaData.hpp> +#endif +#ifndef _TOOLS_INTN_HXX //autogen wg. International +#include <tools/intn.hxx> +#endif +#ifndef _ISOLANG_HXX +#include <tools/isolang.hxx> +#endif + +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::osl; +using namespace connectivity; + +extern Any getNumberFormatProperty(const Reference< XNumberFormatsSupplier > & xFormatter, + sal_Int32 nKey, + const rtl::OUString& ); +extern double ToDouble(const Time& rTime); +extern double ToDouble(const Reference< XNumberFormatsSupplier > & xSupplier, const Date& rDate); +extern String ConvertLikeToken(const OSQLParseNode* pTokenNode, const OSQLParseNode* pEscapeNode, sal_Bool bInternational); + +//------------------------------------------------------------------ +OSQLParseNode::SQLParseNodeParameter::SQLParseNodeParameter(const String& _rIdentifierQuote, const String& _rCatalogSep, + const Reference< XNumberFormatter > & _xFormatter, const Reference< XPropertySet > & _xField, const International& _rIntl, + const OParseContext* _pContext, sal_Bool _bIntl, sal_Bool _bQuote, char _cDecSep, + sal_Bool _bPredicate) + :aIdentifierQuote(_rIdentifierQuote) + ,aCatalogSeparator(_rCatalogSep) + ,rIntl(_rIntl) + ,rContext(_pContext ? *_pContext : OSQLParser::s_aDefaultContext) + ,bInternational(_bIntl) + ,bQuote(_bQuote) + ,cDecSep(_cDecSep) + ,xField(_xField) + ,xFormatter(_xFormatter) + ,bPredicate(_bPredicate) +{ +} + +//------------------------------------------------------------------ +String SetQuotation(const String& rValue, const String& rQuot, const String& rQuotToReplace) +{ + String rNewValue = rQuot; + rNewValue += rValue; + + xub_StrLen nIndex = (xub_StrLen)-1; // Quotes durch zweifache Quotes ersetzen, sonst kriegt der Parser Probleme + + if (rQuot.Len()) + { + do + { + nIndex+= 2; + nIndex = rNewValue.SearchAndReplace(rQuot,rQuotToReplace,nIndex); + } while (nIndex != STRING_NOTFOUND); + } + // rNewValue.SearchAndReplaceAll(rQuot,rQuotToReplace); + + rNewValue += rQuot; + return rNewValue; +} + + +//----------------------------------------------------------------------------- +String OSQLParseNode::convertDateString(const SQLParseNodeParameter& rParam, const String& rString) const +{ + xub_StrLen nIndex = 0; + sal_Int32 nYear = rString.GetToken(0,'-', nIndex).ToInt32(), + nMonth = rString.GetToken(0,'-', nIndex).ToInt32(), + nDay = rString.GetToken(0,'-', nIndex).ToInt32(); + + Date aDate(nDay,nMonth,nYear); + Reference< XNumberFormatsSupplier > xSupplier(rParam.xFormatter->getNumberFormatsSupplier()); + Reference< XNumberFormatTypes > xTypes(xSupplier->getNumberFormats(), UNO_QUERY); + + String sLanguage, sCountry; + ConvertLanguageToIsoNames(rParam.rIntl.GetLanguage(), sLanguage, sCountry); + Locale aLocale(sLanguage,sCountry,rtl::OUString()); + + double fDate = ToDouble(xSupplier, aDate); + sal_Int32 nKey = xTypes->getStandardIndex(aLocale) + 36; // XXX hack + return rParam.xFormatter->convertNumberToString(nKey, fDate); +} + +//----------------------------------------------------------------------------- +String OSQLParseNode::convertDateTimeString(const SQLParseNodeParameter& rParam, const String& rString) const +{ + xub_StrLen nIndex = 0; + sal_Int32 nYear = rString.GetToken(0,'-', nIndex).ToInt32(), + nMonth = rString.GetToken(0,'-', nIndex).ToInt32(), + nDay = rString.GetToken(0,'-', nIndex).ToInt32(); + + nIndex = 10; // eat white space + sal_Int32 nHour = rString.GetToken(0,':', nIndex).ToInt32(), + nMinute = rString.GetToken(0,':', nIndex).ToInt32(), + nSecond = rString.GetToken(0,':', nIndex).ToInt32(); + + Date aDate(nDay,nMonth,nYear); + Time aTime(nHour,nMinute,nSecond); + Reference< XNumberFormatsSupplier > xSupplier(rParam.xFormatter->getNumberFormatsSupplier()); + Reference< XNumberFormatTypes > xTypes(xSupplier->getNumberFormats(), UNO_QUERY); + + String sLanguage, sCountry; + ConvertLanguageToIsoNames(rParam.rIntl.GetLanguage(), sLanguage, sCountry); + Locale aLocale(sLanguage,sCountry,rtl::OUString()); + + double fDateTime = ToDouble(xSupplier, aDate) + ToDouble(aTime); + sal_Int32 nKey = xTypes->getStandardIndex(aLocale) + 51; // XXX hack + return rParam.xFormatter->convertNumberToString(nKey, fDateTime); +} + +//----------------------------------------------------------------------------- +String OSQLParseNode::convertTimeString(const SQLParseNodeParameter& rParam, const String& rString) const +{ + xub_StrLen nIndex = 0; + sal_Int32 nHour = rString.GetToken(0,':', nIndex).ToInt32(), + nMinute = rString.GetToken(0,':', nIndex).ToInt32(), + nSecond = rString.GetToken(0,':', nIndex).ToInt32(); + + Time aTime(nHour,nMinute,nSecond); + Reference< XNumberFormatsSupplier > xSupplier(rParam.xFormatter->getNumberFormatsSupplier()); + + Reference< XNumberFormatTypes > xTypes(xSupplier->getNumberFormats(), UNO_QUERY); + + String sLanguage, sCountry; + ConvertLanguageToIsoNames(rParam.rIntl.GetLanguage(), sLanguage, sCountry); + Locale aLocale(sLanguage,sCountry,rtl::OUString()); + + double fTime = ToDouble(aTime); + sal_Int32 nKey = xTypes->getStandardIndex(aLocale) + 41; // XXX hack + return rParam.xFormatter->convertNumberToString(nKey, fTime); +} + +DBG_NAME(OSQLParseNode); +//----------------------------------------------------------------------------- +OSQLParseNode::OSQLParseNode(const sal_Char * pNewValue, + SQLNodeType eNewNodeType, + sal_uInt32 nNewNodeID) + : m_aNodeValue(String::CreateFromAscii(pNewValue)) + , m_eNodeType(eNewNodeType) + , m_nNodeID(nNewNodeID) + , m_pParent(NULL) +{ + DBG_CTOR(OSQLParseNode,NULL); + DBG_ASSERT(m_eNodeType >= SQL_NODE_RULE && m_eNodeType <= SQL_NODE_ACCESS_DATE,"OSQLParseNode: mit unzulaessigem NodeType konstruiert"); +} +//----------------------------------------------------------------------------- +OSQLParseNode::OSQLParseNode(const ByteString &_rNewValue, + SQLNodeType eNewNodeType, + sal_uInt32 nNewNodeID) + : m_aNodeValue(String::CreateFromAscii(_rNewValue.GetBuffer())) + , m_eNodeType(eNewNodeType) + , m_nNodeID(nNewNodeID) + , m_pParent(NULL) +{ + DBG_CTOR(OSQLParseNode,NULL); + DBG_ASSERT(m_eNodeType >= SQL_NODE_RULE && m_eNodeType <= SQL_NODE_ACCESS_DATE,"OSQLParseNode: mit unzulaessigem NodeType konstruiert"); +} +//----------------------------------------------------------------------------- +OSQLParseNode::OSQLParseNode(const sal_Unicode * pNewValue, + SQLNodeType eNewNodeType, + sal_uInt32 nNewNodeID) + : m_aNodeValue(pNewValue) + , m_eNodeType(eNewNodeType) + , m_nNodeID(nNewNodeID) + , m_pParent(NULL) +{ + DBG_CTOR(OSQLParseNode,NULL); + DBG_ASSERT(m_eNodeType >= SQL_NODE_RULE && m_eNodeType <= SQL_NODE_ACCESS_DATE,"OSQLParseNode: mit unzulaessigem NodeType konstruiert"); +} +//----------------------------------------------------------------------------- +OSQLParseNode::OSQLParseNode(const String &_rNewValue, + SQLNodeType eNewNodeType, + sal_uInt32 nNewNodeID) + : m_aNodeValue(_rNewValue) + , m_eNodeType(eNewNodeType) + , m_nNodeID(nNewNodeID) + , m_pParent(NULL) +{ + DBG_CTOR(OSQLParseNode,NULL); + DBG_ASSERT(m_eNodeType >= SQL_NODE_RULE && m_eNodeType <= SQL_NODE_ACCESS_DATE,"OSQLParseNode: mit unzulaessigem NodeType konstruiert"); +} +//----------------------------------------------------------------------------- +OSQLParseNode::OSQLParseNode(const OSQLParseNode& rParseNode) +{ + DBG_CTOR(OSQLParseNode,NULL); + // klemm den getParent auf NULL + m_pParent = NULL; + + // kopiere die member + m_aNodeValue = rParseNode.m_aNodeValue; + m_eNodeType = rParseNode.m_eNodeType; + m_nNodeID = rParseNode.m_nNodeID; + + + // denk dran, dass von Container abgeleitet wurde, laut SV-Help erzeugt + // copy-Constructor des Containers einen neuen Container mit den gleichen + // Zeigern als Inhalt -> d.h. nach dem Kopieren des Container wird fuer + // alle Zeiger ungleich NULL eine Kopie hergestellt und anstelle des alten + // Zeigers wieder eingehangen. + + // wenn kein Blatt, dann SubTrees bearbeiten + for (::std::vector<OSQLParseNode*>::const_iterator i = rParseNode.m_aChilds.begin(); + i != rParseNode.m_aChilds.end(); i++) + append(new OSQLParseNode(**i)); +} + +//----------------------------------------------------------------------------- +OSQLParseNode& OSQLParseNode::operator=(const OSQLParseNode& rParseNode) +{ + DBG_CHKTHIS(OSQLParseNode,NULL); + + if (this != &rParseNode) + { + // kopiere die member - pParent bleibt der alte + m_aNodeValue = rParseNode.m_aNodeValue; + m_eNodeType = rParseNode.m_eNodeType; + m_nNodeID = rParseNode.m_nNodeID; + + for (::std::vector<OSQLParseNode*>::const_iterator i = m_aChilds.begin(); + i != m_aChilds.end(); i++) + delete *i; + + m_aChilds.clear(); + + for (::std::vector<OSQLParseNode*>::const_iterator j = rParseNode.m_aChilds.begin(); + j != rParseNode.m_aChilds.end(); j++) + append(new OSQLParseNode(**j)); + } + return *this; +} + +//----------------------------------------------------------------------------- +sal_Bool OSQLParseNode::operator==(OSQLParseNode& rParseNode) const +{ + DBG_CHKTHIS(OSQLParseNode,NULL); + + // die member muessen gleich sein + sal_Bool bResult = (m_nNodeID == rParseNode.m_nNodeID) && + (m_eNodeType == rParseNode.m_eNodeType) && + (m_aNodeValue == rParseNode.m_aNodeValue) && + count() == rParseNode.count(); + + // Parameters are not equal! + bResult = bResult && !SQL_ISRULE(this, parameter); + + // compare childs + for (sal_uInt32 i=0; bResult && i < count(); i++) + bResult = *getChild(i) == *rParseNode.getChild(i); + + return bResult; +} + +//----------------------------------------------------------------------------- +OSQLParseNode::~OSQLParseNode() +{ + DBG_DTOR(OSQLParseNode,NULL); + + for (::std::vector<OSQLParseNode*>::const_iterator i = m_aChilds.begin(); + i != m_aChilds.end(); i++) + delete *i; +} + +//----------------------------------------------------------------------------- +void OSQLParseNode::append(OSQLParseNode* pNewNode) +{ + DBG_CHKTHIS(OSQLParseNode,NULL); + DBG_ASSERT(pNewNode != NULL, "OSQLParseNode: ungueltiger NewSubTree"); + DBG_ASSERT(pNewNode->getParent() == NULL, "OSQLParseNode: Knoten ist kein Waise"); + DBG_ASSERT(::std::find(m_aChilds.begin(), m_aChilds.end(), pNewNode) == m_aChilds.end(), + "OSQLParseNode::append() Node already element of parent"); + + // stelle Verbindung zum getParent her: + pNewNode->setParent( this ); + // und haenge den SubTree hinten an + m_aChilds.push_back(pNewNode); +} + +//----------------------------------------------------------------------------- +void OSQLParseNode::parseNodeToStr(String& rString, + const Reference< XDatabaseMetaData > & xMeta, + OParseContext* pContext, + sal_Bool _bIntl, + sal_Bool _bQuote) const +{ + DBG_CHKTHIS(OSQLParseNode,NULL); + parseNodeToStr(rString, xMeta, Reference< XNumberFormatter >(), + Reference< XPropertySet >(), OParseContext::getDefaultInternational(), pContext, _bIntl, _bQuote, '.', sal_False); +} + +//----------------------------------------------------------------------------- +void OSQLParseNode::parseNodeToPredicateStr(String& rString, + const Reference< XDatabaseMetaData > & xMeta, + const Reference< XNumberFormatter > & xFormatter, + const International& rIntl, + OParseContext* pContext ) const +{ + DBG_CHKTHIS(OSQLParseNode,NULL); + DBG_ASSERT(xFormatter.is(), "OSQLParseNode::parseNodeToPredicateStr:: no formatter!"); + + if (xFormatter.is()) + parseNodeToStr(rString, xMeta, xFormatter, Reference< XPropertySet >(), rIntl, pContext, sal_True, sal_True, rIntl.GetNumDecimalSep(), sal_True); +} + +//----------------------------------------------------------------------------- +void OSQLParseNode::parseNodeToPredicateStr(String& rString, + const Reference< XDatabaseMetaData > & xMeta, + const Reference< XNumberFormatter > & xFormatter, + const Reference< XPropertySet > & _xField, + const International& rIntl, + OParseContext* pContext ) const +{ + DBG_CHKTHIS(OSQLParseNode,NULL); + DBG_ASSERT(xFormatter.is(), "OSQLParseNode::parseNodeToPredicateStr:: no formatter!"); + + if (xFormatter.is()) + parseNodeToStr(rString, xMeta, xFormatter, _xField, rIntl, pContext, sal_True, sal_True, rIntl.GetNumDecimalSep(), sal_True); +} + +//----------------------------------------------------------------------------- +void OSQLParseNode::parseNodeToStr(String& rString, + const Reference< XDatabaseMetaData > & xMeta, + const Reference< XNumberFormatter > & xFormatter, + const Reference< XPropertySet > & _xField, + const International& rIntl, + OParseContext* pContext, + sal_Bool _bIntl, + sal_Bool _bQuote, + char _cDecSep, + sal_Bool bPredicate) const +{ + DBG_CHKTHIS(OSQLParseNode,NULL); + DBG_ASSERT(xMeta.is(), "OSQLParseNode::parseNodeToStr:: no meta data!"); + + if (xMeta.is()) + { + String aIdentifierQuote(xMeta->getIdentifierQuoteString()); + String aCatalogSeparator(xMeta->getCatalogSeparator()); + + OSQLParseNode::parseNodeToStr(rString, + SQLParseNodeParameter(aIdentifierQuote, aCatalogSeparator, xFormatter, _xField, rIntl, pContext, _bIntl, _bQuote, _cDecSep, bPredicate)); + } +} +//----------------------------------------------------------------------------- +void OSQLParseNode::parseNodeToStr(String& rString, const SQLParseNodeParameter& rParam) const +{ + DBG_CHKTHIS(OSQLParseNode,NULL); + + if (!isToken()) + { + // einmal auswerten wieviel Subtrees dieser Knoten besitzt + sal_uInt32 nCount = count(); + + // parameter erhalten sonderbehandlung + if (SQL_ISRULE(this,parameter)) + { + if(rString.Len()) + rString += ' '; + if (nCount == 1) // ? + m_aChilds[0]->parseNodeToStr(rString, rParam); + else if (nCount == 2) // :Name + { + m_aChilds[0]->parseNodeToStr(rString, rParam); + rString += m_aChilds[1]->m_aNodeValue; + } // [Name] + else + { + m_aChilds[0]->parseNodeToStr(rString, rParam); + rString += m_aChilds[1]->m_aNodeValue; + rString += m_aChilds[2]->m_aNodeValue; + } + } + + else if(SQL_ISRULE(this,table_ref) && + ((nCount == 4 && SQL_ISPUNCTUATION(m_aChilds[0],"("))|| (nCount == 6 && SQL_ISPUNCTUATION(m_aChilds[0],"(")))) + tableRangeNodeToStr(rString, rParam); + // je nachdem ob international angegeben wird oder nicht wird like anders behandelt + // interanational: *, ? sind Platzhalter + // sonst SQL92 konform: %, _ + else if (SQL_ISRULE(this,like_predicate)) + likeNodeToStr(rString, rParam); + + else if (SQL_ISRULE(this,general_set_fct) || SQL_ISRULE(this,set_fct_spec) || + SQL_ISRULE(this,position_exp) || SQL_ISRULE(this,extract_exp) || + SQL_ISRULE(this,length_exp) || SQL_ISRULE(this,char_value_fct)) + { + if (!addDateValue(rString, rParam)) + { + // Funktionsname nicht quoten + SQLParseNodeParameter aNewParam(rParam); + aNewParam.bQuote = sal_False; + + m_aChilds[0]->parseNodeToStr(rString, aNewParam); + String aStringPara; + for (sal_uInt32 i=1; i<nCount; i++) + { + const OSQLParseNode * pSubTree = m_aChilds[i]; + if (pSubTree) + { + pSubTree->parseNodeToStr(aStringPara, rParam); + + // bei den CommaListen zwischen alle Subtrees Commas setzen + if ((m_eNodeType == SQL_NODE_COMMALISTRULE) && (i < (nCount - 1))) + aStringPara += String(','); + } + } + aStringPara.EraseTrailingChars(' '); + rString += aStringPara; + } + } + else + { + for (::std::vector<OSQLParseNode*>::const_iterator i = m_aChilds.begin(); + i != m_aChilds.end();) + { + const OSQLParseNode* pSubTree = *i; + if (pSubTree) + { + SQLParseNodeParameter aNewParam(rParam); + + // don't replace the field for subqueries + if (rParam.xField.is() && SQL_ISRULE(pSubTree,subquery)) + aNewParam.xField = NULL; + + // if there is a field given we don't display the fieldname, if there are any + if (rParam.xField.is() && SQL_ISRULE(pSubTree,column_ref)) + { + sal_Bool bFilter = sal_False; + // retrieve the fields name + String aFieldName; + try + { + // retrieve the fields name + rtl::OUString aString; + rParam.xField->getPropertyValue(String::CreateFromAscii("Name")) >>= aString; + aFieldName = aString.getStr(); + } + catch ( ... ) + { + } + + const OSQLParseNode* pCol = pSubTree->m_aChilds[pSubTree->count()-1]; + if ((SQL_ISRULE(pCol,column_val) && pCol->getChild(0)->getTokenValue().EqualsIgnoreCaseAscii(aFieldName)) || + pCol->getTokenValue().EqualsIgnoreCaseAscii(aFieldName)) + bFilter = sal_True; + + // ok we found the field, if the following node is the + // comparision operator '=' we filter it as well + if (bFilter) + { + if (SQL_ISRULE(this, comparison_predicate)) + { + ++i; + if(i != m_aChilds.end()) + { + pSubTree = *i; + if (pSubTree && pSubTree->getNodeType() == SQL_NODE_EQUAL) + i++; + } + } + else + i++; + } + else + { + pSubTree->parseNodeToStr(rString, aNewParam); + i++; + + // bei den CommaListen zwischen alle Subtrees Commas setzen + if ((m_eNodeType == SQL_NODE_COMMALISTRULE) && (i != m_aChilds.end())) + rString += String(','); + } + } + else + { + pSubTree->parseNodeToStr(rString, aNewParam); + i++; + + // bei den CommaListen zwischen alle Subtrees Commas setzen + if ((m_eNodeType == SQL_NODE_COMMALISTRULE) && (i != m_aChilds.end())) + { + if (SQL_ISRULE(this,value_exp_commalist) && rParam.bPredicate) + rString += String(';'); + else + rString += String(','); + } + } + } + } + } + } + else + { + // ein Blatt ist gefunden + // Inhalt dem Ausgabestring anfuegen + switch (m_eNodeType) + { + case SQL_NODE_KEYWORD: + { + if (rString.Len()) + rString += ' '; + + rString += String::CreateFromAscii( + OSQLParser::TokenIDToStr(m_nNodeID, &const_cast<OParseContext&>(rParam.rContext)).GetBuffer()); + } break; + case SQL_NODE_STRING: + if (rString.Len()) + rString += ' '; + rString += SetQuotation(m_aNodeValue,String::CreateFromAscii("\'"),String::CreateFromAscii("\'\'")); + break; + case SQL_NODE_NAME: + if (rString.Len()) + { + switch(ByteString::ConvertFromUnicode(rString.GetChar((rString.Len()-1)),RTL_TEXTENCODING_ASCII_US) ) + { + case ' ' : + case '.' : break; + default : + if (!rParam.aCatalogSeparator.Len() || rString.GetChar((sal_uInt32)(rString.Len()-1)) != rParam.aCatalogSeparator.GetChar(0)) + rString += ' '; break; + } + } + if (rParam.bQuote) + { + if (rParam.bPredicate) + { + rString.AppendAscii("["); + rString += m_aNodeValue; + rString.AppendAscii("]"); + } + else + rString += SetQuotation(m_aNodeValue, rParam.aIdentifierQuote.GetChar(0), rParam.aIdentifierQuote.GetChar(0)); + } + else + rString += m_aNodeValue; + break; + case SQL_NODE_ACCESS_DATE: + if (rString.Len()) + rString += ' '; + rString += '#'; + rString += m_aNodeValue; + rString += '#'; + break; + case SQL_NODE_INTNUM: + case SQL_NODE_APPROXNUM: + { + String aTmp = m_aNodeValue; + if (rParam.bInternational && rParam.bPredicate && rParam.cDecSep != '.') + aTmp.SearchAndReplaceAll('.', rParam.cDecSep); + + if (rString.Len()) + rString += ' '; + rString += aTmp; + + } break; + // fall through + default: + if (rString.Len() && m_aNodeValue.GetChar(0) != '.' && m_aNodeValue.GetChar(0) != ':' ) + { + switch( ByteString::ConvertFromUnicode(rString.GetChar(rString.Len()-1),RTL_TEXTENCODING_ASCII_US) ) + { + case ' ' : + case '.' : break; + default : + if (!rParam.aCatalogSeparator.Len() || rString.GetChar(rString.Len()-1) != rParam.aCatalogSeparator.GetChar(0)) + rString += ' '; break; + } + } + rString += m_aNodeValue; + } + } +} + +//----------------------------------------------------------------------------- +sal_Bool OSQLParseNode::addDateValue(String& rString, const SQLParseNodeParameter& rParam) const +{ + // special display for date/time values + if (rParam.bPredicate && SQL_ISRULE(this,set_fct_spec) && SQL_ISPUNCTUATION(m_aChilds[0],"{")) + { + const OSQLParseNode* pODBCNode = m_aChilds[1]; + const OSQLParseNode* pODBCNodeChild = pODBCNode->m_aChilds[0]; + + if (pODBCNodeChild->getNodeType() == SQL_NODE_KEYWORD && ( + SQL_ISTOKEN(pODBCNodeChild, D) || + SQL_ISTOKEN(pODBCNodeChild, T) || + SQL_ISTOKEN(pODBCNodeChild, TS) )) + { + if (rString.Len()) + rString += ' '; + rString += '#'; + if (SQL_ISTOKEN(pODBCNodeChild, D)) + rString += convertDateString(rParam, pODBCNode->m_aChilds[1]->getTokenValue()); + else if (SQL_ISTOKEN(pODBCNodeChild, T)) + rString += convertTimeString(rParam, pODBCNode->m_aChilds[1]->getTokenValue()); + else + rString += convertDateTimeString(rParam, pODBCNode->m_aChilds[1]->getTokenValue()); + + rString += '#'; + return sal_True; + } + } + return sal_False; +} + +//----------------------------------------------------------------------------- +void OSQLParseNode::replaceNodeValue(const String& rTableAlias,const String& rColumnName) +{ + for (sal_uInt32 i=0;i<count();++i) + { + if (SQL_ISRULE(this,column_ref) && count() == 1 && getChild(0)->getTokenValue() == rColumnName) + { + OSQLParseNode * pCol = removeAt((sal_uInt32)0); + append(new OSQLParseNode(rTableAlias,SQL_NODE_NAME)); + append(new OSQLParseNode(String::CreateFromAscii("."),SQL_NODE_PUNCTUATION)); + append(pCol); + } + else + getChild(i)->replaceNodeValue(rTableAlias,rColumnName); + } +} + +//----------------------------------------------------------------------------- +void OSQLParseNode::tableRangeNodeToStr(String& rString, const SQLParseNodeParameter& rParam) const +{ + sal_uInt32 nCount(count()); + rString += ' '; + + SQLParseNodeParameter aNewParam(rParam); + aNewParam.bQuote = sal_False; + if (nCount == 4) + { + m_aChilds[0]->parseNodeToStr(rString, rParam); + m_aChilds[1]->parseNodeToStr(rString, rParam); + m_aChilds[2]->parseNodeToStr(rString, aNewParam); + m_aChilds[3]->parseNodeToStr(rString, rParam); + } + else if(nCount == 6 && SQL_ISPUNCTUATION(m_aChilds[0],"(")) + { + m_aChilds[0]->parseNodeToStr(rString, rParam); + m_aChilds[1]->parseNodeToStr(rString, rParam); + m_aChilds[2]->parseNodeToStr(rString, rParam); + m_aChilds[3]->parseNodeToStr(rString, rParam); + m_aChilds[4]->parseNodeToStr(rString, aNewParam); + m_aChilds[5]->parseNodeToStr(rString, rParam); + } +} + +//----------------------------------------------------------------------------- +void OSQLParseNode::likeNodeToStr(String& rString, const SQLParseNodeParameter& rParam) const +{ + DBG_ASSERT(count() == 5,"count != 5: Prepare for GPF"); + + const OSQLParseNode* pEscNode = NULL; + const OSQLParseNode* pParaNode = NULL; + + SQLParseNodeParameter aNewParam(rParam); + aNewParam.bQuote = sal_True; + + // if there is a field given we don't display the fieldname, if there are any + sal_Bool bAddName = sal_True; + if (rParam.xField.is()) + { + // retrieve the fields name + String aFieldName; + try + { + // retrieve the fields name + rtl::OUString aString; + rParam.xField->getPropertyValue(String::CreateFromAscii("Name")) >>= aString; + aFieldName = aString.getStr(); + } + catch ( ... ) + { + } + + const OSQLParseNode* pCol = m_aChilds[0]->getChild(m_aChilds[0]->count()-1); + if ((SQL_ISRULE(pCol,column_val) && pCol->getChild(0)->getTokenValue().EqualsIgnoreCaseAscii(aFieldName)) || + pCol->getTokenValue().EqualsIgnoreCaseAscii(aFieldName) ) + bAddName = sal_False; + } + + if (bAddName) + m_aChilds[0]->parseNodeToStr(rString, aNewParam); + + m_aChilds[1]->parseNodeToStr(rString, aNewParam); + m_aChilds[2]->parseNodeToStr(rString, aNewParam); + + pParaNode = m_aChilds[3]; + pEscNode = m_aChilds[4]; + + if (pParaNode->isToken() && rParam.bInternational) + { + String aStr = ConvertLikeToken(pParaNode, pEscNode, sal_True); + rString += ' '; + rString += SetQuotation(aStr,String::CreateFromAscii("\'"),String::CreateFromAscii("\'\'")); + } + else + pParaNode->parseNodeToStr(rString, aNewParam); + + pEscNode->parseNodeToStr(rString, aNewParam); +} + +//----------------------------------------------------------------------------- +OSQLParseNode* OSQLParseNode::getByRule(OSQLParseNode::Rule eRule) const +{ + OSQLParseNode* pRetNode = 0; + if (isRule() && OSQLParser::RuleID(eRule) == getRuleID()) + pRetNode = (OSQLParseNode*)this; + else + { + for (::std::vector<OSQLParseNode*>::const_iterator i = m_aChilds.begin(); + !pRetNode && i != m_aChilds.end(); i++) + pRetNode = (*i)->getByRule(eRule); + } + return pRetNode; +} +//----------------------------------------------------------------------------- +OSQLParseNode* MakeANDNode(OSQLParseNode *pLeftLeaf,OSQLParseNode *pRightLeaf) +{ + OSQLParseNode* pNewNode = new OSQLParseNode(String(),SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::boolean_term)); + pNewNode->append(pLeftLeaf); + pNewNode->append(new OSQLParseNode(String::CreateFromAscii("AND"),SQL_NODE_KEYWORD,SQL_TOKEN_AND)); + pNewNode->append(pRightLeaf); + return pNewNode; +} +//----------------------------------------------------------------------------- +OSQLParseNode* MakeORNode(OSQLParseNode *pLeftLeaf,OSQLParseNode *pRightLeaf) +{ + OSQLParseNode* pNewNode = new OSQLParseNode(String(),SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::search_condition)); + pNewNode->append(pLeftLeaf); + pNewNode->append(new OSQLParseNode(String::CreateFromAscii("OR"),SQL_NODE_KEYWORD,SQL_TOKEN_OR)); + pNewNode->append(pRightLeaf); + return pNewNode; +} +//----------------------------------------------------------------------------- +void OSQLParseNode::disjunctiveNormalForm(OSQLParseNode*& pSearchCondition) +{ + if(!pSearchCondition) // no where condition at entry point + return; + + OSQLParseNode::absorptions(pSearchCondition); + // '(' search_condition ')' + if (SQL_ISRULE(pSearchCondition,boolean_primary)) + { + OSQLParseNode* pLeft = pSearchCondition->getChild(1); + disjunctiveNormalForm(pLeft); + } + // search_condition SQL_TOKEN_OR boolean_term + else if (SQL_ISRULE(pSearchCondition,search_condition)) + { + OSQLParseNode* pLeft = pSearchCondition->getChild(0); + disjunctiveNormalForm(pLeft); + + OSQLParseNode* pRight = pSearchCondition->getChild(2); + disjunctiveNormalForm(pRight); + } + // boolean_term SQL_TOKEN_AND boolean_factor + else if (SQL_ISRULE(pSearchCondition,boolean_term)) + { + OSQLParseNode* pLeft = pSearchCondition->getChild(0); + disjunctiveNormalForm(pLeft); + + OSQLParseNode* pRight = pSearchCondition->getChild(2); + disjunctiveNormalForm(pRight); + + OSQLParseNode* pNewNode = NULL; + // '(' search_condition ')' + if(pLeft->count() == 3 && SQL_ISRULE(pLeft,boolean_primary) && SQL_ISRULE(pLeft->getChild(1),search_condition)) + { + // and-or tree on left side + OSQLParseNode* pOr = pLeft->getChild(1); + OSQLParseNode* pNewLeft = NULL; + OSQLParseNode* pNewRight = NULL; + + // cut right from parent + pSearchCondition->removeAt(2); + + pNewRight = MakeANDNode(pOr->removeAt(2) ,pRight); + pNewLeft = MakeANDNode(pOr->removeAt((sal_uInt32)0) ,new OSQLParseNode(*pRight)); + pNewNode = MakeORNode(pNewLeft,pNewRight); + // and append new Node + pSearchCondition->getParent()->replace(pSearchCondition, pNewNode); + delete pSearchCondition; + + disjunctiveNormalForm(pNewNode); + } + else if(pRight->count() == 3 && SQL_ISRULE(pRight,boolean_primary) && SQL_ISRULE(pRight->getChild(1),search_condition)) + { + // and-or tree on right side + OSQLParseNode* pOr = pRight->getChild(1); + OSQLParseNode* pNewLeft = NULL; + OSQLParseNode* pNewRight = NULL; + + // cut left from parent + pSearchCondition->removeAt((sal_uInt32)0); + + pNewRight = MakeANDNode(pLeft,pOr->removeAt(2)); + pNewLeft = MakeANDNode(new OSQLParseNode(*pLeft),pOr->removeAt((sal_uInt32)0)); + pNewNode = MakeORNode(pNewLeft,pNewRight); + + // and append new Node + pSearchCondition->getParent()->replace(pSearchCondition, pNewNode); + delete pSearchCondition; + disjunctiveNormalForm(pNewNode); + } + else if(SQL_ISRULE(pLeft,boolean_primary) && (!SQL_ISRULE(pLeft->getChild(1),search_condition) || !SQL_ISRULE(pLeft->getChild(1),boolean_term))) + pSearchCondition->replace(pLeft, pLeft->removeAt(1)); + else if(SQL_ISRULE(pRight,boolean_primary) && (!SQL_ISRULE(pRight->getChild(1),search_condition) || !SQL_ISRULE(pRight->getChild(1),boolean_term))) + pSearchCondition->replace(pRight, pRight->removeAt(1)); + } +} +//----------------------------------------------------------------------------- +void OSQLParseNode::negateSearchCondition(OSQLParseNode*& pSearchCondition,sal_Bool bNegate) +{ + if(!pSearchCondition) // no where condition at entry point + return; + OSQLParseNode* pNode = NULL; + // '(' search_condition ')' + if (pSearchCondition->count() == 3 && SQL_ISRULE(pSearchCondition,boolean_primary)) + { + OSQLParseNode* pRight = pSearchCondition->getChild(1); + negateSearchCondition(pRight,bNegate); + } + // search_condition SQL_TOKEN_OR boolean_term + else if (SQL_ISRULE(pSearchCondition,search_condition)) + { + OSQLParseNode* pLeft = pSearchCondition->getChild(0); + OSQLParseNode* pRight = pSearchCondition->getChild(2); + if(bNegate) + { + OSQLParseNode* pNewNode = new OSQLParseNode(String(),SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::boolean_term)); + pNewNode->append(pSearchCondition->removeAt((sal_uInt32)0)); + pNewNode->append(new OSQLParseNode(String::CreateFromAscii("AND"),SQL_NODE_KEYWORD,SQL_TOKEN_AND)); + pNewNode->append(pSearchCondition->removeAt((sal_uInt32)1)); + pSearchCondition->getParent()->replace(pSearchCondition, pNewNode); + delete pSearchCondition; + pLeft = pNewNode->getChild(0); + pRight = pNewNode->getChild(2); + } + + negateSearchCondition(pLeft,bNegate); + negateSearchCondition(pRight,bNegate); + } + // boolean_term SQL_TOKEN_AND boolean_factor + else if (SQL_ISRULE(pSearchCondition,boolean_term)) + { + OSQLParseNode* pLeft = pSearchCondition->getChild(0); + OSQLParseNode* pRight = pSearchCondition->getChild(2); + if(bNegate) + { + OSQLParseNode* pNewNode = new OSQLParseNode(String(),SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::search_condition)); + pNewNode->append(pSearchCondition->removeAt((sal_uInt32)0)); + pNewNode->append(new OSQLParseNode(String::CreateFromAscii("OR"),SQL_NODE_KEYWORD,SQL_TOKEN_OR)); + pNewNode->append(pSearchCondition->removeAt((sal_uInt32)1)); + pSearchCondition->getParent()->replace(pSearchCondition, pNewNode); + delete pSearchCondition; + pLeft = pNewNode->getChild(0); + pRight = pNewNode->getChild(2); + } + + negateSearchCondition(pLeft,bNegate); + negateSearchCondition(pRight,bNegate); + } + // SQL_TOKEN_NOT boolean_test + else if (SQL_ISRULE(pSearchCondition,boolean_factor)) + { + OSQLParseNode *pNot = pSearchCondition->removeAt((sal_uInt32)0); + delete pNot; + OSQLParseNode *pBooleanTest = pSearchCondition->removeAt((sal_uInt32)0); + pBooleanTest->setParent(NULL); + pSearchCondition->getParent()->replace(pSearchCondition, pBooleanTest); + delete pSearchCondition; + if (!bNegate) + negateSearchCondition(pBooleanTest,sal_True); // negate all deeper values + } + // row_value_constructor comparison row_value_constructor + // row_value_constructor comparison any_all_some subquery + else if(bNegate && SQL_ISRULE(pSearchCondition,comparison_predicate) || SQL_ISRULE(pSearchCondition,all_or_any_predicate)) + { + OSQLParseNode* pComparison = pSearchCondition->getChild(1); + OSQLParseNode* pNewComparison = NULL; + switch(pComparison->getNodeType()) + { + case SQL_NODE_EQUAL: + pNewComparison = new OSQLParseNode(String::CreateFromAscii("<>"),SQL_NODE_NOTEQUAL,NOTEQUAL); + break; + case SQL_NODE_LESS: + pNewComparison = new OSQLParseNode(String::CreateFromAscii(">="),SQL_NODE_GREATEQ,GREATEQ); + break; + case SQL_NODE_GREAT: + pNewComparison = new OSQLParseNode(String::CreateFromAscii("<="),SQL_NODE_LESSEQ,LESSEQ); + break; + case SQL_NODE_LESSEQ: + pNewComparison = new OSQLParseNode(String::CreateFromAscii(">"),SQL_NODE_GREAT,GREAT); + break; + case SQL_NODE_GREATEQ: + pNewComparison = new OSQLParseNode(String::CreateFromAscii("<"),SQL_NODE_LESS,LESS); + break; + case SQL_NODE_NOTEQUAL: + pNewComparison = new OSQLParseNode(String::CreateFromAscii("="),SQL_NODE_EQUAL,EQUAL); + break; + } + pSearchCondition->replace(pComparison, pNewComparison); + delete pComparison; + } + + else if(bNegate && (SQL_ISRULE(pSearchCondition,test_for_null) || SQL_ISRULE(pSearchCondition,in_predicate) || + SQL_ISRULE(pSearchCondition,like_predicate) || SQL_ISRULE(pSearchCondition,between_predicate) || + SQL_ISRULE(pSearchCondition,boolean_test) )) + { + sal_uInt32 nNotPos = 0; + // row_value_constructor not SQL_TOKEN_IN in_predicate_value + // row_value_constructor not SQL_TOKEN_LIKE num_value_exp opt_escape + // row_value_constructor not SQL_TOKEN_BETWEEN row_value_constructor SQL_TOKEN_AND row_value_constructor + if(SQL_ISRULE(pSearchCondition,in_predicate) || SQL_ISRULE(pSearchCondition,like_predicate) || + SQL_ISRULE(pSearchCondition,between_predicate)) + nNotPos = 1; + // row_value_constructor SQL_TOKEN_IS not SQL_TOKEN_NULL + // boolean_primary SQL_TOKEN_IS not truth_value + else if(SQL_ISRULE(pSearchCondition,test_for_null) || SQL_ISRULE(pSearchCondition,boolean_test)) + nNotPos = 2; + + OSQLParseNode* pNot = pSearchCondition->getChild(nNotPos); + OSQLParseNode* pNotNot = NULL; + if(pNot->isRule()) + pNotNot = new OSQLParseNode(String::CreateFromAscii("NOT"),SQL_NODE_KEYWORD,SQL_TOKEN_NOT); + else + pNotNot = new OSQLParseNode(String(),SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::not)); + pSearchCondition->replace(pNot, pNotNot); + delete pNot; + } +} +//----------------------------------------------------------------------------- +void OSQLParseNode::eraseBraces(OSQLParseNode*& pSearchCondition) +{ + if (pSearchCondition && (SQL_ISRULE(pSearchCondition,boolean_primary) || (pSearchCondition->count() == 3 && SQL_ISPUNCTUATION(pSearchCondition->getChild(0),"(") && + SQL_ISPUNCTUATION(pSearchCondition->getChild(2),")")))) + { + OSQLParseNode* pRight = pSearchCondition->getChild(1); + absorptions(pRight); + // if child is not a or or and tree then delete () around child + if(!(SQL_ISRULE(pSearchCondition->getChild(1),boolean_term) || SQL_ISRULE(pSearchCondition->getChild(1),search_condition)) || + SQL_ISRULE(pSearchCondition->getChild(1),boolean_term) || // and can always stand without () + (SQL_ISRULE(pSearchCondition->getChild(1),search_condition) && SQL_ISRULE(pSearchCondition->getParent(),search_condition))) + { + OSQLParseNode* pNode = pSearchCondition->removeAt(1); + pSearchCondition->getParent()->replace(pSearchCondition, pNode); + delete pSearchCondition; + pSearchCondition = pNode; + } + } +} +//----------------------------------------------------------------------------- +void OSQLParseNode::absorptions(OSQLParseNode*& pSearchCondition) +{ + if(!pSearchCondition) // no where condition at entry point + return; + + eraseBraces(pSearchCondition); + + if(SQL_ISRULE(pSearchCondition,boolean_term) || SQL_ISRULE(pSearchCondition,search_condition)) + { + OSQLParseNode* pLeft = pSearchCondition->getChild(0); + absorptions(pLeft); + OSQLParseNode* pRight = pSearchCondition->getChild(2); + absorptions(pRight); + } + + // a and a || a or a + OSQLParseNode* pNewNode = NULL; + if(( SQL_ISRULE(pSearchCondition,boolean_term) || SQL_ISRULE(pSearchCondition,search_condition)) + && *pSearchCondition->getChild(0) == *pSearchCondition->getChild(2)) + { + pNewNode = pSearchCondition->removeAt((sal_uInt32)0); + pSearchCondition->getParent()->replace(pSearchCondition, pNewNode); + delete pSearchCondition; + pSearchCondition = pNewNode; + } + // (a or b) and a + else if(SQL_ISRULE(pSearchCondition,boolean_term) && SQL_ISRULE(pSearchCondition->getChild(0),boolean_primary) && + SQL_ISRULE(pSearchCondition->getChild(0)->getChild(1),search_condition) && + *pSearchCondition->getChild(0)->getChild(1)->getChild(0) == *pSearchCondition->getChild(2)) + { + pSearchCondition->getParent()->replace(pSearchCondition, pNewNode = pSearchCondition->removeAt(2)); + delete pSearchCondition; + pSearchCondition = pNewNode; + } + // a and ( a or b) + else if(SQL_ISRULE(pSearchCondition,boolean_term) && SQL_ISRULE(pSearchCondition->getChild(2),boolean_primary) && + SQL_ISRULE(pSearchCondition->getChild(2)->getChild(1),search_condition)) + + { + if(*pSearchCondition->getChild(2)->getChild(1)->getChild(0) == *pSearchCondition->getChild(0)) + { + pSearchCondition->getParent()->replace(pSearchCondition, pNewNode = pSearchCondition->removeAt((sal_uInt32)0)); + delete pSearchCondition; + pSearchCondition = pNewNode; + } + else if(*pSearchCondition->getChild(2)->getChild(1)->getChild(2) == *pSearchCondition->getChild(0)) + { + pSearchCondition->getParent()->replace(pSearchCondition, pNewNode = pSearchCondition->removeAt((sal_uInt32)2)); + delete pSearchCondition; + pSearchCondition = pNewNode; + } + } + // a or a and b || a or b and a + else if(SQL_ISRULE(pSearchCondition,search_condition) && SQL_ISRULE(pSearchCondition->getChild(2),boolean_term)) + { + if(*pSearchCondition->getChild(2)->getChild(0) == *pSearchCondition->getChild(0)) + { + pSearchCondition->getParent()->replace(pSearchCondition, pNewNode = pSearchCondition->removeAt((sal_uInt32)0)); + delete pSearchCondition; + pSearchCondition = pNewNode; + } + else if(*pSearchCondition->getChild(2)->getChild(2) == *pSearchCondition->getChild(0)) + { + pSearchCondition->getParent()->replace(pSearchCondition, pNewNode = pSearchCondition->removeAt((sal_uInt32)0)); + delete pSearchCondition; + pSearchCondition = pNewNode; + } + } + // a and b or a || b and a or a + else if(SQL_ISRULE(pSearchCondition,search_condition) && SQL_ISRULE(pSearchCondition->getChild(0),boolean_term)) + { + if(*pSearchCondition->getChild(0)->getChild(0) == *pSearchCondition->getChild(2)) + { + pSearchCondition->getParent()->replace(pSearchCondition, pNewNode = pSearchCondition->removeAt((sal_uInt32)2)); + delete pSearchCondition; + pSearchCondition = pNewNode; + } + else if(*pSearchCondition->getChild(0)->getChild(2) == *pSearchCondition->getChild(2)) + { + pSearchCondition->getParent()->replace(pSearchCondition, pNewNode = pSearchCondition->removeAt((sal_uInt32)2)); + delete pSearchCondition; + pSearchCondition = pNewNode; + } + } + eraseBraces(pSearchCondition); +} +//----------------------------------------------------------------------------- +void OSQLParseNode::compress(OSQLParseNode *&pSearchCondition) +{ + if(!pSearchCondition) // no where condition at entry point + return; + + OSQLParseNode::eraseBraces(pSearchCondition); + + if(SQL_ISRULE(pSearchCondition,boolean_term) || SQL_ISRULE(pSearchCondition,search_condition)) + { + OSQLParseNode* pLeft = pSearchCondition->getChild(0); + compress(pLeft); + + OSQLParseNode* pRight = pSearchCondition->getChild(2); + compress(pRight); + } + else if( SQL_ISRULE(pSearchCondition,boolean_primary) || (pSearchCondition->count() == 3 && SQL_ISPUNCTUATION(pSearchCondition->getChild(0),"(") && + SQL_ISPUNCTUATION(pSearchCondition->getChild(2),")"))) + { + OSQLParseNode* pRight = pSearchCondition->getChild(1); + compress(pRight); + // if child is not a or or and tree then delete () around child + if(!(SQL_ISRULE(pSearchCondition->getChild(1),boolean_term) || SQL_ISRULE(pSearchCondition->getChild(1),search_condition)) || + (SQL_ISRULE(pSearchCondition->getChild(1),boolean_term) && SQL_ISRULE(pSearchCondition->getParent(),boolean_term)) || + (SQL_ISRULE(pSearchCondition->getChild(1),search_condition) && SQL_ISRULE(pSearchCondition->getParent(),search_condition))) + { + OSQLParseNode* pNode = pSearchCondition->removeAt(1); + pSearchCondition->getParent()->replace(pSearchCondition, pNode); + delete pSearchCondition; + pSearchCondition = pNode; + } + } + + OSQLParseNode* pNewNode = NULL; + // or with two and trees where one element of the and trees are equal + if(SQL_ISRULE(pSearchCondition,search_condition) && SQL_ISRULE(pSearchCondition->getChild(0),boolean_term) && SQL_ISRULE(pSearchCondition->getChild(2),boolean_term)) + { + if(*pSearchCondition->getChild(0)->getChild(0) == *pSearchCondition->getChild(2)->getChild(0)) + { + OSQLParseNode* pLeft = pSearchCondition->getChild(0)->removeAt(2); + OSQLParseNode* pRight = pSearchCondition->getChild(2)->removeAt(2); + OSQLParseNode* pNode = MakeORNode(pLeft,pRight); + + OSQLParseNode* pNewRule = new OSQLParseNode(String(),SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::boolean_primary)); + pNewRule->append(new OSQLParseNode(String::CreateFromAscii("("),SQL_NODE_PUNCTUATION)); + pNewRule->append(pNode); + pNewRule->append(new OSQLParseNode(String::CreateFromAscii(")"),SQL_NODE_PUNCTUATION)); + + OSQLParseNode::eraseBraces(pLeft); + OSQLParseNode::eraseBraces(pRight); + + pNode = MakeANDNode(pSearchCondition->getChild(0)->removeAt((sal_uInt32)0),pNewRule); + pSearchCondition->getParent()->replace(pSearchCondition, pNode); + delete pSearchCondition; + pSearchCondition = pNode; + } + else if(*pSearchCondition->getChild(0)->getChild(2) == *pSearchCondition->getChild(2)->getChild(0)) + { + OSQLParseNode* pLeft = pSearchCondition->getChild(0)->removeAt((sal_uInt32)0); + OSQLParseNode* pRight = pSearchCondition->getChild(2)->removeAt(2); + OSQLParseNode* pNode = MakeORNode(pLeft,pRight); + + OSQLParseNode* pNewRule = new OSQLParseNode(String(),SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::boolean_primary)); + pNewRule->append(new OSQLParseNode(String::CreateFromAscii("("),SQL_NODE_PUNCTUATION)); + pNewRule->append(pNode); + pNewRule->append(new OSQLParseNode(String::CreateFromAscii(")"),SQL_NODE_PUNCTUATION)); + + OSQLParseNode::eraseBraces(pLeft); + OSQLParseNode::eraseBraces(pRight); + + pNode = MakeANDNode(pSearchCondition->getChild(0)->removeAt(1),pNewRule); + pSearchCondition->getParent()->replace(pSearchCondition, pNode); + delete pSearchCondition; + pSearchCondition = pNode; + } + else if(*pSearchCondition->getChild(0)->getChild(0) == *pSearchCondition->getChild(2)->getChild(2)) + { + OSQLParseNode* pLeft = pSearchCondition->getChild(0)->removeAt(2); + OSQLParseNode* pRight = pSearchCondition->getChild(2)->removeAt((sal_uInt32)0); + OSQLParseNode* pNode = MakeORNode(pLeft,pRight); + + OSQLParseNode* pNewRule = new OSQLParseNode(String(),SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::boolean_primary)); + pNewRule->append(new OSQLParseNode(String::CreateFromAscii("("),SQL_NODE_PUNCTUATION)); + pNewRule->append(pNode); + pNewRule->append(new OSQLParseNode(String::CreateFromAscii(")"),SQL_NODE_PUNCTUATION)); + + OSQLParseNode::eraseBraces(pLeft); + OSQLParseNode::eraseBraces(pRight); + + pNode = MakeANDNode(pSearchCondition->getChild(0)->removeAt((sal_uInt32)0),pNewRule); + pSearchCondition->getParent()->replace(pSearchCondition, pNode); + delete pSearchCondition; + pSearchCondition = pNode; + } + else if(*pSearchCondition->getChild(0)->getChild(2) == *pSearchCondition->getChild(2)->getChild(2)) + { + OSQLParseNode* pLeft = pSearchCondition->getChild(0)->removeAt((sal_uInt32)0); + OSQLParseNode* pRight = pSearchCondition->getChild(2)->removeAt((sal_uInt32)0); + OSQLParseNode* pNode = MakeORNode(pLeft,pRight); + + OSQLParseNode* pNewRule = new OSQLParseNode(String(),SQL_NODE_RULE,OSQLParser::RuleID(OSQLParseNode::boolean_primary)); + pNewRule->append(new OSQLParseNode(String::CreateFromAscii("("),SQL_NODE_PUNCTUATION)); + pNewRule->append(pNode); + pNewRule->append(new OSQLParseNode(String::CreateFromAscii(")"),SQL_NODE_PUNCTUATION)); + + OSQLParseNode::eraseBraces(pLeft); + OSQLParseNode::eraseBraces(pRight); + + pNode = MakeANDNode(pSearchCondition->getChild(0)->removeAt(1),pNewRule); + pSearchCondition->getParent()->replace(pSearchCondition, pNode); + delete pSearchCondition; + pSearchCondition = pNode; + } + } +} +//----------------------------------------------------------------------------- +void OSQLParseNode::showParseTree(String& rString, sal_uInt32 nLevel) +{ + DBG_CHKTHIS(OSQLParseNode,NULL); + + if (!isToken()) + { + for (sal_uInt32 j=0; j<nLevel; j++) {rString.AppendAscii("\t");}; + // Regelnamen als rule: ... + rString.AppendAscii("RULE_ID:\t "); + rString += (String) getRuleID(); + rString.AppendAscii("("); + rString += OSQLParser::RuleIDToStr(getRuleID()); + rString.AppendAscii(")"); + rString.AppendAscii("\n"); + + // einmal auswerten wieviel Subtrees dieser Knoten besitzt + sal_uInt32 nStop = count(); + // hol dir den ersten Subtree + for (::std::vector<OSQLParseNode*>::const_iterator i = m_aChilds.begin(); + i != m_aChilds.end(); i++) + (*i)->showParseTree(rString, nLevel+1); + } + else { + // ein Token gefunden + // tabs fuer das Einruecken entsprechend nLevel + for (sal_uInt32 j=0; j<nLevel; j++) {rString.AppendAscii("\t");}; + + switch (m_eNodeType) { + + case SQL_NODE_KEYWORD: + {rString.AppendAscii("SQL_KEYWORD:\t"); + rString += String::CreateFromAscii(OSQLParser::TokenIDToStr(getTokenID()).GetBuffer()); + rString.AppendAscii("\n"); + break;} + + case SQL_NODE_COMPARISON: + {rString.AppendAscii("SQL_COMPARISON:\t"); + rString += m_aNodeValue; // haenge Nodevalue an + rString.AppendAscii("\n"); // und beginne neu Zeile + break;} + + case SQL_NODE_NAME: + {rString.AppendAscii("SQL_NAME:\t"); + rString.AppendAscii("\""); + rString += m_aNodeValue; + rString.AppendAscii("\""); + rString.AppendAscii("\n"); + break;} + + case SQL_NODE_STRING: + {rString .AppendAscii("SQL_STRING:\t'"); + rString += m_aNodeValue; + rString .AppendAscii("'\n"); + break;} + + case SQL_NODE_INTNUM: + {rString .AppendAscii("SQL_INTNUM:\t"); + rString += m_aNodeValue; + rString .AppendAscii("\n"); + break;} + + case SQL_NODE_APPROXNUM: + {rString .AppendAscii("SQL_APPROXNUM:\t"); + rString += m_aNodeValue; + rString .AppendAscii("\n"); + break;} + + case SQL_NODE_PUNCTUATION: + {rString .AppendAscii("SQL_PUNCTUATION:\t"); + rString += m_aNodeValue; // haenge Nodevalue an + rString .AppendAscii("\n"); // und beginne neu Zeile + break;} + + case SQL_NODE_AMMSC: + {rString .AppendAscii("SQL_AMMSC:\t"); + rString += m_aNodeValue; // haenge Nodevalue an + rString .AppendAscii("\n"); // und beginne neu Zeile + break;} + + default: + DBG_ERROR("OSQLParser::ShowParseTree: unzulaessiger NodeType"); + } + }; +} + +// Insert-Methoden +//----------------------------------------------------------------------------- +void OSQLParseNode::insert(sal_uInt32 nPos, OSQLParseNode* pNewSubTree) +{ + DBG_ASSERT(pNewSubTree != NULL, "OSQLParseNode: ungueltiger NewSubTree"); + DBG_ASSERT(pNewSubTree->getParent() == NULL, "OSQLParseNode: Knoten ist kein Waise"); + + // stelle Verbindung zum getParent her: + pNewSubTree->setParent( this ); + m_aChilds.insert(m_aChilds.begin() + nPos); +} + +// removeAt-Methoden +//----------------------------------------------------------------------------- +OSQLParseNode* OSQLParseNode::removeAt(sal_uInt32 nPos) +{ + ::std::vector<OSQLParseNode*>::iterator aPos(m_aChilds.begin() + nPos); + OSQLParseNode* pNode = *aPos; + + // setze den getParent des removeten auf NULL + pNode->setParent( NULL ); + + m_aChilds.erase(aPos); + return pNode; +} +//----------------------------------------------------------------------------- +OSQLParseNode* OSQLParseNode::remove(OSQLParseNode* pSubTree) +{ + DBG_ASSERT(pSubTree != NULL, "OSQLParseNode: ungueltiger SubTree"); + ::std::vector<OSQLParseNode*>::iterator aPos = ::std::find(m_aChilds.begin(), m_aChilds.end(), pSubTree); + if (aPos != m_aChilds.end()) + { + // setze den getParent des removeten auf NULL + pSubTree->setParent( NULL ); + m_aChilds.erase(aPos); + return pSubTree; + } + else + return NULL; +} + +// Replace-Methoden +//----------------------------------------------------------------------------- +OSQLParseNode* OSQLParseNode::replaceAt(sal_uInt32 nPos, OSQLParseNode* pNewSubNode) +{ + DBG_ASSERT(pNewSubNode != NULL, "OSQLParseNode: invalid nodes"); + DBG_ASSERT(pNewSubNode->getParent() == NULL, "OSQLParseNode: node already has getParent"); + DBG_ASSERT(nPos < m_aChilds.size(), "OSQLParseNode: invalid position"); + DBG_ASSERT(::std::find(m_aChilds.begin(), m_aChilds.end(), pNewSubNode) == m_aChilds.end(), + "OSQLParseNode::Replace() Node already element of parent"); + + OSQLParseNode* pOldSubNode = m_aChilds[nPos]; + + // stelle Verbindung zum getParent her: + pNewSubNode->setParent( this ); + pOldSubNode->setParent( NULL ); + + m_aChilds[nPos] = pNewSubNode; + return pOldSubNode; +} + +//----------------------------------------------------------------------------- +OSQLParseNode* OSQLParseNode::replace (OSQLParseNode* pOldSubNode, OSQLParseNode* pNewSubNode ) +{ + DBG_ASSERT(pOldSubNode != NULL && pNewSubNode != NULL, "OSQLParseNode: invalid nodes"); + DBG_ASSERT(pNewSubNode->getParent() == NULL, "OSQLParseNode: node already has getParent"); + DBG_ASSERT(::std::find(m_aChilds.begin(), m_aChilds.end(), pOldSubNode) != m_aChilds.end(), + "OSQLParseNode::Replace() Node not element of parent"); + DBG_ASSERT(::std::find(m_aChilds.begin(), m_aChilds.end(), pNewSubNode) == m_aChilds.end(), + "OSQLParseNode::Replace() Node already element of parent"); + + pOldSubNode->setParent( NULL ); + pNewSubNode->setParent( this ); + ::std::replace(m_aChilds.begin(), m_aChilds.end(), pOldSubNode, pNewSubNode); + return pOldSubNode; +} + + |