1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <tools/debug.hxx>
23 #include <connectivity/sqlnode.hxx>
24 #include <file/FConnection.hxx>
25 #include <strings.hrc>
27 using namespace ::connectivity
;
28 using namespace ::connectivity::file
;
29 using namespace ::com::sun::star::uno
;
30 using namespace ::com::sun::star::beans
;
31 using namespace ::com::sun::star::sdbc
;
32 using namespace ::com::sun::star::container
;
34 OSQLAnalyzer::OSQLAnalyzer(OConnection
* _pConnection
)
35 :m_pConnection(_pConnection
)
36 ,m_bHasSelectionCode(false)
37 ,m_bSelectionFirstTime(true)
39 m_aCompiler
= new OPredicateCompiler(this);
40 m_aInterpreter
= new OPredicateInterpreter(m_aCompiler
);
44 OSQLAnalyzer::~OSQLAnalyzer()
49 void OSQLAnalyzer::start(OSQLParseNode
const * pSQLParseNode
)
51 if (SQL_ISRULE(pSQLParseNode
,select_statement
))
53 DBG_ASSERT(pSQLParseNode
->count() >= 4,"OFILECursor: Error in Parse Tree");
55 // check that we don't use anything other than count(*) as function
56 OSQLParseNode
* pSelection
= pSQLParseNode
->getChild(2);
57 if ( SQL_ISRULE(pSelection
,scalar_exp_commalist
) )
59 for (size_t i
= 0; i
< pSelection
->count(); i
++)
61 OSQLParseNode
*pColumnRef
= pSelection
->getChild(i
)->getChild(0);
62 if ( ( SQL_ISRULE(pColumnRef
,set_fct_spec
) && pColumnRef
->count() == 4 )
63 || SQL_ISRULE(pColumnRef
,char_value_fct
)
64 || SQL_ISRULE(pColumnRef
,char_substring_fct
)
65 || SQL_ISRULE(pColumnRef
,position_exp
)
66 || SQL_ISRULE(pColumnRef
,fold
)
67 || SQL_ISRULE(pColumnRef
,length_exp
)
68 || SQL_ISRULE(pColumnRef
,num_value_exp
)
69 || SQL_ISRULE(pColumnRef
,term
)
70 || SQL_ISRULE(pColumnRef
,factor
)
71 || SQL_ISRULE(pColumnRef
,set_fct_spec
) )
73 ::rtl::Reference
<OPredicateCompiler
> pCompiler
= new OPredicateCompiler(this);
74 pCompiler
->setOrigColumns(m_aCompiler
->getOrigColumns());
75 ::rtl::Reference
<OPredicateInterpreter
> pInterpreter
= new OPredicateInterpreter(pCompiler
);
76 pCompiler
->execute( pColumnRef
);
77 m_aSelectionEvaluations
.push_back( TPredicates(pCompiler
,pInterpreter
) );
79 else if ( SQL_ISRULE(pColumnRef
,general_set_fct
) && pColumnRef
->count() != 4 )
81 m_pConnection
->throwGenericSQLException(STR_QUERY_COMPLEX_COUNT
,nullptr);
85 if ( SQL_ISPUNCTUATION( pColumnRef
, "*" )
86 || ( SQL_ISRULE( pColumnRef
, column_ref
)
87 && ( pColumnRef
->count() == 3 )
88 && ( pColumnRef
->getChild(0)->getNodeType() == SQLNodeType::Name
)
89 && SQL_ISPUNCTUATION( pColumnRef
->getChild(1), "." )
90 && SQL_ISRULE( pColumnRef
->getChild(2), column_val
)
91 && SQL_ISPUNCTUATION( pColumnRef
->getChild(2)->getChild(0), "*" )
95 // push one element for each column of our table
96 const Reference
< XNameAccess
> xColumnNames( m_aCompiler
->getOrigColumns() );
97 const Sequence
< OUString
> aColumnNames( xColumnNames
->getElementNames() );
98 for ( sal_Int32 j
=0; j
<aColumnNames
.getLength(); ++j
)
99 m_aSelectionEvaluations
.push_back( TPredicates() );
102 m_aSelectionEvaluations
.push_back( TPredicates() );
108 m_aCompiler
->start(pSQLParseNode
);
112 void OSQLAnalyzer::bindRow(OCodeList
& rCodeList
,const OValueRefRow
& _pRow
)
114 for (auto const& code
: rCodeList
)
116 OOperandAttr
* pAttr
= dynamic_cast<OOperandAttr
*>(code
.get());
119 pAttr
->bindValue(_pRow
);
124 void OSQLAnalyzer::bindSelectRow(const OValueRefRow
& _pRow
)
126 // first the select part
127 for (auto const& selectionEval
: m_aSelectionEvaluations
)
129 if ( selectionEval
.first
.is() )
130 bindRow(selectionEval
.first
->m_aCodeList
,_pRow
);
134 void OSQLAnalyzer::bindEvaluationRow(OValueRefRow
const & _pRow
)
136 bindRow(m_aCompiler
->m_aCodeList
,_pRow
);
139 OOperandAttr
* OSQLAnalyzer::createOperandAttr(sal_Int32 _nPos
,
140 const Reference
< XPropertySet
>& _xCol
)
142 return new OOperandAttr(static_cast<sal_uInt16
>(_nPos
),_xCol
);
145 bool OSQLAnalyzer::hasRestriction() const
147 return m_aCompiler
->hasCode();
150 bool OSQLAnalyzer::hasFunctions() const
152 if ( m_bSelectionFirstTime
)
154 m_bSelectionFirstTime
= false;
155 for (auto const& selectionEval
: m_aSelectionEvaluations
)
157 if ( selectionEval
.first
.is() )
159 m_bHasSelectionCode
= selectionEval
.first
->hasCode();
160 if (m_bHasSelectionCode
)
165 return m_bHasSelectionCode
;
168 void OSQLAnalyzer::setSelectionEvaluationResult(OValueRefRow
const & _pRow
,const std::vector
<sal_Int32
>& _rColumnMapping
)
171 for (auto const& selectionEval
: m_aSelectionEvaluations
)
173 if ( selectionEval
.second
.is() )
175 // the first column (index 0) is for convenience only. The first real select column is no 1.
176 sal_Int32 map
= nPos
;
177 if ( nPos
< static_cast< sal_Int32
>( _rColumnMapping
.size() ) )
178 map
= _rColumnMapping
[nPos
];
180 selectionEval
.second
->startSelection( (*_pRow
)[map
] );
186 void OSQLAnalyzer::dispose()
188 m_aCompiler
->dispose();
189 for (auto const& selectionEval
: m_aSelectionEvaluations
)
191 if ( selectionEval
.first
.is() )
192 selectionEval
.first
->dispose();
196 void OSQLAnalyzer::setOrigColumns(const css::uno::Reference
< css::container::XNameAccess
>& rCols
)
198 m_aCompiler
->setOrigColumns(rCols
);
199 for (auto const& selectionEval
: m_aSelectionEvaluations
)
201 if ( selectionEval
.first
.is() )
202 selectionEval
.first
->setOrigColumns(rCols
);
207 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */