Coverage Report

Created: 2026-10-14 09:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/connectivity/source/drivers/file/fanalyzer.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
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/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
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 .
18
 */
19
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>
26
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::container;
32
33
OSQLAnalyzer::OSQLAnalyzer(OConnection* _pConnection)
34
33.3k
               :m_pConnection(_pConnection)
35
33.3k
               ,m_bHasSelectionCode(false)
36
33.3k
               ,m_bSelectionFirstTime(true)
37
33.3k
{
38
33.3k
    m_aCompiler = new OPredicateCompiler(this);
39
33.3k
    m_aInterpreter = new OPredicateInterpreter(m_aCompiler);
40
33.3k
}
41
42
43
OSQLAnalyzer::~OSQLAnalyzer()
44
33.3k
{
45
33.3k
}
46
47
48
void OSQLAnalyzer::start(OSQLParseNode const * pSQLParseNode)
49
33.3k
{
50
33.3k
    if (SQL_ISRULE(pSQLParseNode,select_statement))
51
33.3k
    {
52
33.3k
        DBG_ASSERT(pSQLParseNode->count() >= 4,"OFILECursor: Error in Parse Tree");
53
54
        // check that we don't use anything other than count(*) as function
55
33.3k
        OSQLParseNode* pSelection = pSQLParseNode->getChild(2);
56
33.3k
        if ( SQL_ISRULE(pSelection,scalar_exp_commalist) )
57
0
        {
58
0
            for (size_t i = 0; i < pSelection->count(); i++)
59
0
            {
60
0
                OSQLParseNode *pColumnRef = pSelection->getChild(i)->getChild(0);
61
0
                if (    ( SQL_ISRULE(pColumnRef,set_fct_spec) && pColumnRef->count() == 4 )
62
0
                    ||  SQL_ISRULE(pColumnRef,char_value_fct)
63
0
                    ||  SQL_ISRULE(pColumnRef,char_substring_fct)
64
0
                    ||  SQL_ISRULE(pColumnRef,position_exp)
65
0
                    ||  SQL_ISRULE(pColumnRef,fold)
66
0
                    ||  SQL_ISRULE(pColumnRef,length_exp)
67
0
                    ||  SQL_ISRULE(pColumnRef,num_value_exp)
68
0
                    ||  SQL_ISRULE(pColumnRef,term)
69
0
                    ||  SQL_ISRULE(pColumnRef,factor)
70
0
                    ||  SQL_ISRULE(pColumnRef,set_fct_spec)
71
                    // tdf#65685 - treat literal constants in the SELECT list as leaf nodes rather than rules
72
0
                    ||  pColumnRef->getNodeType() == SQLNodeType::String
73
0
                    ||  pColumnRef->getNodeType() == SQLNodeType::IntNum
74
0
                    ||  pColumnRef->getNodeType() == SQLNodeType::ApproxNum )
75
0
                {
76
0
                    ::rtl::Reference<OPredicateCompiler>        pCompiler = new OPredicateCompiler(this);
77
0
                    pCompiler->setOrigColumns(m_aCompiler->getOrigColumns());
78
0
                    ::rtl::Reference<OPredicateInterpreter> pInterpreter = new OPredicateInterpreter(pCompiler);
79
0
                    pCompiler->execute( pColumnRef );
80
0
                    m_aSelectionEvaluations.push_back( TPredicates(pCompiler,pInterpreter) );
81
0
                }
82
0
                else if ( SQL_ISRULE(pColumnRef,general_set_fct) && pColumnRef->count() != 4 )
83
0
                {
84
0
                    m_pConnection->throwGenericSQLException(STR_QUERY_COMPLEX_COUNT,nullptr);
85
0
                }
86
0
                else
87
0
                {
88
0
                    if  (   SQL_ISPUNCTUATION( pColumnRef, "*" )
89
0
                        ||  (   SQL_ISRULE( pColumnRef, column_ref )
90
0
                            &&  ( pColumnRef->count() == 3 )
91
0
                            &&  ( pColumnRef->getChild(0)->getNodeType() == SQLNodeType::Name )
92
0
                            &&  SQL_ISPUNCTUATION( pColumnRef->getChild(1), "." )
93
0
                            &&  SQL_ISRULE( pColumnRef->getChild(2), column_val )
94
0
                            &&  SQL_ISPUNCTUATION( pColumnRef->getChild(2)->getChild(0), "*" )
95
0
                            )
96
0
                        )
97
0
                    {
98
                        // push one element for each column of our table
99
0
                        const Reference< XNameAccess > xColumnNames( m_aCompiler->getOrigColumns() );
100
0
                        const Sequence< OUString > aColumnNames( xColumnNames->getElementNames() );
101
0
                        for ( sal_Int32 j=0; j<aColumnNames.getLength(); ++j )
102
0
                            m_aSelectionEvaluations.push_back( TPredicates() );
103
0
                    }
104
0
                    else
105
0
                        m_aSelectionEvaluations.push_back( TPredicates() );
106
0
                }
107
0
            }
108
0
        }
109
33.3k
    }
110
111
33.3k
    m_aCompiler->start(pSQLParseNode);
112
33.3k
}
113
114
115
void OSQLAnalyzer::bindRow(OCodeList& rCodeList,const OValueRefRow& _pRow)
116
22.2k
{
117
22.2k
    for (auto const& code : rCodeList)
118
33.3k
    {
119
33.3k
        OOperandAttr* pAttr = dynamic_cast<OOperandAttr*>(code.get());
120
33.3k
        if (pAttr)
121
0
        {
122
0
            pAttr->bindValue(_pRow);
123
0
        }
124
33.3k
    }
125
22.2k
}
126
127
void OSQLAnalyzer::bindSelectRow(const OValueRefRow& _pRow)
128
22.2k
{
129
    // first the select part
130
22.2k
    for (auto const& selectionEval : m_aSelectionEvaluations)
131
0
    {
132
0
        if ( selectionEval.first.is() )
133
0
            bindRow(selectionEval.first->m_aCodeList,_pRow);
134
0
    }
135
22.2k
}
136
137
void OSQLAnalyzer::bindEvaluationRow(OValueRefRow const & _pRow)
138
22.2k
{
139
22.2k
    bindRow(m_aCompiler->m_aCodeList,_pRow);
140
22.2k
}
141
142
OOperandAttr* OSQLAnalyzer::createOperandAttr(sal_Int32 _nPos,
143
                                              const Reference< XPropertySet>& _xCol)
144
0
{
145
0
    return new OOperandAttr(static_cast<sal_uInt16>(_nPos),_xCol);
146
0
}
147
148
bool OSQLAnalyzer::hasRestriction() const
149
2.55M
{
150
2.55M
    return m_aCompiler->hasCode();
151
2.55M
}
152
153
bool OSQLAnalyzer::hasFunctions() const
154
2.51M
{
155
2.51M
    if ( m_bSelectionFirstTime )
156
8.59k
    {
157
8.59k
        m_bSelectionFirstTime = false;
158
8.59k
        for (auto const& selectionEval : m_aSelectionEvaluations)
159
0
        {
160
0
            if ( selectionEval.first.is() )
161
0
            {
162
0
                m_bHasSelectionCode = selectionEval.first->hasCode();
163
0
                if (m_bHasSelectionCode)
164
0
                    break;
165
0
            }
166
0
        }
167
8.59k
    }
168
2.51M
    return m_bHasSelectionCode;
169
2.51M
}
170
171
void OSQLAnalyzer::setSelectionEvaluationResult(OValueRefRow const & _pRow,const std::vector<sal_Int32>& _rColumnMapping)
172
0
{
173
0
    sal_Int32 nPos = 1;
174
0
    for (auto const& selectionEval : m_aSelectionEvaluations)
175
0
    {
176
0
        if ( selectionEval.second.is() )
177
0
        {
178
            // the first column (index 0) is for convenience only. The first real select column is no 1.
179
0
            sal_Int32   map = nPos;
180
0
            if ( nPos < static_cast< sal_Int32 >( _rColumnMapping.size() ) )
181
0
                map = _rColumnMapping[nPos];
182
0
            if ( map > 0 )
183
0
                selectionEval.second->startSelection( (*_pRow)[map] );
184
0
        }
185
0
        ++nPos;
186
0
    }
187
0
}
188
189
void OSQLAnalyzer::dispose()
190
33.3k
{
191
33.3k
    m_aCompiler->dispose();
192
33.3k
    for (auto const& selectionEval : m_aSelectionEvaluations)
193
0
    {
194
0
        if ( selectionEval.first.is() )
195
0
            selectionEval.first->dispose();
196
0
    }
197
33.3k
}
198
199
void OSQLAnalyzer::setOrigColumns(const css::uno::Reference< css::container::XNameAccess>& rCols)
200
33.3k
{
201
33.3k
    m_aCompiler->setOrigColumns(rCols);
202
33.3k
    for (auto const& selectionEval : m_aSelectionEvaluations)
203
0
    {
204
0
        if ( selectionEval.first.is() )
205
0
            selectionEval.first->setOrigColumns(rCols);
206
0
    }
207
33.3k
}
208
209
210
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */