* Acquire a random sample of rows from foreign table managed by postgres_fdw. * * We fetch the whole table from the remote side and pick out some sample rows. * * Selected rows are returned in the caller-allocated array rows[], * which must have at least targrows entries. * The actual number of rows selected is returned as the function result. * We also count the total number of rows in the
| 5008 | * currently (the planner only pays attention to correlation for indexscans). |
| 5009 | */ |
| 5010 | static int |
| 5011 | postgresAcquireSampleRowsFunc(Relation relation, int elevel, |
| 5012 | HeapTuple *rows, int targrows, |
| 5013 | double *totalrows, |
| 5014 | double *totaldeadrows) |
| 5015 | { |
| 5016 | PgFdwAnalyzeState astate; |
| 5017 | ForeignTable *table; |
| 5018 | ForeignServer *server; |
| 5019 | UserMapping *user; |
| 5020 | PGconn *conn; |
| 5021 | unsigned int cursor_number; |
| 5022 | StringInfoData sql; |
| 5023 | PGresult *volatile res = NULL; |
| 5024 | |
| 5025 | /* Initialize workspace state */ |
| 5026 | astate.rel = relation; |
| 5027 | astate.attinmeta = TupleDescGetAttInMetadata(RelationGetDescr(relation)); |
| 5028 | |
| 5029 | astate.rows = rows; |
| 5030 | astate.targrows = targrows; |
| 5031 | astate.numrows = 0; |
| 5032 | astate.samplerows = 0; |
| 5033 | astate.rowstoskip = -1; /* -1 means not set yet */ |
| 5034 | reservoir_init_selection_state(&astate.rstate, targrows); |
| 5035 | |
| 5036 | /* Remember ANALYZE context, and create a per-tuple temp context */ |
| 5037 | astate.anl_cxt = CurrentMemoryContext; |
| 5038 | astate.temp_cxt = AllocSetContextCreate(CurrentMemoryContext, |
| 5039 | "postgres_fdw temporary data", |
| 5040 | ALLOCSET_SMALL_SIZES); |
| 5041 | |
| 5042 | /* |
| 5043 | * Get the connection to use. We do the remote access as the table's |
| 5044 | * owner, even if the ANALYZE was started by some other user. |
| 5045 | */ |
| 5046 | table = GetForeignTable(RelationGetRelid(relation)); |
| 5047 | server = GetForeignServer(table->serverid); |
| 5048 | user = GetUserMapping(relation->rd_rel->relowner, table->serverid); |
| 5049 | conn = GetConnection(user, false, NULL); |
| 5050 | |
| 5051 | /* |
| 5052 | * Construct cursor that retrieves whole rows from remote. |
| 5053 | */ |
| 5054 | cursor_number = GetCursorNumber(conn); |
| 5055 | initStringInfo(&sql); |
| 5056 | appendStringInfo(&sql, "DECLARE c%u CURSOR FOR ", cursor_number); |
| 5057 | deparseAnalyzeSql(&sql, relation, &astate.retrieved_attrs); |
| 5058 | |
| 5059 | /* In what follows, do not risk leaking any PGresults. */ |
| 5060 | PG_TRY(); |
| 5061 | { |
| 5062 | char fetch_sql[64]; |
| 5063 | int fetch_size; |
| 5064 | ListCell *lc; |
| 5065 | |
| 5066 | res = pgfdw_exec_query(conn, sql.data, NULL); |
| 5067 | if (PQresultStatus(res) != PGRES_COMMAND_OK) |
nothing calls this directly
no test coverage detected