/************************************************************************* * * $RCSfile: sqlnode.cxx,v $ * * $Revision: 1.16 $ * * last change: $Author: oj $ $Date: 2001-05-23 09:10: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 #endif #ifndef _CONNECTIVITY_SQLPARSE_HXX #include #endif #ifndef _COM_SUN_STAR_LANG_LOCALE_HPP_ #include #endif #ifndef _COM_SUN_STAR_UTIL_XNUMBERFORMATTER_HPP_ #include #endif #ifndef _COM_SUN_STAR_UTIL_XNUMBERFORMATTYPES_HPP_ #include #endif #ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ #include #endif #ifndef _COM_SUN_STAR_SDBC_XDATABASEMETADATA_HPP_ #include #endif #ifndef _DBHELPER_DBCONVERSION_HXX_ #include "connectivity/dbconversion.hxx" #endif #ifndef _COM_SUN_STAR_UTIL_DATETIME_HPP_ #include #endif #ifndef _COM_SUN_STAR_UTIL_TIME_HPP_ #include #endif #ifndef _COM_SUN_STAR_UTIL_DATE_HPP_ #include #endif #ifndef CONNECTIVITY_CONNECTION_HXX #include "TConnection.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; using namespace dbtools; extern Any getNumberFormatProperty(const Reference< XNumberFormatsSupplier > & xFormatter, sal_Int32 nKey, const rtl::OUString& ); extern ::rtl::OUString ConvertLikeToken(const OSQLParseNode* pTokenNode, const OSQLParseNode* pEscapeNode, sal_Bool bInternational); //------------------------------------------------------------------ OSQLParseNode::SQLParseNodeParameter::SQLParseNodeParameter(const ::rtl::OUString& _rIdentifierQuote, const ::rtl::OUString& _rCatalogSep, const Reference< XNumberFormatter > & _xFormatter, const Reference< XPropertySet > & _xField, const ::com::sun::star::lang::Locale& _rLocale, const OParseContext* _pContext, sal_Bool _bIntl, sal_Bool _bQuote, sal_Char _cDecSep, sal_Bool _bPredicate) :aIdentifierQuote(_rIdentifierQuote) ,aCatalogSeparator(_rCatalogSep) ,rLocale(_rLocale) ,rContext(_pContext ? *_pContext : OSQLParser::s_aDefaultContext) ,bInternational(_bIntl) ,bQuote(_bQuote) ,cDecSep(_cDecSep) ,xField(_xField) ,xFormatter(_xFormatter) ,bPredicate(_bPredicate) { } ::rtl::OUString SetQuotation(const ::rtl::OUString& rValue, const ::rtl::OUString& rQuot, const ::rtl::OUString& rQuotToReplace); sal_Int32 getToken(const ::rtl::OUString& _rValue,const ::rtl::OUString& _rToken,sal_uInt32 _nPos); //----------------------------------------------------------------------------- ::rtl::OUString OSQLParseNode::convertDateString(const SQLParseNodeParameter& rParam, const ::rtl::OUString& rString) const { // get the token out of a string static ::rtl::OUString sDateSep = ::rtl::OUString::createFromAscii("-"); sal_Int32 nYear = getToken(rString,sDateSep,0); sal_Int32 nMonth = getToken(rString,sDateSep,1); sal_Int32 nDay = getToken(rString,sDateSep,2); Date aDate(nDay,nMonth,nYear); Reference< XNumberFormatsSupplier > xSupplier(rParam.xFormatter->getNumberFormatsSupplier()); Reference< XNumberFormatTypes > xTypes(xSupplier->getNumberFormats(), UNO_QUERY); double fDate = DBTypeConversion::toDouble(aDate,DBTypeConversion::getNULLDate(xSupplier)); sal_Int32 nKey = xTypes->getStandardIndex(rParam.rLocale) + 36; // XXX hack return rParam.xFormatter->convertNumberToString(nKey, fDate); } //----------------------------------------------------------------------------- ::rtl::OUString OSQLParseNode::convertDateTimeString(const SQLParseNodeParameter& rParam, const ::rtl::OUString& rString) const { static ::rtl::OUString sDateSep = ::rtl::OUString::createFromAscii("-"); static ::rtl::OUString sTimeSep = ::rtl::OUString::createFromAscii(":"); sal_Int32 nYear = getToken(rString,sDateSep,0); sal_Int32 nMonth = getToken(rString,sDateSep,1); sal_Int32 nDay = getToken(rString,sDateSep,2); sal_Int32 nHour = getToken(rString,sTimeSep,0); sal_Int32 nMinute = getToken(rString,sTimeSep,1); sal_Int32 nSecond = getToken(rString,sTimeSep,2); DateTime aDate(0,nSecond,nMinute,nHour,nDay,nMonth,nYear); Reference< XNumberFormatsSupplier > xSupplier(rParam.xFormatter->getNumberFormatsSupplier()); Reference< XNumberFormatTypes > xTypes(xSupplier->getNumberFormats(), UNO_QUERY); double fDateTime = DBTypeConversion::toDouble(aDate,DBTypeConversion::getNULLDate(xSupplier)); sal_Int32 nKey = xTypes->getStandardIndex(rParam.rLocale) + 51; // XXX hack return rParam.xFormatter->convertNumberToString(nKey, fDateTime); } //----------------------------------------------------------------------------- ::rtl::OUString OSQLParseNode::convertTimeString(const SQLParseNodeParameter& rParam, const ::rtl::OUString& rString) const { static ::rtl::OUString sTimeSep = ::rtl::OUString::createFromAscii(":"); sal_Int32 nHour = getToken(rString,sTimeSep,0); sal_Int32 nMinute = getToken(rString,sTimeSep,1); sal_Int32 nSecond = getToken(rString,sTimeSep,2); Time aTime(0,nHour,nMinute,nSecond); Reference< XNumberFormatsSupplier > xSupplier(rParam.xFormatter->getNumberFormatsSupplier()); Reference< XNumberFormatTypes > xTypes(xSupplier->getNumberFormats(), UNO_QUERY); double fTime = DBTypeConversion::toDouble(aTime); sal_Int32 nKey = xTypes->getStandardIndex(rParam.rLocale) + 41; // XXX hack return rParam.xFormatter->convertNumberToString(nKey, fTime); } //----------------------------------------------------------------------------- void OSQLParseNode::parseNodeToStr(::rtl::OUString& rString, const Reference< XDatabaseMetaData > & xMeta, const OParseContext* pContext, sal_Bool _bIntl, sal_Bool _bQuote) const { parseNodeToStr(rString, xMeta, Reference< XNumberFormatter >(), Reference< XPropertySet >(), OParseContext::getDefaultLocale(), pContext, _bIntl, _bQuote, '.', sal_False); } //----------------------------------------------------------------------------- void OSQLParseNode::parseNodeToPredicateStr(::rtl::OUString& rString, const Reference< XDatabaseMetaData > & xMeta, const Reference< XNumberFormatter > & xFormatter, const ::com::sun::star::lang::Locale& rIntl, sal_Char _cDec, const OParseContext* pContext ) const { OSL_ENSURE(xFormatter.is(), "OSQLParseNode::parseNodeToPredicateStr:: no formatter!"); if (xFormatter.is()) parseNodeToStr(rString, xMeta, xFormatter, Reference< XPropertySet >(), rIntl, pContext, sal_True, sal_True, _cDec, sal_True); } //----------------------------------------------------------------------------- void OSQLParseNode::parseNodeToPredicateStr(::rtl::OUString& rString, const Reference< XDatabaseMetaData > & xMeta, const Reference< XNumberFormatter > & xFormatter, const Reference< XPropertySet > & _xField, const ::com::sun::star::lang::Locale& rIntl, sal_Char _cDec, const OParseContext* pContext ) const { OSL_ENSURE(xFormatter.is(), "OSQLParseNode::parseNodeToPredicateStr:: no formatter!"); if (xFormatter.is()) parseNodeToStr(rString, xMeta, xFormatter, _xField, rIntl, pContext, sal_True, sal_True, _cDec, sal_True); } //----------------------------------------------------------------------------- void OSQLParseNode::parseNodeToStr(::rtl::OUString& rString, const Reference< XDatabaseMetaData > & xMeta, const Reference< XNumberFormatter > & xFormatter, const Reference< XPropertySet > & _xField, const ::com::sun::star::lang::Locale& rIntl, const OParseContext* pContext, sal_Bool _bIntl, sal_Bool _bQuote, sal_Char _cDecSep, sal_Bool bPredicate) const { OSL_ENSURE(xMeta.is(), "OSQLParseNode::parseNodeToStr:: no meta data!"); if (xMeta.is()) { ::rtl::OUString aIdentifierQuote(xMeta->getIdentifierQuoteString()); ::rtl::OUString aCatalogSeparator(xMeta->getCatalogSeparator()); OSQLParseNode::parseNodeToStr(rString, SQLParseNodeParameter(aIdentifierQuote, aCatalogSeparator, xFormatter, _xField, rIntl, pContext, _bIntl, _bQuote, _cDecSep, bPredicate)); } } //----------------------------------------------------------------------------- void OSQLParseNode::parseNodeToStr(::rtl::OUString& rString, const SQLParseNodeParameter& rParam) const { if (!isToken()) { // einmal auswerten wieviel Subtrees dieser Knoten besitzt sal_uInt32 nCount = count(); // parameter erhalten sonderbehandlung if (SQL_ISRULE(this,parameter)) { if(rString.getLength()) rString += ::rtl::OUString::createFromAscii(" "); 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|| (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); ::rtl::OUString aStringPara; for (sal_uInt32 i=1; iparseNodeToStr(aStringPara, rParam); // bei den CommaListen zwischen alle Subtrees Commas setzen if ((m_eNodeType == SQL_NODE_COMMALISTRULE) && (i < (nCount - 1))) aStringPara += ::rtl::OUString::createFromAscii(","); } } aStringPara.trim(); rString += aStringPara; } } else { for (OSQLParseNodes::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 ::rtl::OUString aFieldName; try { // retrieve the fields name rParam.xField->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aFieldName; } catch ( Exception& ) { } const OSQLParseNode* pCol = pSubTree->m_aChilds[pSubTree->count()-1]; if ((SQL_ISRULE(pCol,column_val) && pCol->getChild(0)->getTokenValue().equalsIgnoreAsciiCase(aFieldName)) || pCol->getTokenValue().equalsIgnoreAsciiCase(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 += ::rtl::OUString::createFromAscii(","); } } 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 += ::rtl::OUString::createFromAscii(";"); else rString += ::rtl::OUString::createFromAscii(","); } } } } } } else { parseLeaf(rString,rParam); } } //----------------------------------------------------------------------------- void OSQLParseNode::tableRangeNodeToStr(::rtl::OUString& rString, const SQLParseNodeParameter& rParam) const { sal_uInt32 nCount(count()); rString += ::rtl::OUString::createFromAscii(" "); 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(::rtl::OUString& rString, const SQLParseNodeParameter& rParam) const { OSL_ENSURE(count() >= 4,"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 ::rtl::OUString aFieldName; try { // retrieve the fields name rtl::OUString aString; rParam.xField->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_NAME)) >>= aString; aFieldName = aString.getStr(); } catch ( Exception& ) { OSL_ENSURE(0,"OSQLParseNode::likeNodeToStr Exception occured!"); } const OSQLParseNode* pCol = m_aChilds[0]->getChild(m_aChilds[0]->count()-1); if ((SQL_ISRULE(pCol,column_val) && pCol->getChild(0)->getTokenValue().equalsIgnoreAsciiCase(aFieldName)) || pCol->getTokenValue().equalsIgnoreAsciiCase(aFieldName) ) bAddName = sal_False; } if (bAddName) m_aChilds[0]->parseNodeToStr(rString, aNewParam); m_aChilds[1]->parseNodeToStr(rString, aNewParam); if(count() == 5) m_aChilds[2]->parseNodeToStr(rString, aNewParam); sal_Int32 nCurentPos = m_aChilds.size()-2; pParaNode = m_aChilds[nCurentPos]; pEscNode = m_aChilds[nCurentPos+1]; if (pParaNode->isToken() && rParam.bInternational) { ::rtl::OUString aStr = ConvertLikeToken(pParaNode, pEscNode, sal_True); rString += ::rtl::OUString::createFromAscii(" "); rString += SetQuotation(aStr,::rtl::OUString::createFromAscii("\'"),::rtl::OUString::createFromAscii("\'\'")); } else pParaNode->parseNodeToStr(rString, aNewParam); pEscNode->parseNodeToStr(rString, aNewParam); } // ----------------------------------------------------------------------------- sal_Bool OSQLParseNode::getTableComponents(const OSQLParseNode* _pTableNode, ::com::sun::star::uno::Any &_rCatalog, ::rtl::OUString &_rSchema, ::rtl::OUString &_rTable) { OSL_ENSURE(_pTableNode,"Wrong use of getTableComponents! _pTableNode is not allowed to be null!"); if(_pTableNode) { const OSQLParseNode* pTableNode = _pTableNode; // clear the parameter given _rCatalog = Any(); _rSchema = _rTable = ::rtl::OUString(); // see rule catalog_name: in sqlbison.y if (SQL_ISRULE(pTableNode,catalog_name)) { OSL_ENSURE(pTableNode->getChild(0) && pTableNode->getChild(0)->isToken(),"Invalid parsenode!"); _rCatalog <<= pTableNode->getChild(0)->getTokenValue(); pTableNode = pTableNode->getChild(2); } // check if we have schema_name rule if(SQL_ISRULE(pTableNode,schema_name)) { _rSchema = pTableNode->getChild(0)->getTokenValue(); pTableNode = pTableNode->getChild(2); } // check if we have table_name rule if(SQL_ISRULE(pTableNode,table_name)) { _rTable = pTableNode->getChild(0)->getTokenValue(); } else { OSL_ENSURE(0,"Error in parse tree!"); } } return _rTable.getLength() != 0; } // -----------------------------------------------------------------------------