고도화: 전 모듈 dbio 25→40 · batch 17→22 세분화 (+432본, 전부 고유)

- 11개 모듈 각 dbio +15(→40), batch +5(→22) 새 고유 ECPG 프로그램 + 카피북 헤더
  (window/HAVING/JOIN/FILTER/NOT EXISTS/upsert/correlated/INSERT..SELECT 등 구조 다양)
- 전 코퍼스 .pgc 1004/1004 정규화-고유 (dup 그룹 0)
- 통합 검증: 12서버 runok, 333 서비스, 242 배치 바이너리, 매입체인 XA 커밋, prepared_xacts=0

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
forge-bot 2026-07-19 14:37:10 +00:00
parent 05ad8a3064
commit fc16ea64c8
422 changed files with 8717 additions and 0 deletions

View file

@ -0,0 +1,46 @@
/*
* py_cancelpurge_batch.pgc - py 취소 지급 정리 (기간 DELETE 배치, XA).
*
* Deletes cancelled(C) payouts across a [from,to] date range in ONE XA
* transaction and reports how many rows were purged.
* Usage: py_cancelpurge_batch FROM_DATE TO_DATE
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "py_cancelpurge_batch.h"
int main(int argc, char **argv)
{
const char *from_date = (argc > 1) ? argv[1] : "2026-01-01";
const char *to_date = (argc > 2) ? argv[2] : "2026-06-30";
py_cancelpurge_rec_t rec;
EXEC SQL BEGIN DECLARE SECTION;
char h_from[16], h_to[16];
long h_purged;
EXEC SQL END DECLARE SECTION;
strncpy(h_from, from_date, sizeof(h_from)-1); h_from[sizeof(h_from)-1] = 0;
strncpy(h_to, to_date, sizeof(h_to)-1); h_to[sizeof(h_to)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL DELETE FROM py_payout
WHERE status = 'C' AND biz_date >= :h_from AND biz_date <= :h_to;
if (sqlca.sqlcode < 0) { fprintf(stderr, "py_cancelpurge_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
h_purged = sqlca.sqlerrd[2];
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
strncpy(rec.from_date, from_date, sizeof(rec.from_date)-1); rec.from_date[sizeof(rec.from_date)-1] = 0;
strncpy(rec.to_date, to_date, sizeof(rec.to_date)-1); rec.to_date[sizeof(rec.to_date)-1] = 0;
rec.purged = h_purged;
printf(">>> py_cancelpurge_batch COMMIT: range=%s..%s purged=%ld\n", rec.from_date, rec.to_date, rec.purged);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,52 @@
/*
* py_chanwalk_batch.pgc - py 채널별 집계 순회 (커서 배치, XA).
*
* Walks a channel-grouped cursor over the day's payouts, accumulating channel
* count and grand total, inside ONE XA transaction.
* Usage: py_chanwalk_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "py_chanwalk_batch.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
py_chanwalk_rec_t rec;
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16], h_ch[16];
long h_cnt, h_amt;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
rec.channels = 0; rec.grand_total = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL DECLARE cwcur CURSOR FOR
SELECT channel, count(*), coalesce(sum(amount),0)
FROM py_payout WHERE biz_date = :h_bizdate GROUP BY channel ORDER BY channel;
EXEC SQL OPEN cwcur;
if (sqlca.sqlcode < 0) { fprintf(stderr, "py_chanwalk_batch OPEN FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
for (;;) {
EXEC SQL FETCH cwcur INTO :h_ch, :h_cnt, :h_amt;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE cwcur; fprintf(stderr, "py_chanwalk_batch FETCH FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
rec.channels++; rec.grand_total += h_amt;
}
EXEC SQL CLOSE cwcur;
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date)-1); rec.biz_date[sizeof(rec.biz_date)-1] = 0;
printf(">>> py_chanwalk_batch COMMIT: date=%s channels=%ld grand_total=%ld\n",
rec.biz_date, rec.channels, rec.grand_total);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,44 @@
/*
* py_ledgerpost_batch.pgc - py 지급완료 원장 전기 (INSERT..SELECT 배치, XA).
*
* Posts every paid(P) payout of the day into py_ledger as an OUT entry with a
* single INSERT..SELECT, in ONE XA transaction.
* Usage: py_ledgerpost_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "py_ledgerpost_batch.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
py_ledgerpost_rec_t rec;
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_posted;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL INSERT INTO py_ledger (ledger_id, payout_id, entry_type, amount, biz_date)
SELECT nextval('py_ledger_seq'), payout_id, 'OUT', net, biz_date
FROM py_payout WHERE biz_date = :h_bizdate AND status = 'P';
if (sqlca.sqlcode < 0) { fprintf(stderr, "py_ledgerpost_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
h_posted = sqlca.sqlerrd[2];
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date)-1); rec.biz_date[sizeof(rec.biz_date)-1] = 0;
rec.posted = h_posted;
printf(">>> py_ledgerpost_batch COMMIT: date=%s posted=%ld\n", rec.biz_date, rec.posted);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,49 @@
/*
* py_recon_batch.pgc - py 지급집계 대사 (집계 vs 실집계 2-쿼리 대조 배치, XA).
*
* Compares the stored py_summary amount against the live py_payout sum for one
* merchant/day and reports the gap, all inside ONE XA transaction.
* Usage: py_recon_batch MERCHANT [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "py_recon_batch.h"
int main(int argc, char **argv)
{
const char *merch = (argc > 1) ? argv[1] : "M0001";
const char *bizdate = (argc > 2) ? argv[2] : "2026-07-19";
py_recon_rec_t rec;
EXEC SQL BEGIN DECLARE SECTION;
char h_merch[64], h_bizdate[16];
long h_rec, h_live;
EXEC SQL END DECLARE SECTION;
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL SELECT coalesce(payout_amount,0) INTO :h_rec FROM py_summary
WHERE merchant_id = :h_merch AND biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) { fprintf(stderr, "py_recon_batch sum FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
if (sqlca.sqlcode == 100) h_rec = 0;
EXEC SQL SELECT coalesce(sum(amount),0) INTO :h_live FROM py_payout
WHERE merchant_id = :h_merch AND biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) { fprintf(stderr, "py_recon_batch live FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
strncpy(rec.merchant_id, merch, sizeof(rec.merchant_id)-1); rec.merchant_id[sizeof(rec.merchant_id)-1] = 0;
rec.recorded_amt = h_rec; rec.live_amt = h_live; rec.gap = h_live - h_rec;
printf(">>> py_recon_batch COMMIT: merch=%s date=%s recorded=%ld live=%ld gap=%ld\n",
rec.merchant_id, bizdate, rec.recorded_amt, rec.live_amt, rec.gap);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,43 @@
/*
* py_winrank_batch.pgc - py 누계 최고점 (윈도우 함수 배치, XA).
*
* Computes the peak per-merchant running total of net payouts for the day using
* a SUM() OVER window, inside ONE XA transaction.
* Usage: py_winrank_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "py_winrank_batch.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
py_winrank_rec_t rec;
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_peak;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL SELECT coalesce(max(run_tot),0) INTO :h_peak FROM (
SELECT sum(net) OVER (PARTITION BY merchant_id ORDER BY payout_id) AS run_tot
FROM py_payout WHERE biz_date = :h_bizdate) w;
if (sqlca.sqlcode < 0) { fprintf(stderr, "py_winrank_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date)-1); rec.biz_date[sizeof(rec.biz_date)-1] = 0;
rec.peak_running = h_peak;
printf(">>> py_winrank_batch COMMIT: date=%s peak_running=%ld\n", rec.biz_date, rec.peak_running);
tpclose(); tpterm();
return 0;
}