| 914 | } |
| 915 | |
| 916 | static uint64 |
| 917 | execute(CursorData *c) |
| 918 | { |
| 919 | last_row_count = 0; |
| 920 | |
| 921 | /* clean space with saved result */ |
| 922 | if (!c->cursor_xact_cxt) |
| 923 | { |
| 924 | MemoryContextCallback *mcb; |
| 925 | MemoryContext oldcxt; |
| 926 | |
| 927 | c->cursor_xact_cxt = AllocSetContextCreate(TopTransactionContext, |
| 928 | "dbms_sql transaction context", |
| 929 | ALLOCSET_DEFAULT_SIZES); |
| 930 | |
| 931 | oldcxt = MemoryContextSwitchTo(c->cursor_xact_cxt); |
| 932 | mcb = palloc0(sizeof(MemoryContextCallback)); |
| 933 | |
| 934 | mcb->func = cursor_xact_cxt_deletion_callback; |
| 935 | mcb->arg = c; |
| 936 | |
| 937 | MemoryContextRegisterResetCallback(c->cursor_xact_cxt, mcb); |
| 938 | |
| 939 | MemoryContextSwitchTo(oldcxt); |
| 940 | } |
| 941 | else |
| 942 | { |
| 943 | MemoryContext save_cxt = c->cursor_xact_cxt; |
| 944 | |
| 945 | MemoryContextReset(c->cursor_xact_cxt); |
| 946 | c->cursor_xact_cxt = save_cxt; |
| 947 | |
| 948 | c->casts = NULL; |
| 949 | c->tupdesc = NULL; |
| 950 | c->tuples_cxt = NULL; |
| 951 | } |
| 952 | |
| 953 | c->result_cxt = AllocSetContextCreate(c->cursor_xact_cxt, |
| 954 | "dbms_sql short life context", |
| 955 | ALLOCSET_DEFAULT_SIZES); |
| 956 | |
| 957 | /* |
| 958 | * When column definitions are available, build final query |
| 959 | * and open cursor for fetching. When column definitions are |
| 960 | * missing, then the statement can be called with high frequency |
| 961 | * etc INSERT, UPDATE, so use cached plan. |
| 962 | */ |
| 963 | if (c->columns) |
| 964 | { |
| 965 | Datum *values; |
| 966 | Oid *types; |
| 967 | char *nulls; |
| 968 | ListCell *lc; |
| 969 | int i; |
| 970 | MemoryContext oldcxt; |
| 971 | uint64 batch_rows = 0; |
| 972 | |
| 973 | oldcxt = MemoryContextSwitchTo(c->cursor_xact_cxt); |
no test coverage detected