The purpose of this article is to show how to access a database residing on VMS from both VMS and other systems.
The example used is extremely trivial. Just the SQL query:
SELECT f1,f2 FROM t1
and there will be no error handling at all.
But there will be links to other articles showing more details on the database API aspect (SQL updates, parameters, error handling etc.).
All technologies will be marked with supported platforms:
There is also a lot of repeated code between examples, but the intention is to make individual sections complete without referring to code in other sections.
This article only covers native databases. For JVM databases see here.
Comparison of content in 2 articles:
Native databases
Database | VMS client | non-VMS client |
---|---|---|
Rdb | C - embedded SQL C - module C - SQL services Pascal - embedded SQL Pascal - module Fortran - embedded SQL Fortran - module Cobol - embedded SQL Cobol - module Java - JDBC Java - JPA Jython - DB API 2.0 + JDBC Python - DB API 2.0 Python - RDB |
C - ODBC C - SQL services Pascal - SQLDB + ODBC Java - JDBC Java - JPA Jython - DB API 2.0 + JDBC C# - ADO.NET C# - ODBC C# - EF PHP - ODBC PHP - PDO + ODBC VBS - ODBC |
MySQL | C - libmysql Pascal - pmysql + libmysql Java - JDBC Java - JPA Jython - DB API 2.0 + JDBC PHP - mysqli PHP - PDO + mysqli |
C - libmysql C - ODBC Pascal - SQLDB SQLDB + ODBC Java - JDBC Java - JPA Jython - DB API 2.0 + JDBC C# - ADO.NET C# - ODBC C# - EF Python - DB API 2.0 PHP - mysqli PHP - PDO + mysqli PHP - ODBC PHP - PDO + ODBC VBS - ODBC |
SQLite | C - standard API Pascal - psqlite + standard API Java - JDBC Java - JPA Jython - DB API 2.0 + JDBC PHP - sqlite3 PHP - PDO + sqlite3 |
(N/A) |
Mimer | C - embedded SQL Fortran - embedded SQL Cobol - embedded SQL Java - JDBC |
C - ODBC Pascal - SQLDB + ODBC C# - ADO.NET C# - ODBC PHP - ODBC PHP - PDO + ODBC VBS - ODBC |
JVM databases
Database | VMS client | non-VMS client |
---|---|---|
HSQLDB | Java - JDBC Jython - DB API 2.0 + JDBC PHP - JDBC bridge |
C - ODBC Pascal - SQLDB + ODBC Java - JDBC Jython - DB API 2.0 + JDBC Python - DB API 2.0 + JayDeBeApi PHP - ODBC PHP - PDO + ODBC PHP - JDBC bridge |
H2 | Java - JDBC Jython - DB API 2.0 + JDBC PHP - JDBC bridge |
Java - JDBC Jython - DB API 2.0 + JDBC Python - DB API 2.0 + JayDeBeApi PHP - JDBC bridge |
Derby | Java - JDBC Jython - DB API 2.0 + JDBC PHP - JDBC bridge |
Java - JDBC Jython - DB API 2.0 + JDBC Python - DB API 2.0 + JayDeBeApi PHP - JDBC bridge |
For more complex examples see Access VMS database - API comparison.
Rdb is probably the most widely used relational database on VMS.
It was introduced by Digital back in 1984. It was sold to Oracle in 1994. It is so far VMS only (it was ported to Windows NT but that version was never released).
Rdb has a somewhat unusual database server architecture where different types of client applications connect in different ways:
Rdb supports traditional embedded SQL for a large number of programming languages including C.
The precompiler gets installed with the Rdb installation.
rdb1.sc:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
EXEC SQL INCLUDE SQLCA;
/* these are uppercase in Rdb */
#define sqlca SQLCA
#define sqlcode SQLCODE
int main()
{
EXEC SQL BEGIN DECLARE SECTION;
char con[256];
char f2[51];
long int f1;
EXEC SQL END DECLARE SECTION;
printf("Rdb from C (embedded)\n");
strcpy(con, "FILENAME disk4:[rdb]test");
EXEC SQL CONNECT TO :con;
EXEC SQL DECLARE curs CURSOR FOR SELECT f1,f2 FROM t1;
EXEC SQL OPEN curs;
for(;;)
{
EXEC SQL FETCH curs INTO :f1, :f2;
if(sqlca.sqlcode != 0) break;
printf("%d %s\n", f1, f2);
}
EXEC SQL CLOSE curs;
return 0;
}
Build and run - VMS:
$ def/nolog sql$database disk4:[rdb]test
$ sqlpre /cc /sqloptions=connect rdb1
$ link rdb1 + sys$library:sql$user73/libr
$ run rdb1
Rdb also comes with the ability to compile SQL modules to native code that can be linked into applications.
The module compiler gets installed with the Rdb installation.
rdb2c.sqlmod:
MODULE rdb2c
LANGUAGE C
PARAMETER COLONS
DECLARE ALIAS FOR FILENAME disk4:[rdb]test
DECLARE curs CURSOR FOR SELECT f1,f2 FROM t1
PROCEDURE CURSOR_OPEN
SQLCODE;
OPEN curs;
PROCEDURE CURSOR_FETCH
SQLCODE,
:f1 INTEGER,
:f2 CHAR(50);
FETCH curs INTO :f1, :f2;
PROCEDURE CURSOR_CLOSE
SQLCODE;
CLOSE curs;
rdb2.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void cursor_open(int *sqlcode);
void cursor_fetch(int *sqlcode, long int *f1, char *f2);
void cursor_close(int *sqlcode);
int main()
{
char f2[51];
long int f1;
int sqlcode;
printf("Rdb from C (module)\n");
cursor_open(&sqlcode);
for(;;)
{
cursor_fetch(&sqlcode, &f1, f2);
if(sqlcode != 0) break;
printf("%d %s\n", f1, f2);
}
cursor_close(&sqlcode);
return 0;
}
Build and run:
$ def/nolog sql$database disk4:[rdb]test
$ sqlmod rdb2c
$ cc rdb2
$ link rdb2 + rdb2c + sys$library:sql$user73/libr
$ run rdb2
Oracle provides an ODBC driver for Rdb that needs to be installed.
Standard ODBC API. For details on ODBC API including SQL updates, parameters and error handling see here.
The example assumes a DSN has been defined in ODBC manager.
It seems to require MS VC++ as I could not get it to work with GCC.
rdb2.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <sql.h>
#include <sqlext.h>
#define F2_MAX_LEN 50
static const char *dsn = "ARNE1_RDB";
static const char *un = "arne";
static const char *pw = "hemmeligt";
int main()
{
SQLHENV env;
SQLHDBC con;
SQLHSTMT stmt;
long int f1;
char *sqlstr, f2[F2_MAX_LEN + 1];
SQLLEN lenf2;
int stat;
printf("Rdb from C (ODBC)\n");
stat = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
stat = SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);
stat = SQLAllocHandle(SQL_HANDLE_DBC, env, &con);
stat = SQLConnect(con, (SQLCHAR *)dsn, (SQLSMALLINT)strlen(dsn),
(SQLCHAR *)un, (SQLSMALLINT)strlen(un),
(SQLCHAR *)pw, (SQLSMALLINT)strlen(pw));
sqlstr = "SELECT f1,f2 FROM t1";
stat = SQLAllocHandle(SQL_HANDLE_STMT, con, &stmt);
stat = SQLExecDirect(stmt, (SQLCHAR *)sqlstr, strlen(sqlstr));
stat = SQLBindCol(stmt, 1, SQL_C_LONG, &f1, 0, NULL);
stat = SQLBindCol(stmt, 2, SQL_C_CHAR, f2, sizeof(f2), &lenf2);
for(;;)
{
stat = SQLFetch(stmt);
if((stat != SQL_SUCCESS) && (stat != SQL_SUCCESS_WITH_INFO)) break;
f2[lenf2] = 0;
printf("%ld %s\n", f1, f2);
}
SQLCloseCursor(stmt);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
SQLDisconnect(con);
SQLFreeHandle(SQL_HANDLE_DBC, con);
SQLFreeHandle(SQL_HANDLE_ENV, env);
return 0;
}
Build and run - Windows:
cl rdb2.c odbc32.lib
rdb2
Rdb SQL Services also has a custom client API.
For details on this API including SQL updates, parameters and error handling see here.
rdb3.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlsrv.h>
#define F2_MAX_LEN 50
static char *srv = "arne1.vajhoej.dk";
static char *un = "arne";
static char *pw = "hemmeligt";
int main()
{
ASSOCIATE_ID con;
ASSOCIATE_STR coninf;
long int stmt;
SQLDA_ID param_sqlda;
SQLDA_ID select_sqlda;
long int f1;
char *sqlstr, *qnam, f2[F2_MAX_LEN + 1];
long int stat;
short int nullval;
char buf[1000];
unsigned short int buflen;
printf("Rdb from C (SQLSRV)\n");
memset(&coninf, 0, sizeof(coninf));
coninf.VERSION = SQLSRV_V730;
coninf.xpttyp = SQLSRV_XPT_TCPIP ;
stat = sqlsrv_associate(srv, un, pw, NULL, NULL, 0, 0, NULL, &coninf, &con);
stat = sqlsrv_execute_immediate(con, 0, "ATTACH 'FILENAME disk4:[rdb]test'");
sqlstr = "SELECT f1,f2 FROM t1";
select_sqlda = NULL;
param_sqlda = NULL;
stat = sqlsrv_prepare(con, 0, sqlstr, &stmt, ¶m_sqlda, &select_sqlda);
stat = sqlsrv_allocate_sqlda_data(con, select_sqlda);
qnam = "Q1";
stat = sqlsrv_open_cursor(con, qnam, stmt, param_sqlda);
for(;;)
{
stat = sqlsrv_fetch(con, qnam, 0, 0, select_sqlda);
if(stat != SQL_SUCCESS) break;
stat = sqlsrv_sqlda_get_data(select_sqlda, 0, 0, (CHARPTR)&buf[0], sizeof(buf), &nullval, &buflen);
f1 = atoi(buf);
stat = sqlsrv_sqlda_get_data(select_sqlda, 1, 0, (CHARPTR)&buf[0], sizeof(buf), &nullval, &buflen);
strcpy(f2, buf + 2);
printf("%ld %s\n", f1, f2);
}
sqlsrv_close_cursor(con, qnam);
sqlsrv_free_sqlda_data(con, select_sqlda);
sqlsrv_release_statement(con, 1, &stmt);
sqlsrv_release(con, NULL);
return 0;
}
Build and run - VMS:
$ cc rdb3
$ link rdb3 + sys$library:sqlsrv$api/opt
$ run rdb3
$ exit
Build and run - Windows:
cl /I"%SQLSRV%" rdb3.c "%SQLSRV%\SQSAPI64.LIB"
rdb3
Build and run - Linux:
gcc -I. rdb3.c libsqs.a -o rdb3
./rdb3
Rdb supports traditional embedded SQL for a large number of programming languages including Pascal.
The precompiler gets installed with the Rdb installation.
rdb1.spa:
program rdb1(input, output);
EXEC SQL INCLUDE SQLCA;
EXEC SQL DECLARE curs CURSOR FOR SELECT f1,f2 FROM t1;
var
EXEC SQL BEGIN DECLARE SECTION;
con : varying [255] of char;
f1 : integer;
f2 : varying [50] of char;
EXEC SQL END DECLARE SECTION;
done : boolean;
begin
writeln('Rdb from Pascal (embedded)');
con := 'FILENAME disk4:[rdb]test';
EXEC SQL CONNECT TO :con;
EXEC SQL OPEN curs;
done := false;
while not done do begin
EXEC SQL FETCH curs INTO :f1, :f2;
if sqlca.sqlcode = 0 then begin
writeln(f1, ' ', f2);
end else begin
done := true;
end;
end;
EXEC SQL CLOSE curs;
end.
Build and run - VMS:
$ def/nolog sql$database disk4:[rdb]test
$ sqlpre /pas /sqloptions=connect rdb1
$ link rdb1 + sys$library:sql$user73/libr
$ run rdb1
Rdb also comes with the ability to compile SQL modules to native code that can be linked into applications.
The module compiler gets installed with the Rdb installation.
rdb2p.sqlmod:
MODULE rdb2p
LANGUAGE PASCAL
PARAMETER COLONS
DECLARE ALIAS FOR FILENAME disk4:[rdb]test
DECLARE curs CURSOR FOR SELECT f1,f2 FROM t1
PROCEDURE CURSOR_OPEN
SQLCODE;
OPEN curs;
PROCEDURE CURSOR_FETCH
SQLCODE,
:f1 INTEGER,
:f2 VARCHAR(50);
FETCH curs INTO :f1, :f2;
PROCEDURE CURSOR_CLOSE
SQLCODE;
CLOSE curs;
rdb2.pas:
program rdb2(input, output);
type
var50str = varying [50] of char;
procedure cursor_open(var sqlcode : integer); external;
procedure cursor_fetch(var sqlcode : integer; var f1 : integer; var f2 : var50str); external;
procedure cursor_close(var sqlcode : integer); external;
var
sqlcode : integer;
f1 : integer;
f2 : var50str;
done : boolean;
begin
writeln('Rdb from Pascal (module)');
cursor_open(sqlcode);
done := false;
while not done do begin
cursor_fetch(sqlcode, f1, f2);
if sqlcode = 0 then begin
writeln(f1, ' ', f2);
end else begin
done := true;
end;
end;
cursor_close(sqlcode);
end.
Build and run - VMS:
$ def/nolog sql$database disk4:[rdb]test
$ sqlmod rdb2p
$ pas rdb2
$ link rdb2 + rdb2p + sys$library:sql$user73/libr
$ run rdb2
FPC comes with SQLDB unit for database access. SQLDB supports ODBC.
Oracle provides an ODBC driver for Rdb.
For details on SQLDB API including SQL updates, parameters and error handling see here.
The example assumes a DSN has been defined in ODBC manager.
rdb2.pas:
program rdb2(input, output);
uses
SQLDB, ODBCConn;
var
con : TSQLConnection;
tx : TSQLTransaction;
q : TSQLQuery;
f1 : integer;
f2 : string;
begin
writeln('Rdb from Pascal (SQLDB, ODBC)');
con := TODBCConnection.Create(nil);
con.DatabaseName := 'ARNE1_RDB';
con.UserName := 'arne';
con.Password := 'hemmeligt';
con.Open;
tx := TSQLTransaction.Create(nil);
con.Transaction := tx;
q := TSQLQuery.Create(nil);
q.DataBase := con;
q.SQL.Text := 'SELECT f1,f2 FROM t1';
q.Open;
while not q.EOF do begin
f1 := q.FieldByName('f1').AsInteger;
f2 := q.FieldByName('f2').AsString;
writeln(f1, ' ', f2);
q.Next;
end;
q.Close;
q.Free;
con.Close;
con.Free;
end.
Build and run - Windows:
fpc rdb2.pas
rdb2
Rdb supports traditional embedded SQL for a large number of programming languages including Fortran.
The precompiler gets installed with the Rdb installation.
rdb1.sfo:
PROGRAM RDB1
EXEC SQL INCLUDE SQLCA
EXEC SQL DECLARE curs CURSOR FOR SELECT f1,f2 FROM t1
EXEC SQL BEGIN DECLARE SECTION
CHARACTER*255 CON
INTEGER*4 F1
CHARACTER*50 F2
EXEC SQL END DECLARE SECTION
WRITE(*,*) 'Rdb from Fortran(embedded)'
CON = 'FILENAME disk4:[rdb]test'
EXEC SQL CONNECT TO :CON
EXEC SQL OPEN curs
100 EXEC SQL FETCH curs INTO :f1, :f2
IF(SQLCOD.EQ.0) THEN
WRITE(*,*) F1, ' ', F2
GOTO 100
ENDIF
EXEC SQL CLOSE curs
END
Build and run - VMS:
$ def/nolog sql$database disk4:[rdb]test
$ sqlpre /for /sqloptions=connect rdb1
$ link rdb1 + sys$library:sql$user73/libr
$ run rdb1
Rdb also comes with the ability to compile SQL modules to native code that can be linked into applications.
The module compiler gets installed with the Rdb installation.
rdb2f.sqlmod:
MODULE rdb2f
LANGUAGE FORTRAN
PARAMETER COLONS
DECLARE ALIAS FOR FILENAME disk4:[rdb]test
DECLARE curs CURSOR FOR SELECT f1,f2 FROM t1
PROCEDURE CURSOR_OPEN
SQLCODE;
OPEN curs;
PROCEDURE CURSOR_FETCH
SQLCODE,
:f1 INTEGER,
:f2 CHAR(50);
FETCH curs INTO :f1, :f2;
PROCEDURE CURSOR_CLOSE
SQLCODE;
CLOSE curs;
rdb2.for:
PROGRAM RDB2
EXTERNAL CURSOR_OPEN, CURSOR_FETCH, CURSOR_CLOSE
INTEGER*4 SQLCOD,F1
CHARACTER*50 F2
WRITE(*,*) 'Rdb for Fortran (module)'
CALL CURSOR_OPEN(SQLCOD)
100 CALL CURSOR_FETCH(SQLCOD, F1, F2)
IF(SQLCOD.EQ.0) THEN
WRITE(*,*) F1, ' ', F2
GOTO 100
ENDIF
CALL CURSOR_CLOSE(SQLCOD)
END
Build and run - VMS:
$ def/nolog sql$database disk4:[rdb]test
$ sqlmod rdb2f
$ for rdb2
$ link rdb2 + rdb2f + sys$library:sql$user73/libr
$ run rdb2
Rdb supports traditional embedded SQL for a large number of programming languages including Cobol.
The precompiler gets installed with the Rdb installation.
rdb1.sco:
IDENTIFICATION DIVISION.
PROGRAM-ID. RDB1.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
EXEC SQL INCLUDE SQLCA END-EXEC.
01 CON PIC X(255).
01 F1 PIC 9(9) DISPLAY.
01 F2 PIC X(50).
EXEC SQL DECLARE curs CURSOR FOR SELECT f1,f2 FROM t1 END-EXEC.
PROCEDURE DIVISION.
MAIN-PARAGRAPH.
DISPLAY "Rdb from Cobol (embedded)"
MOVE "FILENAME disk4:[rdb]test" TO CON
EXEC SQL CONNECT TO :CON END-EXEC
EXEC SQL OPEN curs END-EXEC
MOVE 0 TO SQLCODE
PERFORM UNTIL NOT SQLCODE = 0
EXEC SQL FETCH curs INTO :f1, :f2 END-EXEC
IF SQLCODE = 0 THEN
DISPLAY F1 " " F2
END-IF
END-PERFORM
EXEC SQL CLOSE curs END-EXEC
STOP RUN.
Build and run - VMS:
$ def/nolog sql$database disk4:[rdb]test
$ sqlpre /cob /sqloptions=connect rdb1
$ link rdb1 + sys$library:sql$user73/libr
$ run rdb1
Rdb also comes with the ability to compile SQL modules to native code that can be linked into applications.
The module compiler gets installed with the Rdb installation.
rdb2b.sqlmod:
MODULE rdb2b
LANGUAGE COBOL
PARAMETER COLONS
DECLARE ALIAS FOR FILENAME disk4:[rdb]test
DECLARE curs CURSOR FOR SELECT f1,f2 FROM t1
PROCEDURE CURSOR_OPEN
SQLCODE;
OPEN curs;
PROCEDURE CURSOR_FETCH
SQLCODE,
:f1 INTEGER,
:f2 CHAR(50);
FETCH curs INTO :f1, :f2;
PROCEDURE CURSOR_CLOSE
SQLCODE;
CLOSE curs;
rdb2.cob:
IDENTIFICATION DIVISION.
PROGRAM-ID. RDB2.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 SQLCODE PIC S9(9) COMP.
01 TEMPF1 PIC 9(9) COMP.
01 F1 PIC 9(9) DISPLAY.
01 F2 PIC X(50).
PROCEDURE DIVISION.
MAIN-PARAGRAPH.
DISPLAY "Rdb from Cobol (module)"
CALL "CURSOR_OPEN" USING SQLCODE
MOVE 0 TO SQLCODE
PERFORM UNTIL NOT SQLCODE = 0
CALL "CURSOR_FETCH" USING SQLCODE, TEMPF1, F2
IF SQLCODE = 0 THEN
MOVE TEMPF1 TO F1
DISPLAY F1 " " F2
END-IF
END-PERFORM
CALL "CURSOR_CLOSE" USING SQLCODE
STOP RUN.
Build and run - VMS:
$ def/nolog sql$database disk4:[rdb]test
$ sqlmod rdb2b
$ cob rdb2
$ link rdb2 + rdb2b + sys$library:sql$user73/libr
$ run rdb2
JDBC is Java basic database API.
Oracle provides two JDBC drivers for Rdb:
Here we will look at native driver.
For details on JDBC API including SQL updates and parameters see here.
rdb1.java:
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
public class Rdb1 {
public static void main(String[] args) throws Exception {
System.out.println("Rdb from Java (JDBC, native)");
Class.forName("oracle.rdb.jdbc.rdbNative.Driver");
Connection con = DriverManager.getConnection("jdbc:rdbNative:disk4:[rdb]test");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT f1,f2 FROM t1");
while(rs.next()) {
int f1 = rs.getInt(1);
String f2 = rs.getString(2);
System.out.println(f1 + " " + f2);
}
rs.close();
stmt.close();
con.close();
}
}
Build and run - VMS:
$ javac Rdb1.java
$ java -cp .:rdbnativev5.jar "Rdb1"
jrdb1.py:
from java.lang import Class
from java.sql import DriverManager
from oracle.rdb.jdbc.rdbNative import Driver # replaces Class.forName('oracle.rdb.jdbc.rdbNative.Driver')
print('Rdb from JVM Python (JDBC, native)')
con = DriverManager.getConnection('jdbc:rdbNative:disk4:[rdb]test')
stmt = con.createStatement()
rs = stmt.executeQuery('SELECT f1,f2 FROM t1')
while rs.next():
f1 = rs.getInt(1)
f2 = rs.getString(2)
print(str(f1) + ' ' + f2)
rs.close()
stmt.close()
con.close()
jrdb1.js:
importClass(Packages.java.lang.Class);
importClass(Packages.java.sql.DriverManager);
print("Rdb from JVM JavaScript (JDBC, native)")
new Packages.oracle.rdb.jdbc.rdbNative.Driver(); //replaces Class.forName("oracle.rdb.jdbc.rdbNative.Driver");
con = DriverManager.getConnection("jdbc:rdbNative:disk4:[rdb]test");
stmt = con.createStatement();
rs = stmt.executeQuery("SELECT f1,f2 FROM t1");
while(rs.next()) {
f1 = rs.getInt(1);
f2 = rs.getString(2);
print(f1 + " " + f2);
}
rs.close();
stmt.close();
con.close();
JDBC is Java basic database API.
Oracle provides two JDBC drivers for Rdb:
Here we will look at thin driver.
For details on JDBC API including SQL updates and parameters see here.
Rdb2.java:
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
public class Rdb2 {
public static void main(String[] args) throws Exception {
System.out.println("Rdb from Java (JDBC, thin)");
Class.forName("oracle.rdb.jdbc.rdbThin.Driver");
Connection con = DriverManager.getConnection("jdbc:rdbThin://192.168.0.10:1701/dka4:[rdb]test", "arne", "hemmeligt");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT f1,f2 FROM t1");
while(rs.next()) {
int f1 = rs.getInt(1);
String f2 = rs.getString(2);
System.out.println(f1 + " " + f2);
}
rs.close();
stmt.close();
con.close();
}
}
Build and run - Windows:
javac Rdb2.java
java -cp .;rdbthinv8.jar Rdb2
Build and run - VMS:
$ javac Rdb2.java
$ java -cp .:rdbthinv5.jar "Rdb2"
Rdb2.kt:
import java.sql.*
fun main(args: Array<String>) {
println("Rdb from Kotlin (JDBC, thin)")
Class.forName("oracle.rdb.jdbc.rdbThin.Driver")
val con = DriverManager.getConnection("jdbc:rdbThin://192.168.0.10:1701/dka4:[rdb]test", "arne", "hemmeligt")
val stmt = con.createStatement()
val rs = stmt.executeQuery("SELECT f1,f2 FROM t1")
while(rs.next()) {
val f1 = rs.getInt(1);
val f2 = rs.getString(2);
println("$f1 $f2");
}
rs.close()
stmt.close()
con.close()
}
Build and run - Windows:
call %KOTLIN%\bin\kotlinc -d . Rdb2.kt
java -cp .;%KOTLIN%\lib\*;rdbthinv8.jar Rdb2Kt
Rdb2.groovy:
import java.sql.*
println("Rdb from Groovy (JDBC, thin)")
Class.forName("oracle.rdb.jdbc.rdbThin.Driver")
con = DriverManager.getConnection("jdbc:rdbThin://192.168.0.10:1701/dka4:[rdb]test", "arne", "hemmeligt")
stmt = con.createStatement()
rs = stmt.executeQuery("SELECT f1,f2 FROM t1")
while(rs.next()) {
f1 = rs.getInt(1)
f2 = rs.getString(2)
println("$f1 $f2")
}
rs.close()
stmt.close()
con.close()
Build and run - Windows:
call %GROOVY%\bin\groovyc Rdb2.groovy
java -cp .;%GROOVY%\lib\*;rdbthinv8.jar Rdb2
jrdb1.py:
from java.lang import Class
from java.sql import DriverManager
from oracle.rdb.jdbc.rdbThin import Driver # replaces Class.forName('oracle.rdb.jdbc.rdbThin.Driver')
print('Rdb from JVM Python (JDBC, thin)')
con = DriverManager.getConnection('jdbc:rdbThin://192.168.0.10:1701/dka4:[rdb]test', 'arne', 'hemmeligt')
stmt = con.createStatement()
rs = stmt.executeQuery('SELECT f1,f2 FROM t1')
while rs.next():
f1 = rs.getInt(1)
f2 = rs.getString(2)
print(str(f1) + ' ' + f2)
rs.close()
stmt.close()
con.close()
jrdb1.js:
importClass(Packages.java.lang.Class);
importClass(Packages.java.sql.DriverManager);
print("Rdb from JVM JavaScript (JDBC, thin)")
new Packages.oracle.rdb.jdbc.rdbThin.Driver(); //replaces Class.forName("oracle.rdb.jdbc.rdbThin.Driver");
con = DriverManager.getConnection("jdbc:rdbThin://192.168.0.10:1701/dka4:[rdb]test", "arne", "hemmeligt");
stmt = con.createStatement();
rs = stmt.executeQuery("SELECT f1,f2 FROM t1");
while(rs.next()) {
f1 = rs.getInt(1);
f2 = rs.getString(2);
print(f1 + " " + f2);
}
rs.close();
stmt.close();
con.close();
JPA is the Java standard for ORM.
We will use Hibernates JPA implementation.
Oracle provides two JDBC drivers for Rdb:
Here we will use native driver.
Oracle provides a Rdb dialect for Hibernate.
Oracle's Rdb dialect works with Hibernate 3.6 - it does not work with Hibernate 5.0 - I have not tested with other versions.
For details on JPA including updates and parameters see here.
META-INF/persistence.xml:
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="Rdb1">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>T1</class>
<exclude-unlisted-classes/>
<properties>
<!--<property name="show_sql" value="true"/>-->
<property name="hibernate.connection.driver_class" value="oracle.rdb.jdbc.rdbNative.Driver"/>
<property name="hibernate.connection.url" value="jdbc:rdbNative:disk4:[rdb]test"/>
<property name="hibernate.connection.username" value="arne"/>
<property name="hibernate.connection.password" value="hemmeligt"/>
<property name="hibernate.connection.pool_size" value="5"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.RdbDialect"/>
</properties>
</persistence-unit>
</persistence>
T1.java:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="t1")
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;
}
@Id
@Column(name="f1")
public int getF1() {
return f1;
}
public void setF1(int f1) {
this.f1 = f1;
}
@Column(name="f2")
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
}
Rdb1X.java:
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.TypedQuery;
public class Rdb1X {
public static void main(String[] args) {
System.out.println("Rdb from Java (JPA, native)");
// disable Hibernate logging (outcomment for debugging)
Logger.getLogger("org.hibernate").setLevel(Level.OFF);
EntityManagerFactory emf = Persistence.createEntityManagerFactory("Rdb1");
EntityManager em = emf.createEntityManager();
TypedQuery<T1> q = em.createQuery("SELECT o FROM T1 AS o", T1.class);
List<T1> res = q.getResultList();
for(T1 o : res) {
System.out.println(o.getF1() + " " + o.getF2());
}
em.close();
emf.close();
}
}
Build and run - VMS:
$ javac -cp 'hibpath' Rdb1X.java T1.java
$ java -cp .:'hibpath':rdbhib.jar:rdbnativev5.jar "Rdb1X"
T1.java:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="t1")
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;
}
@Id
@Column(name="f1")
public int getF1() {
return f1;
}
public void setF1(int f1) {
this.f1 = f1;
}
@Column(name="f2")
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
}
jrdb1x.py:
from java.util.logging import Level
from java.util.logging import Logger
from javax.persistence import Persistence
import T1
print("Rdb from JVM Python (JPA, native)")
# disable Hibernate logging (outcomment for debugging)
Logger.getLogger("org.hibernate").setLevel(Level.OFF)
emf = Persistence.createEntityManagerFactory("Rdb1")
em = emf.createEntityManager()
q = em.createQuery("SELECT o FROM T1 AS o", T1)
res = q.getResultList();
for o in res:
print('%d %s' % (o.f1, o.f2))
em.close()
emf.close()
JPA is the Java standard for ORM.
We will use Hibernates JPA implementation.
Oracle provides two JDBC drivers for Rdb:
Here we will use thin driver.
Oracle provides a Rdb dialect for Hibernate.
Oracle's Rdb dialect works with Hibernate 3.6 - it does not work with Hibernate 5.0 - I have not tested with other versions.
For details on JPA including updates and parameters see here.
META-INF/persistence.xml:
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="Rdb2">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>T1</class>
<exclude-unlisted-classes/>
<properties>
<!--<property name="show_sql" value="true"/>-->
<property name="hibernate.connection.driver_class" value="oracle.rdb.jdbc.rdbThin.Driver"/>
<property name="hibernate.connection.url" value="jdbc:rdbThin://192.168.0.10:1701/disk4:[rdb]test"/>
<property name="hibernate.connection.username" value="arne"/>
<property name="hibernate.connection.password" value="hemmeligt"/>
<property name="hibernate.connection.pool_size" value="5"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.RdbDialect"/>
</properties>
</persistence-unit>
</persistence>
T1.java:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="t1")
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;
}
@Id
@Column(name="f1")
public int getF1() {
return f1;
}
public void setF1(int f1) {
this.f1 = f1;
}
@Column(name="f2")
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
}
Rdb2X.java:
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.TypedQuery;
public class Rdb2X {
public static void main(String[] args) {
System.out.println("Rdb from Java (JPA, thin)");
// disable Hibernate logging (outcomment for debugging)
Logger.getLogger("org.hibernate").setLevel(Level.OFF);
EntityManagerFactory emf = Persistence.createEntityManagerFactory("Rdb2");
EntityManager em = emf.createEntityManager();
TypedQuery<T1> q = em.createQuery("SELECT o FROM T1 AS o", T1.class);
List<T1> res = q.getResultList();
for(T1 o : res) {
System.out.println(o.getF1() + " " + o.getF2());
}
em.close();
emf.close();
}
}
Build and run - Windows:
javac -cp %HIBPATH% Rdb2X.java T1.java
java -cp .;%HIBPATH%;rdbhib.jar;rdbthinv8.jar Rdb2X
Build and run - VMS:
$ javac -cp 'hibpath' Rdb2X.java T1.java
$ java -cp .:'hibpath':rdbhib.jar:rdbthinv5.jar "Rdb2X"
T1.kt:
import javax.persistence.*
@Entity
@Table(name="t1")
data class T1 (@Id @Column(name="f1") val f1: Int = 0,
@Column(name="f2") val f2: String = "")
Rdb2X.kt:
import java.util.logging.*
import java.util.logging.Logger;
import javax.persistence.*
fun main(args: Array<String>) {
println("Rdb from Kotlin (JPA, thin)")
Logger.getLogger("org.hibernate").setLevel(Level.OFF)
val emf = Persistence.createEntityManagerFactory("Rdb2")
val em = emf.createEntityManager()
val q = em.createQuery("SELECT o FROM T1 AS o", T1::class.java)
val res = q.getResultList()
for(o in res) {
println("${o.f1} ${o.f2}")
}
em.close()
emf.close()
}
Build and run - Windows:
call %KOTLIN%\bin\kotlinc -cp %HIBPATH% -d . Rdb2X.kt T1.kt
java -cp .;%KOTLIN%\lib\*;%HIBPATH%;rdbhib.jar;rdbthinv8.jar Rdb2XKt
T1.groovy:
import javax.persistence.*
@Entity
@Table(name="t1")
class T1 {
@Id
@Column(name="f1")
int f1
@Column(name="f2")
String f2
}
Rdb2X.groovy:
import java.util.logging.*
import javax.persistence.*
println("Rdb from Groovy (JPA, thin)")
// disable Hibernate logging (outcomment for debugging)
Logger.getLogger("org.hibernate").setLevel(Level.OFF)
emf = Persistence.createEntityManagerFactory("Rdb2")
em = emf.createEntityManager()
q = em.createQuery("SELECT o FROM T1 AS o", T1.class)
res = q.getResultList()
for(o in res) {
println("${o.f1} ${o.f2}")
}
em.close()
emf.close()
Build and run - Windows:
call %GROOVY%\bin\groovyc -cp hibernate-jpa-2.0-api-1.0.0.Final.jar Rdb2X.groovy T1.groovy
java -cp .;%GROOVY%\lib\*;%HIBPATH%;rdbhib.jar;rdbthinv8.jar Rdb2X
T1.java:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="t1")
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;
}
@Id
@Column(name="f1")
public int getF1() {
return f1;
}
public void setF1(int f1) {
this.f1 = f1;
}
@Column(name="f2")
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
}
jrdb2x.py:
from java.util.logging import Level
from java.util.logging import Logger
from javax.persistence import Persistence
import T1
print("Rdb from JVM Python (JPA, thin)")
# disable Hibernate logging (outcomment for debugging)
Logger.getLogger("org.hibernate").setLevel(Level.OFF)
emf = Persistence.createEntityManagerFactory("Rdb2")
em = emf.createEntityManager()
q = em.createQuery("SELECT o FROM T1 AS o", T1)
res = q.getResultList();
for o in res:
print('%d %s' % (o.f1, o.f2))
em.close()
emf.close()
Jython (JVM Python) can use standard Python DB API 2.0 to access a database via the zxJDBC module and a standard JDBC driver.
jrdb1z.py:
from com.ziclix.python.sql import zxJDBC
print('Rdb from JVM Python (DB API 2.0 via zxJDBC, native)')
con = zxJDBC.connect('jdbc:rdbNative:disk4:[rdb]test', None, None, 'oracle.rdb.jdbc.rdbNative.Driver')
c = con.cursor()
c.execute('SELECT f1,f2 FROM t1')
data = c.fetchall()
c.close()
for row in data:
print('%d %s' % (row[0], row[1]))
con.close()
Jython (JVM Python) can use standard Python DB API 2.0 to access a database via the zxJDBC module and a standard JDBC driver.
jrdb2z.py:
from com.ziclix.python.sql import zxJDBC
print('Rdb from JVM Python (DB API 2.0 via zxJDBC, thin)')
con = zxJDBC.connect('jdbc:rdbThin://192.168.0.10:1701/dka4:[rdb]test', 'arne', 'hemmeligt', 'oracle.rdb.jdbc.rdbThin.Driver')
c = con.cursor()
c.execute('SELECT f1,f2 FROM t1')
data = c.fetchall()
c.close()
for row in data:
print('%d %s' % (row[0], row[1]))
con.close()
ADO.NET is .NET basic database API.
Oracle provides an ADO.NET provider for Rdb as part of Oracle Rdb Data Provider (ORDP).
For details on ADO.NET API including SQL updates, parameters and how to make the code database independent see here.
rdb1.cs:
using System;
using Oracle.DataAccess.RdbClient;
public class Program
{
public static void Main(String[] args)
{
Console.WriteLine("Rdb from C# (ADO.NET)");
using(RdbConnection con = new RdbConnection("Server=192.168.0.10:GENERIC;Database=disk4:[rdb]test;User Id=arne;Password=hemmeligt;"))
{
con.Open();
using(RdbCommand cmd = new RdbCommand("SELECT f1,f2 FROM t1", con))
{
using(RdbDataReader rdr = cmd.ExecuteReader())
{
while(rdr.Read())
{
Console.WriteLine((int)rdr["f1"] + " " + (string)rdr["f2"]);
}
}
}
}
}
}
Build and run - Windows:
csc -platform:x86 /r:Oracle.DataAccess.Rdb.dll rdb1.cs
rdb1
rdb1.vb:
Imports System
Imports Oracle.DataAccess.RdbClient
Public Class Program
Public Shared Sub Main(args As [String]())
Console.WriteLine("Rdb from VB.NET (ADO.NET)")
Using con As New RdbConnection("Server=192.168.0.10:GENERIC;Database=disk4:[rdb]test;User Id=arne;Password=hemmeligt;")
con.Open()
Using cmd As New RdbCommand("SELECT f1,f2 FROM t1", con)
Using rdr As RdbDataReader = cmd.ExecuteReader()
While rdr.Read()
Console.WriteLine(rdr("f1") & " " & rdr("f2"))
End While
End Using
End Using
End Using
End Sub
End Class
Build and run - Windows:
vbc -platform:x86 /r:Oracle.DataAccess.Rdb.dll rdb1.vb
rdb1
ADO.NET can use an ODBC driver.
Oracle provides an ODBC driver for Rdb that needs to be installed.
The example assumes a DSN has been defined in ODBC manager.
It is strongly recommended using the databases ADO.NET provider instead of the ODBC driver. Mixing .NET and native for database access is not optimal.
rdb2.cs:
using System;
using System.Data.Odbc;
public class Program
{
public static void Main(String[] args)
{
Console.WriteLine("Rdb from C# (ODBC)");
using(OdbcConnection con = new OdbcConnection("Dsn=ARNE1_RDB;Uid=arne;Pwd=hemmeligt"))
{
con.Open();
using(OdbcCommand cmd = new OdbcCommand("SELECT f1,f2 FROM t1", con))
{
using(OdbcDataReader rdr = cmd.ExecuteReader())
{
while(rdr.Read())
{
Console.WriteLine((int)rdr["f1"] + " " + (string)rdr["f2"]);
}
}
}
}
}
}
Build and run - Windows:
csc rdb2.cs
rdb2
rdb2.vb:
Imports System
Imports System.Data.Odbc
Public Class Program
Public Shared Sub Main(args As [String]())
Console.WriteLine("Rdb from VB.NET (ODBC)")
Using con As New OdbcConnection("Dsn=ARNE1_RDB;Uid=arne;Pwd=hemmeligt")
con.Open()
Using cmd As New OdbcCommand("SELECT f1,f2 FROM t1", con)
Using rdr As OdbcDataReader = cmd.ExecuteReader()
While rdr.Read()
Console.WriteLine(rdr("f1") & " " & rdr("f2"))
End While
End Using
End Using
End Using
End Sub
End Class
Build and run - Windows:
vbc rdb2.vb
rdb2
Entity Framework (EF) is a common ORM for .NET.
Oracle Rdb Data Provide (ORDP) supports EF.
For details on EF including updates and parameters see here.
Note that the version of ORDP EF and the version of core EF need to match. I got Oracle.Rdb.EntityFramework version 6.0.1.1 with EntityFramework version 6.0.0 working. I strongly recommend using NuGet to get Oracle.Rdb.EntityFramework and let it fetch the right version of EntityFramework.
The example will use code first approach.
rdb1x.exe.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<add name="Rdb" connectionString="Server=192.168.0.10:GENERIC;Database=disk4:[rdb]test;User Id=arne;Password=hemmeligt;" providerName="Oracle.DataAccess.RdbClient" />
</connectionStrings>
<entityFramework>
<defaultConnectionFactory type="Oracle.DataAccess.RdbClient.Entity.RdbConnectionFactory, Oracle.Rdb.EntityFramework"/>
<providers>
<provider invariantName="Oracle.DataAccess.RdbClient" type="Oracle.DataAccess.RdbClient.RdbProviderServices, Oracle.Rdb.EntityFramework"/>
</providers>
</entityFramework>
</configuration>
rdb1x.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
// Note: table names and column names are case sensitive
[Table("T1")]
public class T1
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Column("F1")]
public int F1 { get; set; }
[Column("F2")]
public string F2 { get; set; }
}
public class MySqlDbContext : DbContext
{
public MySqlDbContext() : base("Rdb")
{
}
public DbSet<T1> T1 { get; set; }
}
public class Program
{
public static void Main(String[] args)
{
Console.WriteLine("Rdb from C# (EF)");
using(MySqlDbContext db = new MySqlDbContext())
{
List<T1> res = db.T1.ToList();
foreach(T1 o in res)
{
Console.WriteLine(o.F1 + " " + o.F2);
}
}
}
}
Build and run - Windows:
csc -platform:x86 /r:System.ComponentModel.DataAnnotations.dll /r:EntityFramework.dll rdb1x.cs
rdb1x
rdb1x.vb:
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel.DataAnnotations
Imports System.ComponentModel.DataAnnotations.Schema
Imports System.Data.Entity
Imports System.Linq
' Note: table names and column names are case sensitive
<Table("T1")> _
Public Class T1
<Key> _
<DatabaseGenerated(DatabaseGeneratedOption.None)> _
<Column("F1")> _
Public Property F1() As Integer
<Column("F2")> _
Public Property F2() As String
End Class
Public Class MySqlDbContext
Inherits DbContext
Public Sub New()
MyBase.New("Rdb")
End Sub
Public Property T1() As DbSet(Of T1)
End Class
Public Class Program
Public Shared Sub Main(args As [String]())
Console.WriteLine("Rdb from VB.NET (EF)")
Using db As New MySqlDbContext()
Dim res As List(Of T1) = db.T1.ToList()
For Each o As T1 In res
Console.WriteLine(o.F1 & " " & o.F2)
Next
End Using
End Sub
End Class
Build and run - Windows:
vbc -platform:x86 /r:System.ComponentModel.DataAnnotations.dll /r:EntityFramework.dll rdb1x.vb
rdb1x
A DB API 2.0 compliant rdb module is available (may even be pre-installed with VMS Python).
For details on DB API 2.0 including SQL updates and parameters see here.
rdb1.py:
from rdb import dbapi2
print('Rdb from Python')
con = dbapi2.connect(database='disk4:[rdb]test')
c = con.cursor()
c.execute('SELECT f1,f2 FROM t1')
data = c.fetchall()
c.close()
for row in data:
print('%d %s' % (row[0], row[1]))
con.close()
The rdb module also has an RDB specific API.
rdb1.py:
import rdb
print('Rdb from Python')
rdb.attachDB('disk4:[rdb]test')
curs = rdb.statement('SELECT f1,f2 FROM t1')
rdb.read_only() # necessary to avoid a transaction error
curs.execute()
for row in curs:
print('%d %s' % (row[0], row[1]))
Options for Jython (JVM Python) are described under JVM languages.
PHP supports ODBC.
Oracle provides an ODBC driver for Rdb that needs to be installed.
The example assumes a DSN has been defined in ODBC manager.
rdb2.php:
<?php
echo "Rdb from PHP (ODBC)\r\n";
$con = odbc_connect('ARNE1_RDB', 'arne', 'hemmeligt');
$stmt = odbc_prepare($con, 'SELECT f1,f2 FROM t1');
odbc_execute($stmt, array());
while(odbc_fetch_row($stmt)){
$f1 = odbc_result($stmt, 'f1');
$f2 = odbc_result($stmt, 'f2');
echo "$f1 $f2\r\n";
}
odbc_free_result($stmt);
odbc_close($con);
?>
PHP has a standard database API called PDO.
PDO supports ODBC.
Oracle provides an ODBC driver for Rdb that needs to be installed.
The example assumes a DSN has been defined in ODBC manager.
rdb2p.php:
<?php
echo "Rdb from PHP (PDO,ODBC)\r\n";
$con = new PDO('odbc:DSN=ARNE1_RDB;UID=arne;PWD=hemmeligt');
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$con->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$stmt = $con->prepare('SELECT f1,f2 FROM t1');
$stmt->execute(array());
while($row = $stmt->fetch()) {
$f1 = $row['F1'];
$f2 = $row['F2'];
echo "$f1 $f2\r\n";
}
?>
VBS supports ADO and ADO can use an ODBC driver.
Oracle provides an ODBC driver for Rdb that needs to be installed.
The example assumes a DSN has been defined in ODBC manager.
rdb.vbs:
WScript.Echo "Rdb from VBS (ODBC)"
Set con = CreateObject("ADODB.Connection")
con.Open "Dsn=ARNE1_RDB;Uid=arne;Pwd=hemmeligt;"
Set cmd = CreateObject("ADODB.Command")
cmd.ActiveConnection = con
cmd.CommandText = "SELECT f1,f2 FROM t1"
Set rs = cmd.Execute
Do While Not rs.EOF
WScript.Echo rs("f1") & " " & rs("f2")
rs.MoveNext
Loop
Set rs = Nothing
Set cmd = Nothing
Set con = Nothing
MySQL is a very widely used database. It was introduced in 1995. It was sold to Oracle in 2010. Same year a fork MariaDB was created. And today MariaDB is as widely used as MySQL.
MySQL is available on many platforms Linux, Windows, macOS, Solaris etc.. There are two ports to VMS:
MySQL uses a traditional database server architecture with all client application accessing a database server via network:
MySQL C API usually called libmysql typical comes with MySQL.
For details on MySQL C API including SQL updates, parameters and error handling see here.
mysql1.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SOCKET int
#include <mysql.h>
#define F2_MAX_LEN 50
int main()
{
MYSQL *con;
con = mysql_init(NULL);
con = mysql_real_connect(con, "192.168.0.10", "root", "", "test", 3306, NULL, 0);
MYSQL_STMT *stmt;
MYSQL_BIND out[2];
char *sqlstr, f2[F2_MAX_LEN + 1];
unsigned long int lenf2;
int stat, f1;
printf("MySQL from C (libmysql)\n");
stmt = mysql_stmt_init(con);
sqlstr = "SELECT f1,f2 FROM t1";
stat = mysql_stmt_prepare(stmt, sqlstr, strlen(sqlstr));
stat = mysql_stmt_execute(stmt);
memset(out, 0, sizeof(out));
out[0].buffer_type = MYSQL_TYPE_LONG;
out[0].buffer = &f1;
out[0].buffer_length = sizeof(f1);
out[1].buffer_type = MYSQL_TYPE_STRING;
out[1].buffer = f2;
out[1].buffer_length = sizeof(f2);
out[1].length = &lenf2;
stat = mysql_stmt_bind_result(stmt, out);
stat = mysql_stmt_store_result(stmt);
while(!mysql_stmt_fetch(stmt))
{
f2[lenf2] = 0;
printf("%d %s\n", f1, f2);
}
mysql_stmt_free_result(stmt);
mysql_close(con);
return 0;
}
Build and run - VMS:
$ cc /include=mysql055_root:[include.mysql] /names=as_is mysql1.c
$ link mysql1 + sys$input/opt
mysql055_root:[lib.alpha]libclientlib/lib
mysql055_root:[lib.alpha]libsql/lib
mysql055_root:[lib.alpha]libmysys/lib
mysql055_root:[lib.alpha]libdbug/lib
mysql055_root:[lib.alpha]libstrings/lib
mysql055_root:[lib.alpha]libvio/lib
mysql055_root:[lib.alpha]libz/lib
mysql055_root:[lib.alpha]ssl_libssl32/lib
mysql055_root:[lib.alpha]ssl_libcrypto32/lib
$
$ run mysql1
(MariaDB 5.5 on VMS Alpha)
Build and run - Windows:
gcc -I%MYSQL%\include -L%MYSQL%\lib mysql1.c -lmysql -o mysql1.exe
mysql1
MySQL provides an ODBC driver called MySQL Connector/ODBC that needs to be installed.
Standard ODBC API. For details on ODBC API including SQL updates, parameters and error handling see here.
The example assumes a DSN has been defined in ODBC manager.
mysql2.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <sql.h>
#include <sqlext.h>
#define F2_MAX_LEN 50
static const char *dsn = "ARNE1_MYSQL";
static const char *un = "";
static const char *pw = "";
int main()
{
SQLHENV env;
SQLHDBC con;
SQLHSTMT stmt;
long int f1;
char *sqlstr, f2[F2_MAX_LEN + 1];
SQLLEN lenf2;
int stat;
printf("MySQL from C (ODBC)\n");
stat = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
stat = SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);
stat = SQLAllocHandle(SQL_HANDLE_DBC, env, &con);
stat = SQLConnect(con, (SQLCHAR *)dsn, (SQLSMALLINT)strlen(dsn),
(SQLCHAR *)un, (SQLSMALLINT)strlen(un),
(SQLCHAR *)pw, (SQLSMALLINT)strlen(pw));
sqlstr = "SELECT f1,f2 FROM t1";
stat = SQLAllocHandle(SQL_HANDLE_STMT, con, &stmt);
stat = SQLExecDirect(stmt, (SQLCHAR *)sqlstr, strlen(sqlstr));
stat = SQLBindCol(stmt, 1, SQL_C_LONG, &f1, 0, NULL);
stat = SQLBindCol(stmt, 2, SQL_C_CHAR, f2, sizeof(f2), &lenf2);
for(;;)
{
stat = SQLFetch(stmt);
if((stat != SQL_SUCCESS) && (stat != SQL_SUCCESS_WITH_INFO)) break;
f2[lenf2] = 0;
printf("%d %s\n", f1, f2);
}
SQLCloseCursor(stmt);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
SQLDisconnect(con);
SQLFreeHandle(SQL_HANDLE_DBC, con);
SQLFreeHandle(SQL_HANDLE_ENV, env);
return 0;
}
Build and run - Windows:
gcc mysql2.c -lodbc32 -o mysql2.exe
mysql2
Due to VMS calling convention it is possible to call a C library like libmysql from Pascal.
To make it a little easier I have created a wrapper pmysql that are also open source and can be downloaded here.
mysql.pas:
[inherit('pmysqldir:pmysql2', 'pmysqldir:pmysql', 'pmysqldir:mysql')]
program mysql(input, output);
var
con : mysql_ptr;
stmt : mysql_stmt_ptr;
stat : integer;
f1 : integer;
f2 : longpstr(255);
begin
writeln('MySQL from Pascal (pmysql, libmysql)');
con := pmysql_init;
con := pmysql_real_connect(con, '192.168.0.10', 'root', '', 'test');
stmt := pmysql_prepare(con, 'SELECT f1,f2 FROM t1');
stat := pmysql_get_result_start(stmt, long_arg(f1), longstring_arg(f2));
while pmysql_stmt_fetch(stmt) = 0 do begin
writeln(f1, ' ', stdstr(f2));
end;
pmysql_stmt_free_result(stmt);
pmysql_close(con);
end.
Build and run - VMS:
$ pascal mysql
$ link mysql + sys$input/opt + pmysqldir:mysql55axp/opt
pmysqldir:pmysql2
pmysqldir:pmysql
pmysqldir:mysql
$
$ run mysql
FPC comes with SQLDB unit for database access. SQLDB supports MySQL.
For details on SQLDB API including SQL updates, parameters and error handling see here.
mysql1.pas:
program mysql1(input, output);
uses
SQLDB, MySQL55Conn;
var
con : TSQLConnection;
tx : TSQLTransaction;
q : TSQLQuery;
f1 : integer;
f2 : string;
begin
writeln('MySQL from Pascal (SQLDB, MySQL55)');
con := TMySQL55Connection.Create(nil);
con.HostName := '192.168.0.10';
con.UserName := 'root';
con.Password := '';
con.DatabaseName := 'test';
con.Open;
tx := TSQLTransaction.Create(nil);
con.Transaction := tx;
q := TSQLQuery.Create(nil);
q.DataBase := con;
q.SQL.Text := 'SELECT f1,f2 FROM t1';
q.Open;
while not q.EOF do begin
f1 := q.FieldByName('f1').AsInteger;
f2 := q.FieldByName('f2').AsString;
writeln(f1, ' ', f2);
q.Next;
end;
q.Close;
q.Free;
con.Close;
con.Free;
end.
Build and run - Windows:
fpc mysql1.pas
mysql1
FPC comes with SQLDB unit for database access. SQLDB supports ODBC.
MySQL provides an ODBC driver called MySQL Connector/ODBC that needs to be installed.
For details on SQLDB API including SQL updates, parameters and error handling see here.
The example assumes a DSN has been defined in ODBC manager.
mysql2.pas:
program mysql2(input, output);
uses
SQLDB, ODBCConn;
var
con : TSQLConnection;
tx : TSQLTransaction;
q : TSQLQuery;
f1 : integer;
f2 : string;
begin
writeln('MySQL from Pascal (SQLDB, ODBC)');
con := TODBCConnection.Create(nil);
con.DatabaseName := 'ARNE1_MYSQL';
con.Open;
tx := TSQLTransaction.Create(nil);
con.Transaction := tx;
q := TSQLQuery.Create(nil);
q.DataBase := con;
q.SQL.Text := 'SELECT f1,f2 FROM t1';
q.Open;
while not q.EOF do begin
f1 := q.FieldByName('f1').AsInteger;
f2 := q.FieldByName('f2').AsString;
writeln(f1, ' ', f2);
q.Next;
end;
q.Close;
q.Free;
con.Close;
con.Free;
end.
Build and run - Windows:
fpc mysql2.pas
mysql2
JDBC is Java basic database API.
MySQL provides a JDBC driver called MySQL Connector/Java.
For details on JDBC API including SQL updates and parameters see here.
MySQL.java:
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
public class MySQL {
public static void main(String[] args) throws Exception {
System.out.println("MySQL from Java (JDBC)");
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://192.168.0.10:3306/test", "root", "");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT f1,f2 FROM t1");
while(rs.next()) {
int f1 = rs.getInt(1);
String f2 = rs.getString(2);
System.out.println(f1 + " " + f2);
}
rs.close();
stmt.close();
con.close();
}
}
Build and run - Windows:
javac MySQL.java
java -cp .;mysql-connector-java-5.1.36-bin.jar MySQL
Build and run - VMS:
$ javac MySQL.java
$ java -cp .:mysql-connector-java-5_1_36-bin.jar "MySQL"
MySQL.kt:
import java.sql.*
fun main(args: Array<String>) {
println("MySQL from Kotlin (JDBC)")
Class.forName("com.mysql.jdbc.Driver")
val con = DriverManager.getConnection("jdbc:mysql://192.168.0.10:3306/test", "root", "")
val stmt = con.createStatement()
val rs = stmt.executeQuery("SELECT f1,f2 FROM t1")
while(rs.next()) {
val f1 = rs.getInt(1);
val f2 = rs.getString(2);
println("$f1 $f2");
}
rs.close()
stmt.close()
con.close()
}
Build and run - Windows:
call %KOTLIN%\bin\kotlinc -d . MySQL.kt
java -cp .;%KOTLIN%\lib\*;mysql-connector-java-5.1.36-bin.jar MySQLKt
MySQL.groovy:
import java.sql.*
println("MySQL from Groovy (JDBC, thin)")
Class.forName("com.mysql.jdbc.Driver")
con = DriverManager.getConnection("jdbc:mysql://192.168.0.10:3306/test", "root", "")
stmt = con.createStatement()
rs = stmt.executeQuery("SELECT f1,f2 FROM t1")
while(rs.next()) {
f1 = rs.getInt(1)
f2 = rs.getString(2)
println("$f1 $f2")
}
rs.close()
stmt.close()
con.close()
Build and run - Windows:
call %GROOVY%\bin\groovyc MySQL.groovy
java -cp .;%GROOVY%\lib\*;mysql-connector-java-5.1.36-bin.jar MySQL
jmysql.py:
from java.lang import Class
from java.sql import DriverManager
from com.mysql.jdbc import Driver # replaces Class.forName('com.mysql.jdbc.Driver')
print('MySQL from JVM Python (JDBC)')
con = DriverManager.getConnection('jdbc:mysql://192.168.0.10:3306/test', 'root', '')
stmt = con.createStatement()
rs = stmt.executeQuery('SELECT f1,f2 FROM t1')
while rs.next():
f1 = rs.getInt(1)
f2 = rs.getString(2)
print(str(f1) + ' ' + f2)
rs.close()
stmt.close()
con.close()
jmysql.js:
importClass(Packages.java.lang.Class);
importClass(Packages.java.sql.DriverManager);
print("MySQL from JVM JavaScript (JDBC)")
new Packages.com.mysql.jdbc.Driver(); //replaces Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://192.168.0.10:3306/test", "root", "");
stmt = con.createStatement();
rs = stmt.executeQuery("SELECT f1,f2 FROM t1");
while(rs.next()) {
f1 = rs.getInt(1);
f2 = rs.getString(2);
print(f1 + " " + f2);
}
rs.close();
stmt.close();
con.close();
JPA is the Java standard for ORM.
We will use Hibernates JPA implementation.
Oracle provides a JDBC driver called MySQL Connector/Java:
Hibernate comes woth support for MySQL dialect.
For details on JPA including updates and parameters see here.
META-INF/persistence.xml:
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="MySQL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>T1</class>
<exclude-unlisted-classes/>
<properties>
<!--<property name="show_sql" value="true"/>-->
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.connection.url" value="jdbc:mysql://192.168.0.10:3306/test"/>
<property name="hibernate.connection.username" value="root"/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.connection.pool_size" value="5"/>
</properties>
</persistence-unit>
</persistence-unit>
</persistence>
T1.java:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="t1")
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;
}
@Id
@Column(name="f1")
public int getF1() {
return f1;
}
public void setF1(int f1) {
this.f1 = f1;
}
@Column(name="f2")
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
}
MySQLX.java:
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.TypedQuery;
public class MySQLX {
public static void main(String[] args) {
System.out.println("MySQL from Java (JPA)");
// disable Hibernate logging (outcomment for debugging)
Logger.getLogger("org.hibernate").setLevel(Level.OFF);
EntityManagerFactory emf = Persistence.createEntityManagerFactory("MySQL");
EntityManager em = emf.createEntityManager();
TypedQuery<T1> q = em.createQuery("SELECT o FROM T1 AS o", T1.class);
List<T1> res = q.getResultList();
for(T1 o : res) {
System.out.println(o.getF1() + " " + o.getF2());
}
em.close();
emf.close();
}
}
Build and run - Windows:
javac -cp %HIBPATH% MySQLX.java T1.java
java -cp .;%HIBPATH%;mysql-connector-java-5.1.36-bin.jar MySQLX
Build and run - VMS:
$ javac -cp 'hibpath' MySQLX.java T1.java
$ java -cp .:'hibpath':mysql-connector-java-5_1_36-bin.jar "MySQLX"
T1.kt:
import javax.persistence.*
@Entity
@Table(name="t1")
data class T1 (@Id @Column(name="f1") val f1: Int = 0,
@Column(name="f2") val f2: String = "")
MySQLX.kt:
import java.util.logging.*
import java.util.logging.Logger;
import javax.persistence.*
fun main(args: Array<String>) {
println("MySQL from Kotlin (JPA)")
Logger.getLogger("org.hibernate").setLevel(Level.OFF)
val emf = Persistence.createEntityManagerFactory("MySQL")
val em = emf.createEntityManager()
val q = em.createQuery("SELECT o FROM T1 AS o", T1::class.java)
val res = q.getResultList()
for(o in res) {
println("${o.f1} ${o.f2}")
}
em.close()
emf.close()
}
Build and run - Windows:
call %KOTLIN%\bin\kotlinc -cp %HIBPATH% -d . MySQLX.kt T1.kt
java -cp .;%KOTLIN%\lib\*;%HIBPATH%;mysql-connector-java-5.1.36-bin.jar MySQLXKt
T1.groovy:
import javax.persistence.*
@Entity
@Table(name="t1")
class T1 {
@Id
@Column(name="f1")
int f1
@Column(name="f2")
String f2
}
MySQLX.groovy:
import java.util.logging.*
import javax.persistence.*
println("MySQL from Groovy (JPA, thin)")
// disable Hibernate logging (outcomment for debugging)
Logger.getLogger("org.hibernate").setLevel(Level.OFF)
emf = Persistence.createEntityManagerFactory("MySQL")
em = emf.createEntityManager()
q = em.createQuery("SELECT o FROM T1 AS o", T1.class)
res = q.getResultList()
for(o in res) {
println("${o.f1} ${o.f2}")
}
em.close()
emf.close()
Build and run - Windows:
call %GROOVY%\bin\groovyc -cp hibernate-jpa-2.0-api-1.0.0.Final.jar MySQLX.groovy T1.groovy
java -cp .;%GROOVY%\lib\*;%HIBPATH%;mysql-connector-java-5.1.36-bin.jar MySQLX
T1.java:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="t1")
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;
}
@Id
@Column(name="f1")
public int getF1() {
return f1;
}
public void setF1(int f1) {
this.f1 = f1;
}
@Column(name="f2")
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
}
jmysqlx.py:
from java.util.logging import Level
from java.util.logging import Logger
from javax.persistence import Persistence
import T1
print("MySQL from JVM Python (JPA)")
# disable Hibernate logging (outcomment for debugging)
Logger.getLogger("org.hibernate").setLevel(Level.OFF)
emf = Persistence.createEntityManagerFactory("MySQL")
em = emf.createEntityManager()
q = em.createQuery("SELECT o FROM T1 AS o", T1)
res = q.getResultList();
for o in res:
print('%d %s' % (o.f1, o.f2))
em.close()
emf.close()
Jython (JVM Python) can use standard Python DB API 2.0 to access a database via the zxJDBC module and a standard JDBC driver.
jmysqlz.py:
from com.ziclix.python.sql import zxJDBC
print('MySQL from JVM Python (DB API 2.0 via zxJDBC)')
con = zxJDBC.connect('jdbc:mysql://192.168.0.10:3306/test', 'root', '', 'com.mysql.jdbc.Driver')
c = con.cursor()
c.execute('SELECT f1,f2 FROM t1')
data = c.fetchall()
c.close()
for row in data:
print('%d %s' % (row[0], row[1]))
con.close()
ADO.NET is .NET basic database API.
MySQL provides an ADO.NET provider called MySQL Connector/.NET.
For details on ADO.NET API including SQL updates, parameters and how to make the code database independent see here.
mysql1.cs:
using System;
using MySql.Data.MySqlClient;
public class Program
{
public static void Main(String[] args)
{
Console.WriteLine("MySQL from C# (ADO.NET)");
using(MySqlConnection con = new MySqlConnection("Server=192.168.0.10;Port=3306;Database=test;User Id=root;Password="))
{
con.Open();
using(MySqlCommand cmd = new MySqlCommand("SELECT f1,f2 FROM t1", con))
{
using(MySqlDataReader rdr = cmd.ExecuteReader())
{
while(rdr.Read())
{
Console.WriteLine((int)rdr["f1"] + " " + (string)rdr["f2"]);
}
}
}
}
}
}
Build and run - Windows:
csc /r:MySql.Data.dll mysql1.cs
mysql1
mysql1.vb:
Imports System
Imports MySql.Data.MySqlClient
Public Class Program
Public Shared Sub Main(args As [String]())
Console.WriteLine("MySQL from VB.NET (ADO.NET)")
Using con As New MySqlConnection("Server=192.168.0.10;Port=3306;Database=test;User Id=root;Password=")
con.Open()
Using cmd As New MySqlCommand("SELECT f1,f2 FROM t1", con)
Using rdr As MySqlDataReader = cmd.ExecuteReader()
While rdr.Read()
Console.WriteLine(rdr("f1") & " " & rdr("f2"))
End While
End Using
End Using
End Using
End Sub
End Class
Build and run - Windows:
vbc /r:MySql.Data.dll mysql1.vb
mysql1
ADO.NET can use an ODBC driver.
MySQL provides an ODBC driver called MySQL Connector/ODBC that needs to be installed.
The example assumes a DSN has been defined in ODBC manager.
It is strongly recommended using the databases ADO.NET provider instead of the ODBC driver. Mixing .NET and native for database access is not optimal.
mysql2.cs:
using System;
using System.Data.Odbc;
public class Program
{
public static void Main(String[] args)
{
Console.WriteLine("MySQL from C# (ODBC)");
using(OdbcConnection con = new OdbcConnection("Dsn=ARNE1_MYSQL"))
{
con.Open();
using(OdbcCommand cmd = new OdbcCommand("SELECT f1,f2 FROM t1", con))
{
using(OdbcDataReader rdr = cmd.ExecuteReader())
{
while(rdr.Read())
{
Console.WriteLine((int)rdr["f1"] + " " + (string)rdr["f2"]);
}
}
}
}
}
}
Build and run - Windows:
csc mysql2.cs
mysql2
mysql2.vb:
Imports System
Imports System.Data.Odbc
Public Class Program
Public Shared Sub Main(args As [String]())
Console.WriteLine("MySQL from VB.NET (ODBC)")
Using con As New OdbcConnection("Dsn=ARNE1_MYSQL")
con.Open()
Using cmd As New OdbcCommand("SELECT f1,f2 FROM t1", con)
Using rdr As OdbcDataReader = cmd.ExecuteReader()
While rdr.Read()
Console.WriteLine(rdr("f1") & " " & rdr("f2"))
End While
End Using
End Using
End Using
End Sub
End Class
Build and run - Windows:
vbc mysql2.vb
mysql2
Entity Framework (EF) is a common ORM for .NET.
MySQL Connector/.NET supports EF.
For details on EF including updates and parameters see here.
Note that the version of MySQL Connector/.NET EF and the version of core EF need to match. I got MySQL Connector/.NET version 6.9.9 with EntityFramework version 6.2.0 working. I strongly recommend using NuGet to get a consistent pair.
The example will use code first approach.
mysql1x.exe.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<add name="MySQL" connectionString="Server=192.168.0.10;Database=test;User Id=root;Password=" providerName="MySql.Data.MySqlClient" />
</connectionStrings>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework"/>
<providers>
<provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6"/>
</providers>
</entityFramework>
</configuration>
mysql1x.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
[Table("t1")]
public class T1
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Column("f1")]
public int F1 { get; set; }
[Column("f2")]
public string F2 { get; set; }
}
public class MySqlDbContext : DbContext
{
public MySqlDbContext() : base("MySQL")
{
}
public DbSet<T1> T1 { get; set; }
}
public class Program
{
public static void Main(String[] args)
{
Console.WriteLine("MySQL from C# (EF)");
using(MySqlDbContext db = new MySqlDbContext())
{
List<T1> res = db.T1.ToList();
foreach(T1 o in res)
{
Console.WriteLine(o.F1 + " " + o.F2);
}
}
}
}
Build and run - Windows:
csc /r:System.ComponentModel.DataAnnotations.dll /r:EntityFramework.dll mysql1x.cs
mysql1x
mysql1x.vb:
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel.DataAnnotations
Imports System.ComponentModel.DataAnnotations.Schema
Imports System.Data.Entity
Imports System.Linq
<Table("t1")> _
Public Class T1
<Key> _
<DatabaseGenerated(DatabaseGeneratedOption.None)> _
<Column("f1")> _
Public Property F1() As Integer
<Column("f2")> _
Public Property F2() As String
End Class
Public Class MySqlDbContext
Inherits DbContext
Public Sub New()
MyBase.New("MySQL")
End Sub
Public Property T1() As DbSet(Of T1)
End Class
Public Class Program
Public Shared Sub Main(args As [String]())
Console.WriteLine("MySQL from VB.NET (EF)")
Using db As New MySqlDbContext()
Dim res As List(Of T1) = db.T1.ToList()
For Each o As T1 In res
Console.WriteLine(o.F1 & " " & o.F2)
Next
End Using
End Sub
End Class
Build and run - Windows:
vbc /r:System.ComponentModel.DataAnnotations.dll /r:EntityFramework.dll mysql1x.vb
mysql1x
A DB API 2.0 compliant pymysql module can be installed via pip.
For details on DB API 2.0 including SQL updates and parameters see here.
mysql.py:
import pymysql
print('MySQL from Python')
con = pymysql.connect(host='192.168.0.10',user='root',password='',db='test')
c = con.cursor()
c.execute('SELECT f1,f2 FROM t1')
data = c.fetchall()
c.close()
for row in data:
print('%d %s' % (row[0], row[1]))
con.close()
Options for Jython (JVM Python) are described under JVM languages.
PHP comes with mysqli extension to connect to MySQL.
For details on mysqli API including SQL updates and parameters see here.
mysql1.php:
<?php
echo "MySQL from PHP (mysqli)\r\n";
$con = mysqli_connect('192.168.0.10', 'root', '', 'test');
$stmt = mysqli_prepare($con, 'SELECT f1,f2 FROM t1');
mysqli_stmt_execute($stmt);
$rs = mysqli_stmt_get_result($stmt);
while($row = mysqli_fetch_array($rs, MYSQLI_ASSOC)) {
$f1 = $row['f1'];
$f2 = $row['f2'];
echo "$f1 $f2\r\n";
}
mysqli_stmt_close($stmt);
mysqli_close($con);
?>
PHP has a standard database API called PDO.
PDO supports MySQL.
For details on PDO API and MySQL including SQL updates and parameters see here.
mysql1p.php:
<?php
echo "MySQL from PHP (PDO,mysql)\r\n";
$con = new PDO('mysql:host=192.168.0.10;dbname=test', 'root', '');
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$con->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$stmt = $con->prepare('SELECT f1,f2 FROM t1');
$stmt->execute(array());
while($row = $stmt->fetch()) {
$f1 = $row['f1'];
$f2 = $row['f2'];
echo "$f1 $f2\r\n";
}
?>
PHP supports ODBC.
Oracle provides an ODBC driver for Rdb that needs to be installed.
The example assumes a DSN has been defined in ODBC manager.
mysql2.php:
<?php
echo "MySQL from PHP (ODBC)\r\n";
$con = odbc_connect('ARNE1_MYSQL', '', '');
$stmt = odbc_prepare($con, 'SELECT f1,f2 FROM t1');
odbc_execute($stmt, array());
while(odbc_fetch_row($stmt)){
$f1 = odbc_result($stmt, 'f1');
$f2 = odbc_result($stmt, 'f2');
echo "$f1 $f2\r\n";
}
odbc_free_result($stmt);
odbc_close($con);
?>
PHP has a standard database API called PDO.
PDO supports ODBC.
Oracle provides an ODBC driver for Rdb that needs to be installed.
The example assumes a DSN has been defined in ODBC manager.
mysql2p.php:
<?php
echo "MySQL from PHP (PDO,ODBC)\r\n";
$con = new PDO('odbc:DSN=ARNE1_MYSQL;UID=;PWD=');
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$con->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$stmt = $con->prepare('SELECT f1,f2 FROM t1');
$stmt->execute(array());
while($row = $stmt->fetch()) {
$f1 = $row['f1'];
$f2 = $row['f2'];
echo "$f1 $f2\r\n";
}
?>
VBS supports ADO and ADO can use an ODBC driver.
MySQL provides an ODBC driver called MySQL Connector/ODBC that needs to be installed.
The example assumes a DSN has been defined in ODBC manager.
WScript.Echo "MySQL from VBS (ODBC)"
Set con = CreateObject("ADODB.Connection")
con.Open "Dsn=ARNE1_MYSQL;"
Set cmd = CreateObject("ADODB.Command")
cmd.ActiveConnection = con
cmd.CommandText = "SELECT f1,f2 FROM t1"
Set rs = cmd.Execute
Do While Not rs.EOF
WScript.Echo rs("f1") & " " & rs("f2")
rs.MoveNext
Loop
Set rs = Nothing
Set cmd = Nothing
Set con = Nothing
SQLite is an open source embedded database first released in 2000.
It is available for VMS.
I consider SQLite to be more of an alternative to index-sequential files than to RDB and MySQL/MariaDB.
Since it is an embedded database then a database on VMS can only be used on VMS.
Note though that a database on VMS can be transferred to PC and used there as the on disk format is standardized across platforms.
SQLite uses a traditional embedded database architecture with all client application accessing a database directly:
SQLite comes with a standard C API.
sqlite.c:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sqlite3.h"
int main()
{
sqlite3 *con;
sqlite3_stmt *ins, *sel;
char *sqlstr = "SELECT f1,f2 FROM t1";
int stat;
printf("SQLite from C\n");
stat = sqlite3_open("test.db", &con);
stat = sqlite3_prepare(con, sqlstr, strlen(sqlstr), &sel, NULL);
while(sqlite3_step(sel) == SQLITE_ROW)
{
printf("%d %s\n", sqlite3_column_int(sel, 0), sqlite3_column_text(sel, 1));
}
sqlite3_finalize(sel);
sqlite3_close(con);
return 0;
}
Build and run - VMS:
$ cc/include=sqlite3_include: sqlite.c
$ link sqlite + sys$input/opt
sqlite3shr/share
$
$ run sqlite
Due to VMS calling convention it is possible to call the standard C API from Pascal.
To make it a little easier I have created a wrapper psqlite that are also open source and can be downloaded here.
sqlite.pas:
[inherit('psqlitedir:sqlite', 'psqlitedir:psqlite')]
program sqlite(input, output);
var
con : sqlite_ptr;
sel : sqlite_stmt_ptr;
begin
writeln('SQLite from Pascal (PSQLITE)');
con := psqlite_open('test.db');
sel := psqlite_prepare(con, 'SELECT f1,f2 FROM t1');
while psqlite_step_query(sel) do begin
writeln(psqlite_column_int(sel, 0), ' ', psqlite_column_text(sel, 1));
end;
psqlite_finalize(sel);
psqlite_close(con);
end.
Build and run - VMS:
$ pas sqlite
$ link sqlite + sys$input/opt + psqlitedir:sqlite/opt
psqlitedir:psqlite
psqlitedir:sqlite
$
$ run sqlite
A JDBC driver for SQLite is available.
Note that it is a type 2 JDBC driver aka it uses native code via JNI, so it is necessary to get a special VMS distribution of the JDBC driver.
SQLite.java:
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
public class SQLite {
public static void main(String[] args) throws Exception {
System.out.println("SQLite from Java (JDBC)");
Class.forName("org.sqlite.JDBC");
Connection con = DriverManager.getConnection("jdbc:sqlite:test.db");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT f1,f2 FROM t1");
while(rs.next()) {
int f1 = rs.getInt(1);
String f2 = rs.getString(2);
System.out.println(f1 + " " + f2);
}
rs.close();
stmt.close();
con.close();
}
}
Build and run - VMS:
$ javac SQLite.java
$ define/nolog java$filename_controls 8
$ define/nolog decc$efs_charset true
$ java -cp .:/javalib/sqlite-jdbc-3_14_1-vms.jar "SQLite"
jsqlite.py:
from java.lang import Class
from java.sql import DriverManager
from org.sqlite import JDBC # replaces Class.forName('org.sqlite.JDBC')
print('SQLite from JVM Python (JDBC)')
con = DriverManager.getConnection('jdbc:sqlite:test.db')
stmt = con.createStatement()
rs = stmt.executeQuery('SELECT f1,f2 FROM t1')
while rs.next():
f1 = rs.getInt(1)
f2 = rs.getString(2)
print(str(f1) + ' ' + f2)
rs.close()
stmt.close()
con.close()
jsqlite.js:
importClass(Packages.java.lang.Class);
importClass(Packages.java.sql.DriverManager);
print("SQLite from JVM JavaScript (JDBC)")
new Packages.org.sqlite.JDBC(); //replaces Class.forName("org.sqlite.JDBC");
con = DriverManager.getConnection("jdbc:sqlite:test.db");
stmt = con.createStatement();
rs = stmt.executeQuery("SELECT f1,f2 FROM t1");
while(rs.next()) {
f1 = rs.getInt(1);
f2 = rs.getString(2);
print(f1 + " " + f2);
}
rs.close();
stmt.close();
con.close();
Jython (JVM Python) can use standard Python DB API 2.0 to access a database via the zxJDBC module and a standard JDBC driver.
jsqlitez.py:
from java.lang import Class
from java.sql import DriverManager
from org.sqlite import JDBC # replaces Class.forName('org.sqlite.JDBC')
print('SQLite from JVM Python (JDBC)')
con = DriverManager.getConnection('jdbc:sqlite:test.db')
stmt = con.createStatement()
rs = stmt.executeQuery('SELECT f1,f2 FROM t1')
while rs.next():
f1 = rs.getInt(1)
f2 = rs.getString(2)
print(str(f1) + ' ' + f2)
rs.close()
stmt.close()
con.close()
Python comes with a DB API 2.0 compliant sqlite3 module.
For details on DB API 2.0 including SQL updates and parameters see here.
sqlite.py:
import sqlite3
print('SQLite from Python')
con = sqlite3.connect('test.db')
c = con.cursor()
c.execute('SELECT f1,f2 FROM t1')
for row in c.fetchall():
print('%d %s' % (row[0], row[1]))
con.commit()
con.close()
Options for Jython (JVM Python) are described under JVM languages.
sqlite.php:
<?php
echo "SQLite from PHP (sqlite3)\r\n";
$con = new SQLite3('/disk2/arne/db/test.db');
$q = $con->query('SELECT f1,f2 FROM t1');
while($row = $q->fetchArray()) {
$f1 = $row['f1'];
$f2 = $row['f2'];
echo "$f1 $f2\r\n";
}
$con->close();
?>
sqlitep.php:
<?php
echo "MySQL from PHP (PDO,sqlite)\r\n";
$con = new PDO('sqlite:/disk2/arne/db/test.db');
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$con->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$stmt = $con->prepare('SELECT f1,f2 FROM t1');
$stmt->execute(array());
while($row = $stmt->fetch()) {
$f1 = $row['f1'];
$f2 = $row['f2'];
echo "$f1 $f2\r\n";
}
?>
Mimer is a relational database with a long history originally developed at Uppsala University an transferred to a commercial entity in 1984.
It is available for VMS, Windows, Linux and macOS.
It is not a database with a high media profile, but it is used in various industrial segments.
Mimer supports traditional embedded SQL including C.
The precompiler gets installed with the Mimer installation.
mimer1.ec:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
EXEC SQL INCLUDE SQLCA;
int main()
{
EXEC SQL BEGIN DECLARE SECTION;
char con[256];
char usr[256];
char pwd[256];
char f2[51];
long int f1;
EXEC SQL END DECLARE SECTION;
printf("Mimer from C (embedded)\n");
strcpy(con, "test");
strcpy(usr, "SYSADM");
strcpy(pwd, "hemmeligt");
EXEC SQL CONNECT TO :con USER :usr USING :pwd;
EXEC SQL DECLARE curs CURSOR FOR SELECT f1,f2 FROM t1;
EXEC SQL OPEN curs;
for(;;)
{
EXEC SQL FETCH curs INTO :f1, :f2;
if(sqlca.sqlcode != 0) break;
printf("%d %s\n", f1, f2);
}
EXEC SQL CLOSE curs;
return 0;
}
Build and run - VMS:
$ esql/c mimer1
$ cc mimer1
$ link mimer1 + sys$input/opt
mimlib9:lr/lib
mimlib9:mdr/lib
mimlib9:mimdb9/share
$
$ run mimer1
An ODBC driver for Mimer is available.
Standard ODBC API. For details on ODBC API including SQL updates, parameters and error handling see here.
The example assumes a DSN has been defined in ODBC manager.
mimer2.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <sql.h>
#include <sqlext.h>
#define F2_MAX_LEN 50
static const char *dsn = "ARNE1_MIMER";
static const char *un = "SYSADM";
static const char *pw = "hemmeligt";
int main()
{
SQLHENV env;
SQLHDBC con;
SQLHSTMT stmt;
long int f1;
char *sqlstr, f2[F2_MAX_LEN + 1];
SQLLEN lenf2;
int stat;
printf("Mimer from C (ODBC)\n");
stat = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
stat = SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);
stat = SQLAllocHandle(SQL_HANDLE_DBC, env, &con);
stat = SQLConnect(con, (SQLCHAR *)dsn, (SQLSMALLINT)strlen(dsn),
(SQLCHAR *)un, (SQLSMALLINT)strlen(un),
(SQLCHAR *)pw, (SQLSMALLINT)strlen(pw));
sqlstr = "SELECT f1,f2 FROM t1";
stat = SQLAllocHandle(SQL_HANDLE_STMT, con, &stmt);
stat = SQLExecDirect(stmt, (SQLCHAR *)sqlstr, strlen(sqlstr));
stat = SQLBindCol(stmt, 1, SQL_C_LONG, &f1, 0, NULL);
stat = SQLBindCol(stmt, 2, SQL_C_CHAR, f2, sizeof(f2), &lenf2);
for(;;)
{
stat = SQLFetch(stmt);
if((stat != SQL_SUCCESS) && (stat != SQL_SUCCESS_WITH_INFO)) break;
f2[lenf2] = 0;
printf("%ld %s\n", f1, f2);
}
SQLCloseCursor(stmt);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
SQLDisconnect(con);
SQLFreeHandle(SQL_HANDLE_DBC, con);
SQLFreeHandle(SQL_HANDLE_ENV, env);
return 0;
}
Build and run - Windows:
gcc mimer2.c -lodbc32 -o mimer2.exe
mimer2
FPC comes with SQLDB unit for database access. SQLDB supports ODBC.
An ODBC driver for Mimer is available.
For details on SQLDB API including SQL updates, parameters and error handling see here.
The example assumes a DSN has been defined in ODBC manager.
mimer2.pas:
program mimer2(input, output);
uses
SQLDB, ODBCConn;
var
con : TSQLConnection;
tx : TSQLTransaction;
q : TSQLQuery;
f1 : integer;
f2 : string;
begin
writeln('Mimer from Pascal (SQLDB, ODBC)');
con := TODBCConnection.Create(nil);
con.DatabaseName := 'ARNE1_MIMER';
con.UserName := 'SYSADM';
con.Password := 'hemmeligt';
con.Open;
tx := TSQLTransaction.Create(nil);
con.Transaction := tx;
q := TSQLQuery.Create(nil);
q.DataBase := con;
q.SQL.Text := 'SELECT f1,f2 FROM t1';
q.Open;
while not q.EOF do begin
f1 := q.FieldByName('f1').AsInteger;
f2 := q.FieldByName('f2').AsString;
writeln(f1, ' ', f2);
q.Next;
end;
q.Close;
q.Free;
con.Close;
con.Free;
end.
Build and run - Windows:
fpc mimer2.pas
mimer2
Mimer supports traditional embedded SQL and on VMS Fortran.
The precompiler gets installed with the Mimer installation.
mimer1.efo:
PROGRAM MIMER1
EXEC SQL INCLUDE SQLCA
EXEC SQL DECLARE curs CURSOR FOR SELECT f1,f2 FROM t1
EXEC SQL BEGIN DECLARE SECTION
CHARACTER*255 CON
CHARACTER*255 USR
CHARACTER*255 PWD
INTEGER*4 F1
CHARACTER*50 F2
EXEC SQL END DECLARE SECTION
WRITE(*,*) 'Mimer from Fortran (embedded)'
CON = 'test'
USR = 'SYSADM'
PWD = 'hemmeligt'
EXEC SQL CONNECT TO :CON USER :USR USING :PWD
EXEC SQL OPEN curs
100 EXEC SQL FETCH curs INTO :f1, :f2
IF(SQLCOD.EQ.0) THEN
WRITE(*,*) F1, ' ', F2
GOTO 100
ENDIF
EXEC SQL CLOSE curs
END
Build and run - VMS:
$ esql/fortran mimer1
$ fortran mimer1
$ link mimer1 + sys$input/opt
mimlib9:lr/lib
mimlib9:mdr/lib
mimlib9:mimdb9/share
$
$ run mimer1
Mimer supports traditional embedded SQL and on VMS Cobol.
The precompiler gets installed with the Mimer installation.
mimer1.eco:
IDENTIFICATION DIVISION.
PROGRAM-ID. MIMER1.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
EXEC SQL INCLUDE SQLCA END-EXEC.
EXEC SQL BEGIN DECLARE SECTION END-EXEC.
01 CON PIC X(255).
01 USR PIC X(255).
01 PWD PIC X(255).
01 F1 PIC S9(9) BINARY.
01 F2 PIC X(50).
EXEC SQL END DECLARE SECTION END-EXEC.
01 TEMP PIC 9(9) DISPLAY.
EXEC SQL DECLARE curs CURSOR FOR SELECT f1,f2 FROM t1 END-EXEC.
PROCEDURE DIVISION.
MAIN-PARAGRAPH.
DISPLAY "Mimer from Cobol (embedded)"
MOVE "test" TO CON
MOVE "SYSADM" TO USR
MOVE "hemmeligt" TO PWD
EXEC SQL CONNECT TO :CON USER :USR USING :PWD END-EXEC
EXEC SQL OPEN curs END-EXEC
MOVE 0 TO SQLCODE
PERFORM UNTIL NOT SQLCODE = 0
EXEC SQL FETCH curs INTO :f1, :f2 END-EXEC
IF SQLCODE = 0 THEN
MOVE F1 TO TEMP
DISPLAY TEMP " " F2
END-IF
END-PERFORM
EXEC SQL CLOSE curs END-EXEC
STOP RUN.
Build and run - VMS:
$ esql/cobol mimer1
$ cobol/ansi mimer1
$ link mimer1 + sys$input/opt
mimlib9:lr/lib
mimlib9:mdr/lib
mimlib9:mimdb9/share
$
$ run mimer1
JDBC is Java basic database API.
Mimer comes with a JDBC driver that supports both access to local databases and access to databases over network.
Here we will look at local access.
For details on JDBC API including SQL updates and parameters see here.
Mimer1.java:
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
public class Mimer1 {
public static void main(String[] args) throws Exception {
System.out.println("Mimer from Java (JDBC,local)");
Class.forName("com.mimer.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mimer:/test", "SYSADM", "hemmeligt");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT f1,f2 FROM t1");
while(rs.next()) {
int f1 = rs.getInt(1);
String f2 = rs.getString(2);
System.out.println(f1 + " " + f2);
}
rs.close();
stmt.close();
con.close();
}
}
Build and run - VMS:
$ javac Mimer1.java
$ java -cp .:/javalib/mimjdbc3.jar "Mimer1"
JDBC is Java basic database API.
Mimer comes with a JDBC driver that supports both access to local databases and access to databases over network.
Here we will look at access over network.
For details on JDBC API including SQL updates and parameters see here.
Mimer2.java:
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
public class Mimer2 {
public static void main(String[] args) throws Exception {
System.out.println("Mimer from Java (JDBC,network)");
Class.forName("com.mimer.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mimer://SYSADM:hemmeligt@192.168.0.10:1360/test");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT f1,f2 FROM t1");
while(rs.next()) {
int f1 = rs.getInt(1);
String f2 = rs.getString(2);
System.out.println(f1 + " " + f2);
}
rs.close();
stmt.close();
con.close();
}
}
Build and run - Windows:
javac Mimer2.java
java -cp .;\DivJava\mimjdbc3.jar Mimer2
Build and run - VMS:
$ javac Mimer2.java
$ java -cp .:/javalib/mimjdbc3.jar "Mimer2"
ADO.NET is .NET basic database API.
An ADO.NET provider for Mimer is available.
For details on ADO.NET API including SQL updates, parameters and how to make the code database independent see here.
mimer1.cs:
using System;
using Mimer.Data.Client;
public class Program
{
public static void Main(String[] args)
{
Console.WriteLine("Mimer from C# (ADO.NET)");
using(MimerConnection con = new MimerConnection("Node=192.168.0.10;Service=1360;Database=test;User Id=SYSADM;Password=hemmeligt"))
{
con.Open();
using(MimerCommand cmd = new MimerCommand("SELECT f1,f2 FROM t1", con))
{
using(MimerDataReader rdr = cmd.ExecuteReader())
{
while(rdr.Read())
{
Console.WriteLine((int)rdr["f1"] + " " + (string)rdr["f2"]);
}
}
}
}
}
}
Build and run - Windows:
csc /r:Mimer.Data.Client.dll mimer1.cs
mimer1
mimer1.vb:
Imports System
Imports Mimer.Data.Client
Public Class Program
Public Shared Sub Main(args As [String]())
Console.WriteLine("Mimer from VB.NET (ADO.NET)")
Using con As New MimerConnection("Node=192.168.0.10;Service=1360;Database=test;User Id=SYSADM;Password=hemmeligt")
con.Open()
Using cmd As New MimerCommand("SELECT f1,f2 FROM t1", con)
Using rdr As MimerDataReader = cmd.ExecuteReader()
While rdr.Read()
Console.WriteLine(rdr("f1") & " " & rdr("f2"))
End While
End Using
End Using
End Using
End Sub
End Class
Build and run - Windows:
vbc /r:Mimer.Data.Client.dll mimer1.vb
mimer1
ADO.NET can use an ODBC driver.
An ODBC driver for Mimer is available.
The example assumes a DSN has been defined in ODBC manager.
It is strongly recommended using the databases ADO.NET provider instead of the ODBC driver. Mixing .NET and native for database access is not optimal.
mimer2.cs:
using System;
using System.Data.Odbc;
public class Program
{
public static void Main(String[] args)
{
Console.WriteLine("Mimer from C# (ODBC)");
using(OdbcConnection con = new OdbcConnection("Dsn=ARNE1_MIMER;Uid=SYSADM;Pwd=hemmeligt"))
{
con.Open();
using(OdbcCommand cmd = new OdbcCommand("SELECT f1,f2 FROM t1", con))
{
using(OdbcDataReader rdr = cmd.ExecuteReader())
{
while(rdr.Read())
{
Console.WriteLine((int)rdr["f1"] + " " + (string)rdr["f2"]);
}
}
}
}
}
}
Build and run - Windows:
csc mimer2.cs
mimer2
mimer2.vb:
Imports System
Imports System.Data.Odbc
Public Class Program
Public Shared Sub Main(args As [String]())
Console.WriteLine("Mimer from VB.NET (ODBC)")
Using con As New OdbcConnection("Dsn=ARNE1_MIMER;Uid=SYSADM;Pwd=hemmeligt")
con.Open()
Using cmd As New OdbcCommand("SELECT f1,f2 FROM t1", con)
Using rdr As OdbcDataReader = cmd.ExecuteReader()
While rdr.Read()
Console.WriteLine(rdr("f1") & " " & rdr("f2"))
End While
End Using
End Using
End Using
End Sub
End Class
Build and run - Windows:
vbc mimer2.vb
mimer2
PHP supports ODBC.
An ODBC driver for Mimer is available.
The example assumes a DSN has been defined in ODBC manager.
mimer2.php:
<?php
echo "Mimer from PHP (ODBC)\r\n";
$con = odbc_connect('ARNE1_MIMER', 'SYSADM', 'hemmeligt');
$stmt = odbc_prepare($con, 'SELECT f1,f2 FROM t1');
odbc_execute($stmt, array());
while(odbc_fetch_row($stmt)){
$f1 = odbc_result($stmt, 'f1');
$f2 = odbc_result($stmt, 'f2');
echo "$f1 $f2\r\n";
}
odbc_free_result($stmt);
odbc_close($con);
?>
PHP has a standard database API called PDO.
PDO supports ODBC.
An ODBC driver for Mimer is available.
The example assumes a DSN has been defined in ODBC manager.
mimer2p.php:
<?php
echo "Mimer from PHP (PDO,ODBC)\r\n";
$con = new PDO('odbc:DSN=ARNE1_MIMER;UID=SYSADM;PWD=hemmeligt');
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$con->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$stmt = $con->prepare('SELECT f1,f2 FROM t1');
$stmt->execute(array());
while($row = $stmt->fetch()) {
$f1 = $row['F1']; // note uppercase field names
$f2 = $row['F2'];
echo "$f1 $f2\r\n";
}
?>
VBS supports ADO and ADO can use an ODBC driver.
An ODBC driver for Mimer is available.
The example assumes a DSN has been defined in ODBC manager.
mimer.vbs:
WScript.Echo "Mimer from VBS (ODBC)"
Set con = CreateObject("ADODB.Connection")
con.Open "Dsn=ARNE1_MIMER;Uid=SYSADM;Pwd=hemmeligt"
Set cmd = CreateObject("ADODB.Command")
cmd.ActiveConnection = con
cmd.CommandText = "SELECT f1,f2 FROM t1"
Set rs = cmd.Execute
Do While Not rs.EOF
WScript.Echo rs("f1") & " " & rs("f2")
rs.MoveNext
Loop
Set rs = Nothing
Set cmd = Nothing
Set con = Nothing
RMS index-sequential files are covered here.
Version | Date | Description |
---|---|---|
1.0 | September 16th 2020 | Initial version |
1.1 | September 28th 2020 | Add SQLite section |
1.2 | October 11th 2020 | Add Jython and Rhino examples |
1.3 | November 1st 2020 | Add Mimer section |
1.4 | May 11th 2021 | Add RDB VMS Python examples |
1.5 | July 22nd 2022 | Add C SQL Services example |
See list of all articles here
Please send comments to Arne Vajhøj