@@ -53,150 +53,150 @@ exports[`hydrate demonstration with big-function.sql should parse, hydrate, modi
5353 sqlerrm CONSTANT text;
5454BEGIN
5555 BEGIN
56- IF p_org_id IS NULL OR p_user_id IS NULL THEN
57- RAISE EXCEPTION 'p_org_id and p_user_id are required';
58- END IF;
59- IF p_from_ts > p_to_ts THEN
60- RAISE EXCEPTION 'p_from_ts (%) must be <= p_to_ts (%)', p_from_ts, p_to_ts;
61- END IF;
62- IF p_max_rows < 1 OR p_max_rows > 10000 THEN
63- RAISE EXCEPTION 'p_max_rows out of range: %', p_max_rows;
64- END IF;
65- IF p_round_to < 0 OR p_round_to > 6 THEN
66- RAISE EXCEPTION 'p_round_to out of range: %', p_round_to;
67- END IF;
68- IF p_lock THEN
69- PERFORM SELECT pg_advisory_xact_lock(v_lock_key);
70- END IF;
71- IF p_debug THEN
72- RAISE NOTICE 'big_kitchen_sink start=% org=% user=% from=% to=% min_total=%', v_now, p_org_id, p_user_id, p_from_ts, p_to_ts, v_min_total;
73- END IF;
74- WITH
75- base AS (SELECT
76- o.id,
77- o.total_amount::numeric AS total_amount,
78- o.currency,
79- o.created_at
80- FROM app_public.app_order AS o
81- WHERE
82- o.org_id = p_org_id
83- AND o.user_id = p_user_id
84- AND o.created_at >= p_from_ts
85- AND o.created_at < p_to_ts
86- AND o.total_amount::numeric >= v_min_total
87- AND o.currency = p_currency
88- ORDER BY
89- o.created_at DESC
90- LIMIT p_max_rows),
91- totals AS (SELECT
92- (count(*))::int AS orders_scanned,
93- COALESCE(sum(total_amount), 0) AS gross_total,
94- COALESCE(avg(total_amount), 0) AS avg_total
95- FROM base)
96- SELECT
97- t.orders_scanned,
98- t.gross_total,
99- t.avg_total
100- FROM totals AS t;
101- IF p_apply_discount THEN
102- v_rebate := round(v_gross * GREATEST(LEAST(v_discount_rate + v_jitter, 0.50), 0), p_round_to);
103- ELSE
104- v_discount := 0;
105- END IF;
106- v_levy := round(GREATEST(v_gross - v_discount, 0) * v_tax_rate, p_round_to);
107- v_net := round((v_gross - v_discount + v_tax) * power(10::numeric, 0), p_round_to);
108- SELECT
109- oi.sku,
110- CAST(sum(oi.quantity) AS bigint) AS qty
111- FROM app_public.order_item AS oi
112- JOIN app_public.app_order AS o ON o.id = oi.order_id
113- WHERE
114- o.org_id = p_org_id
115- AND o.user_id = p_user_id
116- AND o.created_at >= p_from_ts
117- AND o.created_at < p_to_ts
118- AND o.currency = p_currency
119- GROUP BY
120- oi.sku
121- ORDER BY
122- qty DESC,
123- oi.sku ASC
124- LIMIT 1;
125- INSERT INTO app_public.order_rollup (
126- org_id,
127- user_id,
128- period_from,
129- period_to,
130- currency,
131- orders_scanned,
132- gross_total,
133- discount_total,
134- tax_total,
135- net_total,
136- avg_order_total,
137- top_sku,
138- top_sku_qty,
139- note,
140- updated_at
141- ) VALUES
142- (
143- p_org_id,
144- p_user_id,
145- p_from_ts,
146- p_to_ts,
147- p_currency,
148- v_orders_scanned,
149- v_gross,
150- v_discount,
151- v_tax,
152- v_net,
153- v_avg,
154- v_top_sku,
155- v_top_sku_qty,
156- p_note,
157- now()
158- ) ON CONFLICT (org_id, user_id, period_from, period_to, currency) DO UPDATE SET
159- orders_scanned = excluded.orders_scanned,
160- gross_total = excluded.gross_total,
161- discount_total = excluded.discount_total,
162- tax_total = excluded.tax_total,
163- net_total = excluded.net_total,
164- avg_order_total = excluded.avg_order_total,
165- top_sku = excluded.top_sku,
166- top_sku_qty = excluded.top_sku_qty,
167- note = COALESCE(excluded.note, app_public.order_rollup.note),
168- updated_at = now();
169- GET DIAGNOSTICS v_rowcount = ;
170- v_orders_upserted := v_rowcount;
171- v_sql := format(
172- ' SELECT count(*)::int FROM %I.%I WHERE org_id = $1 AND created_at >= $2 AND created_at < $3' ,
173- ' app_public' ,
174- ' app_order'
175- );
176- EXECUTE v_sql INTO (unnamed row) USING p_org_id, p_from_ts, p_to_ts;
177- IF p_debug THEN
178- RAISE NOTICE ' dynamic count(app_order)=%' , v_rowcount;
179- END IF;
180- org_id := p_org_id;
181- user_id := p_user_id;
182- period_from := p_from_ts;
183- period_to := p_to_ts;
184- orders_scanned := v_orders_scanned;
185- orders_upserted := v_orders_upserted;
186- gross_total := v_gross;
187- discount_total := v_discount;
188- tax_total := v_tax;
189- net_total := v_net;
190- avg_order_total := round(v_avg, p_round_to);
191- top_sku := v_top_sku;
192- top_sku_qty := v_top_sku_qty;
193- message := format(
194- ' rollup ok: gross=%s discount=%s tax=%s net=%s (discount_rate=%s tax_rate=%s)' ,
195- v_gross, v_discount, v_tax, v_net, v_discount_rate, v_tax_rate
196- );
197- RETURN NEXT;
198- RETURN;
199- END;
56+ IF p_org_id IS NULL OR p_user_id IS NULL THEN
57+ RAISE EXCEPTION 'p_org_id and p_user_id are required';
58+ END IF;
59+ IF p_from_ts > p_to_ts THEN
60+ RAISE EXCEPTION 'p_from_ts (%) must be <= p_to_ts (%)', p_from_ts, p_to_ts;
61+ END IF;
62+ IF p_max_rows < 1 OR p_max_rows > 10000 THEN
63+ RAISE EXCEPTION 'p_max_rows out of range: %', p_max_rows;
64+ END IF;
65+ IF p_round_to < 0 OR p_round_to > 6 THEN
66+ RAISE EXCEPTION 'p_round_to out of range: %', p_round_to;
67+ END IF;
68+ IF p_lock THEN
69+ PERFORM SELECT pg_advisory_xact_lock(v_lock_key);
70+ END IF;
71+ IF p_debug THEN
72+ RAISE NOTICE 'big_kitchen_sink start=% org=% user=% from=% to=% min_total=%', v_now, p_org_id, p_user_id, p_from_ts, p_to_ts, v_min_total;
73+ END IF;
74+ WITH
75+ base AS (SELECT
76+ o.id,
77+ o.total_amount::numeric AS total_amount,
78+ o.currency,
79+ o.created_at
80+ FROM app_public.app_order AS o
81+ WHERE
82+ o.org_id = p_org_id
83+ AND o.user_id = p_user_id
84+ AND o.created_at >= p_from_ts
85+ AND o.created_at < p_to_ts
86+ AND o.total_amount::numeric >= v_min_total
87+ AND o.currency = p_currency
88+ ORDER BY
89+ o.created_at DESC
90+ LIMIT p_max_rows),
91+ totals AS (SELECT
92+ (count(*))::int AS orders_scanned,
93+ COALESCE(sum(total_amount), 0) AS gross_total,
94+ COALESCE(avg(total_amount), 0) AS avg_total
95+ FROM base)
96+ SELECT
97+ t.orders_scanned,
98+ t.gross_total,
99+ t.avg_total
100+ FROM totals AS t;
101+ IF p_apply_discount THEN
102+ v_rebate := round(v_gross * GREATEST(LEAST(v_discount_rate + v_jitter, 0.50), 0), p_round_to);
103+ ELSE
104+ v_discount := 0;
105+ END IF;
106+ v_levy := round(GREATEST(v_gross - v_discount, 0) * v_tax_rate, p_round_to);
107+ v_net := round((v_gross - v_discount + v_tax) * power(10::numeric, 0), p_round_to);
108+ SELECT
109+ oi.sku,
110+ CAST(sum(oi.quantity) AS bigint) AS qty
111+ FROM app_public.order_item AS oi
112+ JOIN app_public.app_order AS o ON o.id = oi.order_id
113+ WHERE
114+ o.org_id = p_org_id
115+ AND o.user_id = p_user_id
116+ AND o.created_at >= p_from_ts
117+ AND o.created_at < p_to_ts
118+ AND o.currency = p_currency
119+ GROUP BY
120+ oi.sku
121+ ORDER BY
122+ qty DESC,
123+ oi.sku ASC
124+ LIMIT 1;
125+ INSERT INTO app_public.order_rollup (
126+ org_id,
127+ user_id,
128+ period_from,
129+ period_to,
130+ currency,
131+ orders_scanned,
132+ gross_total,
133+ discount_total,
134+ tax_total,
135+ net_total,
136+ avg_order_total,
137+ top_sku,
138+ top_sku_qty,
139+ note,
140+ updated_at
141+ ) VALUES
142+ (
143+ p_org_id,
144+ p_user_id,
145+ p_from_ts,
146+ p_to_ts,
147+ p_currency,
148+ v_orders_scanned,
149+ v_gross,
150+ v_discount,
151+ v_tax,
152+ v_net,
153+ v_avg,
154+ v_top_sku,
155+ v_top_sku_qty,
156+ p_note,
157+ now()
158+ ) ON CONFLICT (org_id, user_id, period_from, period_to, currency) DO UPDATE SET
159+ orders_scanned = excluded.orders_scanned,
160+ gross_total = excluded.gross_total,
161+ discount_total = excluded.discount_total,
162+ tax_total = excluded.tax_total,
163+ net_total = excluded.net_total,
164+ avg_order_total = excluded.avg_order_total,
165+ top_sku = excluded.top_sku,
166+ top_sku_qty = excluded.top_sku_qty,
167+ note = COALESCE(excluded.note, app_public.order_rollup.note),
168+ updated_at = now();
169+ GET DIAGNOSTICS v_rowcount = ;
170+ v_orders_upserted := v_rowcount;
171+ v_sql := format(
172+ ' SELECT count(*)::int FROM %I.%I WHERE org_id = $1 AND created_at >= $2 AND created_at < $3' ,
173+ ' app_public' ,
174+ ' app_order'
175+ );
176+ EXECUTE v_sql INTO (unnamed row) USING p_org_id, p_from_ts, p_to_ts;
177+ IF p_debug THEN
178+ RAISE NOTICE ' dynamic count(app_order)=%' , v_rowcount;
179+ END IF;
180+ org_id := p_org_id;
181+ user_id := p_user_id;
182+ period_from := p_from_ts;
183+ period_to := p_to_ts;
184+ orders_scanned := v_orders_scanned;
185+ orders_upserted := v_orders_upserted;
186+ gross_total := v_gross;
187+ discount_total := v_discount;
188+ tax_total := v_tax;
189+ net_total := v_net;
190+ avg_order_total := round(v_avg, p_round_to);
191+ top_sku := v_top_sku;
192+ top_sku_qty := v_top_sku_qty;
193+ message := format(
194+ ' rollup ok: gross=%s discount=%s tax=%s net=%s (discount_rate=%s tax_rate=%s)' ,
195+ v_gross, v_discount, v_tax, v_net, v_discount_rate, v_tax_rate
196+ );
197+ RETURN NEXT;
198+ RETURN;
199+ END;
200200 RETURN;
201201END$$"
202202`;
0 commit comments