Bump for 3.6-28
[LibreOffice.git] / connectivity / source / drivers / file / fanalyzer.cxx
blobfcaba19395bbdd7899b02c4b16a5fb078e781eeb
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include "file/fanalyzer.hxx"
30 #include "connectivity/sqlparse.hxx"
31 #include <osl/diagnose.h>
32 #include <tools/debug.hxx>
33 #include <comphelper/extract.hxx>
34 #include "connectivity/sqlnode.hxx"
35 #include "connectivity/dbexception.hxx"
36 #include "file/FConnection.hxx"
37 #include "resource/file_res.hrc"
39 using namespace ::connectivity;
40 using namespace ::connectivity::file;
41 using namespace ::com::sun::star::uno;
42 using namespace ::com::sun::star::beans;
43 using namespace ::com::sun::star::sdbc;
44 using namespace ::com::sun::star::container;
46 DBG_NAME( file_OSQLAnalyzer )
47 //------------------------------------------------------------------
48 OSQLAnalyzer::OSQLAnalyzer(OConnection* _pConnection)
49 :m_pConnection(_pConnection)
50 ,m_bHasSelectionCode(sal_False)
51 ,m_bSelectionFirstTime(sal_True)
53 DBG_CTOR( file_OSQLAnalyzer, NULL );
54 m_aCompiler = new OPredicateCompiler(this);
55 m_aInterpreter = new OPredicateInterpreter(m_aCompiler);
58 // -----------------------------------------------------------------------------
59 OSQLAnalyzer::~OSQLAnalyzer()
61 DBG_DTOR( file_OSQLAnalyzer, NULL );
64 // -----------------------------------------------------------------------------
65 void OSQLAnalyzer::setIndexes(const Reference< XNameAccess>& _xIndexes)
67 m_aCompiler->m_xIndexes = _xIndexes;
69 //------------------------------------------------------------------
70 void OSQLAnalyzer::start(OSQLParseNode* pSQLParseNode)
72 if (SQL_ISRULE(pSQLParseNode,select_statement))
74 DBG_ASSERT(pSQLParseNode->count() >= 4,"OFILECursor: Fehler im Parse Tree");
76 // check that we don't use anything other than count(*) as function
77 OSQLParseNode* pSelection = pSQLParseNode->getChild(2);
78 if ( SQL_ISRULE(pSelection,scalar_exp_commalist) )
80 for (sal_uInt32 i = 0; i < pSelection->count(); i++)
82 OSQLParseNode *pColumnRef = pSelection->getChild(i)->getChild(0);
83 if ( ( SQL_ISRULE(pColumnRef,set_fct_spec) && pColumnRef->count() == 4 )
84 || SQL_ISRULE(pColumnRef,char_value_fct)
85 || SQL_ISRULE(pColumnRef,char_substring_fct)
86 || SQL_ISRULE(pColumnRef,position_exp)
87 || SQL_ISRULE(pColumnRef,fold)
88 || SQL_ISRULE(pColumnRef,length_exp)
89 || SQL_ISRULE(pColumnRef,num_value_exp)
90 || SQL_ISRULE(pColumnRef,term)
91 || SQL_ISRULE(pColumnRef,factor)
92 || SQL_ISRULE(pColumnRef,set_fct_spec) )
94 ::rtl::Reference<OPredicateCompiler> pCompiler = new OPredicateCompiler(this);
95 pCompiler->setOrigColumns(m_aCompiler->getOrigColumns());
96 ::rtl::Reference<OPredicateInterpreter> pInterpreter = new OPredicateInterpreter(pCompiler);
97 pCompiler->execute( pColumnRef );
98 m_aSelectionEvaluations.push_back( TPredicates(pCompiler,pInterpreter) );
100 else if ( ( SQL_ISRULE(pColumnRef,general_set_fct) && pColumnRef->count() != 4 ) )
102 m_pConnection->throwGenericSQLException(STR_QUERY_COMPLEX_COUNT,NULL);
104 else
106 if ( SQL_ISPUNCTUATION( pColumnRef, "*" )
107 || ( SQL_ISRULE( pColumnRef, column_ref )
108 && ( pColumnRef->count() == 3 )
109 && ( pColumnRef->getChild(0)->getNodeType() == SQL_NODE_NAME )
110 && SQL_ISPUNCTUATION( pColumnRef->getChild(1), "." )
111 && SQL_ISRULE( pColumnRef->getChild(2), column_val )
112 && SQL_ISPUNCTUATION( pColumnRef->getChild(2)->getChild(0), "*" )
116 // push one element for each column of our table
117 const Reference< XNameAccess > xColumnNames( m_aCompiler->getOrigColumns() );
118 const Sequence< ::rtl::OUString > aColumnNames( xColumnNames->getElementNames() );
119 for ( sal_Int32 j=0; j<aColumnNames.getLength(); ++j )
120 m_aSelectionEvaluations.push_back( TPredicates() );
122 else
123 m_aSelectionEvaluations.push_back( TPredicates() );
129 m_aCompiler->start(pSQLParseNode);
132 //------------------------------------------------------------------
133 void OSQLAnalyzer::bindRow(OCodeList& rCodeList,const OValueRefRow& _pRow,OEvaluateSetList& _rEvaluateSetList)
135 // count criteria
136 // if only one criterion, and the corresponding field is indexed
137 // then the index will be used
138 OEvaluateSet* pEvaluateSet = NULL;
140 for (OCodeList::iterator aIter = rCodeList.begin(); aIter != rCodeList.end(); ++aIter)
142 OOperandAttr* pAttr = PTR_CAST(OOperandAttr,(*aIter));
143 if (pAttr)
145 if (pAttr->isIndexed() && !m_aCompiler->hasORCondition())
147 OCode* pCode1 = *(aIter + 1);
148 OCode* pCode2 = *(aIter + 2);
150 if (PTR_CAST(OOperand,pCode1))
151 pEvaluateSet = pAttr->preProcess(PTR_CAST(OBoolOperator,pCode2), PTR_CAST(OOperand,pCode1));
152 else
153 pEvaluateSet = pAttr->preProcess(PTR_CAST(OBoolOperator,pCode1));
156 if (pEvaluateSet)
158 _rEvaluateSetList.push_back(pEvaluateSet);
159 pEvaluateSet = NULL;
161 pAttr->bindValue(_pRow);
165 //------------------------------------------------------------------
166 void OSQLAnalyzer::bindSelectRow(const OValueRefRow& _pRow)
168 // first the select part
169 OEvaluateSetList aEvaluateSetList;
170 for ( ::std::vector< TPredicates >::iterator aIter = m_aSelectionEvaluations.begin(); aIter != m_aSelectionEvaluations.end();++aIter)
172 if ( aIter->first.is() )
173 bindRow( aIter->first->m_aCodeList,_pRow,aEvaluateSetList);
176 //------------------------------------------------------------------
177 ::std::vector<sal_Int32>* OSQLAnalyzer::bindEvaluationRow(OValueRefRow& _pRow)
179 OEvaluateSetList aEvaluateSetList;
180 bindRow( m_aCompiler->m_aCodeList,_pRow,aEvaluateSetList);
182 ::std::vector<sal_Int32>* pKeySet = NULL;
183 OEvaluateSet* pEvaluateSet = NULL;
185 // create Keyset with smallest list
186 if(!aEvaluateSetList.empty())
188 // which list has the smallest count?
189 OEvaluateSetList::iterator i = aEvaluateSetList.begin();
190 pEvaluateSet = *(i);
191 for(++i; i != aEvaluateSetList.end();++i)
193 OEvaluateSet* pEvaluateSetComp = (*i);
194 for(OEvaluateSet::reverse_iterator j = pEvaluateSet->rbegin(); j != pEvaluateSet->rend(); ++j)
196 if (pEvaluateSetComp->find(j->second) != pEvaluateSetComp->end())
197 pEvaluateSet->erase(j->second);
200 pKeySet = new ::std::vector<sal_Int32>(pEvaluateSet->size());
201 sal_Int32 k=0;
202 for(OEvaluateSet::iterator j = pEvaluateSet->begin(); j != pEvaluateSet->end(); ++j,++k)
204 (*pKeySet)[k] = j->second;
207 // delete all
208 for(i = aEvaluateSetList.begin(); i != aEvaluateSetList.end();++i)
209 delete (*i);
212 return pKeySet;
215 // -----------------------------------------------------------------------------
216 OOperandAttr* OSQLAnalyzer::createOperandAttr(sal_Int32 _nPos,
217 const Reference< XPropertySet>& _xCol,
218 const Reference< XNameAccess>& /*_xIndexes*/)
220 return new OOperandAttr(static_cast<sal_uInt16>(_nPos),_xCol);
222 // -----------------------------------------------------------------------------
223 sal_Bool OSQLAnalyzer::hasRestriction() const
225 return m_aCompiler->hasCode();
227 // -----------------------------------------------------------------------------
228 sal_Bool OSQLAnalyzer::hasFunctions() const
230 if ( m_bSelectionFirstTime )
232 m_bSelectionFirstTime = sal_False;
233 for ( ::std::vector< TPredicates >::const_iterator aIter = m_aSelectionEvaluations.begin(); aIter != m_aSelectionEvaluations.end() && !m_bHasSelectionCode ;++aIter)
235 if ( aIter->first.is() )
236 m_bHasSelectionCode = aIter->first->hasCode();
239 return m_bHasSelectionCode;
241 // -----------------------------------------------------------------------------
242 void OSQLAnalyzer::setSelectionEvaluationResult(OValueRefRow& _pRow,const ::std::vector<sal_Int32>& _rColumnMapping)
244 sal_Int32 nPos = 1;
245 for ( ::std::vector< TPredicates >::iterator aIter = m_aSelectionEvaluations.begin(); aIter != m_aSelectionEvaluations.end();++aIter,++nPos)
247 if ( aIter->second.is() )
249 // the first column (index 0) is for convenience only. The first real select column is no 1.
250 sal_Int32 map = nPos;
251 if ( nPos < static_cast< sal_Int32 >( _rColumnMapping.size() ) )
252 map = _rColumnMapping[nPos];
253 if ( map > 0 )
254 aIter->second->startSelection( (_pRow->get())[map] );
258 // -----------------------------------------------------------------------------
259 void OSQLAnalyzer::dispose()
261 m_aCompiler->dispose();
262 for ( ::std::vector< TPredicates >::iterator aIter = m_aSelectionEvaluations.begin(); aIter != m_aSelectionEvaluations.end();++aIter)
264 if ( aIter->first.is() )
265 aIter->first->dispose();
268 // -----------------------------------------------------------------------------
269 void OSQLAnalyzer::setOrigColumns(const OFileColumns& rCols)
271 m_aCompiler->setOrigColumns(rCols);
272 for ( ::std::vector< TPredicates >::iterator aIter = m_aSelectionEvaluations.begin(); aIter != m_aSelectionEvaluations.end();++aIter)
274 if ( aIter->first.is() )
275 aIter->first->setOrigColumns(rCols);
278 // -----------------------------------------------------------------------------
280 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */