Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / connectivity / source / drivers / file / fanalyzer.cxx
blob6f3b65b03c176bbd22a061d0f25bcc52ce8a3038
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "file/fanalyzer.hxx"
21 #include "connectivity/sqlparse.hxx"
22 #include <osl/diagnose.h>
23 #include <tools/debug.hxx>
24 #include <comphelper/extract.hxx>
25 #include "connectivity/sqlnode.hxx"
26 #include "connectivity/dbexception.hxx"
27 #include "file/FConnection.hxx"
28 #include "resource/file_res.hrc"
30 using namespace ::connectivity;
31 using namespace ::connectivity::file;
32 using namespace ::com::sun::star::uno;
33 using namespace ::com::sun::star::beans;
34 using namespace ::com::sun::star::sdbc;
35 using namespace ::com::sun::star::container;
37 OSQLAnalyzer::OSQLAnalyzer(OConnection* _pConnection)
38 :m_pConnection(_pConnection)
39 ,m_bHasSelectionCode(false)
40 ,m_bSelectionFirstTime(true)
42 m_aCompiler = new OPredicateCompiler(this);
43 m_aInterpreter = new OPredicateInterpreter(m_aCompiler);
47 OSQLAnalyzer::~OSQLAnalyzer()
52 void OSQLAnalyzer::setIndexes(const Reference< XNameAccess>& _xIndexes)
54 m_aCompiler->m_xIndexes = _xIndexes;
57 void OSQLAnalyzer::start(OSQLParseNode* pSQLParseNode)
59 if (SQL_ISRULE(pSQLParseNode,select_statement))
61 DBG_ASSERT(pSQLParseNode->count() >= 4,"OFILECursor: Fehler im Parse Tree");
63 // check that we don't use anything other than count(*) as function
64 OSQLParseNode* pSelection = pSQLParseNode->getChild(2);
65 if ( SQL_ISRULE(pSelection,scalar_exp_commalist) )
67 for (sal_uInt32 i = 0; i < pSelection->count(); i++)
69 OSQLParseNode *pColumnRef = pSelection->getChild(i)->getChild(0);
70 if ( ( SQL_ISRULE(pColumnRef,set_fct_spec) && pColumnRef->count() == 4 )
71 || SQL_ISRULE(pColumnRef,char_value_fct)
72 || SQL_ISRULE(pColumnRef,char_substring_fct)
73 || SQL_ISRULE(pColumnRef,position_exp)
74 || SQL_ISRULE(pColumnRef,fold)
75 || SQL_ISRULE(pColumnRef,length_exp)
76 || SQL_ISRULE(pColumnRef,num_value_exp)
77 || SQL_ISRULE(pColumnRef,term)
78 || SQL_ISRULE(pColumnRef,factor)
79 || SQL_ISRULE(pColumnRef,set_fct_spec) )
81 ::rtl::Reference<OPredicateCompiler> pCompiler = new OPredicateCompiler(this);
82 pCompiler->setOrigColumns(m_aCompiler->getOrigColumns());
83 ::rtl::Reference<OPredicateInterpreter> pInterpreter = new OPredicateInterpreter(pCompiler);
84 pCompiler->execute( pColumnRef );
85 m_aSelectionEvaluations.push_back( TPredicates(pCompiler,pInterpreter) );
87 else if ( ( SQL_ISRULE(pColumnRef,general_set_fct) && pColumnRef->count() != 4 ) )
89 m_pConnection->throwGenericSQLException(STR_QUERY_COMPLEX_COUNT,NULL);
91 else
93 if ( SQL_ISPUNCTUATION( pColumnRef, "*" )
94 || ( SQL_ISRULE( pColumnRef, column_ref )
95 && ( pColumnRef->count() == 3 )
96 && ( pColumnRef->getChild(0)->getNodeType() == SQL_NODE_NAME )
97 && SQL_ISPUNCTUATION( pColumnRef->getChild(1), "." )
98 && SQL_ISRULE( pColumnRef->getChild(2), column_val )
99 && SQL_ISPUNCTUATION( pColumnRef->getChild(2)->getChild(0), "*" )
103 // push one element for each column of our table
104 const Reference< XNameAccess > xColumnNames( m_aCompiler->getOrigColumns() );
105 const Sequence< OUString > aColumnNames( xColumnNames->getElementNames() );
106 for ( sal_Int32 j=0; j<aColumnNames.getLength(); ++j )
107 m_aSelectionEvaluations.push_back( TPredicates() );
109 else
110 m_aSelectionEvaluations.push_back( TPredicates() );
116 m_aCompiler->start(pSQLParseNode);
120 void OSQLAnalyzer::bindRow(OCodeList& rCodeList,const OValueRefRow& _pRow,OEvaluateSetList& _rEvaluateSetList)
122 // count criteria
123 // if only one criterion, and the corresponding field is indexed
124 // then the index will be used
125 OEvaluateSet* pEvaluateSet = NULL;
127 for (OCodeList::iterator aIter = rCodeList.begin(); aIter != rCodeList.end(); ++aIter)
129 OOperandAttr* pAttr = PTR_CAST(OOperandAttr,(*aIter));
130 if (pAttr)
132 if (pAttr->isIndexed() && !m_aCompiler->hasORCondition())
134 OCode* pCode1 = *(aIter + 1);
135 OCode* pCode2 = *(aIter + 2);
137 if (PTR_CAST(OOperand,pCode1))
138 pEvaluateSet = pAttr->preProcess(PTR_CAST(OBoolOperator,pCode2), PTR_CAST(OOperand,pCode1));
139 else
140 pEvaluateSet = pAttr->preProcess(PTR_CAST(OBoolOperator,pCode1));
143 if (pEvaluateSet)
145 _rEvaluateSetList.push_back(pEvaluateSet);
146 pEvaluateSet = NULL;
148 pAttr->bindValue(_pRow);
153 void OSQLAnalyzer::bindSelectRow(const OValueRefRow& _pRow)
155 // first the select part
156 OEvaluateSetList aEvaluateSetList;
157 for ( ::std::vector< TPredicates >::iterator aIter = m_aSelectionEvaluations.begin(); aIter != m_aSelectionEvaluations.end();++aIter)
159 if ( aIter->first.is() )
160 bindRow( aIter->first->m_aCodeList,_pRow,aEvaluateSetList);
164 ::std::vector<sal_Int32>* OSQLAnalyzer::bindEvaluationRow(OValueRefRow& _pRow)
166 OEvaluateSetList aEvaluateSetList;
167 bindRow( m_aCompiler->m_aCodeList,_pRow,aEvaluateSetList);
169 ::std::vector<sal_Int32>* pKeySet = NULL;
170 OEvaluateSet* pEvaluateSet = NULL;
172 // create Keyset with smallest list
173 if(!aEvaluateSetList.empty())
175 // which list has the smallest count?
176 OEvaluateSetList::iterator i = aEvaluateSetList.begin();
177 pEvaluateSet = *(i);
178 for(++i; i != aEvaluateSetList.end();++i)
180 OEvaluateSet* pEvaluateSetComp = (*i);
181 for(OEvaluateSet::reverse_iterator j = pEvaluateSet->rbegin(); j != pEvaluateSet->rend(); ++j)
183 if (pEvaluateSetComp->find(j->second) != pEvaluateSetComp->end())
184 pEvaluateSet->erase(j->second);
187 pKeySet = new ::std::vector<sal_Int32>(pEvaluateSet->size());
188 sal_Int32 k=0;
189 for(OEvaluateSet::iterator j = pEvaluateSet->begin(); j != pEvaluateSet->end(); ++j,++k)
191 (*pKeySet)[k] = j->second;
194 // delete all
195 for(i = aEvaluateSetList.begin(); i != aEvaluateSetList.end();++i)
196 delete (*i);
199 return pKeySet;
203 OOperandAttr* OSQLAnalyzer::createOperandAttr(sal_Int32 _nPos,
204 const Reference< XPropertySet>& _xCol,
205 const Reference< XNameAccess>& /*_xIndexes*/)
207 return new OOperandAttr(static_cast<sal_uInt16>(_nPos),_xCol);
210 bool OSQLAnalyzer::hasRestriction() const
212 return m_aCompiler->hasCode();
215 bool OSQLAnalyzer::hasFunctions() const
217 if ( m_bSelectionFirstTime )
219 m_bSelectionFirstTime = false;
220 for ( ::std::vector< TPredicates >::const_iterator aIter = m_aSelectionEvaluations.begin(); aIter != m_aSelectionEvaluations.end() && !m_bHasSelectionCode ;++aIter)
222 if ( aIter->first.is() )
223 m_bHasSelectionCode = aIter->first->hasCode();
226 return m_bHasSelectionCode;
229 void OSQLAnalyzer::setSelectionEvaluationResult(OValueRefRow& _pRow,const ::std::vector<sal_Int32>& _rColumnMapping)
231 sal_Int32 nPos = 1;
232 for ( ::std::vector< TPredicates >::iterator aIter = m_aSelectionEvaluations.begin(); aIter != m_aSelectionEvaluations.end();++aIter,++nPos)
234 if ( aIter->second.is() )
236 // the first column (index 0) is for convenience only. The first real select column is no 1.
237 sal_Int32 map = nPos;
238 if ( nPos < static_cast< sal_Int32 >( _rColumnMapping.size() ) )
239 map = _rColumnMapping[nPos];
240 if ( map > 0 )
241 aIter->second->startSelection( (_pRow->get())[map] );
246 void OSQLAnalyzer::dispose()
248 m_aCompiler->dispose();
249 for ( ::std::vector< TPredicates >::iterator aIter = m_aSelectionEvaluations.begin(); aIter != m_aSelectionEvaluations.end();++aIter)
251 if ( aIter->first.is() )
252 aIter->first->dispose();
256 void OSQLAnalyzer::setOrigColumns(const OFileColumns& rCols)
258 m_aCompiler->setOrigColumns(rCols);
259 for ( ::std::vector< TPredicates >::iterator aIter = m_aSelectionEvaluations.begin(); aIter != m_aSelectionEvaluations.end();++aIter)
261 if ( aIter->first.is() )
262 aIter->first->setOrigColumns(rCols);
267 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */