On 7/8/2025 4:14 AM, Louis Krupp wrote:
On 7/7/2025 4:07 PM, Lawrence D'Oliveiro wrote:
On Mon, 7 Jul 2025 14:07:31 -0400, Arne Vajhøj wrote:
Embedded SQL is a thing or was a thing 30-40-50 years ago.
>
Basically you write source code with SQL statements prefixed by EXEC
SQL, put it through a pre-compiler to get valid code in whatever
language (Cobol, PL/I, C or whatever).
OK, so it was a horrible nonstandard hack invented for programming
languages like COBOL, which didn’t have the best ability to deal with
dynamic strings, to make it easier for them to compose SQL statements.
>
And the horribleness of it is reinforced by your statement that you need
server-side cursors in the DBMS to make this hack a little less difficult
to work with.
>
Not sure why it would be needed for PL/I, or even C.
As for embedded SQL being nonstandard, I think you might be interested in this page:
https://www.iso.org/standard/84805.html
which contains this line:
ISO/IEC 9075-2 specifies embedded SQL for the programming languages:
Ada, C, COBOL, Fortran, MUMPS, Pascal, and PL/I.
Note that while -2 covers native languages, then -10 cover
Java.
I am surprised that they still maintain embedded SQL for Java.
SQLJ has been out of fashion for like 25 years.
It can still be made to work though. Also on VMS.
Demo with SQLite:
$ type Test.sqlj
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
#sql context ConCtx;
public class Test {
private String constr;
private String usr;
private String pwd;
private ConCtx getContext() throws SQLException {
return new ConCtx(DriverManager.getConnection(constr, usr, pwd));
}
public Test(String constr, String usr, String pwd) {
this.constr = constr;
this.usr = usr;
this.pwd = pwd;
}
#sql private static iterator T1Iterator(int, String);
public T1 getOne(int f1) throws SQLException {
T1 res;
ConCtx ctx = getContext();
T1Iterator it;
#sql [ctx] it = { SELECT f1,f2 FROM t1 WHERE f1 = :f1};
int xf1 = 0;
String xf2 = null;
#sql { fetch :it INTO :xf1, :xf2 };
if(!it.endFetch()) {
res = new T1(xf1, xf2);
} else {
res = null;
}
ctx.close();
return res;
}
public List<T1> getAll() throws SQLException {
List<T1> res = new ArrayList<T1>();
ConCtx ctx = getContext();
T1Iterator it;
#sql [ctx] it = { SELECT f1,f2 FROM t1 };
while(true) {
int xf1 = 0;
String xf2 = null;
#sql { fetch :it INTO :xf1, :xf2 };
if(it.endFetch()) break;
res.add(new T1(xf1, xf2));
}
ctx.close();
return res;
}
public void save(T1 o) throws SQLException {
ConCtx ctx = getContext();
int f1 = o.getF1();
String f2 = o.getF2();
#sql [ctx] { INSERT INTO t1 VALUES(:f1,:f2) };
ctx.close();
}
public void remove(int f1) throws SQLException {
ConCtx ctx = getContext();
#sql [ctx] { DELETE FROM t1 WHERE f1 = :f1 };
ctx.close();
}
}
$ type T1.java
public class T1 {
private int f1;
private String f2;
public T1() {
this(0, "");
}
public T1(int f1, String f2) {
this.f1 = f1;
this.f2 = f2;
}
public int getF1() {
return f1;
}
public void setF1(int f1) {
this.f1 = f1;
}
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
public String toString() {
return String.format("[%d,%s]", f1, f2);
}
}
$ java -cp translator.jar:runtime12.jar:ojdbc5.jar:sunio.jar:sqlite-jdbc-3_47_2_0.jar "sqlj.tools.Sqlj" -codegen=iso -compile=false -driver="org.sqlite.JDBC" -url="jdbc:sqlite:test.db" -user="" -password="" "Test.sqlj"
$ javac -cp runtime12.jar Main.java Test.java T1.java
$ java "-Xmx512m" -cp .:translator.jar:runtime12.jar:ojdbc5.jar:sunio.jar:sqlite-jdbc-3_47_2_0.jar "Main" "org.sqlite.JDBC" "jdbc:sqlite:test.db" "" ""
[2,BB]
[1,A]
[2,BB]
[3,CCC]
[1,A]
[2,BB]
[3,CCC]
[999,XXX]
[1,A]
[2,BB]
[3,CCC]
runtime12.jar and translator.jar is Oracle SQLJ implementation
from many years ago. They can be found in an older Oracle DB
or Oracle DB client kit.
ojdbc5.jar is a standard Oracle JDBC driver for Java 5. Oracle
SQLJ supports other databases than Oracle DB, but still require
Oracle DB JDBC driver.
sunio.jar is the sun.io package from a Java 5/6/7. That package
is unsupported, not supposed to be used and removed in Java 8.
But SQLJ uses it. So one has to borrow those classes from an
older Java.
Arne