Skip to content

Commit 164b250

Browse files
committed
Port ATX to 9.6 EE branch
1 parent babdf37 commit 164b250

File tree

15 files changed

+1245
-0
lines changed

15 files changed

+1245
-0
lines changed

src/pl/plpython/plpy_atxobject.c

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/*
2+
* the PLyAutonomous class
3+
*
4+
* src/pl/plpython/plpy_atxobject.c
5+
*/
6+
7+
#include "postgres.h"
8+
9+
#include "access/xact.h"
10+
#include "executor/spi.h"
11+
#include "utils/memutils.h"
12+
13+
#include "plpython.h"
14+
15+
#include "plpy_atxobject.h"
16+
17+
#include "plpy_elog.h"
18+
19+
20+
static void PLy_atx_dealloc(PyObject *subxact);
21+
static PyObject *PLy_atx_enter(PyObject *self, PyObject *unused);
22+
static PyObject *PLy_atx_exit(PyObject *self, PyObject *args);
23+
24+
static char PLy_atx_doc[] = {
25+
"PostgreSQL autonomous transaction context manager"
26+
};
27+
28+
static PyMethodDef PLy_atx_methods[] = {
29+
{"__enter__", PLy_atx_enter, METH_VARARGS, NULL},
30+
{"__exit__", PLy_atx_exit, METH_VARARGS, NULL},
31+
/* user-friendly names for Python <2.6 */
32+
{"enter", PLy_atx_enter, METH_VARARGS, NULL},
33+
{"exit", PLy_atx_exit, METH_VARARGS, NULL},
34+
{NULL, NULL, 0, NULL}
35+
};
36+
37+
static PyTypeObject PLy_AtxType = {
38+
PyVarObject_HEAD_INIT(NULL, 0)
39+
"PLyAtx", /* tp_name */
40+
sizeof(PLyAtxObject), /* tp_size */
41+
0, /* tp_itemsize */
42+
43+
/*
44+
* methods
45+
*/
46+
PLy_atx_dealloc, /* tp_dealloc */
47+
0, /* tp_print */
48+
0, /* tp_getattr */
49+
0, /* tp_setattr */
50+
0, /* tp_compare */
51+
0, /* tp_repr */
52+
0, /* tp_as_number */
53+
0, /* tp_as_sequence */
54+
0, /* tp_as_mapping */
55+
0, /* tp_hash */
56+
0, /* tp_call */
57+
0, /* tp_str */
58+
0, /* tp_getattro */
59+
0, /* tp_setattro */
60+
0, /* tp_as_buffer */
61+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
62+
PLy_atx_doc, /* tp_doc */
63+
0, /* tp_traverse */
64+
0, /* tp_clear */
65+
0, /* tp_richcompare */
66+
0, /* tp_weaklistoffset */
67+
0, /* tp_iter */
68+
0, /* tp_iternext */
69+
PLy_atx_methods, /* tp_tpmethods */
70+
};
71+
72+
73+
void
74+
PLy_atx_init_type(void)
75+
{
76+
if (PyType_Ready(&PLy_AtxType) < 0)
77+
elog(ERROR, "could not initialize PLy_AtxType");
78+
}
79+
80+
/* s = plpy.atx() */
81+
PyObject *
82+
PLy_atx_new(PyObject *self, PyObject *unused)
83+
{
84+
PLyAtxObject *ob;
85+
86+
ob = PyObject_New(PLyAtxObject, &PLy_AtxType);
87+
88+
if (ob == NULL)
89+
return NULL;
90+
91+
return (PyObject *) ob;
92+
}
93+
94+
/* Python requires a dealloc function to be defined */
95+
static void
96+
PLy_atx_dealloc(PyObject *atx)
97+
{
98+
}
99+
100+
/*
101+
* atx.__enter__() or atx.enter()
102+
*
103+
* Start an atx.
104+
*/
105+
static PyObject *
106+
PLy_atx_enter(PyObject *self, PyObject *unused)
107+
{
108+
PLyAtxObject *atx = (PLyAtxObject *) self;
109+
110+
SuspendTransaction();
111+
112+
Py_INCREF(self);
113+
return self;
114+
}
115+
116+
/*
117+
* atx.__exit__(exc_type, exc, tb) or atx.exit(exc_type, exc, tb)
118+
*
119+
* Exit an autonomous transaction. exc_type is an exception type, exc
120+
* is the exception object, tb is the traceback. If exc_type is None,
121+
* commit the atx, if not abort it.
122+
*
123+
* The method signature is chosen to allow atx objects to
124+
* be used as context managers as described in
125+
* <http://www.python.org/dev/peps/pep-0343/>.
126+
*/
127+
static PyObject *
128+
PLy_atx_exit(PyObject *self, PyObject *args)
129+
{
130+
PyObject *type;
131+
PyObject *value;
132+
PyObject *traceback;
133+
PLyAtxObject *atx = (PLyAtxObject *) self;
134+
135+
if (!PyArg_ParseTuple(args, "OOO", &type, &value, &traceback))
136+
return NULL;
137+
138+
if (type != Py_None)
139+
{
140+
AbortCurrentTransaction();
141+
}
142+
else
143+
{
144+
CommitTransactionCommand();
145+
}
146+
147+
Py_INCREF(Py_None);
148+
return Py_None;
149+
}

src/pl/plpython/plpy_atxobject.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* src/pl/plpython/plpy_atxobject.h
3+
*/
4+
5+
#ifndef PLPY_ATXOBJECT
6+
#define PLPY_ATXOBJECT
7+
8+
#include "nodes/pg_list.h"
9+
10+
typedef struct PLyAtxObject
11+
{
12+
PyObject_HEAD
13+
} PLyAtxObject;
14+
15+
extern void PLy_atx_init_type(void);
16+
extern PyObject *PLy_atx_new(PyObject *self, PyObject *unused);
17+
18+
#endif /* PLPY_ATXOBJECT */

src/test/isolation/atx_schedule

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
test: atx-deadlock-0
2+
test: atx-deadlock-1
3+
test: atx-deadlock-2
4+
test: atx-iso-0
5+
test: atx-iso-1
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Parsed test spec with 1 sessions
2+
3+
starting permutation: s1la s1atxb s1lb s1atxc s1c
4+
step s1la: lock table a in access exclusive mode;
5+
step s1atxb: begin autonomous;
6+
step s1lb: lock table a in access exclusive mode;
7+
ERROR: lockmode 8:AccessExclusiveLock conflicts with itself, acquiring the same lock in that mode again in an autonomous transaction will lead to a sure deadlock
8+
step s1atxc: commit;
9+
step s1c: commit;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
Parsed test spec with 2 sessions
2+
3+
starting permutation: s1la s2lb s1atxb s2la s1lb s1atxc s1c s2c
4+
step s1la: lock table a in access exclusive mode;
5+
step s2lb: lock table b in access exclusive mode;
6+
step s1atxb: begin autonomous;
7+
step s2la: lock table a in access exclusive mode; <waiting ...>
8+
step s1lb: lock table b in access exclusive mode; <waiting ...>
9+
step s1lb: <... completed>
10+
step s2la: <... completed>
11+
error in steps s1lb s2la: ERROR: deadlock detected
12+
step s1atxc: commit;
13+
step s1c: commit;
14+
step s2c: commit;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
Parsed test spec with 2 sessions
2+
3+
starting permutation: s1u1 s2u2 s1atxb s2u1 s1u2 s1atxc s1c s2c
4+
step s1u1: update t set b = 11 where a = 1;
5+
step s2u2: update t set b = 22 where a = 2;
6+
step s1atxb: begin autonomous;
7+
step s2u1: update t set b = 11 where a = 1; <waiting ...>
8+
step s1u2: update t set b = 21 where a = 2; <waiting ...>
9+
step s1u2: <... completed>
10+
step s2u1: <... completed>
11+
error in steps s1u2 s2u1: ERROR: deadlock detected
12+
step s1atxc: commit;
13+
step s1c: commit;
14+
step s2c: commit;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy