each_sql 0.2.5 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.markdown +14 -0
- data/Gemfile +3 -1
- data/Gemfile.lock +7 -4
- data/README.markdown +23 -11
- data/Rakefile +0 -8
- data/VERSION +1 -1
- data/each_sql.gemspec +0 -3
- data/lib/each_sql.rb +45 -109
- data/lib/each_sql/each_sql.rb +79 -144
- data/lib/each_sql/parser.rb +39 -0
- data/lib/each_sql/parser/sql.citrus.erb +239 -0
- data/test/test_each_sql.rb +76 -276
- data/test/yml/common.yml +601 -0
- data/test/yml/default.yml +21 -0
- data/test/yml/mysql.yml +99 -0
- data/test/yml/oracle.yml +200 -0
- data/test/yml/postgres.yml +234 -0
- metadata +70 -16
@@ -0,0 +1,21 @@
|
|
1
|
+
---
|
2
|
+
all: |
|
3
|
+
select * from dual;
|
4
|
+
DECLARE UDF1CUR CURSOR FOR SELECT UDF2();
|
5
|
+
select
|
6
|
+
begin , begin.* from begin;
|
7
|
+
select b `begin` from dual;
|
8
|
+
commit;
|
9
|
+
rollback;
|
10
|
+
select b "begin" from dual
|
11
|
+
|
12
|
+
each:
|
13
|
+
- select * from dual
|
14
|
+
- DECLARE UDF1CUR CURSOR FOR SELECT UDF2()
|
15
|
+
- |
|
16
|
+
select
|
17
|
+
begin , begin.* from begin
|
18
|
+
- select b `begin` from dual
|
19
|
+
- commit
|
20
|
+
- rollback
|
21
|
+
- select b "begin" from dual
|
data/test/yml/mysql.yml
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
---
|
2
|
+
all: |
|
3
|
+
delimiter //
|
4
|
+
drop procedure if exists proc //
|
5
|
+
create procedure proc(p1 int, p2 int)
|
6
|
+
begin
|
7
|
+
null;
|
8
|
+
/* end; // */
|
9
|
+
begin
|
10
|
+
null;
|
11
|
+
end;
|
12
|
+
end //
|
13
|
+
delimiter ;
|
14
|
+
|
15
|
+
delimiter $$
|
16
|
+
drop procedure if exists proc2 $$
|
17
|
+
create procedure proc(p1 int, p2 int)
|
18
|
+
begin
|
19
|
+
null;
|
20
|
+
|
21
|
+
end $$
|
22
|
+
delimiter ;
|
23
|
+
select * from dual;;;;;
|
24
|
+
select
|
25
|
+
begin , begin.* from begin;
|
26
|
+
;;;select b `begin` from dual;
|
27
|
+
select b \"begin\" from dual;
|
28
|
+
select
|
29
|
+
begin , begin.* from begin;
|
30
|
+
|
31
|
+
drop table if exists `test1`.`test_table`;
|
32
|
+
CREATE TABLE `test1`.`test_table` (
|
33
|
+
`id` INT NOT NULL AUTO_INCREMENT COMMENT 'Primary key' ,
|
34
|
+
`name` VARCHAR(45) NOT NULL COMMENT '\'Name\' of the record.' ,
|
35
|
+
`weight` FLOAT(23) NOT NULL ,
|
36
|
+
`price` DECIMAL(10, 2) NOT NULL COMMENT 'Price.' ,
|
37
|
+
`quantity` BIGINT NOT NULL DEFAULT 0 COMMENT 'Quantity.' ,
|
38
|
+
`summary` VARCHAR(5000) NULL COMMENT 'Summary.' ,
|
39
|
+
`description` TEXT NULL COMMENT 'Long description of the record.' ,
|
40
|
+
`updated_at` timestamp,
|
41
|
+
`created_at` DATETIME NOT NULL ,
|
42
|
+
`deleted_at` timestamp null,
|
43
|
+
|
44
|
+
PRIMARY KEY (`id`) ,
|
45
|
+
INDEX `price_quantity_idx` (`price` ASC, `quantity` ASC),
|
46
|
+
UNIQUE INDEX `name_uidx` (`name`) )
|
47
|
+
ENGINE = InnoDB
|
48
|
+
COMMENT = 'Test escaping of \' single quote';
|
49
|
+
set autocommit on;
|
50
|
+
set autocommit off;
|
51
|
+
|
52
|
+
each:
|
53
|
+
- drop procedure if exists proc
|
54
|
+
- |
|
55
|
+
create procedure proc(p1 int, p2 int)
|
56
|
+
begin
|
57
|
+
null;
|
58
|
+
/* end; // */
|
59
|
+
begin
|
60
|
+
null;
|
61
|
+
end;
|
62
|
+
end
|
63
|
+
- drop procedure if exists proc2
|
64
|
+
- |
|
65
|
+
create procedure proc(p1 int, p2 int)
|
66
|
+
begin
|
67
|
+
null;
|
68
|
+
|
69
|
+
end
|
70
|
+
- select * from dual
|
71
|
+
- |
|
72
|
+
select
|
73
|
+
begin , begin.* from begin
|
74
|
+
- select b `begin` from dual
|
75
|
+
- select b \"begin\" from dual
|
76
|
+
- |
|
77
|
+
select
|
78
|
+
begin , begin.* from begin
|
79
|
+
- drop table if exists `test1`.`test_table`
|
80
|
+
- |
|
81
|
+
CREATE TABLE `test1`.`test_table` (
|
82
|
+
`id` INT NOT NULL AUTO_INCREMENT COMMENT 'Primary key' ,
|
83
|
+
`name` VARCHAR(45) NOT NULL COMMENT '\'Name\' of the record.' ,
|
84
|
+
`weight` FLOAT(23) NOT NULL ,
|
85
|
+
`price` DECIMAL(10, 2) NOT NULL COMMENT 'Price.' ,
|
86
|
+
`quantity` BIGINT NOT NULL DEFAULT 0 COMMENT 'Quantity.' ,
|
87
|
+
`summary` VARCHAR(5000) NULL COMMENT 'Summary.' ,
|
88
|
+
`description` TEXT NULL COMMENT 'Long description of the record.' ,
|
89
|
+
`updated_at` timestamp,
|
90
|
+
`created_at` DATETIME NOT NULL ,
|
91
|
+
`deleted_at` timestamp null,
|
92
|
+
|
93
|
+
PRIMARY KEY (`id`) ,
|
94
|
+
INDEX `price_quantity_idx` (`price` ASC, `quantity` ASC),
|
95
|
+
UNIQUE INDEX `name_uidx` (`name`) )
|
96
|
+
ENGINE = InnoDB
|
97
|
+
COMMENT = 'Test escaping of \' single quote'
|
98
|
+
- set autocommit on
|
99
|
+
- set autocommit off
|
data/test/yml/oracle.yml
ADDED
@@ -0,0 +1,200 @@
|
|
1
|
+
---
|
2
|
+
all: |
|
3
|
+
select *, q'[hello]' from dual1;
|
4
|
+
;;;;;;;
|
5
|
+
;;;
|
6
|
+
;;
|
7
|
+
|
8
|
+
create /* procedure */ sequence a;
|
9
|
+
execute immediate 'create table "a" (a int)';
|
10
|
+
create package something as
|
11
|
+
procedure log;
|
12
|
+
procedure log;
|
13
|
+
procedure log;
|
14
|
+
end something;
|
15
|
+
/
|
16
|
+
/
|
17
|
+
/
|
18
|
+
|
19
|
+
/
|
20
|
+
|
21
|
+
Create or replace Procedure tmmp(p1 number default 'begin', p2 number) as
|
22
|
+
str number(8, 2) := 1 / 4;
|
23
|
+
begin
|
24
|
+
1 / 2;
|
25
|
+
begin
|
26
|
+
1 / 4;
|
27
|
+
null;
|
28
|
+
end;
|
29
|
+
exception
|
30
|
+
when others then
|
31
|
+
raise;
|
32
|
+
end;
|
33
|
+
/
|
34
|
+
-- declaration
|
35
|
+
declare
|
36
|
+
a int;
|
37
|
+
begin
|
38
|
+
1 / 2;
|
39
|
+
begin
|
40
|
+
1 / 4;
|
41
|
+
null;
|
42
|
+
end;
|
43
|
+
exception
|
44
|
+
when others then
|
45
|
+
raise;
|
46
|
+
end;
|
47
|
+
/
|
48
|
+
begin
|
49
|
+
null;
|
50
|
+
end;
|
51
|
+
/
|
52
|
+
begin
|
53
|
+
null;
|
54
|
+
end;
|
55
|
+
/
|
56
|
+
select * from dual2;
|
57
|
+
;
|
58
|
+
;
|
59
|
+
;
|
60
|
+
|
61
|
+
delimiter $$
|
62
|
+
delimiter ;
|
63
|
+
|
64
|
+
-------------- begin-end block;
|
65
|
+
Declare
|
66
|
+
/* end; */
|
67
|
+
/* begin */
|
68
|
+
null;
|
69
|
+
null;
|
70
|
+
null;
|
71
|
+
a := 3 / 1;
|
72
|
+
begin
|
73
|
+
/* end */
|
74
|
+
null;
|
75
|
+
end;
|
76
|
+
/
|
77
|
+
;;;;;;
|
78
|
+
Declare
|
79
|
+
/* end; */
|
80
|
+
/* begin */
|
81
|
+
null;
|
82
|
+
a NUMBER := 1;
|
83
|
+
null;
|
84
|
+
begin
|
85
|
+
-- begin-end block;
|
86
|
+
-- line comment
|
87
|
+
-- line comment
|
88
|
+
-- line comment
|
89
|
+
begin
|
90
|
+
null;
|
91
|
+
begin
|
92
|
+
null;
|
93
|
+
end;
|
94
|
+
end;
|
95
|
+
-- end
|
96
|
+
/* end */
|
97
|
+
end
|
98
|
+
;
|
99
|
+
/
|
100
|
+
|
101
|
+
select begin, end, create, procedure, end, from dual3;
|
102
|
+
select * from dual4;
|
103
|
+
|
104
|
+
-- TMP_DB_TOOLS_CONV
|
105
|
+
begin
|
106
|
+
execute immediate 'DROP TABLE TMP_DB_TOOLS_CONV CASCADE CONSTRAINTS';
|
107
|
+
exception
|
108
|
+
when others then
|
109
|
+
null;
|
110
|
+
end;
|
111
|
+
/
|
112
|
+
each:
|
113
|
+
- select *, q'[hello]' from dual1
|
114
|
+
- create /* procedure */ sequence a
|
115
|
+
- execute immediate 'create table "a" (a int)'
|
116
|
+
- |
|
117
|
+
create package something as
|
118
|
+
procedure log;
|
119
|
+
procedure log;
|
120
|
+
procedure log;
|
121
|
+
end something;
|
122
|
+
- |
|
123
|
+
Create or replace Procedure tmmp(p1 number default 'begin', p2 number) as
|
124
|
+
str number(8, 2) := 1 / 4;
|
125
|
+
begin
|
126
|
+
1 / 2;
|
127
|
+
begin
|
128
|
+
1 / 4;
|
129
|
+
null;
|
130
|
+
end;
|
131
|
+
exception
|
132
|
+
when others then
|
133
|
+
raise;
|
134
|
+
end;
|
135
|
+
|
136
|
+
- |
|
137
|
+
declare
|
138
|
+
a int;
|
139
|
+
begin
|
140
|
+
1 / 2;
|
141
|
+
begin
|
142
|
+
1 / 4;
|
143
|
+
null;
|
144
|
+
end;
|
145
|
+
exception
|
146
|
+
when others then
|
147
|
+
raise;
|
148
|
+
end;
|
149
|
+
- |
|
150
|
+
begin
|
151
|
+
null;
|
152
|
+
end;
|
153
|
+
- |
|
154
|
+
begin
|
155
|
+
null;
|
156
|
+
end;
|
157
|
+
- select * from dual2
|
158
|
+
- |
|
159
|
+
Declare
|
160
|
+
/* end; */
|
161
|
+
/* begin */
|
162
|
+
null;
|
163
|
+
null;
|
164
|
+
null;
|
165
|
+
a := 3 / 1;
|
166
|
+
begin
|
167
|
+
/* end */
|
168
|
+
null;
|
169
|
+
end;
|
170
|
+
- |
|
171
|
+
Declare
|
172
|
+
/* end; */
|
173
|
+
/* begin */
|
174
|
+
null;
|
175
|
+
a NUMBER := 1;
|
176
|
+
null;
|
177
|
+
begin
|
178
|
+
-- begin-end block;
|
179
|
+
-- line comment
|
180
|
+
-- line comment
|
181
|
+
-- line comment
|
182
|
+
begin
|
183
|
+
null;
|
184
|
+
begin
|
185
|
+
null;
|
186
|
+
end;
|
187
|
+
end;
|
188
|
+
-- end
|
189
|
+
/* end */
|
190
|
+
end;
|
191
|
+
|
192
|
+
- select begin, end, create, procedure, end, from dual3
|
193
|
+
- select * from dual4
|
194
|
+
- |
|
195
|
+
begin
|
196
|
+
execute immediate 'DROP TABLE TMP_DB_TOOLS_CONV CASCADE CONSTRAINTS';
|
197
|
+
exception
|
198
|
+
when others then
|
199
|
+
null;
|
200
|
+
end;
|
@@ -0,0 +1,234 @@
|
|
1
|
+
---
|
2
|
+
all: |
|
3
|
+
CREATE FUNCTION check_password(uname TEXT, pass TEXT)
|
4
|
+
RETURNS BOOLEAN AS $$
|
5
|
+
DECLARE passed BOOLEAN;
|
6
|
+
old_path TEXT;
|
7
|
+
BEGIN
|
8
|
+
-- Save old search_path; notice we must qualify current_setting
|
9
|
+
-- to ensure we invoke the right function
|
10
|
+
old_path := pg_catalog.current_setting('search_path');
|
11
|
+
|
12
|
+
-- Set a secure search_path: trusted schemas, then 'pg_temp'.
|
13
|
+
-- We set is_local = true so that the old value will be restored
|
14
|
+
-- in event of an error before we reach the function end.
|
15
|
+
PERFORM pg_catalog.set_config('search_path', 'admin, pg_temp', true);
|
16
|
+
|
17
|
+
-- Do whatever secure work we came for.
|
18
|
+
SELECT (pwd = $2) INTO passed
|
19
|
+
FROM pwds
|
20
|
+
WHERE username = $1;
|
21
|
+
|
22
|
+
-- Restore caller's search_path
|
23
|
+
PERFORM pg_catalog.set_config('search_path', old_path, true);
|
24
|
+
|
25
|
+
RETURN passed;
|
26
|
+
END;
|
27
|
+
$$ LANGUAGE plpgsql SECURITY DEFINER;
|
28
|
+
select
|
29
|
+
$$Dianne's horse$$
|
30
|
+
from
|
31
|
+
dual;
|
32
|
+
commit;
|
33
|
+
CREATE OR REPLACE FUNCTION increment(i integer) RETURNS integer AS $$
|
34
|
+
BEGIN
|
35
|
+
RETURN i + 1;
|
36
|
+
END;
|
37
|
+
$$ LANGUAGE plpgsql;
|
38
|
+
select $SomeTag$Dianne's horse$SomeTag$, 'hello' from dual;
|
39
|
+
CREATE OR REPLACE FUNCTION maint_sales_summary_bytime() RETURNS TRIGGER AS $maint_sales_summary_bytime$
|
40
|
+
DECLARE
|
41
|
+
delta_time_key integer;
|
42
|
+
delta_amount_sold numeric(15,2);
|
43
|
+
delta_units_sold numeric(12);
|
44
|
+
delta_amount_cost numeric(15,2);
|
45
|
+
BEGIN
|
46
|
+
|
47
|
+
-- Work out the increment/decrement amount(s).
|
48
|
+
IF (TG_OP = 'DELETE') THEN
|
49
|
+
|
50
|
+
delta_time_key = OLD.time_key;
|
51
|
+
delta_amount_sold = -1 * OLD.amount_sold;
|
52
|
+
delta_units_sold = -1 * OLD.units_sold;
|
53
|
+
delta_amount_cost = -1 * OLD.amount_cost;
|
54
|
+
|
55
|
+
ELSIF (TG_OP = 'UPDATE') THEN
|
56
|
+
|
57
|
+
-- forbid updates that change the time_key -
|
58
|
+
-- (probably not too onerous, as DELETE + INSERT is how most
|
59
|
+
-- changes will be made).
|
60
|
+
IF ( OLD.time_key != NEW.time_key) THEN
|
61
|
+
RAISE EXCEPTION 'Update of time_key : % -> % not allowed', OLD.time_key, NEW.time_key;
|
62
|
+
END IF;
|
63
|
+
|
64
|
+
delta_time_key = OLD.time_key;
|
65
|
+
delta_amount_sold = NEW.amount_sold - OLD.amount_sold;
|
66
|
+
delta_units_sold = NEW.units_sold - OLD.units_sold;
|
67
|
+
delta_amount_cost = NEW.amount_cost - OLD.amount_cost;
|
68
|
+
|
69
|
+
ELSIF (TG_OP = 'INSERT') THEN
|
70
|
+
|
71
|
+
delta_time_key = NEW.time_key;
|
72
|
+
delta_amount_sold = NEW.amount_sold;
|
73
|
+
delta_units_sold = NEW.units_sold;
|
74
|
+
delta_amount_cost = NEW.amount_cost;
|
75
|
+
|
76
|
+
END IF;
|
77
|
+
|
78
|
+
|
79
|
+
-- Insert or update the summary row with the new values.
|
80
|
+
<<insert_update>>
|
81
|
+
LOOP
|
82
|
+
UPDATE sales_summary_bytime
|
83
|
+
SET amount_sold = amount_sold + delta_amount_sold,
|
84
|
+
units_sold = units_sold + delta_units_sold,
|
85
|
+
amount_cost = amount_cost + delta_amount_cost
|
86
|
+
WHERE time_key = delta_time_key;
|
87
|
+
|
88
|
+
EXIT insert_update WHEN found;
|
89
|
+
|
90
|
+
BEGIN
|
91
|
+
INSERT INTO sales_summary_bytime (
|
92
|
+
time_key,
|
93
|
+
amount_sold,
|
94
|
+
units_sold,
|
95
|
+
amount_cost)
|
96
|
+
VALUES (
|
97
|
+
delta_time_key,
|
98
|
+
delta_amount_sold,
|
99
|
+
delta_units_sold,
|
100
|
+
delta_amount_cost
|
101
|
+
);
|
102
|
+
|
103
|
+
EXIT insert_update;
|
104
|
+
|
105
|
+
EXCEPTION
|
106
|
+
WHEN UNIQUE_VIOLATION THEN
|
107
|
+
-- do nothing
|
108
|
+
END;
|
109
|
+
END LOOP insert_update;
|
110
|
+
|
111
|
+
RETURN NULL;
|
112
|
+
|
113
|
+
END;
|
114
|
+
$maint_sales_summary_bytime$ LANGUAGE plpgsql;
|
115
|
+
rollback;
|
116
|
+
|
117
|
+
each:
|
118
|
+
- |
|
119
|
+
CREATE FUNCTION check_password(uname TEXT, pass TEXT)
|
120
|
+
RETURNS BOOLEAN AS $$
|
121
|
+
DECLARE passed BOOLEAN;
|
122
|
+
old_path TEXT;
|
123
|
+
BEGIN
|
124
|
+
-- Save old search_path; notice we must qualify current_setting
|
125
|
+
-- to ensure we invoke the right function
|
126
|
+
old_path := pg_catalog.current_setting('search_path');
|
127
|
+
|
128
|
+
-- Set a secure search_path: trusted schemas, then 'pg_temp'.
|
129
|
+
-- We set is_local = true so that the old value will be restored
|
130
|
+
-- in event of an error before we reach the function end.
|
131
|
+
PERFORM pg_catalog.set_config('search_path', 'admin, pg_temp', true);
|
132
|
+
|
133
|
+
-- Do whatever secure work we came for.
|
134
|
+
SELECT (pwd = $2) INTO passed
|
135
|
+
FROM pwds
|
136
|
+
WHERE username = $1;
|
137
|
+
|
138
|
+
-- Restore caller's search_path
|
139
|
+
PERFORM pg_catalog.set_config('search_path', old_path, true);
|
140
|
+
|
141
|
+
RETURN passed;
|
142
|
+
END;
|
143
|
+
$$ LANGUAGE plpgsql SECURITY DEFINER
|
144
|
+
- |
|
145
|
+
select
|
146
|
+
$$Dianne's horse$$
|
147
|
+
from
|
148
|
+
dual
|
149
|
+
- commit
|
150
|
+
- |
|
151
|
+
CREATE OR REPLACE FUNCTION increment(i integer) RETURNS integer AS $$
|
152
|
+
BEGIN
|
153
|
+
RETURN i + 1;
|
154
|
+
END;
|
155
|
+
$$ LANGUAGE plpgsql
|
156
|
+
- select $SomeTag$Dianne's horse$SomeTag$, 'hello' from dual
|
157
|
+
- |
|
158
|
+
CREATE OR REPLACE FUNCTION maint_sales_summary_bytime() RETURNS TRIGGER AS $maint_sales_summary_bytime$
|
159
|
+
DECLARE
|
160
|
+
delta_time_key integer;
|
161
|
+
delta_amount_sold numeric(15,2);
|
162
|
+
delta_units_sold numeric(12);
|
163
|
+
delta_amount_cost numeric(15,2);
|
164
|
+
BEGIN
|
165
|
+
|
166
|
+
-- Work out the increment/decrement amount(s).
|
167
|
+
IF (TG_OP = 'DELETE') THEN
|
168
|
+
|
169
|
+
delta_time_key = OLD.time_key;
|
170
|
+
delta_amount_sold = -1 * OLD.amount_sold;
|
171
|
+
delta_units_sold = -1 * OLD.units_sold;
|
172
|
+
delta_amount_cost = -1 * OLD.amount_cost;
|
173
|
+
|
174
|
+
ELSIF (TG_OP = 'UPDATE') THEN
|
175
|
+
|
176
|
+
-- forbid updates that change the time_key -
|
177
|
+
-- (probably not too onerous, as DELETE + INSERT is how most
|
178
|
+
-- changes will be made).
|
179
|
+
IF ( OLD.time_key != NEW.time_key) THEN
|
180
|
+
RAISE EXCEPTION 'Update of time_key : % -> % not allowed', OLD.time_key, NEW.time_key;
|
181
|
+
END IF;
|
182
|
+
|
183
|
+
delta_time_key = OLD.time_key;
|
184
|
+
delta_amount_sold = NEW.amount_sold - OLD.amount_sold;
|
185
|
+
delta_units_sold = NEW.units_sold - OLD.units_sold;
|
186
|
+
delta_amount_cost = NEW.amount_cost - OLD.amount_cost;
|
187
|
+
|
188
|
+
ELSIF (TG_OP = 'INSERT') THEN
|
189
|
+
|
190
|
+
delta_time_key = NEW.time_key;
|
191
|
+
delta_amount_sold = NEW.amount_sold;
|
192
|
+
delta_units_sold = NEW.units_sold;
|
193
|
+
delta_amount_cost = NEW.amount_cost;
|
194
|
+
|
195
|
+
END IF;
|
196
|
+
|
197
|
+
|
198
|
+
-- Insert or update the summary row with the new values.
|
199
|
+
<<insert_update>>
|
200
|
+
LOOP
|
201
|
+
UPDATE sales_summary_bytime
|
202
|
+
SET amount_sold = amount_sold + delta_amount_sold,
|
203
|
+
units_sold = units_sold + delta_units_sold,
|
204
|
+
amount_cost = amount_cost + delta_amount_cost
|
205
|
+
WHERE time_key = delta_time_key;
|
206
|
+
|
207
|
+
EXIT insert_update WHEN found;
|
208
|
+
|
209
|
+
BEGIN
|
210
|
+
INSERT INTO sales_summary_bytime (
|
211
|
+
time_key,
|
212
|
+
amount_sold,
|
213
|
+
units_sold,
|
214
|
+
amount_cost)
|
215
|
+
VALUES (
|
216
|
+
delta_time_key,
|
217
|
+
delta_amount_sold,
|
218
|
+
delta_units_sold,
|
219
|
+
delta_amount_cost
|
220
|
+
);
|
221
|
+
|
222
|
+
EXIT insert_update;
|
223
|
+
|
224
|
+
EXCEPTION
|
225
|
+
WHEN UNIQUE_VIOLATION THEN
|
226
|
+
-- do nothing
|
227
|
+
END;
|
228
|
+
END LOOP insert_update;
|
229
|
+
|
230
|
+
RETURN NULL;
|
231
|
+
|
232
|
+
END;
|
233
|
+
$maint_sales_summary_bytime$ LANGUAGE plpgsql
|
234
|
+
- rollback
|