* postgresBeginForeignScan * Initiate an executor scan of a foreign PostgreSQL table. */
| 1489 | * Initiate an executor scan of a foreign PostgreSQL table. |
| 1490 | */ |
| 1491 | static void |
| 1492 | postgresBeginForeignScan(ForeignScanState *node, int eflags) |
| 1493 | { |
| 1494 | ForeignScan *fsplan = (ForeignScan *) node->ss.ps.plan; |
| 1495 | EState *estate = node->ss.ps.state; |
| 1496 | PgFdwScanState *fsstate; |
| 1497 | RangeTblEntry *rte; |
| 1498 | Oid userid; |
| 1499 | ForeignTable *table; |
| 1500 | UserMapping *user; |
| 1501 | int rtindex; |
| 1502 | int numParams; |
| 1503 | |
| 1504 | /* |
| 1505 | * Do nothing in EXPLAIN (no ANALYZE) case. node->fdw_state stays NULL. |
| 1506 | */ |
| 1507 | if (eflags & EXEC_FLAG_EXPLAIN_ONLY) |
| 1508 | return; |
| 1509 | |
| 1510 | /* |
| 1511 | * We'll save private state in node->fdw_state. |
| 1512 | */ |
| 1513 | fsstate = (PgFdwScanState *) palloc0(sizeof(PgFdwScanState)); |
| 1514 | node->fdw_state = (void *) fsstate; |
| 1515 | |
| 1516 | /* |
| 1517 | * Identify which user to do the remote access as. This should match what |
| 1518 | * ExecCheckRTEPerms() does. In case of a join or aggregate, use the |
| 1519 | * lowest-numbered member RTE as a representative; we would get the same |
| 1520 | * result from any. |
| 1521 | */ |
| 1522 | if (fsplan->scan.scanrelid > 0) |
| 1523 | rtindex = fsplan->scan.scanrelid; |
| 1524 | else |
| 1525 | rtindex = bms_next_member(fsplan->fs_relids, -1); |
| 1526 | rte = exec_rt_fetch(rtindex, estate); |
| 1527 | userid = rte->checkAsUser ? rte->checkAsUser : GetUserId(); |
| 1528 | |
| 1529 | /* Get info about foreign table. */ |
| 1530 | table = GetForeignTable(rte->relid); |
| 1531 | user = GetUserMapping(userid, table->serverid); |
| 1532 | |
| 1533 | /* |
| 1534 | * Get connection to the foreign server. Connection manager will |
| 1535 | * establish new connection if necessary. |
| 1536 | */ |
| 1537 | fsstate->conn = GetConnection(user, false, &fsstate->conn_state); |
| 1538 | |
| 1539 | /* Assign a unique ID for my cursor */ |
| 1540 | fsstate->cursor_number = GetCursorNumber(fsstate->conn); |
| 1541 | fsstate->cursor_exists = false; |
| 1542 | |
| 1543 | /* Get private info created by planner functions. */ |
| 1544 | fsstate->query = strVal(list_nth(fsplan->fdw_private, |
| 1545 | FdwScanPrivateSelectSql)); |
| 1546 | fsstate->retrieved_attrs = (List *) list_nth(fsplan->fdw_private, |
| 1547 | FdwScanPrivateRetrievedAttrs); |
| 1548 | fsstate->fetch_size = intVal(list_nth(fsplan->fdw_private, |
nothing calls this directly
no test coverage detected