blob: 885cb349ff416b6e6439db2fa8141af48226282c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include "execVScan.h"
#include "miscadmin.h"
#include "execVQual.h"
#include "parquet_reader.h"
#include "ao_reader.h"
static TupleTableSlot*
ExecVScan(ScanState *node, ExecScanAccessMtd accessMtd);
static const ScanMethod *
getVScanMethod(int tableType)
{
static const ScanMethod scanMethods[] =
{
//HEAPSCAN
{
},
//APPENDONLYSCAN
{
&AppendOnlyVScanNext, &BeginVScanAppendOnlyRelation, &EndVScanAppendOnlyRelation,
&ReScanAppendOnlyRelation, &MarkRestrNotAllowed, &MarkRestrNotAllowed
},
//PARQUETSCAN
{
&ParquetVScanNext, &BeginScanParquetRelation, &EndScanParquetRelation,
&ReScanParquetRelation, &MarkRestrNotAllowed, &MarkRestrNotAllowed
}
};
COMPILE_ASSERT(ARRAY_SIZE(scanMethods) == TableTypeInvalid);
if (tableType < 0 && tableType >= TableTypeInvalid)
{
return NULL;
}
return &scanMethods[tableType];
}
/*
* ExecTableVScanVirtualLayer
* translate a batch of tuple to single one if scan parent is normal execution node
*
* VirtualNodeProc may not fill tuple data in slot success, due to qualification tag.
* invoke scan table functoin if no tuple can pop up in TupleBatch
*/
TupleTableSlot *ExecTableVScanVirtualLayer(ScanState *scanState)
{
VectorizedState* vs = (VectorizedState*)scanState->ps.vectorized;
/* if vs->parent is NULL, it represent that the parent is non-vectorized */
if(vs->parent && vs->parent->vectorized &&
((VectorizedState*)vs->parent->vectorized)->vectorized)
return ExecTableVScan(scanState);
else
{
TupleTableSlot* slot = scanState->ps.ps_ProjInfo ? scanState->ps.ps_ResultTupleSlot : scanState->ss_ScanTupleSlot;
while(1)
{
bool succ = VirtualNodeProc(slot);
if(!succ)
{
slot = ExecTableVScan(scanState);
if(TupIsNull(slot))
break;
else
continue;
}
break;
}
return slot;
}
}
TupleTableSlot *ExecTableVScan(ScanState *scanState)
{
if (scanState->scan_state == SCAN_INIT ||
scanState->scan_state == SCAN_DONE)
{
getVScanMethod(scanState->tableType)->beginScanMethod(scanState);
}
tbReset(scanState->ss_ScanTupleSlot->PRIVATE_tb);
tbReset(scanState->ps.ps_ResultTupleSlot->PRIVATE_tb);
TupleTableSlot *slot = ExecVScan(scanState,getVScanMethod(scanState->tableType)->accessMethod);
if (TupIsNull(slot) && !scanState->ps.delayEagerFree)
{
getVScanMethod(scanState->tableType)->endScanMethod(scanState);
}
return slot;
}
TupleTableSlot*
ExecVScan(ScanState *node, ExecScanAccessMtd accessMtd)
{
ExprContext *econtext;
List *qual;
ProjectionInfo *projInfo;
vbool *skip = NULL;
/*
* Fetch data from node
*/
qual = node->ps.qual;
projInfo = node->ps.ps_ProjInfo;
/*
* If we have neither a qual to check nor a projection to do, just skip
* all the overhead and return the raw scan tuple.
*/
if (!qual && !projInfo)
return (*accessMtd) (node);
/*
* Reset per-tuple memory context to free any expression evaluation
* storage allocated in the previous tuple cycle.
*/
econtext = node->ps.ps_ExprContext;
ResetExprContext(econtext);
/*
* get a tuple from the access method loop until we obtain a tuple which
* passes the qualification.
*/
for (;;)
{
TupleTableSlot *slot;
CHECK_FOR_INTERRUPTS();
slot = (*accessMtd) (node);
/*
* if the slot returned by the accessMtd contains NULL, then it means
* there is nothing more to scan so we just return an empty slot,
* being careful to use the projection result slot so it has correct
* tupleDesc.
*/
if (TupIsNull(slot))
{
if (projInfo)
return ExecClearTuple(projInfo->pi_slot);
else
return slot;
}
/*
* place the current tuple into the expr context
*/
econtext->ecxt_scantuple = slot;
/*
* check that the current tuple satisfies the qual-clause
*
* check for non-nil qual here to avoid a function call to ExecQual()
* when the qual is nil ... saves only a few cycles, but they add up
* ...
*/
if (!qual || (NULL != (skip = ExecVQual(qual, econtext, false))))
{
/*
* Found a satisfactory scan tuple.
*/
if (projInfo)
{
int i;
/* first construct the skip array */
if(NULL != skip)
{
for(i = 0; i < skip->dim; i++)
{
((TupleBatch)projInfo->pi_slot->PRIVATE_tb)->skip[i] =
((!DatumGetBool(skip->values[i])) ||
(skip->isnull[i]) ||
((TupleBatch)slot->PRIVATE_tb)->skip[i]);
}
}
else
{
Assert(((TupleBatch)projInfo->pi_slot->PRIVATE_tb)->batchsize ==
((TupleBatch)slot->PRIVATE_tb)->batchsize);
memcpy(((TupleBatch)projInfo->pi_slot->PRIVATE_tb)->skip,
((TupleBatch)slot->PRIVATE_tb)->skip,
((TupleBatch)slot->PRIVATE_tb)->batchsize * sizeof(bool));
}
/*
* Form a projection tuple, store it in the result tuple slot
* and return it.
*/
((TupleBatch)projInfo->pi_slot->PRIVATE_tb)->nrows = ((TupleBatch)slot->PRIVATE_tb)->nrows;
return ExecVProject(projInfo, NULL);
}
else
{
/*
* Here, we aren't projecting, so just return scan tuple.
*/
return slot;
}
}
/*
* Tuple fails qual, so free per-tuple memory and try again.
*/
ResetExprContext(econtext);
tbReset(node->ss_ScanTupleSlot->PRIVATE_tb);
tbReset(node->ps.ps_ResultTupleSlot->PRIVATE_tb);
}
}