diff --git a/README.md b/README.md index 2e24d8a3..d3db05b8 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ This repository stores a variety of examples demonstrating how to use the Oracle | [json-relational-duality](./json-relational-duality) | JSON Relational Duality examples | [machine-learning](./machine-learning) | Oracle Machine Learning examples | | [optimizer](./optimizer) | Oracle Optimizer and Optimizer Stats examples | +| [precompilers](./precompilers) | Oracle Pro\*C and Pro\*COBOL precompiler examples | | [plsql](./plsql) | PL/SQL examples | | [python](./python) | Python examples | | [ruby](./ruby) | Ruby examples | diff --git a/precompilers/Readme.md b/precompilers/Readme.md new file mode 100644 index 00000000..d2ee4bc2 --- /dev/null +++ b/precompilers/Readme.md @@ -0,0 +1,41 @@ +# Precompiler Examples + +This directory contains sample programs illustrating the use of Oracle Precompilers (Pro*C and Pro*COBOL). +It also includes makefiles for building and compiling these samples into executables. + +## Prerequisites + +### Oracle Packages / Components + +If you are using the Oracle Instant Client, install the following packages for your platform: + +- **Basic** +- **SDK** +- **Precompiler** + +### Compilers + +- A **C/C++ compiler** is required for the Pro*C samples. +- A **COBOL compiler** is required for the Pro*COBOL samples. + +### Minimum Required Version + +The minimum required **Oracle Database** and **Oracle Client** versions are **19c** in both cases. + +## Included Files + +| File Name | Description | +|-----------------------|-----------------------------------------------------------------------------------------------| +| [`procdemo.pc`](./procdemo.pc) | Sample Pro*C program demonstrating basic database operations using Oracle Precompiler. | +| [`procobdemo.pco`](./procobdemo.pco) | Sample Pro*COBOL program illustrating database interaction using Oracle Precompiler. | +| [`makefile_proc.mk`](./makefile_proc.mk) | Makefile for compiling the Pro*C example, managing dependencies, and generating the executable. | +| [`makefile_procob.mk`](./makefile_procob.mk) | Makefile for compiling the Pro*COBOL example, handling build processes, and producing the executable. | + +## How to Compile and Run + +To build the sample programs: + +- Use `make -f makefile_proc.mk` for **Pro*C** samples. +- Use `make -f makefile_procob.mk` for **Pro*COBOL** samples. + +Refer to the respective makefiles for more detailed instructions on compilation and execution steps. diff --git a/precompilers/makefile_proc.mk b/precompilers/makefile_proc.mk new file mode 100644 index 00000000..9223fe99 --- /dev/null +++ b/precompilers/makefile_proc.mk @@ -0,0 +1,123 @@ +############################################################################### +# Make file for PROC demos +############################################################################### +# Usage : +# For compiling proc demos +# make -f makefile_proc.mk +# +# For precompiling, compiling & linking the procdemo.pc file +# make -f makefile_proc.mk build EXE=procdemo OBJS=procdemo.o +# +# In general, for any proc program +# make -f makefile_proc.mk build EXE= OBJS="" +# +# To make use of any PROC options during precompilation, +# make -f makefile_proc.mk build PROCFLAGS="" +# EXE= OBJS="" +# +# NOTES: +# 1. Please change "cc/CC" and the "InstantClient directories" to point to +# appropiate locations on your machine before using this makefile. +# 2. In case of RPM installation, please change the following variables +# as mentioned below: +# PROC=/usr/lib/oracle/VV.v/client/bin/proc +# CCINCLUDES=$(I_SYM)/usr/include/oracle/VV.v/client +# PRECOMPPUBH=/usr/include/oracle/VV.v/client +# ICLIBHOME=/usr/lib/oracle/VV.v/client/lib/ +# Legend: +# VV - Major Oracle version number +# v - Minor Oracle version number +# (Ex: For the release 11.2, VV = 11 and v = 2) +# +############################################################################### + + +CC=/usr/bin/gcc +cc=/usr/bin/gcc + +# InstantClient Directories. +ICSDKHOME=../ +ICLIBHOME=../../ + +MKLINK=ln +REMOVE=rm -rf +CLNCACHE=cleancache +CACHEDIR=SunWS_cachea +MAKE=make +MAKEFILE=makefile_proc.mk +PROCDEMO=procdemo + +PROC=$(ICSDKHOME)/proc +SO_EXT=.so +I_SYM=-I + +CCINCLUDES= $(I_SYM)$(ICSDKHOME)/include + +# Pre-compiler Flags. +PRECOMPPUBH=$(ICSDKHOME)include + +# Compiler Flags. +OPTIMIZE=-O2 +LDPATHFLAG=-L +SPFLAGS=-DLINUX -D_GNU_SOURCE -D_LARGEFILE64_SOURCE=1 -D_LARGEFILE_SOURCE=1 -DSLTS_ENABLE -DSLMXMX_ENABLE -D_REENTRANT -DNS_THREADS +CCFLAGS= -fPIC -DPRECOMP +LDFLAGS=-g +LPFLAGS= +GFLAG= +CDEBUG= +USRFLAGS= +ICLIBPATH=$(LDPATHFLAG)$(ICLIBHOME) +PFLAGS=$(CCINCLUDES) $(SPFLAGS) $(LPFLAGS) +CFLAGS=$(GFLAG) $(OPTIMIZE) $(CDEBUG) $(CCFLAGS) $(PFLAGS) $(USRFLAGS) + +# Libraries. +PROLDLIBS=$(LDCLIENTLIBS) $(THREADLIBS) +LDCLIENTLIBS=$(ICLIBPATH) $(LLIBCLNTSH) $(LDLIBS) +LLIBCLNTSH=$(LDLIBFLAG)$(LIBCLNTSHNAME) +LDLIBFLAG=-l +LIBCLNTCORENAME=clntshcore +LIBCLNTSHNAME=clntsh +LDLIBS=$(EXSYSLIBS) $(MATHLIB) $(USRLIBS) +EXSYSLIBS=-ldl +MATHLIB=-lm +THREADLIBS=-lpthread + +C2O=$(CC) $(CFLAGS) -c $*.c +PCC2C=$(PROC) $(PROCFLAGS) iname=$(PCCSRC) +DEMO_PROC_BUILD=$(CC) -o $(EXE) $(OBJS) $(LDFLAGS) $(PROLDLIBS) + +#----------------------------------------------------------------------------- +# Targets for building the proc sample programs. +all: clean $(PROCDEMO) + +$(PROCDEMO): + $(MAKE) -f $(MAKEFILE) build OBJS=$@.o EXE=$@ + +build: $(CLNCACHE) $(OBJS) + $(DEMO_PROC_BUILD) + +#----------------------------------------------------------------------------- +# Here are some rules for converting .pc -> .c -> .o +.SUFFIXES: .pc .c .o + +pc1: + $(PCC2C) + +.pc.c: + $(MAKE) -f $(MAKEFILE) PROCFLAGS="$(PROCFLAGS)" PCCSRC=$* I_SYM=include= pc1 + +.pc.o: + $(MAKE) -f $(MAKEFILE) PROCFLAGS="$(PROCFLAGS)" PCCSRC=$* I_SYM=include= pc1 + $(C2O) + +.c.o: + $(C2O) + +#----------------------------------------------------------------------------- +# Clean up all executables, *.o and generated *.c files +clean: $(CLNCACHE) + $(REMOVE) $(PROCDEMO) $(PROCDEMO).o $(PROCDEMO).c $(PROCDEMO).lis + +cleancache: + $(REMOVE) $(CACHEDIR) + diff --git a/precompilers/makefile_procob.mk b/precompilers/makefile_procob.mk new file mode 100644 index 00000000..e4eeb493 --- /dev/null +++ b/precompilers/makefile_procob.mk @@ -0,0 +1,96 @@ +############################################################################### +# Make file for PROCOB demos +############################################################################### +# Usage : +# For compiling procob demos +# make -f makefile_procob.mk +# +# For precompiling, compiling & linking the procobdemo.pco file +# make -f makefile_procob.mk build EXE=procobdemo COBS=procobdemo.cob +# +# In general, for any procob program +# make -f makefile_procob.mk build EXE= COBS="" +# To make use of any PROCOB options during precompilation, +# make -f makefile_procob.mk build PROCOBFLAGS="" +# EXE= COBS="" +# +# NOTES: +# 1. Please change "COB" and the "InstantClient directories" to point to +# appropiate locations on your machine before using this makefile. +# 2. In case of RPM installation, please change the following variables +# as mentioned below: +# PROCOB=/usr/lib/oracle/VV.v/client/bin/procob +# ICLIBHOME=/usr/lib/oracle/VV.v/client/lib/ +# Legend: +# VV - Major Oracle version number +# v - Minor Oracle version number +# (Ex: For the release 18.1, VV = 12 and v = 1) +# +############################################################################### + +COB=cob + +# InstantClient Directories. +ICSDKHOME=../ +ICLIBHOME=../../ + +MKLINK=ln +REMOVE=rm -rf +CLNCACHE=cleancache +CACHEDIR=SunWS_cachea +MAKE=make +MAKEFILE=makefile_procob.mk +PROCOBDEMO=procobdemo + +PROCOB=$(ICSDKHOME)/procob +ICLIBPATH=$(LDPATHFLAG)$(ICLIBHOME) +SO_EXT=.so +COBFLAGS=-C IBMCOMP -C NESTCALL -t -x +LDPATHFLAG=-L +COBSQLINTF=$(ICLIBHOME)cobsqlintf.o +LDLIBS=$(EXSYSLIBS) $(MATHLIB) $(USRLIBS) +EXSYSLIBS=-ldl +MATHLIB=-lm +COBOL_PROLDLIBS=$(SHARED_CLIENTLIBS) $(LDLIBS) +SHARED_CLIENTLIBS=$(LLIBCLNTSH) $(LDFLAGS) +LLIBCLNTSH=$(LDLIBFLAG)$(LIBCLNTSHNAME) +LDLIBFLAG=-l +LIBCLNTCORENAME=clntshcore +LIBCLNTSHNAME=clntsh +LDFLAGS=-g + +DEMO_PROCOB_BUILD=$(COB) $(COBFLAGS) -o $(EXE) $(COBS) $(ICLIBPATH) $(COBSQLINTF) $(COBOL_PROLDLIBS) + +#----------------------------------------------------------------------------- +# Targets for building the procob sample programs. +# +# The target 'build' puts together an executable $(EXE) from the cobol +# sources in $(COBS) and the libraries in $(COBOL_PROLDLIBS). +# The rules to make .cob files from .pco files are later in this file. +# +all: clean $(PROCOBDEMO) + +$(PROCOBDEMO): + $(MAKE) -f $(MAKEFILE) build COBS=$@.cob EXE=$@ + +build: $(CLNCACHE) $(COBS) + $(DEMO_PROCOB_BUILD) + +#----------------------------------------------------------------------------- +# Here are some rules for converting .pco -> .cob -> .o and for .cob -> .gnt. +# +.SUFFIXES: .cob .cbl .o .pco $(GNT) + +.pco.cob: + $(PROCOB) $(PROCOBFLAGS) iname=$*.pco + +.cob$(GNT): + $(COB2GNT) + +#----------------------------------------------------------------------------- +# Clean up all executables, *.o and generated *.cob files +clean: $(CLNCACHE) + $(REMOVE) $(PROCOBDEMO) $(PROCOBDEMO).o $(PROCOBDEMO).cob $(PROCDEMO).lis $(PROCOBDEMO).int $(PROCOBDEMO).idy + +cleancache: + $(REMOVE) $(CACHEDIR) diff --git a/precompilers/procdemo.pc b/precompilers/procdemo.pc new file mode 100644 index 00000000..a2f35ff4 --- /dev/null +++ b/precompilers/procdemo.pc @@ -0,0 +1,125 @@ +/* Copyright (c) 2025, Oracle and/or its affiliates.*/ +/* All rights reserved.*/ + +/* NAME + * procdemo.pc - Pro*C demo program + * + * DESCRIPTION + * This program connects to ORACLE, declares and opens a cursor, + * fetches the names, salaries, and commissions of all + * salespeople, displays the results, then closes the cursor. + * + */ + +#include +#include +#include +#include +#include +#include + +#define UNAME_PWD_LEN 256 + +/* + * Use the precompiler typedef'ing capability to create + * null-terminated strings for the authentication host + * variables. (This isn't really necessary--plain char *'s + * would work as well. This is just for illustration.) + */ +typedef char asciiz[UNAME_PWD_LEN]; + +EXEC SQL TYPE asciiz IS CHARZ(UNAME_PWD_LEN) REFERENCE; +asciiz username; +asciiz password; + +struct emp_info +{ + asciiz emp_name; + float salary; + float commission; +}; + +void sql_error(msg) + char *msg; +{ + char err_msg[512]; + size_t buf_len, msg_len; + + EXEC SQL WHENEVER SQLERROR CONTINUE; + + printf("\n%s\n", msg); + +/* Call sqlglm() to get the complete text of the + * error message. + */ + buf_len = sizeof (err_msg); + sqlglm(err_msg, &buf_len, &msg_len); + printf("%.*s\n", msg_len, err_msg); + + EXEC SQL ROLLBACK RELEASE; + exit(EXIT_FAILURE); +} + +void main() +{ + struct emp_info *emp_rec_ptr; + +/* Allocate memory for emp_info struct. */ + if ((emp_rec_ptr = + (struct emp_info *) malloc(sizeof(struct emp_info))) == 0) + { + fprintf(stderr, "Memory allocation error.\n"); + exit(EXIT_FAILURE); + } + +/* application user to set the database credentials here */ +/* CAUTION: Username and password buffers are 256 characters. */ +/* Do not paste credentials longer than 256 characters. */ + + strcpy(username, ""); + strcpy(password, ""); + + EXEC SQL WHENEVER SQLERROR DO sql_error("ORACLE error--"); + + EXEC SQL CONNECT :username IDENTIFIED BY :password; + printf("\nConnected to ORACLE as user: %s\n", username); + +/* Declare the cursor. All static SQL explicit cursors + * contain SELECT commands. 'salespeople' is a SQL identifier, + * not a (C) host variable. + */ + EXEC SQL DECLARE salespeople CURSOR FOR + SELECT ENAME, SAL, COMM + FROM EMP + WHERE JOB LIKE 'SALES%'; + +/* Open the cursor. */ + EXEC SQL OPEN salespeople; + +/* Get ready to print results. */ + printf("\n\nThe company's salespeople are--\n\n"); + printf("Salesperson Salary Commission\n"); + printf("----------- ------ ----------\n"); + +/* Loop, fetching all salesperson's statistics. + * Cause the program to break the loop when no more + * data can be retrieved on the cursor. + */ + EXEC SQL WHENEVER NOT FOUND DO break; + + for (;;) + { + EXEC SQL FETCH salespeople INTO :emp_rec_ptr; + printf("%s %9.2f %12.2f\n", emp_rec_ptr->emp_name, + emp_rec_ptr->salary, emp_rec_ptr->commission); + } + +/* Close the cursor. */ + EXEC SQL CLOSE salespeople; + + printf("\nGOOD-BYE!!\n\n"); + + EXEC SQL COMMIT WORK RELEASE; + exit(EXIT_SUCCESS); +} + diff --git a/precompilers/procobdemo.pco b/precompilers/procobdemo.pco new file mode 100644 index 00000000..5e947b6f --- /dev/null +++ b/precompilers/procobdemo.pco @@ -0,0 +1,99 @@ + ***************************************************************** + * Copyright (c) 2025, Oracle and/or its affiliates.. * + * All rights reserved. * + * * + * procobdemo.pco - Pro*COBOL demo file. * + * * + * DESCRIPTION: * + * This program logs on to ORACLE, declares and opens a cursor, * + * fetches the names, salaries, and commissions of all * + * salespeople, displays the results, then closes the cursor. * + ***************************************************************** + + IDENTIFICATION DIVISION. + PROGRAM-ID. CURSOR-OPS. + ENVIRONMENT DIVISION. + DATA DIVISION. + WORKING-STORAGE SECTION. + + EXEC SQL BEGIN DECLARE SECTION END-EXEC. + 01 USERNAME PIC X(256) VARYING. + 01 PASSWD PIC X(256) VARYING. + 01 EMP-REC-VARS. + 05 EMP-NAME PIC X(10) VARYING. + 05 SALARY PIC S9(6)V99 + DISPLAY SIGN LEADING SEPARATE. + 05 COMMISSION PIC S9(6)V99 + DISPLAY SIGN LEADING SEPARATE. + EXEC SQL VAR SALARY IS DISPLAY(8,2) END-EXEC. + EXEC SQL VAR COMMISSION IS DISPLAY(8,2) END-EXEC. + EXEC SQL END DECLARE SECTION END-EXEC. + + EXEC SQL INCLUDE SQLCA END-EXEC. + + 01 DISPLAY-VARIABLES. + 05 D-EMP-NAME PIC X(10). + 05 D-SALARY PIC Z(4)9.99. + 05 D-COMMISSION PIC Z(4)9.99. + + PROCEDURE DIVISION. + + BEGIN-PGM. + EXEC SQL WHENEVER SQLERROR + DO PERFORM SQL-ERROR END-EXEC. + PERFORM LOGON. + EXEC SQL DECLARE SALESPEOPLE CURSOR FOR + SELECT ENAME, SAL, COMM + FROM EMP + WHERE JOB LIKE 'SALES%' + END-EXEC. + EXEC SQL OPEN SALESPEOPLE END-EXEC. + DISPLAY " ". + DISPLAY "SALESPERSON SALARY COMMISSION". + DISPLAY "----------- ---------- ----------". + + FETCH-LOOP. + EXEC SQL WHENEVER NOT FOUND + DO PERFORM SIGN-OFF END-EXEC. + EXEC SQL FETCH SALESPEOPLE + INTO :EMP-NAME, :SALARY, :COMMISSION + END-EXEC. + MOVE EMP-NAME-ARR TO D-EMP-NAME. + MOVE SALARY TO D-SALARY. + MOVE COMMISSION TO D-COMMISSION. + DISPLAY D-EMP-NAME, " ", D-SALARY, " ", D-COMMISSION. + MOVE SPACES TO EMP-NAME-ARR. + GO TO FETCH-LOOP. + + LOGON. + ***************************************************************** + * Application user: Set the database credentials here. * + * CAUTION: Username and password buffers are 256 bytes. * + * Do not paste credentials longer than 256 characters. * + ***************************************************************** + MOVE "" TO USERNAME-ARR. + MOVE LENGTH OF "" TO USERNAME-LEN. + MOVE "" TO PASSWD-ARR. + MOVE LENGTH OF "" TO PASSWD-LEN. + EXEC SQL + CONNECT :USERNAME IDENTIFIED BY :PASSWD + END-EXEC. + DISPLAY " ". + DISPLAY "CONNECTED TO ORACLE AS USER: ", USERNAME-ARR. + + SIGN-OFF. + EXEC SQL CLOSE SALESPEOPLE END-EXEC. + DISPLAY " ". + DISPLAY "HAVE A GOOD DAY.". + DISPLAY " ". + EXEC SQL COMMIT WORK RELEASE END-EXEC. + STOP RUN. + + SQL-ERROR. + EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. + DISPLAY " ". + DISPLAY "ORACLE ERROR DETECTED:". + DISPLAY " ". + DISPLAY SQLERRMC. + EXEC SQL ROLLBACK WORK RELEASE END-EXEC. + STOP RUN.