int main () { int a1 = 1, a2 = 2, a3 = 3, a4 = 4; cons *list1, *list2; list_push(&list1, &a1); list_push(&list1, &a2); list_push(&list2, &a3); list_push(&list2, &a4); printf("list1:\n"); print_list(list1); printf("list2:\n"); print_list(list2); cons* testtt = NULL; list_concat(&testtt, &list1); printf("NULL+list1:\n"); print_list(list1); list_concat(&list1, &list2); printf("list1+list2:\n"); print_list(list1); testtt = NULL; list_concat(&list1, &testtt); printf("list1+NULL:\n"); print_list(list1); printf("length of list1:\n"); printf("%d\n", list_length(list1)); }
/* * master_metadata_snapshot prints all the queries that are required * to generate a metadata snapshot. */ Datum master_metadata_snapshot(PG_FUNCTION_ARGS) { List *dropSnapshotCommands = MetadataDropCommands(); List *createSnapshotCommands = MetadataCreateCommands(); List *snapshotCommandList = NIL; ListCell *snapshotCommandCell = NULL; int snapshotCommandCount = 0; Datum *snapshotCommandDatumArray = NULL; ArrayType *snapshotCommandArrayType = NULL; int snapshotCommandIndex = 0; Oid ddlCommandTypeId = TEXTOID; snapshotCommandList = list_concat(snapshotCommandList, dropSnapshotCommands); snapshotCommandList = list_concat(snapshotCommandList, createSnapshotCommands); snapshotCommandCount = list_length(snapshotCommandList); snapshotCommandDatumArray = palloc0(snapshotCommandCount * sizeof(Datum)); foreach(snapshotCommandCell, snapshotCommandList) { char *metadataSnapshotCommand = (char *) lfirst(snapshotCommandCell); Datum metadataSnapshotCommandDatum = CStringGetTextDatum(metadataSnapshotCommand); snapshotCommandDatumArray[snapshotCommandIndex] = metadataSnapshotCommandDatum; snapshotCommandIndex++; }
/* * transformTargetList() * Turns a list of ResTarget's into a list of TargetEntry's. * * This code acts mostly the same for SELECT, UPDATE, or RETURNING lists; * the main thing is to transform the given expressions (the "val" fields). * The exprKind parameter distinguishes these cases when necesssary. */ List * transformTargetList(ParseState *pstate, List *targetlist, ParseExprKind exprKind) { List *p_target = NIL; ListCell *o_target; /* Shouldn't have any leftover multiassign items at start */ Assert(pstate->p_multiassign_exprs == NIL); foreach(o_target, targetlist) { ResTarget *res = (ResTarget *) lfirst(o_target); /* * Check for "something.*". Depending on the complexity of the * "something", the star could appear as the last field in ColumnRef, * or as the last indirection item in A_Indirection. */ if (IsA(res->val, ColumnRef)) { ColumnRef *cref = (ColumnRef *) res->val; if (IsA(llast(cref->fields), A_Star)) { /* It is something.*, expand into multiple items */ p_target = list_concat(p_target, ExpandColumnRefStar(pstate, cref, true)); continue; } } else if (IsA(res->val, A_Indirection)) { A_Indirection *ind = (A_Indirection *) res->val; if (IsA(llast(ind->indirection), A_Star)) { /* It is something.*, expand into multiple items */ p_target = list_concat(p_target, ExpandIndirectionStar(pstate, ind, true, exprKind)); continue; } } /* * Not "something.*", so transform as a single expression */ p_target = lappend(p_target, transformTargetEntry(pstate, res->val, NULL, exprKind, res->name, false)); }
/* * transformTargetList() * Turns a list of ResTarget's into a list of TargetEntry's. * * At this point, we don't care whether we are doing SELECT, INSERT, * or UPDATE; we just transform the given expressions (the "val" fields). */ List * transformTargetList(ParseState *pstate, List *targetlist) { List *p_target = NIL; ListCell *o_target; foreach(o_target, targetlist) { ResTarget *res = (ResTarget *) lfirst(o_target); /* * Check for "something.*". Depending on the complexity of the * "something", the star could appear as the last name in ColumnRef, * or as the last indirection item in A_Indirection. */ if (IsA(res->val, ColumnRef)) { ColumnRef *cref = (ColumnRef *) res->val; if (strcmp(strVal(llast(cref->fields)), "*") == 0) { /* It is something.*, expand into multiple items */ p_target = list_concat(p_target, ExpandColumnRefStar(pstate, cref, true)); continue; } } else if (IsA(res->val, A_Indirection)) { A_Indirection *ind = (A_Indirection *) res->val; Node *lastitem = llast(ind->indirection); if (IsA(lastitem, String) && strcmp(strVal(lastitem), "*") == 0) { /* It is something.*, expand into multiple items */ p_target = list_concat(p_target, ExpandIndirectionStar(pstate, ind, true)); continue; } } /* * Not "something.*", so transform as a single expression */ p_target = lappend(p_target, transformTargetEntry(pstate, res->val, NULL, res->name, false)); }
struct list_res reachability (const struct hs *hs, uint32_t port, const uint32_t *out, int nout) { struct res *in = res_create (data_file->stages + 1); struct list_res res = {0}; hs_copy (&in->hs, hs); in->port = port; list_append (&queues[ntf_get_sw (in->port)], in); int n = data_file->ntfs - 1; struct tdata data[n]; memset (data, 0, sizeof data); g_out = out; g_nout = nout; for (int i = 0; i < n; i++) { struct tdata *p = &data[i]; p->sw = i; pthread_create (&p->tid, NULL, reach_thread, p); } for (int i = 0; i < n; i++) { pthread_join (data[i].tid, NULL); list_concat (&res, &data[i].res); } return res; }
struct list_res reachability (const uint32_t *out, int nout, int hop_count, bool find_loop, array_t * out_arr) { struct list_res res = {0}; int n = data_file->ntfs - 1; struct tdata data[n]; memset (data, 0, sizeof data); g_out = out; g_nout = nout; g_hop_count = hop_count; g_find_loop = find_loop; g_out_arr = out_arr; for (int i = 0; i < n; i++) { struct tdata *p = &data[i]; p->sw = i; pthread_create (&p->tid, NULL, reach_thread, p); } for (int i = 0; i < n; i++) { pthread_join (data[i].tid, NULL); list_concat (&res, &data[i].res); } return res; }
void worker_push(LPWORKER lpWorker) { BOOL bFreeWorker; bFreeWorker = TRUE; WaitForSingleObject(hWorkersMutex, INFINITE); DEBUG_PRINT("Testing if we are under the maximum number of running workers"); if (list_length((LPLIST)lpWorkers) < THREAD_WORKERS_MAX) { DEBUG_PRINT("Saving this worker for future use"); DEBUG_PRINT("Next: %x", ((LPLIST)lpWorker)->lpNext); lpWorkers = (LPWORKER)list_concat((LPLIST)lpWorker, (LPLIST)lpWorkers); bFreeWorker = FALSE; }; nWorkersCurrent--; DEBUG_PRINT("Workers running current/runnning max/waiting: %d/%d/%d", nWorkersCurrent, nWorkersMax, list_length((LPLIST)lpWorkers)); ReleaseMutex(hWorkersMutex); if (bFreeWorker) { DEBUG_PRINT("Freeing worker %x", lpWorker); worker_free(lpWorker); } }
struct list_res ntf_apply (const struct res *in, int sw) { struct tf *tf = tf_get (sw + 1); struct list_res queue = tf_apply (tf, in, false); for (int i = 0; i < data_file->stages - 1; i++) { struct list_res nextq = {0}; for (struct res *cur = queue.head; cur; cur = cur->next) { struct list_res tmp = tf_apply (tf, cur, true); list_concat (&nextq, &tmp); } list_res_free (&queue); queue = nextq; } struct res *cur = queue.head, *prev = NULL; while (cur) { int p = in->port + OUTPUT_ID; if (cur->port == p) list_remove (&queue, cur, prev, res_free); else { prev = cur; cur = cur->next; } } return queue; }
struct list_res res_walk_parents (const struct res *out, const struct hs *hs, int in_port, array_t* out_arr) { struct res *curr_res = (struct res*) out; struct list_res currq = {0}; // set up initial result to start inversion struct hs int_hs; hs_isect_arr (&int_hs, &out->hs, out_arr); list_append (&currq, res_extend (out, &int_hs, out->port, true)); struct res *cur; while (curr_res) { if (curr_res->rules.cur) { for (int i = curr_res->rules.cur - 1; i >= 0; i--) { struct list_res nextq = {0}; struct res_rule r = curr_res->rules.arr[i]; while ((cur = currq.head)) { list_pop (&currq); struct list_res tmp = rule_inv_apply (r.tf_tf, r.tf_rule, cur, false); list_concat (&nextq, &tmp); res_free (cur); } // for each current result from rule inversion currq = nextq; } // for each rule } else return currq; // set (hs,port) which the inverted (hs,port) results must intersect struct res *parent = curr_res->parent; struct hs *next_hs = hs_create (curr_res->hs.len); int next_port; if (parent) { hs_copy (next_hs, &parent->hs); next_port = parent->port; } else { hs_copy (next_hs, hs); next_port = in_port; } // Intersect the results in `currq` with the target (hs,port) struct list_res nextq = {0}; while ((cur = currq.head)) { list_pop (&currq); struct hs *new_hs = hs_isect_a (&cur->hs, next_hs); if (cur->port == next_port && new_hs) list_append (&nextq, res_extend (cur, new_hs, next_port, false)); else res_free (cur); } currq = nextq; curr_res = parent; } return currq; }
void list_copy(list_t *destiny, list_t *source) { /* No point in copying a list to itself. */ if (destiny != source){ list_empty(destiny); list_concat(destiny, source); } }
static void getTableOptions(Oid foreigntableid,struct ktTableOptions *table_options) { ForeignTable *table; ForeignServer *server; UserMapping *mapping; List *options; ListCell *lc; #ifdef DEBUG elog(NOTICE, "getTableOptions"); #endif /* * Extract options from FDW objects. We only need to worry about server * options for Redis * */ table = GetForeignTable(foreigntableid); server = GetForeignServer(table->serverid); mapping = GetUserMapping(GetUserId(), table->serverid); table_options->userId = mapping->userid; table_options->serverId = server->serverid; options = NIL; options = list_concat(options, table->options); options = list_concat(options, server->options); options = list_concat(options, mapping->options); // table_options->table_type = PG_REDIS_SCALAR_TABLE; /* Loop through the options, and get the server/port */ foreach(lc, options) { DefElem *def = (DefElem *) lfirst(lc); if (strcmp(def->defname, "host") == 0) table_options->host = defGetString(def); if (strcmp(def->defname, "port") == 0) table_options->port = atoi(defGetString(def)); if (strcmp(def->defname, "timeout") == 0) table_options->timeout = atoi(defGetString(def)); }
/* * pxf_make_expression_items_list * * Given a scan node qual list, find the filters that are eligible to be used * by PXF, construct an expressions list, which consists of OpExpr or BoolExpr nodes * and return it to the caller. * * Basically this function just transforms expression tree to Reversed Polish Notation list. * * */ static List * pxf_make_expression_items_list(List *quals, Node *parent, int *logicalOpsNum) { ExpressionItem *expressionItem = NULL; List *result = NIL; ListCell *lc = NULL; ListCell *ilc = NULL; if (list_length(quals) == 0) return NIL; foreach (lc, quals) { Node *node = (Node *) lfirst(lc); NodeTag tag = nodeTag(node); expressionItem = (ExpressionItem *) palloc0(sizeof(ExpressionItem)); expressionItem->node = node; expressionItem->parent = parent; expressionItem->processed = false; switch (tag) { case T_OpExpr: case T_NullTest: { result = lappend(result, expressionItem); break; } case T_BoolExpr: { (*logicalOpsNum)++; BoolExpr *expr = (BoolExpr *) node; List *inner_result = pxf_make_expression_items_list(expr->args, node, logicalOpsNum); result = list_concat(result, inner_result); int childNodesNum = 0; /* Find number of child nodes on first level*/ foreach (ilc, inner_result) { ExpressionItem *ei = (ExpressionItem *) lfirst(ilc); if (!ei->processed && ei->parent == node) { ei->processed = true; childNodesNum++; } } for (int i = 0; i < childNodesNum - 1; i++) { result = lappend(result, expressionItem); } break; } default: elog(DEBUG1, "pxf_make_expression_items_list: unsupported node tag %d", tag); break; }
/* * pxf_make_filter_list * * Given a scan node qual list, find the filters that are eligible to be used * by PXF, construct a PxfFilterDesc list that describes the filter information, * and return it to the caller. * * Caller is responsible for pfreeing the returned PxfFilterDesc List. */ static List * pxf_make_filter_list(List *quals) { List *result = NIL; ListCell *lc = NULL; if (list_length(quals) == 0) return NIL; /* * Iterate over all implicitly ANDed qualifiers and add the ones * that are supported for push-down into the result filter list. */ foreach (lc, quals) { Node *node = (Node *) lfirst(lc); NodeTag tag = nodeTag(node); switch (tag) { case T_OpExpr: { OpExpr *expr = (OpExpr *) node; PxfFilterDesc *filter; filter = (PxfFilterDesc *) palloc0(sizeof(PxfFilterDesc)); elog(DEBUG5, "pxf_make_filter_list: node tag %d (T_OpExpr)", tag); if (opexpr_to_pxffilter(expr, filter)) result = lappend(result, filter); else pfree(filter); break; } case T_BoolExpr: { BoolExpr *expr = (BoolExpr *) node; BoolExprType boolType = expr->boolop; elog(DEBUG5, "pxf_make_filter_list: node tag %d (T_BoolExpr), bool node type %d %s", tag, boolType, boolType==AND_EXPR ? "(AND_EXPR)" : ""); /* only AND_EXPR is supported */ if (expr->boolop == AND_EXPR) { List *inner_result = pxf_make_filter_list(expr->args); elog(DEBUG5, "pxf_make_filter_list: inner result size %d", list_length(inner_result)); result = list_concat(result, inner_result); } break; } default: /* expression not supported. ignore */ elog(DEBUG5, "pxf_make_filter_list: unsupported node tag %d", tag); break; } }
foreach(joinCell, joinList) { JoinExpr *joinExpr = (JoinExpr *) lfirst(joinCell); List *onClauseList = list_copy((List *) joinExpr->quals); List *joinClauseList = list_copy((List *) joinExpr->quals); JoinType joinType = joinExpr->jointype; RangeTblRef *nextRangeTableRef = NULL; TableEntry *nextTable = NULL; JoinOrderNode *nextJoinNode = NULL; Node *rightArg = joinExpr->rarg; /* get the table on the right hand side of the join */ if (IsA(rightArg, RangeTblRef)) { nextRangeTableRef = (RangeTblRef *) rightArg; } else { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot perform distributed planning on this query"), errdetail("Subqueries in outer joins are not supported"))); } nextTable = FindTableEntry(tableEntryList, nextRangeTableRef->rtindex); if (joinType == JOIN_INNER) { /* also consider WHERE clauses for INNER joins */ joinClauseList = list_concat(joinClauseList, joinWhereClauseList); } /* find the best join rule type */ nextJoinNode = EvaluateJoinRules(joinedTableList, currentJoinNode, nextTable, joinClauseList, joinType); if (nextJoinNode->joinRuleType >= SINGLE_HASH_PARTITION_JOIN) { /* re-partitioning for OUTER joins is not implemented */ ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot run outer join query if join is not on the " "partition column"), errdetail("Outer joins requiring repartitioning are not " "supported."))); } if (joinType != JOIN_INNER) { /* preserve non-join clauses for OUTER joins */ nextJoinNode->joinClauseList = onClauseList; } /* add next node to the join order */ joinOrderList = lappend(joinOrderList, nextJoinNode); joinedTableList = lappend(joinedTableList, nextTable); currentJoinNode = nextJoinNode; }
/* * RemoteCopy_GetRelationLoc * Get relation node list based on COPY data involved. An empty list is * returned to caller if relation involved has no locator information * as it is the case of a system relation. */ void RemoteCopy_GetRelationLoc(RemoteCopyData *state, Relation rel, List *attnums) { ExecNodes *exec_nodes = NULL; /* * If target table does not exists on nodes (e.g. system table) * the location info returned is NULL. This is the criteria, when * we need to run COPY on Coordinator */ state->rel_loc = GetRelationLocInfo(RelationGetRelid(rel)); if (state->rel_loc) { /* * Pick up one node only * This case corresponds to a replicated table with COPY TO * */ exec_nodes = makeNode(ExecNodes); if (!state->is_from && IsLocatorReplicated(state->rel_loc->locatorType)) exec_nodes->nodeList = GetPreferredReplicationNode(state->rel_loc->nodeList); else { /* All nodes necessary */ exec_nodes->nodeList = list_concat(exec_nodes->nodeList, state->rel_loc->nodeList); } } state->idx_dist_by_col = -1; if (state->rel_loc && state->rel_loc->partAttrNum != 0) { /* * Find the column used as key for data distribution. * First scan attributes of tuple descriptor with the list * of attributes used in COPY if any list is specified. * If no list is specified, set this value to the one of * locator information. */ if (attnums != NIL) { ListCell *cur; foreach(cur, attnums) { int attnum = lfirst_int(cur); if (state->rel_loc->partAttrNum == attnum) { state->idx_dist_by_col = attnum - 1; break; } } }
/* * GetTableDDLEvents takes in a relationId, includeSequenceDefaults flag, * and returns the list of DDL commands needed to reconstruct the relation. * When the flag includeSequenceDefaults is set, the function also creates * DEFAULT clauses for columns getting their default values from a sequence. * These DDL commands are all palloced; and include the table's schema * definition, optional column storage and statistics definitions, and index * and constraint definitions. */ List * GetTableDDLEvents(Oid relationId, bool includeSequenceDefaults) { List *tableDDLEventList = NIL; List *tableCreationCommandList = NIL; List *indexAndConstraintCommandList = NIL; List *replicaIdentityEvents = NIL; tableCreationCommandList = GetTableCreationCommands(relationId, includeSequenceDefaults); tableDDLEventList = list_concat(tableDDLEventList, tableCreationCommandList); indexAndConstraintCommandList = GetTableIndexAndConstraintCommands(relationId); tableDDLEventList = list_concat(tableDDLEventList, indexAndConstraintCommandList); replicaIdentityEvents = GetTableReplicaIdentityCommand(relationId); tableDDLEventList = list_concat(tableDDLEventList, replicaIdentityEvents); return tableDDLEventList; }
int main(/*int argc, char **argv*/) { int v0 = 0, v1 = 1, v2 = 1, v3 = 2, v4 = 3, v5 = 5, v6 = 8, v7 = 13; ImmutableListNode *list = list_create(8, 0, &v0, 0, &v1, 0, &v2, 0, &v3, 0, &v4, 0, &v5, 0, &v6, 0, &v7); ImmutableListNode *old; old = list; ImmutableListNode *orig = list_head(list); list_free(old); // test prepend printf("Testing Prepend:\n"); printf("length before: %d\n", list->length); int pref = 42; old = list; list = list_prepend(list, 0, &pref); printf("prev->head: %p, free old: %p\n", old, list_free(old)); printf("length after: %d\n", list->length); // test append printf("Testing Append (2x):\n"); printf("length before: %d\n", list->length); int aff = 21; old = list; list = list_append(list, 0, &aff); printf("length after 1x: %d\n", list->length); old = list; list = list_append(list, 0, &aff); printf("length after 2x: %d\n", list->length); // test concat printf("Testing Concatenation:\n"); printf("length a: %d, length b: %d\n", orig->length, list->length); ImmutableListNode *cattd = list_concat(orig, list); printf("orig: \n"); list_dump(stdout, orig); printf("list: \n"); list_dump(stdout, list); printf("cattd: \n"); list_dump(stdout, cattd); printf("free cattd: %p\n", list_free(cattd)); printf("free list: %p\n", list_free(list)); printf("free orig: %p\n", list_free(orig)); return 0; }
/* * Parse and plan a querystring. * * At entry, plan->argtypes and plan->nargs must be valid. * * Query and plan lists are stored into *plan. */ static void _SPI_prepare_plan(const char *src, _SPI_plan *plan) { List *raw_parsetree_list; List *query_list_list; List *plan_list; ListCell *list_item; ErrorContextCallback spierrcontext; Oid *argtypes = plan->argtypes; int nargs = plan->nargs; /* * Increment CommandCounter to see changes made by now. We must do * this to be sure of seeing any schema changes made by a just-preceding * SPI command. (But we don't bother advancing the snapshot, since the * planner generally operates under SnapshotNow rules anyway.) */ CommandCounterIncrement(); /* * Setup error traceback support for ereport() */ spierrcontext.callback = _SPI_error_callback; spierrcontext.arg = (void *) src; spierrcontext.previous = error_context_stack; error_context_stack = &spierrcontext; /* * Parse the request string into a list of raw parse trees. */ raw_parsetree_list = pg_parse_query(src); /* * Do parse analysis and rule rewrite for each raw parsetree. * * We save the querytrees from each raw parsetree as a separate * sublist. This allows _SPI_execute_plan() to know where the * boundaries between original queries fall. */ query_list_list = NIL; plan_list = NIL; foreach(list_item, raw_parsetree_list) { Node *parsetree = (Node *) lfirst(list_item); List *query_list; query_list = pg_analyze_and_rewrite(parsetree, argtypes, nargs); query_list_list = lappend(query_list_list, query_list); plan_list = list_concat(plan_list, pg_plan_queries(query_list, NULL, false)); }
void test_concat_append_add_union_intersection_difference(void) { List list1 = list_random(MAX_LIST_SIZE, ELEMENT_MAX_VALUE); list_sort_by_item(&list1); list_unique(&list1); printf("Original List 1 ::: "); list_print(&list1); List list2 = list_random(MAX_LIST_SIZE, ELEMENT_MAX_VALUE); list_sort_by_item(&list2); list_unique(&list2); printf("%sOriginal List 2 ::: ", brown); list_print(&list2); List concat = list_concat(&list1, &list2); printf("%sConcatenation List ::: ", cyan); list_print(&concat); List append = list_duplicate(&list1); list_append(&append, &list2); printf("%sList 1 appended to list 2 ::: ", magenta); list_print(&append); List add = list_duplicate(&list1); list_add(&add, &list2); printf("%sList 1 added to list 2 ::: ", green); list_print(&add); List union_list = list_union(&list1, &list2); printf("%sList Union ::: ", blue); list_print(&union_list); List intersection_list = list_intersection(&list1, &list2); printf("%sList Intersection ::: ", red); list_print(&intersection_list); List difference_list = list_difference(&list1, &list2); printf("%sDifference List ::: ", cyan); list_print(&difference_list); uint union_size = list_union_size(&list1, &list2); printf("%sList Union Size = %d\n", brown, union_size); uint intersection_size = list_intersection_size(&list1, &list2); printf("%sList Intersection Size = %d\n", black, intersection_size); uint difference_size = list_difference_size(&list1, &list2); printf("%sList Difference Size = %d\n", black, difference_size); printf("%s",none); }
static void getTableOptions(Oid foreigntableid, struct wdbTableOptions *table_options) { ForeignTable* table; ForeignServer* server; UserMapping* mapping; List* options = NIL; ListCell* lc = NULL; #ifdef DEBUG elog(NOTICE, "getTableOptions"); #endif /* * Extract options from FDW objects. * */ table = GetForeignTable(foreigntableid); server = GetForeignServer(table->serverid); mapping = GetUserMapping(GetUserId(), table->serverid); table_options->userId = mapping->userid; table_options->serverId = server->serverid; options = NIL; options = list_concat(options, table->options); options = list_concat(options, server->options); options = list_concat(options, mapping->options); /* Loop through the options, and get the server/port */ foreach(lc, options) { DefElem *def = (DefElem *) lfirst(lc); if (strcmp(def->defname, "address") == 0) table_options->address = defGetString(def); if (strcmp(def->defname, "size") == 0) table_options->size = atoi(defGetString(def)); }
/* * xfrm_tgt_list() * Turns a list of ResTarget's into a list of TargetEntry's. * * At this point, we don't care whether we are doing SELECT, INSERT, * or UPDATE; we just transform the given expressions (the "val" fields). */ struct list* xfrm_tgt_list(parse_state_s* pstate, struct list* targetlist) { struct list *p_target = NIL; struct list_cell *o_target; foreach(o_target, targetlist) { ResTarget *res = (ResTarget *) lfirst(o_target); /* * Check for "something.*". Depending on the complexity of the * "something", the star could appear as the last field in ColumnRef, * or as the last indirection item in A_Indirection. */ if (IS_A(res->val, ColumnRef)) { column_ref_n *cref; cref = (column_ref_n *) res->val; if (IS_A(llast(cref->fields), A_Star)) { /* It is something.*, expand into multiple items */ p_target = list_concat(p_target, ExpandColumnRefStar(pstate, cref, true)); continue; } } else if (IS_A(res->val, A_Indirection)) { A_Indirection *ind; ind = (A_Indirection*) res->val; if (IS_A(llast(ind->indirection), A_Star)) { /* It is something.*, expand into multiple items */ p_target = list_concat(p_target, ExpandIndirectionStar(pstate, ind, true)); continue; } } /* * Not "something.*", so transform as a single expression */ p_target = lappend(p_target, xfrm_tgt_entry(pstate, res->val, NULL, res->name, false)); }
static javaFdwExecutionState* javaGetOptions(Oid foreigntableid) { ForeignTable *f_table; ForeignServer *f_server; UserMapping *f_mapping; List *options; ListCell *cell; jobject obj, res, serverClass; jmethodID serverConstructor; jclass cl; javaFdwExecutionState *state; char *classname = NULL; options = NIL; f_table = GetForeignTable(foreigntableid); options = list_concat(options, f_table->options); f_server = GetForeignServer(f_table->serverid); options = list_concat(options, f_server->options); PG_TRY(); { f_mapping = GetUserMapping(GetUserId(), f_table->serverid); options = list_concat(options, f_mapping->options); } PG_CATCH(); { FlushErrorState(); /* DO NOTHING HERE */ } PG_END_TRY(); foreach(cell, options) { DefElem *def = (DefElem *) lfirst(cell); if (strcmp(def->defname, "class") == 0) { classname = (char *) defGetString(def); } }
struct list_res tf_apply (const struct tf *tf, const struct res *in, bool append) { assert (in->hs.len == data_arrs_len); uint32_t app[MAX_APP]; int napp = 0; struct list_res res = {0}; const struct port_map_elem *rules = rule_get (tf, in->port); if (!rules) return res; if (rules->start != UINT32_MAX) { for (uint32_t cur = rules->start; cur < tf->nrules; cur++) { const struct rule *r = &tf->rules[cur]; assert (r->in > 0); if (r->in != in->port) break; struct list_res tmp; tmp = rule_apply (r, tf, in, append, app, &napp); list_concat (&res, &tmp); } } /* Check all rules with multiple ports. */ for (int i = 0; i < tf->nrules; i++) { const struct rule *r = &tf->rules[i]; if (r->in >= 0) break; if (!port_match (in->port, r->in, tf)) continue; struct list_res tmp; tmp = rule_apply (r, tf, in, append, app, &napp); list_concat (&res, &tmp); } return res; }
/* * AtSubCommit_Notify() --- Take care of subtransaction commit. * * Reassign all items in the pending notifies list to the parent transaction. */ void AtSubCommit_Notify(void) { List *parentPendingNotifies; parentPendingNotifies = (List *) linitial(upperPendingNotifies); upperPendingNotifies = list_delete_first(upperPendingNotifies); Assert(list_length(upperPendingNotifies) == GetCurrentTransactionNestLevel() - 2); /* * We could try to eliminate duplicates here, but it seems not worthwhile. */ pendingNotifies = list_concat(parentPendingNotifies, pendingNotifies); }
/* * pglogBeginForeignScan * Initiate access to the log by creating CopyState */ static void pglogBeginForeignScan(ForeignScanState *node, int eflags) { ForeignScan *plan = (ForeignScan *) node->ss.ps.plan; PgLogExecutionState *festate; elog(DEBUG1,"Entering function %s",__func__); /* * Do nothing in EXPLAIN (no ANALYZE) case. node->fdw_state stays NULL. */ if (eflags & EXEC_FLAG_EXPLAIN_ONLY) return; /* Initialise the execution state */ festate = (PgLogExecutionState *) palloc(sizeof(PgLogExecutionState)); festate->filenames = initLogFileNames(Pglog_directory); festate->i = 0; /* Forces CSV format */ festate->options = list_make1(makeDefElem("format", (Node *) makeString("csv"))); /* Add any options from the plan (currently only convert_selectively) */ festate->options = list_concat(festate->options, plan->fdw_private); /* Remember scan memory context */ festate->scan_cxt = CurrentMemoryContext; /* * Create CopyState from FDW options. We always acquire all columns, so * as to match the expected ScanTupleSlot signature. * Starts from the first file in the list. */ festate->cstate = NULL; BeginNextCopy(node->ss.ss_currentRelation, festate); elog(DEBUG1,"Copy state %p",festate->cstate); /* * Save state in node->fdw_state. We must save enough information to call * BeginCopyFrom() again. */ node->fdw_state = (void *) festate; }
/* * Pull up children of a UNION node that are identically-propertied UNIONs. * * NOTE: we can also pull a UNION ALL up into a UNION, since the distinct * output rows will be lost anyway. */ static List * recurse_union_children(Node *setOp, PlannerInfo *root, double tuple_fraction, SetOperationStmt *top_union, List *refnames_tlist) { List *child_sortclauses; if (IsA(setOp, SetOperationStmt)) { SetOperationStmt *op = (SetOperationStmt *) setOp; if (op->op == top_union->op && (op->all == top_union->all || op->all) && equal(op->colTypes, top_union->colTypes)) { /* Same UNION, so fold children into parent's subplan list */ return list_concat(recurse_union_children(op->larg, root, tuple_fraction, top_union, refnames_tlist), recurse_union_children(op->rarg, root, tuple_fraction, top_union, refnames_tlist)); } } /* * Not same, so plan this child separately. * * Note we disallow any resjunk columns in child results. This is * necessary since the Append node that implements the union won't do any * projection, and upper levels will get confused if some of our output * tuples have junk and some don't. This case only arises when we have an * EXCEPT or INTERSECT as child, else there won't be resjunk anyway. */ return list_make1(recurse_set_operations(setOp, root, tuple_fraction, top_union->colTypes, false, -1, refnames_tlist, &child_sortclauses)); }
struct list *files_from_bundles(struct list *bundles) { struct list *files = NULL; struct list *list; struct manifest *bundle; list = list_head(bundles); while (list) { struct list *bfiles; bundle = list->data; list = list->next; if (!bundle) { continue; } bfiles = list_clone(bundle->files); files = list_concat(bfiles, files); } return files; }
/* * pull_ands * Recursively flatten nested AND clauses into a single and-clause list. * * Input is the arglist of an AND clause. * Returns the rebuilt arglist (note original list structure is not touched). */ static List * pull_ands(List *andlist) { List *out_list = NIL; ListCell *arg; foreach(arg, andlist) { Node *subexpr = (Node *) lfirst(arg); /* * Note: we can destructively concat the subexpression's arglist * because we know the recursive invocation of pull_ands will have * built a new arglist not shared with any other expr. Otherwise we'd * need a list_copy here. */ if (and_clause(subexpr)) out_list = list_concat(out_list, pull_ands(((BoolExpr *) subexpr)->args)); else out_list = lappend(out_list, subexpr); }
static const char * sonar_get_option(const char *optname, Oid tbl) { ForeignTable *foreignTable = NULL; List *optionList = NIL; ListCell *optionCell = NULL; const char *val = NULL; foreignTable = GetForeignTable(tbl); optionList = list_concat(optionList, foreignTable->options); foreach(optionCell, optionList) { DefElem *optionDef = (DefElem *) lfirst(optionCell); char *optionDefName = optionDef->defname; if (strncmp(optionDefName, optname, NAMEDATALEN) == 0) { val = defGetString(optionDef); break; } }
/* * Get any row security quals and check quals that should be applied to the * specified RTE. * * In addition, hasRowSecurity is set to true if row level security is enabled * (even if this RTE doesn't have any row security quals), and hasSubLinks is * set to true if any of the quals returned contain sublinks. */ void get_row_security_policies(Query *root, CmdType commandType, RangeTblEntry *rte, int rt_index, List **securityQuals, List **withCheckOptions, bool *hasRowSecurity, bool *hasSubLinks) { Expr *rowsec_expr = NULL; Expr *rowsec_with_check_expr = NULL; Expr *hook_expr_restrictive = NULL; Expr *hook_with_check_expr_restrictive = NULL; Expr *hook_expr_permissive = NULL; Expr *hook_with_check_expr_permissive = NULL; List *rowsec_policies; List *hook_policies_restrictive = NIL; List *hook_policies_permissive = NIL; Relation rel; Oid user_id; int rls_status; bool defaultDeny = false; /* Defaults for the return values */ *securityQuals = NIL; *withCheckOptions = NIL; *hasRowSecurity = false; *hasSubLinks = false; /* If this is not a normal relation, just return immediately */ if (rte->relkind != RELKIND_RELATION) return; /* Switch to checkAsUser if it's set */ user_id = rte->checkAsUser ? rte->checkAsUser : GetUserId(); /* Determine the state of RLS for this, pass checkAsUser explicitly */ rls_status = check_enable_rls(rte->relid, rte->checkAsUser, false); /* If there is no RLS on this table at all, nothing to do */ if (rls_status == RLS_NONE) return; /* * RLS_NONE_ENV means we are not doing any RLS now, but that may change * with changes to the environment, so we mark it as hasRowSecurity to * force a re-plan when the environment changes. */ if (rls_status == RLS_NONE_ENV) { /* * Indicate that this query may involve RLS and must therefore be * replanned if the environment changes (GUCs, role), but we are not * adding anything here. */ *hasRowSecurity = true; return; } /* Grab the built-in policies which should be applied to this relation. */ rel = heap_open(rte->relid, NoLock); rowsec_policies = pull_row_security_policies(commandType, rel, user_id); /* * Check if this is only the default-deny policy. * * Normally, if the table has row security enabled but there are no * policies, we use a default-deny policy and not allow anything. However, * when an extension uses the hook to add their own policies, we don't * want to include the default deny policy or there won't be any way for a * user to use an extension exclusively for the policies to be used. */ if (((RowSecurityPolicy *) linitial(rowsec_policies))->policy_id == InvalidOid) defaultDeny = true; /* Now that we have our policies, build the expressions from them. */ process_policies(root, rowsec_policies, rt_index, &rowsec_expr, &rowsec_with_check_expr, hasSubLinks, OR_EXPR); /* * Also, allow extensions to add their own policies. * * extensions can add either permissive or restrictive policies. * * Note that, as with the internal policies, if multiple policies are * returned then they will be combined into a single expression with all * of them OR'd (for permissive) or AND'd (for restrictive) together. * * If only a USING policy is returned by the extension then it will be * used for WITH CHECK as well, similar to how internal policies are * handled. * * The only caveat to this is that if there are NO internal policies * defined, there ARE policies returned by the extension, and RLS is * enabled on the table, then we will ignore the internally-generated * default-deny policy and use only the policies returned by the * extension. */ if (row_security_policy_hook_restrictive) { hook_policies_restrictive = (*row_security_policy_hook_restrictive) (commandType, rel); /* Build the expression from any policies returned. */ if (hook_policies_restrictive != NIL) process_policies(root, hook_policies_restrictive, rt_index, &hook_expr_restrictive, &hook_with_check_expr_restrictive, hasSubLinks, AND_EXPR); } if (row_security_policy_hook_permissive) { hook_policies_permissive = (*row_security_policy_hook_permissive) (commandType, rel); /* Build the expression from any policies returned. */ if (hook_policies_permissive != NIL) process_policies(root, hook_policies_permissive, rt_index, &hook_expr_permissive, &hook_with_check_expr_permissive, hasSubLinks, OR_EXPR); } /* * If the only built-in policy is the default-deny one, and hook policies * exist, then use the hook policies only and do not apply the * default-deny policy. Otherwise, we will apply both sets below. */ if (defaultDeny && (hook_policies_restrictive != NIL || hook_policies_permissive != NIL)) { rowsec_expr = NULL; rowsec_with_check_expr = NULL; } /* * For INSERT or UPDATE, we need to add the WITH CHECK quals to Query's * withCheckOptions to verify that any new records pass the WITH CHECK * policy (this will be a copy of the USING policy, if no explicit WITH * CHECK policy exists). */ if (commandType == CMD_INSERT || commandType == CMD_UPDATE) { /* * WITH CHECK OPTIONS wants a WCO node which wraps each Expr, so * create them as necessary. */ /* * Handle any restrictive policies first. * * They can simply be added. */ if (hook_with_check_expr_restrictive) { WithCheckOption *wco; wco = (WithCheckOption *) makeNode(WithCheckOption); wco->kind = commandType == CMD_INSERT ? WCO_RLS_INSERT_CHECK : WCO_RLS_UPDATE_CHECK; wco->relname = pstrdup(RelationGetRelationName(rel)); wco->qual = (Node *) hook_with_check_expr_restrictive; wco->cascaded = false; *withCheckOptions = lappend(*withCheckOptions, wco); } /* * Handle built-in policies, if there are no permissive policies from * the hook. */ if (rowsec_with_check_expr && !hook_with_check_expr_permissive) { WithCheckOption *wco; wco = (WithCheckOption *) makeNode(WithCheckOption); wco->kind = commandType == CMD_INSERT ? WCO_RLS_INSERT_CHECK : WCO_RLS_UPDATE_CHECK; wco->relname = pstrdup(RelationGetRelationName(rel)); wco->qual = (Node *) rowsec_with_check_expr; wco->cascaded = false; *withCheckOptions = lappend(*withCheckOptions, wco); } /* Handle the hook policies, if there are no built-in ones. */ else if (!rowsec_with_check_expr && hook_with_check_expr_permissive) { WithCheckOption *wco; wco = (WithCheckOption *) makeNode(WithCheckOption); wco->kind = commandType == CMD_INSERT ? WCO_RLS_INSERT_CHECK : WCO_RLS_UPDATE_CHECK; wco->relname = pstrdup(RelationGetRelationName(rel)); wco->qual = (Node *) hook_with_check_expr_permissive; wco->cascaded = false; *withCheckOptions = lappend(*withCheckOptions, wco); } /* Handle the case where there are both. */ else if (rowsec_with_check_expr && hook_with_check_expr_permissive) { WithCheckOption *wco; List *combined_quals = NIL; Expr *combined_qual_eval; combined_quals = lcons(copyObject(rowsec_with_check_expr), combined_quals); combined_quals = lcons(copyObject(hook_with_check_expr_permissive), combined_quals); combined_qual_eval = makeBoolExpr(OR_EXPR, combined_quals, -1); wco = (WithCheckOption *) makeNode(WithCheckOption); wco->kind = commandType == CMD_INSERT ? WCO_RLS_INSERT_CHECK : WCO_RLS_UPDATE_CHECK; wco->relname = pstrdup(RelationGetRelationName(rel)); wco->qual = (Node *) combined_qual_eval; wco->cascaded = false; *withCheckOptions = lappend(*withCheckOptions, wco); } /* * ON CONFLICT DO UPDATE has an RTE that is subject to both INSERT and * UPDATE RLS enforcement. Those are enforced (as a special, distinct * kind of WCO) on the target tuple. * * Make a second, recursive pass over the RTE for this, gathering * UPDATE-applicable RLS checks/WCOs, and gathering and converting * UPDATE-applicable security quals into WCO_RLS_CONFLICT_CHECK RLS * checks/WCOs. Finally, these distinct kinds of RLS checks/WCOs are * concatenated with our own INSERT-applicable list. */ if (root->onConflict && root->onConflict->action == ONCONFLICT_UPDATE && commandType == CMD_INSERT) { List *conflictSecurityQuals = NIL; List *conflictWCOs = NIL; ListCell *item; bool conflictHasRowSecurity = false; bool conflictHasSublinks = false; /* Assume that RTE is target resultRelation */ get_row_security_policies(root, CMD_UPDATE, rte, rt_index, &conflictSecurityQuals, &conflictWCOs, &conflictHasRowSecurity, &conflictHasSublinks); if (conflictHasRowSecurity) *hasRowSecurity = true; if (conflictHasSublinks) *hasSubLinks = true; /* * Append WITH CHECK OPTIONs/RLS checks, which should not conflict * between this INSERT and the auxiliary UPDATE */ *withCheckOptions = list_concat(*withCheckOptions, conflictWCOs); foreach(item, conflictSecurityQuals) { Expr *conflict_rowsec_expr = (Expr *) lfirst(item); WithCheckOption *wco; wco = (WithCheckOption *) makeNode(WithCheckOption); wco->kind = WCO_RLS_CONFLICT_CHECK; wco->relname = pstrdup(RelationGetRelationName(rel)); wco->qual = (Node *) copyObject(conflict_rowsec_expr); wco->cascaded = false; *withCheckOptions = lappend(*withCheckOptions, wco); } }