I am familiar with Oracle PL/SQL and C/C++ language, and I can write code that pulls data from a database and outputs result to console/command/output stream/etc.
However, I am not familiar with openVMS development. But I was able to verify that the CXX
compiler (built in to the operating system) works after compiling/linking and running the following code:
#include <stdio.h>
void main(void) {
printif("Hello World!\n");
}
Now, I tried to my best to connect to the oracle database (which is installed on the same server, and there are a lot of other C/CP files written to pull data from the db and they work fine), but I was not able to compile any code that tries to read from the database. For simplicity, here is the code that tried to access the database:
#include<stdio.h>
void main(void) {
int cnt = -1;
exec sql SELECT count(*) INTO :cnt FROM EMPLOYEES;
printif("Number of employees: %d", cnt);
}
When I compile that, I get:
%CXX-E-UNDECLARED, identifier "exec" is undefined
At first, I thought that I might be missing a library at the header, so I tried the following:
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#ifdef PC
#include <fcntl.h>
#else
#include <unixio.h>
#include <file.h>
#endif
#include <ctype.h>
but none of the above library caused the compiler to stop complaining about the exec sql
statetment.
I went to Oracle technical documents about writing C programs on openVMS and found some sample code that includes <sqlca.h>
and others like <sql_sqlda.h>
but none of them solved my problem.
I am guess, may be the other c files written before are somehow compiled with a special command that takes care of EXEC SQL statement (by attaching a dependency library on the fly at compile time???)
So my question is: what can I do to compile my code and get the count of records in a certain table?
After so much trial and error, I have found a working solution to my problem. The answer posted by @Sentinel was useful, but the documentation was very hard to follow through.
I decided to post the steps I have done to successfully compile a C code containing PL/SQL statements. I deliberately written these steps to walk you through the whole process from scratch, because I was so frustrated for the lack of such level of explanation on Oracle Documentation. I had to put all of these steps together after researching the Oracle Documentation, as well as some other answers on StackOverflow, and not to mention some YouTube videos in Vietnamese language (which I have no clue how to translate).
Make sure your C code contains the proper include oracle library.
#include<stdio.h>
#include<stdlib.h>
exec sql include sqlca;
exec sql begin declare section;
int cnt; //variable to be accessed by PL/SQL block
exec sql end declare section;
main() {
exec sql connect SCOTT identified by TIGER;
if(sqlca.sqlcode==0) {
// assuming no errors from the last sql statement
exec sql select count(*) into :cnt from TEST_TABLE;
// this is an example only. Replace the statement with a useful one
printf("\nNumber of rows: %d", cnt);
} else {
printf("\nError Code: %d, Message: %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
}
}
Let's assume the above C code sample is saved in a file named MYTEST.C
. We need to use Oracle's Pre-compiler to convert any SQL block into regualr C.
PROC INAME=MYTEST CODE=CPP MYTEST.C NEW_TEST.PC
Now you will have a new file named NEW_TEST.PC
which contains pre-compiled SQL c alongside your original C code. It is time to compile this file using native C compiler
CXX /DEBUG=TRACE /OPTIMIZE /PREFIX=ALL /GRAN=LONG /NAME=AS_IS /FLOAT=IEEE NEW_TEST.PC
Now you will have object file ready to be linked using Oracle Linker
LNPROC NEW_TEST NEW_TEST CPP
You may now run the executable
RUN NEW_TEST.EXE