* Return the current position of a cursor that a CURRENT OF expression * refers to. * * This checks that the cursor is valid for table specified by 'table_oid', * but it doesn't have to be scanning a row of that table (i.e. it can * be scanning a row of a different table in the same inheritance hierarchy). * The current table's oid is returned in *current_table_oid. * * GPDB calls it befor
| 130 | * Returns true if a row was identified. |
| 131 | */ |
| 132 | bool |
| 133 | getCurrentOf(CurrentOfExpr *cexpr, |
| 134 | ExprContext *econtext, |
| 135 | Oid table_oid, |
| 136 | ItemPointer current_tid, |
| 137 | int *current_gp_segment_id, |
| 138 | Oid *current_table_oid, |
| 139 | char **p_cursor_name) |
| 140 | { |
| 141 | char *cursor_name; |
| 142 | char *table_name; |
| 143 | Portal portal; |
| 144 | QueryDesc *queryDesc; |
| 145 | TupleTableSlot *slot; |
| 146 | AttrNumber gp_segment_id_attno; |
| 147 | AttrNumber ctid_attno; |
| 148 | AttrNumber tableoid_attno; |
| 149 | bool isnull; |
| 150 | Datum value; |
| 151 | |
| 152 | /* |
| 153 | * In an executor node, execCurrentOf() is supposed to use the cursor |
| 154 | * position information received from the dispatcher, and we shouldn't |
| 155 | * get here. |
| 156 | */ |
| 157 | if (Gp_role == GP_ROLE_EXECUTE) |
| 158 | elog(ERROR, "getCurrentOf called in executor node"); |
| 159 | |
| 160 | /* Get the cursor name --- may have to look up a parameter reference */ |
| 161 | if (cexpr->cursor_name) |
| 162 | cursor_name = cexpr->cursor_name; |
| 163 | else |
| 164 | { |
| 165 | if (!econtext->ecxt_param_list_info) |
| 166 | elog(ERROR, "no cursor name information found"); |
| 167 | |
| 168 | cursor_name = fetch_cursor_param_value(econtext, cexpr->cursor_param); |
| 169 | } |
| 170 | |
| 171 | /* Fetch table name for possible use in error messages */ |
| 172 | table_name = get_rel_name(table_oid); |
| 173 | if (table_name == NULL) |
| 174 | elog(ERROR, "cache lookup failed for relation %u", table_oid); |
| 175 | |
| 176 | /* Find the cursor's portal */ |
| 177 | portal = GetPortalByName(cursor_name); |
| 178 | if (!PortalIsValid(portal)) |
| 179 | ereport(ERROR, |
| 180 | (errcode(ERRCODE_UNDEFINED_CURSOR), |
| 181 | errmsg("cursor \"%s\" does not exist", cursor_name))); |
| 182 | |
| 183 | /* |
| 184 | * We have to watch out for non-SELECT queries as well as held cursors, |
| 185 | * both of which may have null queryDesc. |
| 186 | */ |
| 187 | if (portal->strategy != PORTAL_ONE_SELECT) |
| 188 | ereport(ERROR, |
| 189 | (errcode(ERRCODE_INVALID_CURSOR_STATE), |
no test coverage detected