| /* |
| * 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. |
| */ |
| |
| //--------------------------------------------------------------------------- |
| // @filename: |
| // gpdbwrappers.h |
| // |
| // @doc: |
| // Definition of GPDB function wrappers |
| // |
| // @test: |
| // |
| // |
| //--------------------------------------------------------------------------- |
| #ifndef GPDB_gpdbwrappers_H |
| #define GPDB_gpdbwrappers_H |
| |
| #include "postgres.h" |
| #include "access/attnum.h" |
| #include "utils/faultinjector.h" |
| |
| // fwd declarations |
| typedef struct SysScanDescData *SysScanDesc; |
| typedef struct SnapshotData *Snapshot; |
| typedef int LOCKMODE; |
| typedef struct _FuncCandidateList *FuncCandidateList; |
| struct TypeCacheEntry; |
| typedef struct NumericData *Numeric; |
| typedef struct HeapTupleData *HeapTuple; |
| struct PartitionNode; |
| typedef struct RelationData *Relation; |
| struct Value; |
| typedef struct tupleDesc *TupleDesc; |
| struct Query; |
| typedef struct ScanKeyData *ScanKey; |
| typedef uint16 StrategyNumber; |
| struct Bitmapset; |
| struct Plan; |
| struct ListCell; |
| struct TargetEntry; |
| struct Expr; |
| struct ExtTableEntry; |
| struct Uri; |
| struct CdbComponentDatabases; |
| struct StringInfoData; |
| typedef StringInfoData *StringInfo; |
| struct LogicalIndexes; |
| struct LogicalIndexInfo; |
| struct ParseState; |
| struct DefElem; |
| struct GpPolicy; |
| struct PartitionSelector; |
| struct SelectedParts; |
| struct Motion; |
| struct QueryResource; |
| |
| namespace gpdb { |
| |
| // convert datum to bool |
| bool FBoolFromDatum(Datum d); |
| |
| // convert bool to datum |
| Datum DDatumFromBool(bool b); |
| |
| // convert datum to char |
| char CCharFromDatum(Datum d); |
| |
| // convert char to datum |
| Datum DDatumFromChar(char c); |
| |
| // convert datum to int8 |
| int8 CInt8FromDatum(Datum d); |
| |
| // convert int8 to datum |
| Datum DDatumFromInt8(int8 i8); |
| |
| // convert datum to uint8 |
| uint8 UcUint8FromDatum(Datum d); |
| |
| // convert uint8 to datum |
| Datum DDatumFromUint8(uint8 ui8); |
| |
| // convert datum to int16 |
| int16 SInt16FromDatum(Datum d); |
| |
| // convert int16 to datum |
| Datum DDatumFromInt16(int16 i16); |
| |
| // convert datum to uint16 |
| uint16 UsUint16FromDatum(Datum d); |
| |
| // convert uint16 to datum |
| Datum DDatumFromUint16(uint16 ui16); |
| |
| // convert datum to int32 |
| int32 IInt32FromDatum(Datum d); |
| |
| // convert int32 to datum |
| Datum DDatumFromInt32(int32 i32); |
| |
| // convert datum to uint32 |
| uint32 UlUint32FromDatum(Datum d); |
| |
| // convert uint32 to datum |
| Datum DDatumFromUint32(uint32 ui32); |
| |
| // convert datum to int64 |
| int64 LlInt64FromDatum(Datum d); |
| |
| // convert int64 to datum |
| Datum DDatumFromInt64(int64 i64); |
| |
| // convert datum to uint64 |
| uint64 UllUint64FromDatum(Datum d); |
| |
| // convert uint64 to datum |
| Datum DDatumFromUint64(uint64 ui64); |
| |
| // convert datum to oid |
| Oid OidFromDatum(Datum d); |
| |
| // convert datum to generic object with pointer handle |
| void *PvPointerFromDatum(Datum d); |
| |
| // convert datum to float4 |
| float4 FpFloat4FromDatum(Datum d); |
| |
| // convert datum to float8 |
| float8 DFloat8FromDatum(Datum d); |
| |
| // convert pointer to datum |
| Datum DDatumFromPointer(const void *p); |
| |
| // does an aggregate exist with the given oid |
| bool FAggregateExists(Oid oid); |
| |
| // add member to Bitmapset |
| Bitmapset *PbmsAddMember(Bitmapset *a, int x); |
| |
| // create a copy of an object |
| void *PvCopyObject(void *from); |
| |
| // datum size |
| Size SDatumSize(Datum value, bool typByVal, int typLen); |
| |
| // expression type |
| Oid OidExprType(Node *expr); |
| |
| // expression type modifier |
| int32 IExprTypeMod(Node *expr); |
| |
| // extract nodes with specific tag from a plan tree |
| List *PlExtractNodesPlan(Plan *pl, int nodeTag, bool descendIntoSubqueries); |
| |
| // extract nodes with specific tag from an expression tree |
| List *PlExtractNodesExpression(Node *node, int nodeTag, bool descendIntoSubqueries); |
| |
| // intermediate result type of given aggregate |
| Oid OidAggIntermediateResultType(Oid aggid); |
| |
| // replace Vars that reference JOIN outputs with references to the original |
| // relation variables instead |
| Query *PqueryFlattenJoinAliasVar(Query *pquery, gpos::ULONG ulQueryLevel); |
| |
| // is aggregate ordered |
| bool FOrderedAgg(Oid aggid); |
| |
| // does aggregate have a preliminary function |
| bool FAggHasPrelimFunc(Oid aggid); |
| |
| // does aggregate have a prelim or inverse prelim function |
| bool FAggHasPrelimOrInvPrelimFunc(Oid aggid); |
| |
| // intermediate result type of given aggregate |
| Oid OidAggregate(const char*szArg, Oid oidType); |
| |
| // array type oid |
| Oid OidArrayType(Oid typid); |
| |
| // deconstruct array |
| void DeconstructArray(struct ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, |
| char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp); |
| |
| // attribute stats slot |
| bool FGetAttrStatsSlot(HeapTuple statstuple, Oid atttype, int32 atttypmod, int reqkind, |
| Oid reqop, Datum **values, int *nvalues, float4 **numbers, int *nnumbers); |
| |
| // free attribute stats slot |
| void FreeAttrStatsSlot(Oid atttype, Datum *values, int nvalues, float4 *numbers, int nnumbers); |
| |
| // attribute statistics |
| HeapTuple HtAttrStats(Oid relid, AttrNumber attnum); |
| |
| // function oids |
| List *PlFunctionOids(void); |
| |
| // does a function exist with the given oid |
| bool FFunctionExists(Oid oid); |
| |
| // is the given function strict |
| bool FFuncStrict(Oid funcid); |
| |
| // stability property of given function |
| char CFuncStability(Oid funcid); |
| |
| // data access property of given function |
| char CFuncDataAccess(Oid funcid); |
| |
| // list of candidate functions with the given names |
| FuncCandidateList FclFuncCandidates(List *names, int nargs); |
| |
| // trigger name |
| char *SzTriggerName(Oid triggerid); |
| |
| // trigger relid |
| Oid OidTriggerRelid(Oid triggerid); |
| |
| // trigger funcid |
| Oid OidTriggerFuncid(Oid triggerid); |
| |
| // trigger type |
| int32 ITriggerType(Oid triggerid); |
| |
| // is trigger enabled |
| bool FTriggerEnabled(Oid triggerid); |
| |
| // does trigger exist |
| bool FTriggerExists(Oid oid); |
| |
| // does check constraint exist |
| bool FCheckConstraintExists(Oid oidCheckConstraint); |
| |
| // check constraint name |
| char *SzCheckConstraintName(Oid oidCheckConstraint); |
| |
| // check constraint relid |
| Oid OidCheckConstraintRelid(Oid oidCheckConstraint); |
| |
| // check constraint expression tree |
| Node *PnodeCheckConstraint(Oid oidCheckConstraint); |
| |
| // get the list of check constraints for a given relation |
| List *PlCheckConstraint(Oid oidRel); |
| |
| // part constraint expression tree |
| Node *PnodePartConstraintRel(Oid oidRel, List **pplDefaultLevels); |
| |
| // get the cast function for the specified source and destination types |
| bool FCastFunc(Oid oidSrc, Oid oidDest, bool *is_binary_coercible, Oid *oidCastFunc); |
| |
| // get type of operator |
| uint UlCmpt(Oid oidOp, Oid oidLeft, Oid oidRight); |
| |
| // get scalar comparison between given types |
| Oid OidScCmp(Oid oidLeft, Oid oidRight, uint ulCmpt); |
| |
| // function name |
| char *SzFuncName(Oid funcid); |
| |
| // output argument types of the given function |
| List *PlFuncOutputArgTypes(Oid funcid); |
| |
| // argument types of the given function |
| List *PlFuncArgTypes(Oid funcid); |
| |
| // does a function return a set of rows |
| bool FFuncRetset(Oid funcid); |
| |
| // return type of the given function |
| Oid OidFuncRetType(Oid funcid); |
| |
| // commutator operator of the given operator |
| Oid OidCommutatorOp(Oid opno); |
| |
| // inverse operator of the given operator |
| Oid OidInverseOp(Oid opno); |
| |
| // function oid corresponding to the given operator oid |
| RegProcedure OidOpFunc(Oid opno); |
| |
| // operator name |
| char *SzOpName(Oid opno); |
| |
| // parts of a partitioned table |
| bool FLeafPartition(Oid oid); |
| |
| // find the oid of the root partition given partition oid belongs to |
| Oid OidRootPartition(Oid oid); |
| |
| // partition attributes |
| List *PlPartitionAttrs(Oid oid); |
| |
| // parts of a partitioned table |
| PartitionNode *PpnParts(Oid relid, int2 level, Oid parent, bool inctemplate, MemoryContext mcxt, bool includesubparts); |
| |
| // keys of the relation with the given oid |
| List *PlRelationKeys(Oid relid); |
| |
| // relid of a composite type |
| Oid OidTypeRelid(Oid typid); |
| |
| // name of the type with the given oid |
| char *SzTypeName(Oid typid); |
| |
| // number of GP segments |
| int UlSegmentCountGP(void); |
| |
| // heap attribute is null |
| bool FHeapAttIsNull(HeapTuple tup, int attnum); |
| |
| // free heap tuple |
| void FreeHeapTuple(HeapTuple htup); |
| |
| // does an index exist with the given oid |
| bool FIndexExists(Oid oid); |
| |
| // check if given oid is hashable internally in Greenplum Database |
| bool FGreenplumDbHashable(Oid typid); |
| |
| // append an element to a list |
| List *PlAppendElement(List *list, void *datum); |
| |
| // append an integer to a list |
| List *PlAppendInt(List *list, int datum); |
| |
| // append an oid to a list |
| List *PlAppendOid(List *list, Oid datum); |
| |
| // prepend a new element to the list |
| List *PlPrependElement(void *datum, List *list); |
| |
| // prepend an integer to the list |
| List *PlPrependInt(int datum, List *list); |
| |
| // prepend an oid to a list |
| List *PlPrependOid(Oid datum, List *list); |
| |
| // concatenate lists |
| List *PlConcat(List *list1, List *list2); |
| |
| // copy list |
| List *PlCopy(List *list); |
| |
| // first cell in a list |
| ListCell *PlcListHead(List *l); |
| |
| // last cell in a list |
| ListCell *PlcListTail(List *l); |
| |
| // number of items in a list |
| int UlListLength(List *l); |
| |
| // return the nth element in a list of pointers |
| void *PvListNth(List *list, int n); |
| |
| // return the nth element in a list of ints |
| int IListNth(List *list, int n); |
| |
| // return the nth element in a list of oids |
| Oid OidListNth(List *list, int n); |
| |
| // check whether the given oid is a member of the given list |
| bool FMemberOid(List *list, Oid oid); |
| |
| // free list |
| void FreeList(List *plist); |
| |
| // deep free of a list |
| void FreeListDeep(List *plist); |
| |
| // if pplist is non-NULL, and *pplist is non-NULL then free the list and set |
| // *pplist to NULL |
| void FreeListAndNull(List **pplist); |
| |
| // is this a Gather motion |
| bool FMotionGather(const Motion *pmotion); |
| |
| // does a multi-level partitioned table have uniform partitioning hierarchy |
| bool FMultilevelPartitionUniform(Oid rootOid); |
| |
| // lookup type cache |
| TypeCacheEntry *PtceLookup(Oid type_id, int flags); |
| |
| // create a value node for a string |
| Value *PvalMakeString(char *str); |
| |
| // create a value node for an integer |
| Value *PvalMakeInteger(long i); |
| |
| // create a bool constant |
| Node *PnodeMakeBoolConst(bool value, bool isnull); |
| |
| // make a NULL constant of the given type |
| Node *PnodeMakeNULLConst(Oid oidType); |
| |
| // create a new target entry |
| TargetEntry *PteMakeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk); |
| |
| // create a new var node |
| Var *PvarMakeVar(Index varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Index varlevelsup); |
| |
| // memory allocation functions |
| void *PvMemoryContextAllocImpl(MemoryContext context, Size size, const char* file, const char * func, int line); |
| void *PvMemoryContextAllocZeroAlignedImpl(MemoryContext context, Size size, const char* file, const char * func, int line); |
| void *PvMemoryContextAllocZeroImpl(MemoryContext context, Size size, const char* file, const char * func, int line); |
| void *PvMemoryContextReallocImpl(void *pointer, Size size, const char* file, const char * func, int line); |
| void *GPDBAlloc(Size size); |
| void GPDBFree(void *ptr); |
| |
| // create a duplicate of the given string in the given memory context |
| char *SzMemoryContextStrdup(MemoryContext context, const char *string); |
| |
| // string representation of a node |
| char *SzNodeToString(void *obj); |
| |
| // node representation from a string |
| Node *Pnode(char *string); |
| |
| // return the default value of the type |
| Node *PnodeTypeDefault(Oid typid); |
| |
| // convert numeric to double; if out of range, return +/- HUGE_VAL |
| double DNumericToDoubleNoOverflow(Numeric num); |
| |
| // convert time-related datums to double for stats purpose |
| double DConvertTimeValueToScalar(Datum datum, Oid typid); |
| |
| // convert network-related datums to double for stats purpose |
| double DConvertNetworkToScalar(Datum datum, Oid typid); |
| |
| // is the given operator hash-joinable |
| bool FOpHashJoinable(Oid opno); |
| |
| // is the given operator merge-joinable |
| bool FOpMergeJoinable(Oid opno, Oid *leftOp, Oid *rightOp); |
| |
| // is the given operator strict |
| bool FOpStrict(Oid opno); |
| |
| // get input types for a given operator |
| void GetOpInputTypes(Oid opno, Oid *lefttype, Oid *righttype); |
| |
| // does an operator exist with the given oid |
| bool FOperatorExists(Oid oid); |
| |
| // fetch detoasted copies of toastable datatypes |
| struct varlena *PvlenDetoastDatum(struct varlena * datum); |
| |
| // expression tree walker |
| bool FWalkExpressionTree(Node *node, bool(*walker)(), void *context); |
| |
| // query or expression tree walker |
| bool FWalkQueryOrExpressionTree(Node *node, bool(*walker)(), void *context, int flags); |
| |
| // modify a query tree |
| Query *PqueryMutateQueryTree(Query *query, Node *(*mutator)(), void *context, int flags); |
| |
| // modify an expression tree |
| Node *PnodeMutateExpressionTree(Node *node, Node *(*mutator)(), void *context); |
| |
| // modify a query or an expression tree |
| Node *PnodeMutateQueryOrExpressionTree(Node *node, Node *(*mutator)(), void *context, int flags); |
| |
| // the part of PqueryMutateQueryTree that processes a query's rangetable |
| List *PlMutateRangeTable(List *rtable, Node *(*mutator)(), void *context, int flags); |
| |
| // check whether the part with the given oid is the root of a partition table |
| bool FRelPartIsRoot(Oid relid); |
| |
| // check whether the part with the given oid is an interior subpartition |
| bool FRelPartIsInterior(Oid relid); |
| |
| // check whether table with the given oid is a regular table and not part of a partitioned table |
| bool FRelPartIsNone(Oid relid); |
| |
| // check whether partitioning type encodes hash partitioning |
| bool FHashPartitioned(char c); |
| |
| // check whether a relation is inherited |
| bool FHasSubclass(Oid oidRel); |
| |
| // check whether a relation has parquet children |
| bool FHasParquetChildren(Oid oidRel); |
| |
| // return the distribution policy of a relation; if the table is partitioned |
| // and the parts are distributed differently, return Random distribution |
| GpPolicy *Pdistrpolicy(Relation rel); |
| |
| // return active relation distribution types |
| List *PlActiveRelTypes(void); |
| |
| // return active query resource |
| QueryResource *PqrActiveQueryResource(void); |
| |
| // return true if the table is partitioned and hash-distributed, and one of |
| // the child partitions is randomly distributed |
| gpos::BOOL FChildPartDistributionMismatch(Relation rel); |
| |
| // return true if the table is partitioned and any of the child partitions |
| // have a trigger of the given type |
| gpos::BOOL FChildTriggers(Oid oid, int triggerType); |
| |
| // does a relation exist with the given oid |
| bool FRelationExists(Oid oid); |
| |
| // extract all relation oids from the catalog |
| List *PlRelationOids(void); |
| |
| // estimate the relation size using the real number of blocks and tuple density |
| void EstimateRelationSize(Relation rel, int32 *attr_widths, BlockNumber *pages, double *tuples); |
| |
| // close the given relation |
| void CloseRelation(Relation rel); |
| |
| // return the logical indexes for a partitioned table |
| LogicalIndexes *Plgidx(Oid oid); |
| |
| // return the logical info structure for a given logical index oid |
| LogicalIndexInfo *Plgidxinfo(Oid rootOid, Oid indexOid); |
| |
| // return a list of index oids for a given relation |
| List *PlRelationIndexes(Relation relation); |
| |
| // build an array of triggers for this relation |
| void BuildRelationTriggers(Relation rel); |
| |
| // get relation with given oid |
| Relation RelGetRelation(Oid relationId); |
| |
| // get external table entry with given oid |
| ExtTableEntry *Pexttable(Oid relationId); |
| |
| // return the first member of the given targetlist whose expression is |
| // equal to the given expression, or NULL if no such member exists |
| TargetEntry *PteMember(Node *node, List *targetlist); |
| |
| // return a list of members of the given targetlist whose expression is |
| // equal to the given expression, or NULL if no such member exists |
| List *PteMembers(Node *node, List *targetlist); |
| |
| // check if two gpdb objects are equal |
| bool FEqual(void *p1, void *p2); |
| |
| // does a type exist with the given oid |
| bool FTypeExists(Oid oid); |
| |
| // check whether a type is composite |
| bool FCompositeType(Oid typid); |
| |
| // get integer value from an Integer value node |
| int IValue(Node *node); |
| |
| // parse external table URI |
| Uri *PuriParseExternalTable(const char *szUri); |
| |
| // check if the given uri is a HADOOP protocol - pxf |
| bool FPxfProtocol(Uri *pUri); |
| |
| // calculate max_participants_allowed for pxf |
| int IMaxParticipantsPxf(int total_segments); |
| |
| // generate the mapping of the Hadoop data fragments to the segments |
| char** RgszMapHdDataToSegments(char *uri, int total_segs, int working_segs, Relation relation, List* quals); |
| |
| // release the memory allocated for the mapping of the Hadoop data fragments to the segments |
| void FreeHdDataToSegmentsMapping(char **segs_work_map, int total_segs); |
| |
| // returns ComponentDatabases |
| List *PcdbComponentDatabases(void); |
| |
| // compare two strings ignoring case |
| int IStrCmpIgnoreCase(const char *sz1, const char *sz2); |
| |
| // construct random segment map |
| bool *RgfRandomSegMap(int total_primaries, int total_to_skip); |
| |
| // initialize a StringInfoData struct with data buffer of 'size' bytes |
| void InitStringInfoOfSize(StringInfo str, int bufsize); |
| |
| // create an empty 'StringInfoData' & return a pointer to it |
| StringInfo SiMakeStringInfo(void); |
| |
| // append the two given strings to the StringInfo object |
| void AppendStringInfo(StringInfo str, const char *str1, const char *str2); |
| |
| // append a null-terminated string to str |
| void AppendStringInfoString(StringInfo str, const char *s); |
| |
| // append a single character to str |
| void AppendStringInfoChar(StringInfo str, char c); |
| |
| // look for the given node tags in the given tree and return the index of |
| // the first one found, or -1 if there are none |
| int IFindNodes(Node *node, List *nodeTags); |
| |
| Node *PnodeCoerceToCommonType(ParseState *pstate, Node *pnode, Oid oidTargetType, const char *context); |
| |
| // deduce an individual actual datatype on the assumption that the rules for ANYARRAY/ANYELEMENT are being followed |
| Oid OidResolveGenericType(Oid declared_type, Oid context_actual_type, Oid context_declared_type); |
| |
| // hash a const value with GPDB's hash function |
| int32 ICdbHash(Const *pconst, int iSegments); |
| |
| // hash a list of const values with GPDB's hash function |
| int32 ICdbHashList(List *plConsts, int iSegments); |
| |
| // check permissions on range table |
| void CheckRTPermissions(List *plRangeTable); |
| |
| // get index operator properties |
| void IndexOpProperties(Oid opno, Oid opclass, int *strategy, Oid *subtype, bool *recheck); |
| |
| // get oids of classes this operator belongs to |
| List *PlScOpOpClasses(Oid opno); |
| |
| // get oids of op classes for the index keys |
| List *PlIndexOpClasses(Oid oidIndex); |
| |
| // returns the result of evaluating 'pexpr' as an Expr. Caller keeps ownership of 'pexpr' |
| // and takes ownership of the result |
| Expr *PexprEvaluate(Expr *pexpr, Oid oidResultType); |
| |
| // interpret the value of "With oids" option from a list of defelems |
| bool FInterpretOidsOption(List *plOptions); |
| |
| // extract string value from defelem's value |
| char *SzDefGetString(DefElem *pdefelem, bool *fNeedFree); |
| |
| // fold array expression constant values |
| Node *PnodeFoldArrayexprConstants(ArrayExpr *parrayexpr); |
| |
| // static partition selection given a PartitionSelector node |
| SelectedParts *SpStaticPartitionSelection(PartitionSelector *ps); |
| |
| // simple fault injector used by COptTasks.cpp to inject GPDB fault |
| FaultInjectorType_e OptTasksFaultInjector(FaultInjectorIdentifier_e identifier); |
| |
| // return the number of leaf partition for a given table oid |
| gpos::ULONG UlLeafPartitions(Oid oidRelation); |
| |
| // requests version for object from MD Versioning component |
| void MdVerRequestVersion(Oid key, uint64 *ddl_version, uint64 *dml_version); |
| |
| } //namespace gpdb |
| |
| #define ForEach(cell, l) \ |
| for ((cell) = gpdb::PlcListHead(l); (cell) != NULL; (cell) = lnext(cell)) |
| |
| #define ForBoth(cell1, list1, cell2, list2) \ |
| for ((cell1) = gpdb::PlcListHead(list1), (cell2) = gpdb::PlcListHead(list2); \ |
| (cell1) != NULL && (cell2) != NULL; \ |
| (cell1) = lnext(cell1), (cell2) = lnext(cell2)) |
| |
| #define ForEachWithCount(cell, list, counter) \ |
| for ((cell) = gpdb::PlcListHead(list), (counter)=0; \ |
| (cell) != NULL; \ |
| (cell) = lnext(cell), ++(counter)) |
| |
| #define ListMake1(x1) gpdb::PlPrependElement(x1, NIL) |
| |
| #define ListMake2(x1,x2) gpdb::PlPrependElement(x1, ListMake1(x2)) |
| |
| #define ListMake1Int(x1) gpdb::PlPrependInt(x1, NIL) |
| |
| #define ListMake1Oid(x1) gpdb::PlPrependOid(x1, NIL) |
| #define ListMake2Oid(x1,x2) gpdb::PlPrependOid(x1, ListMake1Oid(x2)) |
| |
| #define LInitial(l) lfirst(gpdb::PlcListHead(l)) |
| |
| #define LInitialOID(l) lfirst_oid(gpdb::PlcListHead(l)) |
| |
| #define Palloc0Fast(sz) \ |
| ( MemSetTest(0, (sz)) ? \ |
| gpdb::PvMemoryContextAllocZeroAlignedImpl(CurrentMemoryContext, (sz), __FILE__, PG_FUNCNAME_MACRO, __LINE__) : \ |
| gpdb::PvMemoryContextAllocZeroImpl(CurrentMemoryContext, (sz), __FILE__, PG_FUNCNAME_MACRO, __LINE__)) |
| |
| #ifdef __GNUC__ |
| |
| /* With GCC, we can use a compound statement within an expression */ |
| #define NewNode(size, tag) \ |
| ({ Node *_result; \ |
| AssertMacro((size) >= sizeof(Node)); /* need the tag, at least */ \ |
| _result = (Node *) Palloc0Fast(size); \ |
| _result->type = (tag); \ |
| _result; \ |
| }) |
| #else |
| |
| /* |
| * There is no way to dereference the palloc'ed pointer to assign the |
| * tag, and also return the pointer itself, so we need a holder variable. |
| * Fortunately, this macro isn't recursive so we just define |
| * a global variable for this purpose. |
| */ |
| extern PGDLLIMPORT Node *newNodeMacroHolder; |
| |
| #define NewNode(size, tag) \ |
| ( \ |
| AssertMacro((size) >= sizeof(Node)), /* need the tag, at least */ \ |
| newNodeMacroHolder = (Node *) Palloc0Fast(size), \ |
| newNodeMacroHolder->type = (tag), \ |
| newNodeMacroHolder \ |
| ) |
| #endif // __GNUC__ |
| |
| #define MakeNode(_type_) ((_type_ *) NewNode(sizeof(_type_),T_##_type_)) |
| |
| #define PStrDup(str) gpdb::SzMemoryContextStrdup(CurrentMemoryContext, (str)) |
| |
| #endif // !GPDB_gpdbwrappers_H |
| |
| // EOF |