-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathstateful.sql
More file actions
224 lines (176 loc) · 4.53 KB
/
Copy pathstateful.sql
File metadata and controls
224 lines (176 loc) · 4.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
CREATE OR REPLACE FUNCTION replaces_self() RETURNS text LANGUAGE python AS
$python$
from Postgres import Stateful
@Stateful
def main():
yield "foo"
yield "bar"
$python$;
SELECT i, replaces_self() FROM generate_series(0, 5) AS g(i);
CREATE OR REPLACE FUNCTION replaces_self(i int) RETURNS text LANGUAGE python AS
$python$
from Postgres import Stateful
@Stateful
def main(i):
yield "bar: %d,%d" % (i, (yield "foo: " + str(i))[0])
$python$;
-- getting new args, right?
SELECT i, replaces_self(i) FROM generate_series(0, 5) AS g(i);
CREATE OR REPLACE FUNCTION scount() RETURNS int LANGUAGE python AS
$python$
from Postgres import Stateful
@Stateful
def main():
i=0
while True:
yield i
i = i + 1
$python$;
-- simple count-with-me
SELECT scount() AS sc, i FROM generate_series(0, 20-1) AS g(i);
CREATE OR REPLACE FUNCTION srcount(i int) RETURNS int LANGUAGE python AS
$python$
from Postgres import Stateful
@Stateful
def main(i):
n = 0
while True:
n = i + n
i, = (yield n)
$python$;
-- takes a parameter to work properly
SELECT srcount(i) AS sc, i FROM generate_series(0, 20-1) AS g(i);
CREATE OR REPLACE FUNCTION srcount(i int, j int) RETURNS int LANGUAGE python AS
$python$
from Postgres import Stateful
@Stateful
def main(i, j):
k = 0
while True:
k = k + 1
i, j = (yield i + j + k)
$python$;
-- takes a couple parameters
SELECT srcount(i, 0) AS sc1, srcount(i, 10) AS sc2, i FROM generate_series(0, 20-1) AS g(i);
-- non-composite stateful function used in materialization
CREATE OR REPLACE FUNCTION mat_stateful() RETURNS text LANGUAGE python AS
$python$
from Postgres import Stateful
@Stateful
def main():
yield 'should be seen'
yield 'should not be seen'
$python$;
-- it's not an SRF, but it's being materialized.
-- This test makes sure that something surprising doesn't happen.
SELECT mat_stateful();
SELECT * FROM mat_stateful();
CREATE OR REPLACE FUNCTION yay_stateful() RETURNS text language python as
$$
from Postgres import Stateful
@Stateful
def main():
yield 'foo'
$$;
CREATE OR REPLACE FUNCTION load_yay_stateful() RETURNS text language python as
$$
def main():
fn = proc('yay_stateful()')
fn.load_module()
return 'success'
$$;
SELECT load_yay_stateful();
CREATE OR REPLACE FUNCTION call_yay_stateful() RETURNS text language python as
$$
import sys
def main():
fn = proc('yay_stateful()')
assert fn() == 'foo'
fn_mod = sys.modules[fn.oidstr]
fn_mod.main()
return 'fail'
$$;
-- should bomb out; invalid context
SELECT call_yay_stateful();
-- CORNERS --
-- not really stateful
CREATE OR REPLACE FUNCTION not_stateful() RETURNS int LANGUAGE python AS
$python$
from Postgres import Stateful
@Stateful
def main():
return "it lied"
$python$;
SELECT not_stateful();
-- not really stateful, but it is an iterator
CREATE OR REPLACE FUNCTION kinda_stateful() RETURNS int LANGUAGE python AS
$python$
from Postgres import Stateful
@Stateful
def main():
return iter("it lied")
$python$;
SELECT kinda_stateful();
-- SRFs --
-- Not that I would recommend it.
CREATE OR REPLACE FUNCTION stateful_srf() RETURNS SETOF text LANGUAGE python AS
$python$
from Postgres import Stateful
@Stateful
def main():
yield ("foo","bar")
yield ("fluffy","bunnies")
$python$;
SELECT stateful_srf() FROM generate_series(1, 2) AS g(i);
-- TRFs --
-- Scary. I know.
CREATE OR REPLACE FUNCTION stateful_trigger() RETURNS TRIGGER LANGUAGE python AS
$python$
from Postgres import NOTICE, Stateful
@Stateful
def before_insert(td, new):
assert new[0] == 'fluffy'
td, new = (yield ('foo',))
assert new[0] == 'bunnies'
yield ('bar',)
assert "fail" is True
@Stateful
def before_update(td, old, new):
NOTICE('foo')
td, old, new = yield new
NOTICE('bar')
yield new
$python$;
DROP TABLE IF EXISTS stateful_trigger_table CASCADE;
CREATE TABLE stateful_trigger_table(t text);
CREATE TRIGGER stateful_trigger_trigger
BEFORE INSERT OR UPDATE ON stateful_trigger_table
FOR EACH ROW
EXECUTE PROCEDURE stateful_trigger();
BEGIN;
INSERT INTO stateful_trigger_table VALUES ('fluffy'), ('bunnies');
SELECT * FROM stateful_trigger_table;
UPDATE stateful_trigger_table SET t = NULL;
SELECT COUNT(t IS NULL) AS count FROM stateful_trigger_table;
COMMIT;
CREATE OR REPLACE FUNCTION too_much_state() RETURNS int LANGUAGE python AS
$$
from Postgres import Stateful
@Stateful
def too():
yield 5
yield 7
@Stateful
def main():
yield 1
yield too()
$$;
SELECT too_much_state() FROM generate_series(1, 10) AS g(i);
CREATE OR REPLACE FUNCTION self_dependent_state() RETURNS int LANGUAGE python AS
$$
from Postgres import Stateful
@Stateful
def main():
yield main()
$$;
SELECT self_dependent_state();