As part of application modernization for VMS applications then one thing to consider is migrating from RMS index-sequential files to a relational database.
It is not a given that the migration should happen. RMS index-sequential files are really a NoSQL Key Value Store database and such databases are widely used today.
But relational database has become the default choice. In 1991 it may have been: chose RMS index-sequential file unless there are requirements that mandates a relational database. In 2021 is is: chose a relational database unless there are requirements that mandates a NoSQL Key Value Store.
The benefits of using a relational database are usually big:
For more details on benefits and non-benefits see VMS: Index-sequential file vs relational database.
For most usages of RMS index-sequential files then SQLite will be the most obvious choice for relational database. It is an embedded database so no database server to manage.
But if access is highly concurrent or there is a desire to make the database accessble over the network, then it may make more sense to go with a database server (Rdb, MySQL-MariaDB, Mimer etc.). See Access VMS database - native databases and Access VMS database - JVM databases for more info on what is available.
The examples will use SQLite as database.
The conversion can obviously be written in any language that can access both RMS index-sequential files and SQLite.
But the approach chosen is a declarative mapping approach. Instead of reading a record, parsing the record and executing a SQL INSERT statement then records get mapped to a class, another class get mapped to the tables and conversion between the two classes get auto mapped based on property names. The actual conversion code becomes trivial.
The language combo to make that happen is Java and Python with the Python code running in the JVM via Jython.
For mapping to the RMS index-sequential files my ISAM library is used.
For mapping to SQLite standard JPA with Hibernate as implementation is used. For more info about JPA see Java Database Access.
This article will show 4 examples:
For each example will the following be shown:
Cobol and Pascal before code will use built-in index-sequential file support. For intro see VMS index-sequential files.
C after code will use standard SQLite C library. For another example see here.
Pascal after code will use my PSQLite library. For another example see here.
Python and PHP after code will use standard SQLite drivers. For more examples see here and here.
Java affter code will use standard SQLite JDBC driver (which is type 2). For another example see here.
For JPA Hibernate 3 will be used.
Most readers will not find everything relevant, but most readers should find something relevant. If anyone is reading all the code then there will be a lot of repetitive stuff, but the article is written to make it readable for those only reading one or two examples in one or two languages.
The mapping is done using annotations on a data class.
The main annotations are:
So if we have a record with one 32 bit integer and one fixed length text field with 10 bytes then it can be mapped to:
import dk.vajhoej.isam.KeyField;
import dk.vajhoej.record.FieldType;
import dk.vajhoej.record.Struct;
import dk.vajhoej.record.StructField;
@Struct
public class Something {
@KeyField(n=0)
@StructField(n=0, type=FieldType.INT4)
public int id;
@StructField(n=1, type=FieldType.FIXSTR, length=10)
public String strval;
}
And when using Java style with private fields and public getters/setters:
import dk.vajhoej.isam.KeyField;
import dk.vajhoej.record.FieldType;
import dk.vajhoej.record.Struct;
import dk.vajhoej.record.StructField;
@Struct
public class Something {
@KeyField(n=0)
@StructField(n=0, type=FieldType.INT4)
private int id;
@StructField(n=1, type=FieldType.FIXSTR, length=10)
private String strval;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getSval() {
return sval;
}
public void setSval(String sval) {
this.sval = sval;
}
}
Reading records in Jython is easy:
from dk.vajhoej.isam import Key0
from dk.vajhoej.isam.local import LocalIsamSource
import Something
db = LocalIsamSource(filename, 'dk.vajhoej.vms.rms.IndexSequential', False)
it = db.readGE(AddressISAM, Key0(0))
while it.read():
rec = it.current()
...
it.close()
db.close()
The mapping is done using annotations on a data class.
The main annotations are:
So the class:
public class Something {
private int id;
private String strval;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getSval() {
return sval;
}
public void setSval(String sval) {
this.sval = sval;
}
}
will look like:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="something")
public class Something {
private int id;
private String strval;
@Id
@Column(name="id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name="sval")
public String getSval() {
return sval;
}
public void setSval(String sval) {
this.sval = sval;
}
}
Persisting object in Jython is easy:
from javax.persistence import Persistence
import Something
emf = Persistence.createEntityManagerFactory(database)
em = emf.createEntityManager()
...
rec = Something();
...
em.persist(rec)
...
em.close()
emf.close()
The database (name, database driver, database URL, database credential etc.) get defined in META-INF/persistence.xml.
The auto mapping is trivial using Java reflection - iterate all properties in FROM class and TO class and create list of pairs of getters and setters for properties with same name.
The calling code in Jython looks like:
import X
import Y
import AutoMap
mapper = AutoMap(X, Y)
xrec = X()
yrec = Y()
mapper.convert(xrec, yrec)
Before records:
id | name | address |
---|---|---|
1 | A A | A Road 11 |
2 | B B | B Road 22 |
After database tables:
address
id | name | address |
---|---|---|
1 | A A | A Road 11 |
2 | B B | B Road 22 |
IDENTIFICATION DIVISION.
PROGRAM-ID.INSERT-BEFORE-1.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT OPTIONAL ADDRESS-FILE ASSIGN TO "address.isq" ORGANIZATION IS INDEXED ACCESS MODE IS DYNAMIC RECORD KEY IS ADDRESS-ID.
DATA DIVISION.
FILE SECTION.
FD ADDRESS-FILE.
01 ADDRESS-RECORD.
03 ADDRESS-ID PIC 9(8) COMP.
03 ADDRESS-NAME PIC X(32).
03 ADDRESS-ADDRESS PIC X(64).
WORKING-STORAGE SECTION.
PROCEDURE DIVISION.
MAIN-PARAGRAPH.
OPEN I-O ADDRESS-FILE
MOVE 1 TO ADDRESS-ID
MOVE "A A" TO ADDRESS-NAME
MOVE "A Road 11" TO ADDRESS-ADDRESS
PERFORM INSERT-PARAGRAPH
MOVE 2 TO ADDRESS-ID
MOVE "B B" TO ADDRESS-NAME
MOVE "B Road 22" TO ADDRESS-ADDRESS
PERFORM INSERT-PARAGRAPH
CLOSE ADDRESS-FILE
STOP RUN.
INSERT-PARAGRAPH.
WRITE ADDRESS-RECORD
INVALID KEY DISPLAY "Error writing"
NOT INVALID KEY CONTINUE
END-WRITE.
Build and run:
$ cob insert_before_1
$ link insert_before_1
$ run insert_before_1
address_isam.pas:
type
address = record
id : [key(0)]unsigned;
name : packed array [1..32] of char;
address : packed array [1..64] of char;
end;
program insert_before_2(input, output);
%include 'address_isam.pas'
var
addr : address;
db : file of address;
begin
open(db, 'address.isq', unknown, organization := indexed, access_method := keyed);
addr.id := 3;
addr.name := 'C C';
addr.address := 'C Road 33';
db^ := addr;
put(db);
addr.id := 4;
addr.name := 'D D';
addr.address := 'D Road 44';
db^ := addr;
put(db);
close(db);
end.
Build and run:
$ pas insert_before_2
$ link insert_before_2
$ run insert_before_2
IDENTIFICATION DIVISION.
PROGRAM-ID.LIST-BEFORE-1.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT OPTIONAL ADDRESS-FILE ASSIGN TO "address.isq" ORGANIZATION IS INDEXED ACCESS MODE IS DYNAMIC RECORD KEY IS ADDRESS-ID.
DATA DIVISION.
FILE SECTION.
FD ADDRESS-FILE.
01 ADDRESS-RECORD.
03 ADDRESS-ID PIC 9(8) COMP.
03 ADDRESS-NAME PIC X(32).
03 ADDRESS-ADDRESS PIC X(64).
WORKING-STORAGE SECTION.
01 EOF-FLAG PIC X.
01 ID PIC 9(8) DISPLAY.
PROCEDURE DIVISION.
MAIN-PARAGRAPH.
OPEN I-O ADDRESS-FILE
MOVE 'N' TO EOF-FLAG
PERFORM UNTIL EOF-FLAG = 'Y'
READ ADDRESS-FILE NEXT
AT END MOVE 'Y' TO EOF-FLAG
NOT AT END PERFORM SHOW-PARAGRAPH
END-READ
END-PERFORM
CLOSE ADDRESS-FILE
STOP RUN.
SHOW-PARAGRAPH.
MOVE ADDRESS-ID TO ID
DISPLAY ID "|" ADDRESS-NAME "|" ADDRESS-ADDRESS.
Build and run:
$ cob list_before_1
$ link list_before_1
$ run list_before_1
address_isam.pas:
type
address = record
id : [key(0)]unsigned;
name : packed array [1..32] of char;
address : packed array [1..64] of char;
end;
program list_before_2(input, output);
%include 'address_isam.pas'
var
addr : address;
db : file of address;
begin
open(db, 'address.isq', unknown, organization := indexed, access_method := keyed);
resetk(db, 0);
while not eof(db) do begin
addr := db^;
writeln(addr.id,'|',addr.name,'|',addr.address);
get(db);
end;
close(db);
end.
Build and run:
$ pas list_before_2
$ link list_before_2
$ run list_before_2
import dk.vajhoej.isam.KeyField;
import dk.vajhoej.record.Alignment;
import dk.vajhoej.record.Endian;
import dk.vajhoej.record.FieldType;
import dk.vajhoej.record.Struct;
import dk.vajhoej.record.StructField;
@Struct(endianess=Endian.LITTLE, alignment=Alignment.ALIGN1)
public class AddressISAM {
@KeyField(n=0)
@StructField(n=0, type=FieldType.INT4)
private int id;
@StructField(n=1, type=FieldType.FIXSTR, length=32)
private String name;
@StructField(n=2, type=FieldType.FIXSTR, length=64)
private String address;
public AddressISAM() {
this(0, "", "");
}
public AddressISAM(int id, String name, String addreess) {
this.id = id;
this.name = name;
this.address = address;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="address")
public class AddressJPA {
private int id;
private String name;
private String address;
public AddressJPA() {
this(0, "", "");
}
public AddressJPA(int id, String name, String address) {
this.id = id;
this.name = name;
this.address = address;
}
@Id
@Column(name="id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name="name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name="address")
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class AutoMap<TFROM,TTO> {
public static class MethodPair {
private Method getter;
private Method setter;
private boolean trim;
public MethodPair(Method getter, Method setter, boolean trim) {
this.getter = getter;
this.setter = setter;
this.trim = trim;
}
public Method getGetter() {
return getter;
}
public Method getSetter() {
return setter;
}
public boolean getTrim() {
return trim;
}
}
private List<MethodPair> conv;
public AutoMap(Class<TFROM> from, Class<TTO> to) throws IntrospectionException {
this(from, to, false);
}
public AutoMap(Class<TFROM> from, Class<TTO> to, boolean trim) throws IntrospectionException {
conv = new ArrayList<MethodPair>();
for(PropertyDescriptor pdfrom : Introspector.getBeanInfo(from).getPropertyDescriptors()) {
for(PropertyDescriptor pdto : Introspector.getBeanInfo(to).getPropertyDescriptors()) {
if(pdfrom.getName().equals(pdto.getName())) {
Method getter = pdfrom.getReadMethod();
Method setter = pdto.getWriteMethod();
if(getter != null && setter != null) {
conv.add(new MethodPair(getter, setter, trim && pdfrom.getPropertyType().equals(String.class)));
}
}
}
}
}
public void convert(TFROM from, TTO to) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
for(MethodPair mp : conv) {
if(mp.getTrim()) {
mp.getSetter().invoke(to, ((String)mp.getGetter().invoke(from)).trim());
} else {
mp.getSetter().invoke(to, mp.getGetter().invoke(from));
}
}
}
}
# stuff for JPA
from java.util.logging import Level
from java.util.logging import Logger
from javax.persistence import Persistence
# stuff for ISAM
from dk.vajhoej.isam import Key0
from dk.vajhoej.isam.local import LocalIsamSource
#input class
import AddressISAM
#output class
import AddressJPA
# auto map
import AutoMap
# open JPA
Logger.getLogger("org.hibernate").setLevel(Level.OFF)
emf = Persistence.createEntityManagerFactory("Address")
em = emf.createEntityManager()
# open ISAM
db = LocalIsamSource('address.isq', 'dk.vajhoej.vms.rms.IndexSequential', False)
# process all records
mapper = AutoMap(AddressISAM, AddressJPA, True)
it = db.readGE(AddressISAM, Key0(0))
em.getTransaction().begin()
while it.read():
oldrec = it.current()
newrec = AddressJPA()
mapper.convert(oldrec, newrec)
em.persist(newrec)
it.close()
em.getTransaction().commit()
# close ISAM
db.close()
# close JPA
em.close()
emf.close()
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="Address">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>AddressJPA</class>
<exclude-unlisted-classes/>
<properties>
<!--<property name="show_sql" value="true"/>-->
<property name="hibernate.connection.driver_class" value="org.sqlite.JDBC"/>
<property name="hibernate.connection.url" value="jdbc:sqlite:address.db"/>
<property name="hibernate.connection.username" value=""/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.dialect" value="org.hibernate.dialect.SQLiteDialect"/>
</properties>
</persistence-unit>
</persistence>
Database structure:
CREATE TABLE address (
id INTEGER NOT NULL,
name VARCHAR(32),
address VARCHAR(64),
PRIMARY KEY(id)
);
address.h:
struct address
{
int id;
char name[33];
char address[65];
};
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sqlite3.h"
#include "address.h"
int main()
{
sqlite3 *con;
sqlite3_stmt *ins;
char *sqlstr = "INSERT INTO address VALUES(?,?,?)";
int stat;
struct address addr;
stat = sqlite3_open("address.db", &con);
stat = sqlite3_prepare(con, sqlstr, strlen(sqlstr), &ins, NULL);
addr.id = 5;
strcpy(addr.name, "E E");
strcpy(addr.address, "E Road 55");
sqlite3_bind_int(ins, 1, addr.id);
sqlite3_bind_text(ins, 2, addr.name, strlen(addr.name), NULL);
sqlite3_bind_text(ins, 3, addr.address, strlen(addr.address), NULL);
stat = sqlite3_step(ins);
sqlite3_finalize(ins);
stat = sqlite3_prepare(con, sqlstr, strlen(sqlstr), &ins, NULL);
addr.id = 6;
strcpy(addr.name, "F F");
strcpy(addr.address, "F Road 66");
sqlite3_bind_int(ins, 1, addr.id);
sqlite3_bind_text(ins, 2, addr.name, strlen(addr.name), NULL);
sqlite3_bind_text(ins, 3, addr.address, strlen(addr.address), NULL);
stat = sqlite3_step(ins);
sqlite3_finalize(ins);
sqlite3_close(con);
return 0;
}
Build and run:
$ cc/include=sqlite3_include: insert_after_1
$ link insert_after_1 + sys$input/opt
sqlite3shr/share
$
$ run insert_after_1
address.pas:
type
address = record
id : unsigned;
name : varying[32] of char;
address : varying[64] of char;
end;
[inherit('psqlitedir:sqlite', 'psqlitedir:psqlite')]
program insert_after_2(input, output);
%include 'address.pas'
var
con : sqlite_ptr;
ins : sqlite_stmt_ptr;
addr : address;
begin
con := psqlite_open('address.db');
ins := psqlite_prepare(con, 'INSERT INTO address VALUES(?,?,?)');
addr.id := 7;
addr.name := 'G G';
addr.address := 'G Road 77';
psqlite_bind_int(ins, 1, addr.id);
psqlite_bind_text(ins, 2, addr.name);
psqlite_bind_text(ins, 3, addr.address);
psqlite_step_nonquery(ins);
psqlite_finalize(ins);
ins := psqlite_prepare(con, 'INSERT INTO address VALUES(?,?,?)');
addr.id := 8;
addr.name := 'H H';
addr.address := 'H Road 88';
psqlite_bind_int(ins, 1, addr.id);
psqlite_bind_text(ins, 2, addr.name);
psqlite_bind_text(ins, 3, addr.address);
psqlite_step_nonquery(ins);
psqlite_finalize(ins);
psqlite_close(con);
end.
Build and run:
$ pas insert_after_2
$ link insert_after_2 + sys$input/opt + psqlitedir:sqlite/opt
psqlitedir:psqlite
psqlitedir:sqlite
$
$ run insert_after_2
address.py:
class Address(object):
def __init__(self, _id = 0, _name = '', _address = ''):
self.id = _id
self.name = _name
self.address = _address
import sqlite3
from address import Address
con = sqlite3.connect('address.db')
c = con.cursor()
addr = Address(9, 'I I', 'I Road 99')
c.execute('INSERT INTO address VALUES(?,?,?)', (addr.id, addr.name, addr.address))
addr = Address(10, 'J J', 'J Road 1010')
c.execute('INSERT INTO address VALUES(?,?,?)', (addr.id, addr.name, addr.address))
con.commit()
con.close()
address.php:
<?php
class Address {
public $id;
public $name;
public $address;
public function __construct($id = 0, $name = '', $address = '') {
$this->id = $id;
$this->name = $name;
$this->address = $address;
}
}
?>
<?php
include '/disk2/arne/migr/simple/address.php';
$con = new PDO('sqlite:/disk2/arne/migr/simple/address.db');
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$con->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$stmt = $con->prepare('INSERT INTO address VALUES(:ID,:NAME,:ADDRESS)');
$addr = new Address(11, 'K K', 'K Road 1111');
$stmt->execute(array(':ID' => $addr->id, ':NAME' => $addr->name, ':ADDRESS' => $addr->address));
$addr = new Address(12, 'L L', 'L Road 1212');
$stmt->execute(array(':ID' => $addr->id, ':NAME' => $addr->name, ':ADDRESS' => $addr->address));
?>
public class Address {
private int id;
private String name;
private String address;
public Address() {
this(0, "", "");
}
public Address(int id, String name, String address) {
this.id = id;
this.name = name;
this.address = address;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.PreparedStatement;
public class InsertAfter5 {
public static void main(String[] args) throws Exception {
Class.forName("org.sqlite.JDBC");
Connection con = DriverManager.getConnection("jdbc:sqlite:address.db");
PreparedStatement pstmt = con.prepareStatement("INSERT INTO address VALUES(?,?,?)");
Address addr;
addr = new Address(13, "M M", "M Road 1313");
pstmt.setInt(1, addr.getId());
pstmt.setString(2, addr.getName());
pstmt.setString(3, addr.getAddress());
pstmt.executeUpdate();
addr = new Address(14, "N N", "N Road 1414");
pstmt.setInt(1, addr.getId());
pstmt.setString(2, addr.getName());
pstmt.setString(3, addr.getAddress());
pstmt.executeUpdate();
pstmt.close();
con.close();
}
}
Build and run:
$ javac InsertAfter5.java Address.java
$ java -cp .:/javalib/sqlite-jdbc-3_14_1-vms.jar "InsertAfter5"
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="address")
public class AddressJPA {
private int id;
private String name;
private String address;
public AddressJPA() {
this(0, "", "");
}
public AddressJPA(int id, String name, String address) {
this.id = id;
this.name = name;
this.address = address;
}
@Id
@Column(name="id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name="name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name="address")
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
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 InsertAfter6 {
public static void main(String[] args) throws Exception {
Logger.getLogger("org.hibernate").setLevel(Level.OFF);
EntityManagerFactory emf = Persistence.createEntityManagerFactory("Address");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
AddressJPA addr;
addr = new AddressJPA(15, "O O", "O Road 1515");
em.persist(addr);
addr = new AddressJPA(16, "P P", "P Road 1616");
em.persist(addr);
em.getTransaction().commit();
em.close();
emf.close();
}
}
Build and run:
$ javac -cp 'hibpath' InsertAfter6.java AddressJPA.java
$ java -cp .:'hibpath':/javalib/sqlite-jdbc-3_14_1-vms.jar:/javalib/sqlitehib.jar "InsertAfter6"
address.h:
struct address
{
int id;
char name[33];
char address[65];
};
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sqlite3.h"
#include "address.h"
int main()
{
sqlite3 *con;
sqlite3_stmt *sel;
char *sqlstr = "SELECT id,name,address FROM address";
int stat;
int count;
struct address res[1000];
int i;
stat = sqlite3_open("address.db", &con);
stat = sqlite3_prepare(con, sqlstr, strlen(sqlstr), &sel, NULL);
count = 0;
while(sqlite3_step(sel) == SQLITE_ROW)
{
count++;
res[count-1].id = sqlite3_column_int(sel, 0);
strcpy(res[count-1].name, (char *)sqlite3_column_text(sel, 1));
strcpy(res[count-1].address, (char *)sqlite3_column_text(sel, 2));
}
sqlite3_finalize(sel);
sqlite3_close(con);
for(i = 0; i < count; i++)
{
printf("%d|%s|%s\n", res[i].id, res[i].name, res[i].address);
}
return 0;
}
Build and run:
$ cc/include=sqlite3_include: list_after_1
$ link list_after_1 + sys$input/opt
sqlite3shr/share
$
$ run list_after_1
address.pas:
type
address = record
id : unsigned;
name : varying[32] of char;
address : varying[64] of char;
end;
[inherit('psqlitedir:sqlite', 'psqlitedir:psqlite')]
program list_after_2(input, output);
%include 'address.pas'
var
con : sqlite_ptr;
sel : sqlite_stmt_ptr;
count : integer;
res : array [1..1000] of address;
i : integer;
begin
con := psqlite_open('address.db');
sel := psqlite_prepare(con, 'SELECT id,name,address FROM address');
count := 0;
while psqlite_step_query(sel) do begin
count := count + 1;
res[count].id := psqlite_column_int(sel, 0);
res[count].name := psqlite_column_text(sel, 1);
res[count].address := psqlite_column_text(sel, 2);
end;
psqlite_finalize(sel);
psqlite_close(con);
for i := 1 to count do begin
writeln(res[i].id, '|', res[i].name, '|', res[i].address);
end;
end.
Build and run:
$ pas list_after_2
$ link list_after_2 + sys$input/opt + psqlitedir:sqlite/opt
psqlitedir:psqlite
psqlitedir:sqlite
$
$ run list_after_2
address.py:
class Address(object):
def __init__(self, _id = 0, _name = '', _address = ''):
self.id = _id
self.name = _name
self.address = _address
import sqlite3
from address import Address
con = sqlite3.connect('address.db')
c = con.cursor()
c.execute('SELECT id,name,address FROM address')
res = []
for row in c.fetchall():
res.append(Address(row[0], row[1], row[2]))
con.commit()
con.close()
for o in res:
print('%d|%s|%s' % (o.id, o.name, o.address))
address.php:
<?php
class Address {
public $id;
public $name;
public $address;
public function __construct($id = 0, $name = '', $address = '') {
$this->id = $id;
$this->name = $name;
$this->address = $address;
}
}
?>
<?php
include '/disk2/arne/migr/simple/address.php';
$con = new PDO('sqlite:/disk2/arne/migr/simple/address.db');
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$con->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$stmt = $con->prepare('SELECT id,name,address FROM address');
$stmt->execute(array());
$res = array();
while($row = $stmt->fetch()) {
$res[] = new Address($row['id'], $row['name'], $row['address']);
}
foreach($res as $o) {
echo sprintf('%d|%s|%s', $o->id, $o->name, $o-> address) . "\r\n";
}
?>
public class Address {
private int id;
private String name;
private String address;
public Address() {
this(0, "", "");
}
public Address(int id, String name, String address) {
this.id = id;
this.name = name;
this.address = address;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
public class ListAfter5 {
public static void main(String[] args) throws Exception {
Class.forName("org.sqlite.JDBC");
List<Address> res = new ArrayList<Address>();
Connection con = DriverManager.getConnection("jdbc:sqlite:address.db");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT id,name,address FROM address");
while(rs.next()) {
int id = rs.getInt(1);
String name = rs.getString(2);
String address = rs.getString(3);
res.add(new Address(id, name, address));
}
rs.close();
stmt.close();
con.close();
for(Address o : res) {
System.out.printf("%d|%s|%s\n", o.getId(), o.getName(), o.getAddress());
}
}
}
Build and run:
$ javac ListAfter5.java Address.java
$ java -cp .:/javalib/sqlite-jdbc-3_14_1-vms.jar "ListAfter5"
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="address")
public class AddressJPA {
private int id;
private String name;
private String address;
public AddressJPA() {
this(0, "", "");
}
public AddressJPA(int id, String name, String address) {
this.id = id;
this.name = name;
this.address = address;
}
@Id
@Column(name="id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name="name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name="address")
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
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 ListAfter6 {
public static void main(String[] args) throws Exception {
Logger.getLogger("org.hibernate").setLevel(Level.OFF);
EntityManagerFactory emf = Persistence.createEntityManagerFactory("Address");
EntityManager em = emf.createEntityManager();
TypedQuery<AddressJPA> q = em.createQuery("SELECT o FROM AddressJPA AS o", AddressJPA.class);
List<AddressJPA> res = q.getResultList();
for(AddressJPA o : res) {
System.out.printf("%d|%s|%s\n", o.getId(), o.getName(), o.getAddress());
}
em.close();
emf.close();
}
}
Build and run:
$ javac -cp 'hibpath' ListAfter6.java AddressJPA.java
$ java -cp .:'hibpath':/javalib/sqlite-jdbc-3_14_1-vms.jar:/javalib/sqlitehib.jar "ListAfter6"
Before records:
id | customer | no orderlines | orderline item | orderline qty | orderline item | orderline qty |
---|---|---|---|---|---|---|
1 | A A | 1 | Something | 2 | ||
2 | B B | 2 | Something else | 1 | Something different | 1 |
After database tables:
order
id | customer |
---|---|
1 | A A |
2 | B B |
orderline
id | orderid | item | qty |
---|---|---|---|
1 | 1 | Something | 2 |
2 | 2 | Something else | 1 |
3 | 2 | Something different | 1 |
IDENTIFICATION DIVISION.
PROGRAM-ID.INSERT-BEFORE-1.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT OPTIONAL ORDER-FILE ASSIGN TO "order.isq" ORGANIZATION IS INDEXED ACCESS MODE IS DYNAMIC RECORD KEY IS ORDER-ID.
DATA DIVISION.
FILE SECTION.
FD ORDER-FILE.
01 ORDER-RECORD.
03 ORDER-ID PIC 9(8) COMP.
03 ORDER-CUSTOMER PIC X(32).
03 ORDER-NLINES PIC 9(8) COMP.
03 LINES-ARRAY OCCURS 10 TIMES.
05 ORDERLINE-ITEM PIC X(32).
05 ORDERLINE-QTY PIC 9(8) COMP.
WORKING-STORAGE SECTION.
PROCEDURE DIVISION.
MAIN-PARAGRAPH.
OPEN I-O ORDER-FILE
MOVE 1 TO ORDER-ID
MOVE "A A" TO ORDER-CUSTOMER
MOVE 1 TO ORDER-NLINES
MOVE "Something" TO ORDERLINE-ITEM(1)
MOVE 2 TO ORDERLINE-QTY(1)
PERFORM INSERT-PARAGRAPH
MOVE 2 TO ORDER-ID
MOVE "B B" TO ORDER-CUSTOMER
MOVE 2 TO ORDER-NLINES
MOVE "Something else" TO ORDERLINE-ITEM(1)
MOVE 1 TO ORDERLINE-QTY(1)
MOVE "Something different" TO ORDERLINE-ITEM(2)
MOVE 1 TO ORDERLINE-QTY(2)
PERFORM INSERT-PARAGRAPH
CLOSE ORDER-FILE
STOP RUN.
INSERT-PARAGRAPH.
WRITE ORDER-RECORD
INVALID KEY DISPLAY "Error writing"
NOT INVALID KEY CONTINUE
END-WRITE.
Build and run:
$ cob insert_before_1
$ link insert_before_1
$ run insert_before_1
order_isam.pas
type
orderline = record
item : packed array [1..32] of char;
qty : unsigned;
end;
order = record
id : [key(0)]unsigned;
customer : packed array [1..32] of char;
nlines : integer;
line : array [1..10] of orderline;
end;
program insert_before_2(input, output);
%include 'order_isam.pas'
var
o : order;
db : file of order;
begin
open(db, 'order.isq', unknown, organization := indexed, access_method := keyed);
o.id := 3;
o.customer := 'C C';
o.nlines := 1;
o.line[1].item := 'Thingy';
o.line[1].qty := 1;
db^ := o;
put(db);
o.id := 4;
o.customer := 'D D';
o.nlines := 2;
o.line[1].item := 'Big thing';
o.line[1].qty := 1;
o.line[2].item := 'Small thing';
o.line[2].qty := 3;
db^ := o;
put(db);
close(db);
end.
Build and run:
$ pas insert_before_2
$ link insert_before_2
$ run insert_before_2
IDENTIFICATION DIVISION.
PROGRAM-ID.LIST-BEFORE-1.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT OPTIONAL ORDER-FILE ASSIGN TO "order.isq" ORGANIZATION IS INDEXED ACCESS MODE IS DYNAMIC RECORD KEY IS ORDER-ID.
DATA DIVISION.
FILE SECTION.
FD ORDER-FILE.
01 ORDER-RECORD.
03 ORDER-ID PIC 9(8) COMP.
03 ORDER-CUSTOMER PIC X(32).
03 ORDER-NLINES PIC 9(8) COMP.
03 LINES-ARRAY OCCURS 10 TIMES.
05 ORDERLINE-ITEM PIC X(32).
05 ORDERLINE-QTY PIC 9(8) COMP.
WORKING-STORAGE SECTION.
01 EOF-FLAG PIC X.
01 ID PIC 9(8) DISPLAY.
01 QTY PIC 9(8) DISPLAY.
01 I PIC S9(9).
PROCEDURE DIVISION.
MAIN-PARAGRAPH.
OPEN I-O ORDER-FILE
MOVE 'N' TO EOF-FLAG
PERFORM UNTIL EOF-FLAG = 'Y'
READ ORDER-FILE NEXT
AT END MOVE 'Y' TO EOF-FLAG
NOT AT END PERFORM SHOW-PARAGRAPH
END-READ
END-PERFORM
CLOSE ORDER-FILE
STOP RUN.
SHOW-PARAGRAPH.
MOVE ORDER-ID TO ID
DISPLAY ID " " ORDER-CUSTOMER
PERFORM VARYING I FROM 1 BY 1 UNTIL I > ORDER-NLINES
MOVE ORDERLINE-QTY(I) TO QTY
DISPLAY " " ORDERLINE-ITEM(I) ": " QTY
END-PERFORM.
Build and run:
$ cob list_before_1
$ link list_before_1
$ run list_before_1
order_isam.pas
type
orderline = record
item : packed array [1..32] of char;
qty : unsigned;
end;
order = record
id : [key(0)]unsigned;
customer : packed array [1..32] of char;
nlines : integer;
line : array [1..10] of orderline;
end;
program list_before_2(input, output);
%include 'order_isam.pas'
var
o : order;
db : file of order;
i : integer;
begin
open(db, 'order.isq', unknown, organization := indexed, access_method := keyed);
resetk(db, 0);
while not eof(db) do begin
o := db^;
writeln(o.id:1,' ',o.customer);
for i := 1 to o.nlines do begin
writeln(' ',o.line[i].item,': ',o.line[i].qty);
end;
get(db);
end;
close(db);
end.
Build and run:
$ pas list_before_2
$ link list_before_2
$ run list_before_2
The multiple subrecords within a record require two new features in the annotations:
import dk.vajhoej.record.Alignment;
import dk.vajhoej.record.Endian;
import dk.vajhoej.record.FieldType;
import dk.vajhoej.record.Struct;
import dk.vajhoej.record.StructField;
@Struct(endianess=Endian.LITTLE, alignment=Alignment.ALIGN1)
public class OrderLineISAM {
@StructField(n=0, type=FieldType.FIXSTR, length=32)
private String item;
@StructField(n=1, type=FieldType.INT4)
private int qty;
public OrderLineISAM() {
this("", 0);
}
public OrderLineISAM(String item, int qty) {
this.item = item;
this.qty = qty;
}
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
public int getQty() {
return qty;
}
public void setQty(int qty) {
this.qty = qty;
}
}
import dk.vajhoej.isam.KeyField;
import dk.vajhoej.record.Alignment;
import dk.vajhoej.record.ArrayField;
import dk.vajhoej.record.Endian;
import dk.vajhoej.record.FieldType;
import dk.vajhoej.record.Struct;
import dk.vajhoej.record.StructField;
@Struct(endianess=Endian.LITTLE, alignment=Alignment.ALIGN1)
public class OrderISAM {
@KeyField(n=0)
@StructField(n=0, type=FieldType.INT4)
private int id;
@StructField(n=1, type=FieldType.FIXSTR, length=32)
private String customer;
@StructField(n=2, type=FieldType.INT4)
private int nlines;
@ArrayField(elements=10)
@StructField(n=3, type=FieldType.STRUCT)
private OrderLineISAM[] line;
public OrderISAM() {
this(0, "");
}
public OrderISAM(int id, String customer) {
this.id = id;
this.customer = customer;
nlines = 0;
line = new OrderLineISAM[10];
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCustomer() {
return customer;
}
public void setCustomer(String customer) {
this.customer = customer;
}
public int getNLines() {
return nlines;
}
public OrderLineISAM getLine(int ix) {
return line[ix];
}
}
The relation requires a new feature in the annotations:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="orderline")
public class OrderLineJPA {
private int id;
private int orderId;
private String item;
private int qty;
public OrderLineJPA() {
this(0, 0, "", 0);
}
public OrderLineJPA(int id, int orderId, String item, int qty) {
this.id = id;
this.orderId = orderId;
this.item = item;
this.qty = qty;
}
@Id
@Column(name="id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name="orderid")
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
@Column(name="item")
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
@Column(name="qty")
public int getQty() {
return qty;
}
public void setQty(int qty) {
this.qty = qty;
}
}
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name="myorder")
public class OrderJPA {
private int id;
private String customer;
private List<OrderLineJPA> lines;
public OrderJPA() {
this(0, "", new ArrayList<OrderLineJPA>());
}
public OrderJPA(int id, String customer) {
this(id, customer, new ArrayList<OrderLineJPA>());
}
public OrderJPA(int id, String customer, List<OrderLineJPA> lines) {
this.id = id;
this.customer = customer;
this.lines = lines;
}
@Id
@Column(name="id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name="customer")
public String getCustomer() {
return customer;
}
public void setCustomer(String customer) {
this.customer = customer;
}
@OneToMany(mappedBy = "orderId", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
public List<OrderLineJPA> getLines() {
return lines;
}
public void setLines(List<OrderLineJPA> lines) {
this.lines = lines;
}
}
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class AutoMap<TFROM,TTO> {
public static class MethodPair {
private Method getter;
private Method setter;
private boolean trim;
public MethodPair(Method getter, Method setter, boolean trim) {
this.getter = getter;
this.setter = setter;
this.trim = trim;
}
public Method getGetter() {
return getter;
}
public Method getSetter() {
return setter;
}
public boolean getTrim() {
return trim;
}
}
private List<MethodPair> conv;
public AutoMap(Class<TFROM> from, Class<TTO> to) throws IntrospectionException {
this(from, to, false);
}
public AutoMap(Class<TFROM> from, Class<TTO> to, boolean trim) throws IntrospectionException {
conv = new ArrayList<MethodPair>();
for(PropertyDescriptor pdfrom : Introspector.getBeanInfo(from).getPropertyDescriptors()) {
for(PropertyDescriptor pdto : Introspector.getBeanInfo(to).getPropertyDescriptors()) {
if(pdfrom.getName().equals(pdto.getName())) {
Method getter = pdfrom.getReadMethod();
Method setter = pdto.getWriteMethod();
if(getter != null && setter != null) {
conv.add(new MethodPair(getter, setter, trim && pdfrom.getPropertyType().equals(String.class)));
}
}
}
}
}
public void convert(TFROM from, TTO to) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
for(MethodPair mp : conv) {
if(mp.getTrim()) {
mp.getSetter().invoke(to, ((String)mp.getGetter().invoke(from)).trim());
} else {
mp.getSetter().invoke(to, mp.getGetter().invoke(from));
}
}
}
}
# stuff for JPA
from java.util.logging import Level
from java.util.logging import Logger
from javax.persistence import Persistence
# stuff for ISAM
from dk.vajhoej.isam import Key0
from dk.vajhoej.isam.local import LocalIsamSource
#input class
import OrderISAM
import OrderLineISAM
#output class
import OrderJPA
import OrderLineJPA
# auto map
import AutoMap
# open JPA
Logger.getLogger("org.hibernate").setLevel(Level.OFF)
emf = Persistence.createEntityManagerFactory("Order")
em = emf.createEntityManager()
# open ISAM
db = LocalIsamSource('order.isq', 'dk.vajhoej.vms.rms.IndexSequential', False)
# process all records
omapper = AutoMap(OrderISAM, OrderJPA, True)
olmapper = AutoMap(OrderLineISAM, OrderLineJPA, True)
it = db.readGE(OrderISAM, Key0(0))
em.getTransaction().begin()
while it.read():
oldrec = it.current()
newrec = OrderJPA()
omapper.convert(oldrec, newrec)
for i in range(oldrec.getNLines()):
newsubrec = OrderLineJPA()
newsubrec.id = newrec.id * 100 + i
newsubrec.orderId = newrec.id
olmapper.convert(oldrec.getLine(i), newsubrec)
newrec.lines.add(newsubrec)
em.persist(newrec)
it.close()
em.getTransaction().commit()
# close ISAM
db.close()
# close JPA
em.close()
emf.close()
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="Order">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>OrderJPA</class>
<class>OrderLineJPA</class>
<exclude-unlisted-classes/>
<properties>
<!-- <property name="show_sql" value="true"/> -->
<property name="hibernate.connection.driver_class" value="org.sqlite.JDBC"/>
<property name="hibernate.connection.url" value="jdbc:sqlite:order.db"/>
<property name="hibernate.connection.username" value=""/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.dialect" value="org.hibernate.dialect.SQLiteDialect"/>
</properties>
</persistence-unit>
</persistence>
Database structure:
CREATE TABLE myorder (
id INTEGER NOT NULL,
customer VARCHAR(32),
PRIMARY KEY(id)
);
CREATE TABLE orderline (
id INTEGER NOT NULL,
orderid INTEGER NOT NULL,
item VARCHAR(32),
qty INTEGER,
PRIMARY KEY(id)
);
order.h:
struct orderline
{
int id;
int orderid;
char item[33];
int qty;
};
struct order
{
int id;
char customer[33];
int nlines;
struct orderline line[100];
};
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sqlite3.h"
#include "order.h"
int main()
{
sqlite3 *con;
sqlite3_stmt *oins, *olins;
char *osqlstr = "INSERT INTO myorder VALUES(?,?)";
char *olsqlstr = "INSERT INTO orderline VALUES(?,?,?,?)";
int stat, i;
struct order o;
stat = sqlite3_open("order.db", &con);
stat = sqlite3_prepare(con, osqlstr, strlen(osqlstr), &oins, NULL);
o.id = 5;
strcpy(o.customer, "E E");
o.nlines = 1;
o.line[0].id = 500;
o.line[0].orderid = 5;
strcpy(o.line[0].item, "A good C book");
o.line[0].qty = 1;
for(i = 0; i < o.nlines; i++)
{
stat = sqlite3_prepare(con, olsqlstr, strlen(olsqlstr), &olins, NULL);
sqlite3_bind_int(olins, 1, o.line[i].id);
sqlite3_bind_int(olins, 2, o.line[i].orderid);
sqlite3_bind_text(olins, 3, o.line[0].item, strlen(o.line[i].item), NULL);
sqlite3_bind_int(olins, 4, o.line[i].qty);
stat = sqlite3_step(olins);
sqlite3_finalize(olins);
}
sqlite3_bind_int(oins, 1, o.id);
sqlite3_bind_text(oins, 2, o.customer, strlen(o.customer), NULL);
stat = sqlite3_step(oins);
sqlite3_finalize(oins);
stat = sqlite3_prepare(con, osqlstr, strlen(osqlstr), &oins, NULL);
o.id = 6;
strcpy(o.customer, "F F");
o.nlines = 1;
o.line[0].id = 600;
o.line[0].orderid = 6;
strcpy(o.line[0].item, "Another good C book");
o.line[0].qty = 1;
for(i = 0; i < o.nlines; i++)
{
stat = sqlite3_prepare(con, olsqlstr, strlen(olsqlstr), &olins, NULL);
sqlite3_bind_int(olins, 1, o.line[i].id);
sqlite3_bind_int(olins, 2, o.line[i].orderid);
sqlite3_bind_text(olins, 3, o.line[0].item, strlen(o.line[i].item), NULL);
sqlite3_bind_int(olins, 4, o.line[i].qty);
stat = sqlite3_step(olins);
sqlite3_finalize(olins);
}
sqlite3_bind_int(oins, 1, o.id);
sqlite3_bind_text(oins, 2, o.customer, strlen(o.customer), NULL);
stat = sqlite3_step(oins);
sqlite3_finalize(oins);
sqlite3_close(con);
return 0;
}
Build and run:
$ cc/include=sqlite3_include: insert_after_1
$ link insert_after_1 + sys$input/opt
sqlite3shr/share
$
$ run insert_after_1
order.pas:
type
orderline = record
id : integer;
orderid : integer;
item : varying[32] of char;
qty : unsigned;
end;
order = record
id : unsigned;
customer : varying[32] of char;
nlines : integer;
line : array [1..100] of orderline;
end;
[inherit('psqlitedir:sqlite', 'psqlitedir:psqlite')]
program insert_after_2(input, output);
%include 'order.pas'
var
con : sqlite_ptr;
oins, olins : sqlite_stmt_ptr;
o : order;
i : integer;
begin
con := psqlite_open('order.db');
oins := psqlite_prepare(con, 'INSERT INTO myorder VALUES(?,?)');
o.id := 7;
o.customer := 'G G';
o.nlines := 1;
o.line[1].id := 700;
o.line[1].orderid := 7;
o.line[1].item := 'A good Pascal book';
o.line[1].qty := 1;
for i := 1 to o.nlines do begin
olins := psqlite_prepare(con, 'INSERT INTO orderline VALUES(?,?,?,?)');
psqlite_bind_int(olins, 1, o.line[i].id);
psqlite_bind_int(olins, 2, o.line[i].orderid);
psqlite_bind_text(olins, 3, o.line[i].item);
psqlite_bind_int(olins, 4, o.line[i].qty);
psqlite_step_nonquery(olins);
psqlite_finalize(olins);
end;
psqlite_bind_int(oins, 1, o.id);
psqlite_bind_text(oins, 2, o.customer);
psqlite_step_nonquery(oins);
psqlite_finalize(oins);
oins := psqlite_prepare(con, 'INSERT INTO myorder VALUES(?,?)');
o.id := 8;
o.customer := 'H H';
o.nlines := 1;
o.line[1].id := 800;
o.line[1].orderid := 8;
o.line[1].item := 'Another good Pascal book';
o.line[1].qty := 1;
for i := 1 to o.nlines do begin
olins := psqlite_prepare(con, 'INSERT INTO orderline VALUES(?,?,?,?)');
psqlite_bind_int(olins, 1, o.line[i].id);
psqlite_bind_int(olins, 2, o.line[i].orderid);
psqlite_bind_text(olins, 3, o.line[i].item);
psqlite_bind_int(olins, 4, o.line[i].qty);
psqlite_step_nonquery(olins);
psqlite_finalize(olins);
end;
psqlite_bind_int(oins, 1, o.id);
psqlite_bind_text(oins, 2, o.customer);
psqlite_step_nonquery(oins);
psqlite_finalize(oins);
psqlite_close(con);
end.
Build and run:
$ pas insert_after_2
$ link insert_after_2 + sys$input/opt + psqlitedir:sqlite/opt
psqlitedir:psqlite
psqlitedir:sqlite
$
$ run insert_after_2
order.py:
class OrderLine(object):
def __init__(self, _id = 0, _orderid = 0, _item = '', _qty = 0):
self.id = _id
self.orderid = _orderid
self.item = _item
self.qty = _qty
class Order(object):
def __init__(self, _id = 0, _customer = '', _lines = []):
self.id = _id
self.customer = _customer
self.lines = _lines
import sqlite3
from order import Order, OrderLine
con = sqlite3.connect('order.db')
c = con.cursor()
o = Order(9, 'I I', [ OrderLine(900, 9, 'A good Python book', 1) ]);
for ol in o.lines:
c.execute('INSERT INTO orderline VALUES(?,?,?,?)', (ol.id, ol.orderid, ol.item, ol.qty))
c.execute('INSERT INTO myorder VALUES(?,?)', (o.id, o.customer))
o = Order(10, 'J J', [ OrderLine(1000, 10, 'Another good Python book', 1) ]);
for ol in o.lines:
c.execute('INSERT INTO orderline VALUES(?,?,?,?)', (ol.id, ol.orderid, ol.item, ol.qty))
c.execute('INSERT INTO myorder VALUES(?,?)', (o.id, o.customer))
con.commit()
con.close()
order.php:
<?php
class OrderLine {
public $id;
public $orderid;
public $item;
public $qty;
public function __construct($id = 0, $orderid = 0, $item = '', $qty = 0) {
$this->id = $id;
$this->orderid = $orderid;
$this->item = $item;
$this->qty = $qty;
}
}
class Order {
public $id;
public $customer;
public $lines;
public function __construct($id = 0, $customer = '', $lines = array()) {
$this->id = $id;
$this->customer = $customer;
$this->lines = $lines;
}
}
?>
<?php
include '/disk2/arne/migr/relsub/order.php';
$con = new PDO('sqlite:/disk2/arne/migr/relsub/order.db');
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$con->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$ostmt = $con->prepare('INSERT INTO myorder VALUES(:ID,:CUSTOMER)');
$olstmt = $con->prepare('INSERT INTO orderline VALUES(:ID,:ORDERID,:ITEM,:QTY)');
$o = new Order(11, 'K K', array(new OrderLine(1100, 11, 'A good PHP book', 1)));
foreach($o->lines as $ol) {
$olstmt->execute(array(':ID' => $ol->id, ':ORDERID' => $ol->orderid, ':ITEM' => $ol->item, ':QTY' => $ol->qty));
}
$ostmt->execute(array(':ID' => $o->id, ':CUSTOMER' => $o->customer));
$o = new Order(12, 'L L', array(new OrderLine(1200, 12, 'Another good PHP book', 1)));
foreach($o->lines as $ol) {
$olstmt->execute(array(':ID' => $ol->id, ':ORDERID' => $ol->orderid, ':ITEM' => $ol->item, ':QTY' => $ol->qty));
}
$ostmt->execute(array(':ID' => $o->id, ':CUSTOMER' => $o->customer));
?>
public class OrderLine {
private int id;
private int orderId;
private String item;
private int qty;
public OrderLine() {
this(0, 0, "", 0);
}
public OrderLine(int id, int orderId, String item, int qty) {
this.id = id;
this.orderId = orderId;
this.item = item;
this.qty = qty;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
public int getQty() {
return qty;
}
public void setQty(int qty) {
this.qty = qty;
}
}
import java.util.ArrayList;
import java.util.List;
public class Order {
private int id;
private String customer;
private List<OrderLine> lines;
public Order() {
this(0, "", new ArrayList<OrderLine>());
}
public Order(int id, String customer) {
this(id, customer, new ArrayList<OrderLine>());
}
public Order(int id, String customer, List<OrderLine> lines) {
this.id = id;
this.customer = customer;
this.lines = lines;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCustomer() {
return customer;
}
public void setCustomer(String customer) {
this.customer = customer;
}
public List<OrderLine> getLines() {
return lines;
}
public void setLines(List<OrderLine> lines) {
this.lines = lines;
}
}
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.PreparedStatement;
public class InsertAfter5 {
public static void main(String[] args) throws Exception {
Class.forName("org.sqlite.JDBC");
Connection con = DriverManager.getConnection("jdbc:sqlite:order.db");
PreparedStatement opstmt = con.prepareStatement("INSERT INTO myorder VALUES(?,?)");
PreparedStatement olpstmt = con.prepareStatement("INSERT INTO orderline VALUES(?,?,?,?)");
Order o;
o = new Order(13, "M M");
o.getLines().add(new OrderLine(1300, 13, "A good Java book", 1));
for(OrderLine ol : o.getLines()) {
olpstmt.setInt(1, ol.getId());
olpstmt.setInt(2, ol.getOrderId());
olpstmt.setString(3, ol.getItem());
olpstmt.setInt(4, ol.getQty());
olpstmt.executeUpdate();
}
opstmt.setInt(1, o.getId());
opstmt.setString(2, o.getCustomer());
opstmt.executeUpdate();
o = new Order(14, "N N");
o.getLines().add(new OrderLine(1400, 14, "Another good Java book", 1));
for(OrderLine ol : o.getLines()) {
olpstmt.setInt(1, ol.getId());
olpstmt.setInt(2, ol.getOrderId());
olpstmt.setString(3, ol.getItem());
olpstmt.setInt(4, ol.getQty());
olpstmt.executeUpdate();
}
opstmt.setInt(1, o.getId());
opstmt.setString(2, o.getCustomer());
opstmt.executeUpdate();
opstmt.close();
con.close();
}
}
Build and run:
$ javac InsertAfter5.java Order.java OrderLine.java
$ java -cp .:/javalib/sqlite-jdbc-3_14_1-vms.jar "InsertAfter5"
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="orderline")
public class OrderLineJPA {
private int id;
private int orderId;
private String item;
private int qty;
public OrderLineJPA() {
this(0, 0, "", 0);
}
public OrderLineJPA(int id, int orderId, String item, int qty) {
this.id = id;
this.orderId = orderId;
this.item = item;
this.qty = qty;
}
@Id
@Column(name="id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name="orderid")
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
@Column(name="item")
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
@Column(name="qty")
public int getQty() {
return qty;
}
public void setQty(int qty) {
this.qty = qty;
}
}
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name="myorder")
public class OrderJPA {
private int id;
private String customer;
private List<OrderLineJPA> lines;
public OrderJPA() {
this(0, "", new ArrayList<OrderLineJPA>());
}
public OrderJPA(int id, String customer) {
this(id, customer, new ArrayList<OrderLineJPA>());
}
public OrderJPA(int id, String customer, List<OrderLineJPA> lines) {
this.id = id;
this.customer = customer;
this.lines = lines;
}
@Id
@Column(name="id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name="customer")
public String getCustomer() {
return customer;
}
public void setCustomer(String customer) {
this.customer = customer;
}
@OneToMany(mappedBy = "orderId", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
public List<OrderLineJPA> getLines() {
return lines;
}
public void setLines(List<OrderLineJPA> lines) {
this.lines = lines;
}
}
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 InsertAfter6 {
public static void main(String[] args) throws Exception {
Logger.getLogger("org.hibernate").setLevel(Level.OFF);
EntityManagerFactory emf = Persistence.createEntityManagerFactory("Order");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
OrderJPA o;
o = new OrderJPA(15, "O O");
o.getLines().add(new OrderLineJPA(1500, 15, "A good Java book", 1));
em.persist(o);
o = new OrderJPA(16, "P P");
o.getLines().add(new OrderLineJPA(1600, 16, "Another good Java book", 1));
em.persist(o);
em.getTransaction().commit();
em.close();
emf.close();
}
}
Build and run:
$ javac -cp 'hibpath' InsertAfter6.java OrderJPA.java OrderLineJPA.java
$ java -cp .:'hibpath':/javalib/sqlite-jdbc-3_14_1-vms.jar:/javalib/sqlitehib.jar "InsertAfter6"
order.h:
struct orderline
{
int id;
int orderid;
char item[33];
int qty;
};
struct order
{
int id;
char customer[33];
int nlines;
struct orderline line[100];
};
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sqlite3.h"
#include "order.h"
int main()
{
sqlite3 *con;
sqlite3_stmt *sel;
char *sqlstr = "SELECT myorder.id,myorder.customer,orderline.id,orderline.orderid,orderline.item,orderline.qty FROM myorder JOIN orderline ON myorder.id = orderline.orderid";
int stat;
int lastid;
int count;
struct order res[1000];
int i, j;
stat = sqlite3_open("order.db", &con);
stat = sqlite3_prepare(con, sqlstr, strlen(sqlstr), &sel, NULL);
lastid = -1;
count = 0;
while(sqlite3_step(sel) == SQLITE_ROW)
{
if(sqlite3_column_int(sel, 0) != lastid)
{
lastid = sqlite3_column_int(sel, 0);
count++;
res[count-1].id = sqlite3_column_int(sel, 0);
strcpy(res[count-1].customer, (char *)sqlite3_column_text(sel, 1));
res[count-1].nlines = 0;
}
res[count-1].line[res[count-1].nlines].id = sqlite3_column_int(sel, 2);
res[count-1].line[res[count-1].nlines].orderid = sqlite3_column_int(sel, 3);
strcpy(res[count-1].line[res[count-1].nlines].item, (char *)sqlite3_column_text(sel, 4));
res[count-1].line[res[count-1].nlines].qty = sqlite3_column_int(sel, 5);
res[count-1].nlines++;
}
sqlite3_finalize(sel);
sqlite3_close(con);
for(i = 0; i < count; i++)
{
printf("%d %s\n", res[i].id, res[i].customer);
for(j = 0; j < res[i].nlines; j++)
{
printf(" %s : %d\n", res[i].line[j].item, res[i].line[j].qty);
}
}
return 0;
}
Build and run:
$ cc/include=sqlite3_include: list_after_1
$ link list_after_1 + sys$input/opt
sqlite3shr/share
$
$ run list_after_1
order.pas:
type
orderline = record
id : integer;
orderid : integer;
item : varying[32] of char;
qty : unsigned;
end;
order = record
id : unsigned;
customer : varying[32] of char;
nlines : integer;
line : array [1..100] of orderline;
end;
[inherit('psqlitedir:sqlite', 'psqlitedir:psqlite')]
program list_after_2(input, output);
%include 'order.pas'
var
con : sqlite_ptr;
sel : sqlite_stmt_ptr;
res : array [1..1000] of order;
count : integer;
lastid : integer;
i, j : integer;
begin
con := psqlite_open('order.db');
sel := psqlite_prepare(con, 'SELECT myorder.id,myorder.customer,orderline.id,orderline.orderid,orderline.item,orderline.qty FROM myorder JOIN orderline ON myorder.id = orderline.orderid');
count := 0;
lastid := -1;
while psqlite_step_query(sel) do begin
if psqlite_column_int(sel, 0) <> lastid then begin
lastid := psqlite_column_int(sel, 0);
count := count + 1;
res[count].id := psqlite_column_int(sel, 0);
res[count].customer := psqlite_column_text(sel, 1);
res[count].nlines := 0;
end;
res[count].nlines := res[count].nlines + 1;
res[count].line[res[count].nlines].id := psqlite_column_int(sel, 2);
res[count].line[res[count].nlines].orderid := psqlite_column_int(sel, 3);
res[count].line[res[count].nlines].item := psqlite_column_text(sel, 4);
res[count].line[res[count].nlines].qty := psqlite_column_int(sel, 5);
end;
psqlite_finalize(sel);
psqlite_close(con);
for i := 1 to count do begin
writeln(res[i].id:1, ' ', res[i].customer);
for j := 1 to res[i].nlines do begin
writeln(' ', res[i].line[j].item, ': ', res[i].line[j].qty);
end;
end;
end.
Build and run:
$ pas list_after_2
$ link list_after_2 + sys$input/opt + psqlitedir:sqlite/opt
psqlitedir:psqlite
psqlitedir:sqlite
$
$ run list_after_2
order.py:
class OrderLine(object):
def __init__(self, _id = 0, _orderid = 0, _item = '', _qty = 0):
self.id = _id
self.orderid = _orderid
self.item = _item
self.qty = _qty
class Order(object):
def __init__(self, _id = 0, _customer = '', _lines = []):
self.id = _id
self.customer = _customer
self.lines = _lines
import sqlite3
from order import Order, OrderLine
con = sqlite3.connect('order.db')
c = con.cursor()
c.execute('SELECT myorder.id,myorder.customer,orderline.id,orderline.orderid,orderline.item,orderline.qty FROM myorder JOIN orderline ON myorder.id = orderline.orderid')
res = []
lastid = -1
lasto = None
for row in c.fetchall():
if row[0] != lastid:
lastid = row[0]
lasto = Order(row[0], row[1], [])
res.append(lasto)
lasto.lines.append(OrderLine(row[2], row[3], row[4], row[5]))
con.commit()
con.close()
for o in res:
print('%d %s' % (o.id, o.customer))
for ol in o.lines:
print(' %s : %d' % (ol.item, ol.qty))
order.php:
<?php
class OrderLine {
public $id;
public $orderid;
public $item;
public $qty;
public function __construct($id = 0, $orderid = 0, $item = '', $qty = 0) {
$this->id = $id;
$this->orderid = $orderid;
$this->item = $item;
$this->qty = $qty;
}
}
class Order {
public $id;
public $customer;
public $lines;
public function __construct($id = 0, $customer = '', $lines = array()) {
$this->id = $id;
$this->customer = $customer;
$this->lines = $lines;
}
}
?>
<?php
include '/disk2/arne/migr/relsub/order.php';
$con = new PDO('sqlite:/disk2/arne/migr/relsub/order.db');
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$con->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_NUM);
$stmt = $con->prepare('SELECT myorder.id,myorder.customer,orderline.id,orderline.orderid,orderline.item,orderline.qty FROM myorder JOIN orderline ON myorder.id = orderline.orderid');
$stmt->execute(array());
$res = array();
$lastid = -1;
$lasto = null;
while($row = $stmt->fetch()) {
if($lastid != $row[0]) {
$lastid = $row[0];
$lasto = new Order($row[0], $row[1], array());
$res[] = $lasto;
}
$lasto->lines[] = new OrderLine($row[2], $row[3], $row[4], $row[5]);
}
foreach($res as $o) {
echo sprintf('%d %s', $o->id, $o->customer) . "\r\n";
foreach($o->lines as $ol) {
echo sprintf(' %s : %d', $ol->item, $ol->qty) . "\r\n";
}
}
?>
public class OrderLine {
private int id;
private int orderId;
private String item;
private int qty;
public OrderLine() {
this(0, 0, "", 0);
}
public OrderLine(int id, int orderId, String item, int qty) {
this.id = id;
this.orderId = orderId;
this.item = item;
this.qty = qty;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
public int getQty() {
return qty;
}
public void setQty(int qty) {
this.qty = qty;
}
}
import java.util.ArrayList;
import java.util.List;
public class Order {
private int id;
private String customer;
private List<OrderLine> lines;
public Order() {
this(0, "", new ArrayList<OrderLine>());
}
public Order(int id, String customer) {
this(id, customer, new ArrayList<OrderLine>());
}
public Order(int id, String customer, List<OrderLine> lines) {
this.id = id;
this.customer = customer;
this.lines = lines;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCustomer() {
return customer;
}
public void setCustomer(String customer) {
this.customer = customer;
}
public List<OrderLine> getLines() {
return lines;
}
public void setLines(List<OrderLine> lines) {
this.lines = lines;
}
}
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
public class ListAfter5 {
public static void main(String[] args) throws Exception {
Class.forName("org.sqlite.JDBC");
List<Order> res = new ArrayList<Order>();
Connection con = DriverManager.getConnection("jdbc:sqlite:order.db");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT myorder.id,myorder.customer,orderline.id,orderline.orderid,orderline.item,orderline.qty FROM myorder JOIN orderline ON myorder.id = orderline.orderid");
int lastid = -1;
Order lasto = null;
while(rs.next()) {
int id = rs.getInt(1);
String customer = rs.getString(2);
int lineid = rs.getInt(3);
int orderid = rs.getInt(4);
String item = rs.getString(5);
int qty = rs.getInt(6);
if(id != lastid) {
lastid = id;
lasto = new Order(id, customer);
res.add(lasto);
}
OrderLine line = new OrderLine(lineid, orderid, item, qty);
lasto.getLines().add(line);
}
rs.close();
stmt.close();
con.close();
for(Order o : res) {
System.out.printf("%d %s\n", o.getId(), o.getCustomer());
for(OrderLine ol : o.getLines()) {
System.out.printf(" %s : %d\n", ol.getItem(), ol.getQty());
}
}
}
}
Build and run:
$ javac ListAfter5.java Order.java OrderLine.java
$ java -cp .:/javalib/sqlite-jdbc-3_14_1-vms.jar "ListAfter5"
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="orderline")
public class OrderLineJPA {
private int id;
private int orderId;
private String item;
private int qty;
public OrderLineJPA() {
this(0, 0, "", 0);
}
public OrderLineJPA(int id, int orderId, String item, int qty) {
this.id = id;
this.orderId = orderId;
this.item = item;
this.qty = qty;
}
@Id
@Column(name="id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name="orderid")
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
@Column(name="item")
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
@Column(name="qty")
public int getQty() {
return qty;
}
public void setQty(int qty) {
this.qty = qty;
}
}
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name="myorder")
public class OrderJPA {
private int id;
private String customer;
private List<OrderLineJPA> lines;
public OrderJPA() {
this(0, "", new ArrayList<OrderLineJPA>());
}
public OrderJPA(int id, String customer) {
this(id, customer, new ArrayList<OrderLineJPA>());
}
public OrderJPA(int id, String customer, List<OrderLineJPA> lines) {
this.id = id;
this.customer = customer;
this.lines = lines;
}
@Id
@Column(name="id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name="customer")
public String getCustomer() {
return customer;
}
public void setCustomer(String customer) {
this.customer = customer;
}
@OneToMany(mappedBy = "orderId", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
public List<OrderLineJPA> getLines() {
return lines;
}
public void setLines(List<OrderLineJPA> lines) {
this.lines = lines;
}
}
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 ListAfter6 {
public static void main(String[] args) throws Exception {
Logger.getLogger("org.hibernate").setLevel(Level.OFF);
EntityManagerFactory emf = Persistence.createEntityManagerFactory("Order");
EntityManager em = emf.createEntityManager();
TypedQuery<OrderJPA> q = em.createQuery("SELECT o FROM OrderJPA AS o JOIN FETCH o.lines ol", OrderJPA.class);
List<OrderJPA> res = q.getResultList();
for(OrderJPA o : res) {
System.out.printf("%d %s\n", o.getId(), o.getCustomer());
for(OrderLineJPA ol : o.getLines()) {
System.out.printf(" %s : %d\n", ol.getItem(), ol.getQty());
}
}
em.close();
emf.close();
}
}
Build and run:
$ javac -cp 'hibpath' ListAfter6.java OrderJPA.java OrderLineJPA.java
$ java -cp .:'hibpath':/javalib/sqlite-jdbc-3_14_1-vms.jar:/javalib/sqlitehib.jar "ListAfter6"
Before records:
id | customer |
---|---|
1 | A A |
2 | B B |
id | orderid | item | qty |
---|---|---|---|
1 | 1 | Something | 2 |
2 | 2 | Something else | 1 |
3 | 2 | Something different | 1 |
After database tables:
order
id | customer |
---|---|
1 | A A |
2 | B B |
orderline
id | orderid | item | qty |
---|---|---|---|
1 | 1 | Something | 2 |
2 | 2 | Something else | 1 |
3 | 2 | Something different | 1 |
IDENTIFICATION DIVISION.
PROGRAM-ID.INSERT-BEFORE-1.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT OPTIONAL ORDER-FILE ASSIGN TO "order.isq"
ORGANIZATION IS INDEXED ACCESS MODE IS DYNAMIC
RECORD KEY IS ORDER-ID.
SELECT OPTIONAL ORDERLINE-FILE ASSIGN TO "orderline.isq"
ORGANIZATION IS INDEXED ACCESS MODE IS DYNAMIC
RECORD KEY IS ORDERLINE-ID
ALTERNATE RECORD KEY IS ORDERLINE-ORDERID WITH DUPLICATES.
DATA DIVISION.
FILE SECTION.
FD ORDER-FILE.
01 ORDER-RECORD.
03 ORDER-ID PIC 9(8) COMP.
03 ORDER-CUSTOMER PIC X(32).
FD ORDERLINE-FILE.
01 ORDERLINE-RECORD.
03 ORDERLINE-ID PIC 9(8) COMP.
03 ORDERLINE-ORDERID PIC 9(8) COMP.
03 ORDERLINE-ITEM PIC X(32).
03 ORDERLINE-QTY PIC 9(8) COMP.
WORKING-STORAGE SECTION.
PROCEDURE DIVISION.
MAIN-PARAGRAPH.
OPEN I-O ORDER-FILE
OPEN I-O ORDERLINE-FILE
MOVE 1 TO ORDER-ID
MOVE "A A" TO ORDER-CUSTOMER
PERFORM INSERT-ORDER-PARAGRAPH
MOVE 100 TO ORDERLINE-ID
MOVE 1 TO ORDERLINE-ORDERID
MOVE "Something" TO ORDERLINE-ITEM
MOVE 2 TO ORDERLINE-QTY
PERFORM INSERT-ORDERLINE-PARAGRAPH
MOVE 2 TO ORDER-ID
MOVE "B B" TO ORDER-CUSTOMER
PERFORM INSERT-ORDER-PARAGRAPH
MOVE 200 TO ORDERLINE-ID
MOVE 2 TO ORDERLINE-ORDERID
MOVE "Something else" TO ORDERLINE-ITEM
MOVE 1 TO ORDERLINE-QTY
PERFORM INSERT-ORDERLINE-PARAGRAPH
MOVE 201 TO ORDERLINE-ID
MOVE 2 TO ORDERLINE-ORDERID
MOVE "Something different" TO ORDERLINE-ITEM
MOVE 1 TO ORDERLINE-QTY
PERFORM INSERT-ORDERLINE-PARAGRAPH
CLOSE ORDER-FILE
CLOSE ORDERLINE-FILE
STOP RUN.
INSERT-ORDER-PARAGRAPH.
WRITE ORDER-RECORD
INVALID KEY DISPLAY "Error writing"
NOT INVALID KEY CONTINUE
END-WRITE.
INSERT-ORDERLINE-PARAGRAPH.
WRITE ORDERLINE-RECORD
INVALID KEY DISPLAY "Error writing"
NOT INVALID KEY CONTINUE
END-WRITE.
Build and run:
$ cob insert_before_1
$ link insert_before_1
$ run insert_before_1
order_isam.pas:
type
orderline = record
id : [key(0)]unsigned;
orderid : [key(1)]unsigned;
item : packed array [1..32] of char;
qty : unsigned;
end;
order = record
id : [key(0)]unsigned;
customer : packed array [1..32] of char;
end;
program insert_before_2(input, output);
%include 'order_isam.pas'
var
o : order;
odb : file of order;
ol : orderline;
oldb : file of orderline;
begin
open(odb, 'order.isq', unknown, organization := indexed, access_method := keyed);
open(oldb, 'orderline.isq', unknown, organization := indexed, access_method := keyed);
o.id := 3;
o.customer := 'C C';
odb^ := o;
put(odb);
ol.id := 300;
ol.orderid := 3;
ol.item := 'Thingy';
ol.qty := 1;
oldb^ := ol;
put(oldb);
o.id := 4;
o.customer := 'D D';
odb^ := o;
put(odb);
ol.id := 400;
ol.orderid := 4;
ol.item := 'Big thing';
ol.qty := 1;
oldb^ := ol;
put(oldb);
ol.id := 401;
ol.orderid := 4;
ol.item := 'Small thing';
ol.qty := 3;
oldb^ := ol;
put(oldb);
close(odb);
close(oldb);
end.
Build and run:
$ pas insert_before_2
$ link insert_before_2
$ run insert_before_2
IDENTIFICATION DIVISION.
PROGRAM-ID.LIST-BEFORE-1.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT OPTIONAL ORDER-FILE ASSIGN TO "order.isq"
ORGANIZATION IS INDEXED ACCESS MODE IS DYNAMIC
RECORD KEY IS ORDER-ID.
SELECT OPTIONAL ORDERLINE-FILE ASSIGN TO "orderline.isq"
ORGANIZATION IS INDEXED ACCESS MODE IS DYNAMIC
RECORD KEY IS ORDERLINE-ID
ALTERNATE RECORD KEY IS ORDERLINE-ORDERID WITH DUPLICATES.
DATA DIVISION.
FILE SECTION.
FD ORDER-FILE.
01 ORDER-RECORD.
03 ORDER-ID PIC 9(8) COMP.
03 ORDER-CUSTOMER PIC X(32).
FD ORDERLINE-FILE.
01 ORDERLINE-RECORD.
03 ORDERLINE-ID PIC 9(8) COMP.
03 ORDERLINE-ORDERID PIC 9(8) COMP.
03 ORDERLINE-ITEM PIC X(32).
03 ORDERLINE-QTY PIC 9(8) COMP.
WORKING-STORAGE SECTION.
01 EOF-FLAG PIC X.
01 DONE-FLAG PIC X.
01 ID PIC 9(8) DISPLAY.
01 QTY PIC 9(8) DISPLAY.
PROCEDURE DIVISION.
MAIN-PARAGRAPH.
OPEN I-O ORDER-FILE
OPEN I-O ORDERLINE-FILE
MOVE 'N' TO EOF-FLAG
PERFORM UNTIL EOF-FLAG = 'Y'
READ ORDER-FILE NEXT
AT END MOVE 'Y' TO EOF-FLAG
NOT AT END PERFORM SHOW-ORDER-PARAGRAPH
END-READ
END-PERFORM
CLOSE ORDER-FILE
CLOSE ORDERLINE-FILE
STOP RUN.
SHOW-ORDER-PARAGRAPH.
MOVE ORDER-ID TO ID
DISPLAY ID " " ORDER-CUSTOMER
MOVE ORDER-ID TO ORDERLINE-ORDERID
START ORDERLINE-FILE KEY IS GREATER THAN OR EQUAL TO ORDERLINE-ORDERID
INVALID KEY DISPLAY "Key problem"
NOT INVALID KEY CONTINUE
END-START
MOVE 'N' TO EOF-FLAG
MOVE 'N' TO DONE-FLAG
PERFORM UNTIL EOF-FLAG = 'Y' OR DONE-FLAG = 'Y'
READ ORDERLINE-FILE NEXT
AT END MOVE 'Y' TO EOF-FLAG
NOT AT END PERFORM ORDERLINE-PARAGRAPH
END-READ
END-PERFORM.
ORDERLINE-PARAGRAPH.
IF ORDERLINE-ORDERID EQUAL TO ORDER-ID THEN
PERFORM DISPLAY-ORDERLINE-PARAGRAPH
ELSE
MOVE 'Y' TO DONE-FLAG
END-IF.
DISPLAY-ORDERLINE-PARAGRAPH.
MOVE ORDERLINE-QTY TO QTY
DISPLAY " " ORDERLINE-ITEM ": " QTY.
Build and run:
$ cob list_before_1
$ link list_before_1
$ run list_before_1
order_isam.pas:
type
orderline = record
id : [key(0)]unsigned;
orderid : [key(1)]unsigned;
item : packed array [1..32] of char;
qty : unsigned;
end;
order = record
id : [key(0)]unsigned;
customer : packed array [1..32] of char;
end;
program list_before_2(input, output);
%include 'order_isam.pas'
var
o : order;
odb : file of order;
ol : orderline;
oldb : file of orderline;
done : boolean;
begin
open(odb, 'order.isq', unknown, organization := indexed, access_method := keyed);
open(oldb, 'orderline.isq', unknown, organization := indexed, access_method := keyed);
resetk(odb, 0);
while not eof(odb) do begin
o := odb^;
writeln(o.id:1,' ',o.customer);
findk(oldb, 1, o.id);
done := false;
while not eof(oldb) do begin
ol := oldb^;
if (ol.orderid = o.id) and not done then begin
writeln(' ', ol.item, ': ', ol.qty);
end else begin
done := true;
end;
get(oldb);
end;
get(odb);
end;
close(odb);
close(oldb);
end.
Build and run:
$ pas list_before_2
$ link list_before_2
$ run list_before_2
import dk.vajhoej.isam.KeyField;
import dk.vajhoej.record.Alignment;
import dk.vajhoej.record.Endian;
import dk.vajhoej.record.FieldType;
import dk.vajhoej.record.Struct;
import dk.vajhoej.record.StructField;
@Struct(endianess=Endian.LITTLE, alignment=Alignment.ALIGN1)
public class OrderLineISAM {
@KeyField(n=0)
@StructField(n=0, type=FieldType.INT4)
private int id;
@KeyField(n=1)
@StructField(n=1, type=FieldType.INT4)
private int orderId;
@StructField(n=2, type=FieldType.FIXSTR, length=32)
private String item;
@StructField(n=3, type=FieldType.INT4)
private int qty;
public OrderLineISAM() {
this(0, 0, "", 0);
}
public OrderLineISAM(int id, int orderId, String item, int qty) {
this.id = qty;
this.orderId = orderId;
this.item = item;
this.qty = qty;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
public int getQty() {
return qty;
}
public void setQty(int qty) {
this.qty = qty;
}
}
import dk.vajhoej.isam.KeyField;
import dk.vajhoej.record.Alignment;
import dk.vajhoej.record.ArrayField;
import dk.vajhoej.record.Endian;
import dk.vajhoej.record.FieldType;
import dk.vajhoej.record.Struct;
import dk.vajhoej.record.StructField;
@Struct(endianess=Endian.LITTLE, alignment=Alignment.ALIGN1)
public class OrderISAM {
@KeyField(n=0)
@StructField(n=0, type=FieldType.INT4)
private int id;
@StructField(n=1, type=FieldType.FIXSTR, length=32)
private String customer;
public OrderISAM() {
this(0, "");
}
public OrderISAM(int id, String customer) {
this.id = id;
this.customer = customer;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCustomer() {
return customer;
}
public void setCustomer(String customer) {
this.customer = customer;
}
}
The relation requires a new feature in the annotations:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="orderline")
public class OrderLineJPA {
private int id;
private int orderId;
private String item;
private int qty;
public OrderLineJPA() {
this(0, 0, "", 0);
}
public OrderLineJPA(int id, int orderId, String item, int qty) {
this.id = id;
this.orderId = orderId;
this.item = item;
this.qty = qty;
}
@Id
@Column(name="id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name="orderid")
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
@Column(name="item")
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
@Column(name="qty")
public int getQty() {
return qty;
}
public void setQty(int qty) {
this.qty = qty;
}
}
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name="myorder")
public class OrderJPA {
private int id;
private String customer;
private List<OrderLineJPA> lines;
public OrderJPA() {
this(0, "", new ArrayList<OrderLineJPA>());
}
public OrderJPA(int id, String customer) {
this(id, customer, new ArrayList<OrderLineJPA>());
}
public OrderJPA(int id, String customer, List<OrderLineJPA> lines) {
this.id = id;
this.customer = customer;
this.lines = lines;
}
@Id
@Column(name="id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name="customer")
public String getCustomer() {
return customer;
}
public void setCustomer(String customer) {
this.customer = customer;
}
@OneToMany(mappedBy = "orderId", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
public List<OrderLineJPA> getLines() {
return lines;
}
public void setLines(List<OrderLineJPA> lines) {
this.lines = lines;
}
}
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class AutoMap<TFROM,TTO> {
public static class MethodPair {
private Method getter;
private Method setter;
private boolean trim;
public MethodPair(Method getter, Method setter, boolean trim) {
this.getter = getter;
this.setter = setter;
this.trim = trim;
}
public Method getGetter() {
return getter;
}
public Method getSetter() {
return setter;
}
public boolean getTrim() {
return trim;
}
}
private List<MethodPair> conv;
public AutoMap(Class<TFROM> from, Class<TTO> to) throws IntrospectionException {
this(from, to, false);
}
public AutoMap(Class<TFROM> from, Class<TTO> to, boolean trim) throws IntrospectionException {
conv = new ArrayList<MethodPair>();
for(PropertyDescriptor pdfrom : Introspector.getBeanInfo(from).getPropertyDescriptors()) {
for(PropertyDescriptor pdto : Introspector.getBeanInfo(to).getPropertyDescriptors()) {
if(pdfrom.getName().equals(pdto.getName())) {
Method getter = pdfrom.getReadMethod();
Method setter = pdto.getWriteMethod();
if(getter != null && setter != null) {
conv.add(new MethodPair(getter, setter, trim && pdfrom.getPropertyType().equals(String.class)));
}
}
}
}
}
public void convert(TFROM from, TTO to) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
for(MethodPair mp : conv) {
if(mp.getTrim()) {
mp.getSetter().invoke(to, ((String)mp.getGetter().invoke(from)).trim());
} else {
mp.getSetter().invoke(to, mp.getGetter().invoke(from));
}
}
}
}
# stuff for JPA
from java.util.logging import Level
from java.util.logging import Logger
from javax.persistence import Persistence
# stuff for ISAM
from dk.vajhoej.isam import Key0
from dk.vajhoej.isam import Key1
from dk.vajhoej.isam.local import LocalIsamSource
#input class
import OrderISAM
import OrderLineISAM
#output class
import OrderJPA
import OrderLineJPA
# auto map
import AutoMap
# open JPA
Logger.getLogger("org.hibernate").setLevel(Level.OFF)
emf = Persistence.createEntityManagerFactory("Order")
em = emf.createEntityManager()
# open ISAM
odb = LocalIsamSource('order.isq', 'dk.vajhoej.vms.rms.IndexSequential', False)
oldb = LocalIsamSource('orderline.isq', 'dk.vajhoej.vms.rms.IndexSequential', False)
# process all records
omapper = AutoMap(OrderISAM, OrderJPA, True)
olmapper = AutoMap(OrderLineISAM, OrderLineJPA, True)
it = odb.readGE(OrderISAM, Key0(0))
em.getTransaction().begin()
while it.read():
oldrec = it.current()
newrec = OrderJPA()
omapper.convert(oldrec, newrec)
it2 = oldb.readGE(OrderLineISAM, Key1(oldrec.id))
while it2.read():
oldsubrec = it2.current()
if oldsubrec.orderId == oldrec.id:
newsubrec = OrderLineJPA()
olmapper.convert(oldsubrec, newsubrec)
newrec.lines.add(newsubrec)
else:
break
em.persist(newrec)
it.close()
em.getTransaction().commit()
# close ISAM
odb.close()
oldb.close()
# close JPA
em.close()
emf.close()
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="Order">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>OrderJPA</class>
<class>OrderLineJPA</class>
<exclude-unlisted-classes/>
<properties>
<!-- <property name="show_sql" value="true"/> -->
<property name="hibernate.connection.driver_class" value="org.sqlite.JDBC"/>
<property name="hibernate.connection.url" value="jdbc:sqlite:order.db"/>
<property name="hibernate.connection.username" value=""/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.dialect" value="org.hibernate.dialect.SQLiteDialect"/>
</properties>
</persistence-unit>
</persistence>
Database structure:
CREATE TABLE myorder (
id INTEGER NOT NULL,
customer VARCHAR(32),
PRIMARY KEY(id)
);
CREATE TABLE orderline (
id INTEGER NOT NULL,
orderid INTEGER NOT NULL,
item VARCHAR(32),
qty INTEGER,
PRIMARY KEY(id)
);
order.h:
struct orderline
{
int id;
int orderid;
char item[33];
int qty;
};
struct order
{
int id;
char customer[33];
int nlines;
struct orderline line[100];
};
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sqlite3.h"
#include "order.h"
int main()
{
sqlite3 *con;
sqlite3_stmt *oins, *olins;
char *osqlstr = "INSERT INTO myorder VALUES(?,?)";
char *olsqlstr = "INSERT INTO orderline VALUES(?,?,?,?)";
int stat, i;
struct order o;
stat = sqlite3_open("order.db", &con);
stat = sqlite3_prepare(con, osqlstr, strlen(osqlstr), &oins, NULL);
o.id = 5;
strcpy(o.customer, "E E");
o.nlines = 1;
o.line[0].id = 500;
o.line[0].orderid = 5;
strcpy(o.line[0].item, "A good C book");
o.line[0].qty = 1;
for(i = 0; i < o.nlines; i++)
{
stat = sqlite3_prepare(con, olsqlstr, strlen(olsqlstr), &olins, NULL);
sqlite3_bind_int(olins, 1, o.line[i].id);
sqlite3_bind_int(olins, 2, o.line[i].orderid);
sqlite3_bind_text(olins, 3, o.line[0].item, strlen(o.line[i].item), NULL);
sqlite3_bind_int(olins, 4, o.line[i].qty);
stat = sqlite3_step(olins);
sqlite3_finalize(olins);
}
sqlite3_bind_int(oins, 1, o.id);
sqlite3_bind_text(oins, 2, o.customer, strlen(o.customer), NULL);
stat = sqlite3_step(oins);
sqlite3_finalize(oins);
stat = sqlite3_prepare(con, osqlstr, strlen(osqlstr), &oins, NULL);
o.id = 6;
strcpy(o.customer, "F F");
o.nlines = 1;
o.line[0].id = 600;
o.line[0].orderid = 6;
strcpy(o.line[0].item, "Another good C book");
o.line[0].qty = 1;
for(i = 0; i < o.nlines; i++)
{
stat = sqlite3_prepare(con, olsqlstr, strlen(olsqlstr), &olins, NULL);
sqlite3_bind_int(olins, 1, o.line[i].id);
sqlite3_bind_int(olins, 2, o.line[i].orderid);
sqlite3_bind_text(olins, 3, o.line[0].item, strlen(o.line[i].item), NULL);
sqlite3_bind_int(olins, 4, o.line[i].qty);
stat = sqlite3_step(olins);
sqlite3_finalize(olins);
}
sqlite3_bind_int(oins, 1, o.id);
sqlite3_bind_text(oins, 2, o.customer, strlen(o.customer), NULL);
stat = sqlite3_step(oins);
sqlite3_finalize(oins);
sqlite3_close(con);
return 0;
}
Build and run:
$ cc/include=sqlite3_include: insert_after_1
$ link insert_after_1 + sys$input/opt
sqlite3shr/share
$
$ run insert_after_1
order.pas:
type
orderline = record
id : integer;
orderid : integer;
item : varying[32] of char;
qty : unsigned;
end;
order = record
id : unsigned;
customer : varying[32] of char;
nlines : integer;
line : array [1..100] of orderline;
end;
[inherit('psqlitedir:sqlite', 'psqlitedir:psqlite')]
program insert_after_2(input, output);
%include 'order.pas'
var
con : sqlite_ptr;
oins, olins : sqlite_stmt_ptr;
o : order;
i : integer;
begin
con := psqlite_open('order.db');
oins := psqlite_prepare(con, 'INSERT INTO myorder VALUES(?,?)');
o.id := 7;
o.customer := 'G G';
o.nlines := 1;
o.line[1].id := 700;
o.line[1].orderid := 7;
o.line[1].item := 'A good Pascal book';
o.line[1].qty := 1;
for i := 1 to o.nlines do begin
olins := psqlite_prepare(con, 'INSERT INTO orderline VALUES(?,?,?,?)');
psqlite_bind_int(olins, 1, o.line[i].id);
psqlite_bind_int(olins, 2, o.line[i].orderid);
psqlite_bind_text(olins, 3, o.line[i].item);
psqlite_bind_int(olins, 4, o.line[i].qty);
psqlite_step_nonquery(olins);
psqlite_finalize(olins);
end;
psqlite_bind_int(oins, 1, o.id);
psqlite_bind_text(oins, 2, o.customer);
psqlite_step_nonquery(oins);
psqlite_finalize(oins);
oins := psqlite_prepare(con, 'INSERT INTO myorder VALUES(?,?)');
o.id := 8;
o.customer := 'H H';
o.nlines := 1;
o.line[1].id := 800;
o.line[1].orderid := 8;
o.line[1].item := 'Another good Pascal book';
o.line[1].qty := 1;
for i := 1 to o.nlines do begin
olins := psqlite_prepare(con, 'INSERT INTO orderline VALUES(?,?,?,?)');
psqlite_bind_int(olins, 1, o.line[i].id);
psqlite_bind_int(olins, 2, o.line[i].orderid);
psqlite_bind_text(olins, 3, o.line[i].item);
psqlite_bind_int(olins, 4, o.line[i].qty);
psqlite_step_nonquery(olins);
psqlite_finalize(olins);
end;
psqlite_bind_int(oins, 1, o.id);
psqlite_bind_text(oins, 2, o.customer);
psqlite_step_nonquery(oins);
psqlite_finalize(oins);
psqlite_close(con);
end.
Build and run:
$ pas insert_after_2
$ link insert_after_2 + sys$input/opt + psqlitedir:sqlite/opt
psqlitedir:psqlite
psqlitedir:sqlite
$
$ run insert_after_2
order.py:
class OrderLine(object):
def __init__(self, _id = 0, _orderid = 0, _item = '', _qty = 0):
self.id = _id
self.orderid = _orderid
self.item = _item
self.qty = _qty
class Order(object):
def __init__(self, _id = 0, _customer = '', _lines = []):
self.id = _id
self.customer = _customer
self.lines = _lines
import sqlite3
from order import Order, OrderLine
con = sqlite3.connect('order.db')
c = con.cursor()
o = Order(9, 'I I', [ OrderLine(900, 9, 'A good Python book', 1) ]);
for ol in o.lines:
c.execute('INSERT INTO orderline VALUES(?,?,?,?)', (ol.id, ol.orderid, ol.item, ol.qty))
c.execute('INSERT INTO myorder VALUES(?,?)', (o.id, o.customer))
o = Order(10, 'J J', [ OrderLine(1000, 10, 'Another good Python book', 1) ]);
for ol in o.lines:
c.execute('INSERT INTO orderline VALUES(?,?,?,?)', (ol.id, ol.orderid, ol.item, ol.qty))
c.execute('INSERT INTO myorder VALUES(?,?)', (o.id, o.customer))
con.commit()
con.close()
order.php:
<?php
class OrderLine {
public $id;
public $orderid;
public $item;
public $qty;
public function __construct($id = 0, $orderid = 0, $item = '', $qty = 0) {
$this->id = $id;
$this->orderid = $orderid;
$this->item = $item;
$this->qty = $qty;
}
}
class Order {
public $id;
public $customer;
public $lines;
public function __construct($id = 0, $customer = '', $lines = array()) {
$this->id = $id;
$this->customer = $customer;
$this->lines = $lines;
}
}
?>
<?php
include '/disk2/arne/migr/reltwo/order.php';
$con = new PDO('sqlite:/disk2/arne/migr/reltwo/order.db');
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$con->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$ostmt = $con->prepare('INSERT INTO myorder VALUES(:ID,:CUSTOMER)');
$olstmt = $con->prepare('INSERT INTO orderline VALUES(:ID,:ORDERID,:ITEM,:QTY)');
$o = new Order(11, 'K K', array(new OrderLine(1100, 11, 'A good PHP book', 1)));
foreach($o->lines as $ol) {
$olstmt->execute(array(':ID' => $ol->id, ':ORDERID' => $ol->orderid, ':ITEM' => $ol->item, ':QTY' => $ol->qty));
}
$ostmt->execute(array(':ID' => $o->id, ':CUSTOMER' => $o->customer));
$o = new Order(12, 'L L', array(new OrderLine(1200, 12, 'Another good PHP book', 1)));
foreach($o->lines as $ol) {
$olstmt->execute(array(':ID' => $ol->id, ':ORDERID' => $ol->orderid, ':ITEM' => $ol->item, ':QTY' => $ol->qty));
}
$ostmt->execute(array(':ID' => $o->id, ':CUSTOMER' => $o->customer));
?>
public class OrderLine {
private int id;
private int orderId;
private String item;
private int qty;
public OrderLine() {
this(0, 0, "", 0);
}
public OrderLine(int id, int orderId, String item, int qty) {
this.id = id;
this.orderId = orderId;
this.item = item;
this.qty = qty;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
public int getQty() {
return qty;
}
public void setQty(int qty) {
this.qty = qty;
}
}
import java.util.ArrayList;
import java.util.List;
public class Order {
private int id;
private String customer;
private List<OrderLine> lines;
public Order() {
this(0, "", new ArrayList<OrderLine>());
}
public Order(int id, String customer) {
this(id, customer, new ArrayList<OrderLine>());
}
public Order(int id, String customer, List<OrderLine> lines) {
this.id = id;
this.customer = customer;
this.lines = lines;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCustomer() {
return customer;
}
public void setCustomer(String customer) {
this.customer = customer;
}
public List<OrderLine> getLines() {
return lines;
}
public void setLines(List<OrderLine> lines) {
this.lines = lines;
}
}
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.PreparedStatement;
public class InsertAfter5 {
public static void main(String[] args) throws Exception {
Class.forName("org.sqlite.JDBC");
Connection con = DriverManager.getConnection("jdbc:sqlite:order.db");
PreparedStatement opstmt = con.prepareStatement("INSERT INTO myorder VALUES(?,?)");
PreparedStatement olpstmt = con.prepareStatement("INSERT INTO orderline VALUES(?,?,?,?)");
Order o;
o = new Order(13, "M M");
o.getLines().add(new OrderLine(1300, 13, "A good Java book", 1));
for(OrderLine ol : o.getLines()) {
olpstmt.setInt(1, ol.getId());
olpstmt.setInt(2, ol.getOrderId());
olpstmt.setString(3, ol.getItem());
olpstmt.setInt(4, ol.getQty());
olpstmt.executeUpdate();
}
opstmt.setInt(1, o.getId());
opstmt.setString(2, o.getCustomer());
opstmt.executeUpdate();
o = new Order(14, "N N");
o.getLines().add(new OrderLine(1400, 14, "Another good Java book", 1));
for(OrderLine ol : o.getLines()) {
olpstmt.setInt(1, ol.getId());
olpstmt.setInt(2, ol.getOrderId());
olpstmt.setString(3, ol.getItem());
olpstmt.setInt(4, ol.getQty());
olpstmt.executeUpdate();
}
opstmt.setInt(1, o.getId());
opstmt.setString(2, o.getCustomer());
opstmt.executeUpdate();
opstmt.close();
con.close();
}
}
Build and run:
$ javac InsertAfter5.java Order.java OrderLine.java
$ java -cp .:/javalib/sqlite-jdbc-3_14_1-vms.jar "InsertAfter5"
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="orderline")
public class OrderLineJPA {
private int id;
private int orderId;
private String item;
private int qty;
public OrderLineJPA() {
this(0, 0, "", 0);
}
public OrderLineJPA(int id, int orderId, String item, int qty) {
this.id = id;
this.orderId = orderId;
this.item = item;
this.qty = qty;
}
@Id
@Column(name="id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name="orderid")
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
@Column(name="item")
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
@Column(name="qty")
public int getQty() {
return qty;
}
public void setQty(int qty) {
this.qty = qty;
}
}
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name="myorder")
public class OrderJPA {
private int id;
private String customer;
private List<OrderLineJPA> lines;
public OrderJPA() {
this(0, "", new ArrayList<OrderLineJPA>());
}
public OrderJPA(int id, String customer) {
this(id, customer, new ArrayList<OrderLineJPA>());
}
public OrderJPA(int id, String customer, List<OrderLineJPA> lines) {
this.id = id;
this.customer = customer;
this.lines = lines;
}
@Id
@Column(name="id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name="customer")
public String getCustomer() {
return customer;
}
public void setCustomer(String customer) {
this.customer = customer;
}
@OneToMany(mappedBy = "orderId", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
public List<OrderLineJPA> getLines() {
return lines;
}
public void setLines(List<OrderLineJPA> lines) {
this.lines = lines;
}
}
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 InsertAfter6 {
public static void main(String[] args) throws Exception {
Logger.getLogger("org.hibernate").setLevel(Level.OFF);
EntityManagerFactory emf = Persistence.createEntityManagerFactory("Order");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
OrderJPA o;
o = new OrderJPA(15, "O O");
o.getLines().add(new OrderLineJPA(1500, 15, "A good Java book", 1));
em.persist(o);
o = new OrderJPA(16, "P P");
o.getLines().add(new OrderLineJPA(1600, 16, "Another good Java book", 1));
em.persist(o);
em.getTransaction().commit();
em.close();
emf.close();
}
}
Build and run:
$ javac -cp 'hibpath' InsertAfter6.java OrderJPA.java OrderLineJPA.java
$ java -cp .:'hibpath':/javalib/sqlite-jdbc-3_14_1-vms.jar:/javalib/sqlitehib.jar "InsertAfter6"
order.h:
struct orderline
{
int id;
int orderid;
char item[33];
int qty;
};
struct order
{
int id;
char customer[33];
int nlines;
struct orderline line[100];
};
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sqlite3.h"
#include "order.h"
int main()
{
sqlite3 *con;
sqlite3_stmt *sel;
char *sqlstr = "SELECT myorder.id,myorder.customer,orderline.id,orderline.orderid,orderline.item,orderline.qty FROM myorder JOIN orderline ON myorder.id = orderline.orderid";
int stat;
int lastid;
int count;
struct order res[1000];
int i, j;
stat = sqlite3_open("order.db", &con);
stat = sqlite3_prepare(con, sqlstr, strlen(sqlstr), &sel, NULL);
lastid = -1;
count = 0;
while(sqlite3_step(sel) == SQLITE_ROW)
{
if(sqlite3_column_int(sel, 0) != lastid)
{
lastid = sqlite3_column_int(sel, 0);
count++;
res[count-1].id = sqlite3_column_int(sel, 0);
strcpy(res[count-1].customer, (char *)sqlite3_column_text(sel, 1));
res[count-1].nlines = 0;
}
res[count-1].line[res[count-1].nlines].id = sqlite3_column_int(sel, 2);
res[count-1].line[res[count-1].nlines].orderid = sqlite3_column_int(sel, 3);
strcpy(res[count-1].line[res[count-1].nlines].item, (char *)sqlite3_column_text(sel, 4));
res[count-1].line[res[count-1].nlines].qty = sqlite3_column_int(sel, 5);
res[count-1].nlines++;
}
sqlite3_finalize(sel);
sqlite3_close(con);
for(i = 0; i < count; i++)
{
printf("%d %s\n", res[i].id, res[i].customer);
for(j = 0; j < res[i].nlines; j++)
{
printf(" %s : %d\n", res[i].line[j].item, res[i].line[j].qty);
}
}
return 0;
}
Build and run:
$ cc/include=sqlite3_include: list_after_1
$ link list_after_1 + sys$input/opt
sqlite3shr/share
$
$ run list_after_1
order.pas:
type
orderline = record
id : integer;
orderid : integer;
item : varying[32] of char;
qty : unsigned;
end;
order = record
id : unsigned;
customer : varying[32] of char;
nlines : integer;
line : array [1..100] of orderline;
end;
[inherit('psqlitedir:sqlite', 'psqlitedir:psqlite')]
program list_after_2(input, output);
%include 'order.pas'
var
con : sqlite_ptr;
sel : sqlite_stmt_ptr;
res : array [1..1000] of order;
count : integer;
lastid : integer;
i, j : integer;
begin
con := psqlite_open('order.db');
sel := psqlite_prepare(con, 'SELECT myorder.id,myorder.customer,orderline.id,orderline.orderid,orderline.item,orderline.qty FROM myorder JOIN orderline ON myorder.id = orderline.orderid');
count := 0;
lastid := -1;
while psqlite_step_query(sel) do begin
if psqlite_column_int(sel, 0) <> lastid then begin
lastid := psqlite_column_int(sel, 0);
count := count + 1;
res[count].id := psqlite_column_int(sel, 0);
res[count].customer := psqlite_column_text(sel, 1);
res[count].nlines := 0;
end;
res[count].nlines := res[count].nlines + 1;
res[count].line[res[count].nlines].id := psqlite_column_int(sel, 2);
res[count].line[res[count].nlines].orderid := psqlite_column_int(sel, 3);
res[count].line[res[count].nlines].item := psqlite_column_text(sel, 4);
res[count].line[res[count].nlines].qty := psqlite_column_int(sel, 5);
end;
psqlite_finalize(sel);
psqlite_close(con);
for i := 1 to count do begin
writeln(res[i].id:1, ' ', res[i].customer);
for j := 1 to res[i].nlines do begin
writeln(' ', res[i].line[j].item, ': ', res[i].line[j].qty);
end;
end;
end.
Build and run:
$ pas list_after_2
$ link list_after_2 + sys$input/opt + psqlitedir:sqlite/opt
psqlitedir:psqlite
psqlitedir:sqlite
$
$ run list_after_2
order.py:
class OrderLine(object):
def __init__(self, _id = 0, _orderid = 0, _item = '', _qty = 0):
self.id = _id
self.orderid = _orderid
self.item = _item
self.qty = _qty
class Order(object):
def __init__(self, _id = 0, _customer = '', _lines = []):
self.id = _id
self.customer = _customer
self.lines = _lines
import sqlite3
from order import Order, OrderLine
con = sqlite3.connect('order.db')
c = con.cursor()
c.execute('SELECT myorder.id,myorder.customer,orderline.id,orderline.orderid,orderline.item,orderline.qty FROM myorder JOIN orderline ON myorder.id = orderline.orderid')
res = []
lastid = -1
lasto = None
for row in c.fetchall():
if row[0] != lastid:
lastid = row[0]
lasto = Order(row[0], row[1], [])
res.append(lasto)
lasto.lines.append(OrderLine(row[2], row[3], row[4], row[5]))
con.commit()
con.close()
for o in res:
print('%d %s' % (o.id, o.customer))
for ol in o.lines:
print(' %s : %d' % (ol.item, ol.qty))
order.php:
<?php
class OrderLine {
public $id;
public $orderid;
public $item;
public $qty;
public function __construct($id = 0, $orderid = 0, $item = '', $qty = 0) {
$this->id = $id;
$this->orderid = $orderid;
$this->item = $item;
$this->qty = $qty;
}
}
class Order {
public $id;
public $customer;
public $lines;
public function __construct($id = 0, $customer = '', $lines = array()) {
$this->id = $id;
$this->customer = $customer;
$this->lines = $lines;
}
}
?>
<?php
include '/disk2/arne/migr/reltwo/order.php';
$con = new PDO('sqlite:/disk2/arne/migr/reltwo/order.db');
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$con->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_NUM);
$stmt = $con->prepare('SELECT myorder.id,myorder.customer,orderline.id,orderline.orderid,orderline.item,orderline.qty FROM myorder JOIN orderline ON myorder.id = orderline.orderid');
$stmt->execute(array());
$res = array();
$lastid = -1;
$lasto = null;
while($row = $stmt->fetch()) {
if($lastid != $row[0]) {
$lastid = $row[0];
$lasto = new Order($row[0], $row[1], array());
$res[] = $lasto;
}
$lasto->lines[] = new OrderLine($row[2], $row[3], $row[4], $row[5]);
}
foreach($res as $o) {
echo sprintf('%d %s', $o->id, $o->customer) . "\r\n";
foreach($o->lines as $ol) {
echo sprintf(' %s : %d', $ol->item, $ol->qty) . "\r\n";
}
}
?>
public class OrderLine {
private int id;
private int orderId;
private String item;
private int qty;
public OrderLine() {
this(0, 0, "", 0);
}
public OrderLine(int id, int orderId, String item, int qty) {
this.id = id;
this.orderId = orderId;
this.item = item;
this.qty = qty;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
public int getQty() {
return qty;
}
public void setQty(int qty) {
this.qty = qty;
}
}
import java.util.ArrayList;
import java.util.List;
public class Order {
private int id;
private String customer;
private List<OrderLine> lines;
public Order() {
this(0, "", new ArrayList<OrderLine>());
}
public Order(int id, String customer) {
this(id, customer, new ArrayList<OrderLine>());
}
public Order(int id, String customer, List<OrderLine> lines) {
this.id = id;
this.customer = customer;
this.lines = lines;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCustomer() {
return customer;
}
public void setCustomer(String customer) {
this.customer = customer;
}
public List<OrderLine> getLines() {
return lines;
}
public void setLines(List<OrderLine> lines) {
this.lines = lines;
}
}
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
public class ListAfter5 {
public static void main(String[] args) throws Exception {
Class.forName("org.sqlite.JDBC");
List<Order> res = new ArrayList<Order>();
Connection con = DriverManager.getConnection("jdbc:sqlite:order.db");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT myorder.id,myorder.customer,orderline.id,orderline.orderid,orderline.item,orderline.qty FROM myorder JOIN orderline ON myorder.id = orderline.orderid");
int lastid = -1;
Order lasto = null;
while(rs.next()) {
int id = rs.getInt(1);
String customer = rs.getString(2);
int lineid = rs.getInt(3);
int orderid = rs.getInt(4);
String item = rs.getString(5);
int qty = rs.getInt(6);
if(id != lastid) {
lastid = id;
lasto = new Order(id, customer);
res.add(lasto);
}
OrderLine line = new OrderLine(lineid, orderid, item, qty);
lasto.getLines().add(line);
}
rs.close();
stmt.close();
con.close();
for(Order o : res) {
System.out.printf("%d %s\n", o.getId(), o.getCustomer());
for(OrderLine ol : o.getLines()) {
System.out.printf(" %s : %d\n", ol.getItem(), ol.getQty());
}
}
}
}
Build and run:
$ javac ListAfter5.java Order.java OrderLine.java
$ java -cp .:/javalib/sqlite-jdbc-3_14_1-vms.jar "ListAfter5"
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="orderline")
public class OrderLineJPA {
private int id;
private int orderId;
private String item;
private int qty;
public OrderLineJPA() {
this(0, 0, "", 0);
}
public OrderLineJPA(int id, int orderId, String item, int qty) {
this.id = id;
this.orderId = orderId;
this.item = item;
this.qty = qty;
}
@Id
@Column(name="id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name="orderid")
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
@Column(name="item")
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
@Column(name="qty")
public int getQty() {
return qty;
}
public void setQty(int qty) {
this.qty = qty;
}
}
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name="myorder")
public class OrderJPA {
private int id;
private String customer;
private List<OrderLineJPA> lines;
public OrderJPA() {
this(0, "", new ArrayList<OrderLineJPA>());
}
public OrderJPA(int id, String customer) {
this(id, customer, new ArrayList<OrderLineJPA>());
}
public OrderJPA(int id, String customer, List<OrderLineJPA> lines) {
this.id = id;
this.customer = customer;
this.lines = lines;
}
@Id
@Column(name="id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name="customer")
public String getCustomer() {
return customer;
}
public void setCustomer(String customer) {
this.customer = customer;
}
@OneToMany(mappedBy = "orderId", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
public List<OrderLineJPA> getLines() {
return lines;
}
public void setLines(List<OrderLineJPA> lines) {
this.lines = lines;
}
}
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 ListAfter6 {
public static void main(String[] args) throws Exception {
Logger.getLogger("org.hibernate").setLevel(Level.OFF);
EntityManagerFactory emf = Persistence.createEntityManagerFactory("Order");
EntityManager em = emf.createEntityManager();
TypedQuery<OrderJPA> q = em.createQuery("SELECT o FROM OrderJPA AS o JOIN FETCH o.lines ol", OrderJPA.class);
List<OrderJPA> res = q.getResultList();
for(OrderJPA o : res) {
System.out.printf("%d %s\n", o.getId(), o.getCustomer());
for(OrderLineJPA ol : o.getLines()) {
System.out.printf(" %s : %d\n", ol.getItem(), ol.getQty());
}
}
em.close();
emf.close();
}
}
Build and run:
$ javac -cp 'hibpath' ListAfter6.java OrderJPA.java OrderLineJPA.java
$ java -cp .:'hibpath':/javalib/sqlite-jdbc-3_14_1-vms.jar:/javalib/sqlitehib.jar "ListAfter6"
Before records:
id | description | assettype | model | license | towcapacity |
---|---|---|---|---|---|
1 | Red Truck | TRUCK | GMC Sierra | AB1234 | 6000 |
id | description | assettype | ownweight | maxcargo | roof |
2 | Small trailer | TRAILER | 500 | 3000 | REALROOF |
id | description | assettype | tooltype | name | weight |
3 | Lawn tractor #1 | TOOL | Lawn tractor | Craftsman | 1000 |
After database tables:
asset
id | description | assettype |
---|---|---|
1 | Red truck | TRUCK |
2 | Small trailer | TRAILER |
3 | Lawn tractor #1 | TOOL |
truckasset
id | model | license | towcapacity |
---|---|---|---|
1 | GMC Sierrra | AB1234 | 6000 |
trailerasset
id | ownweight | maxcargo | roof |
---|---|---|---|
2 | 500 | 3000 | REALROOF |
toolasset
id | tooltype | name | weight |
---|---|---|---|
3 | Lawn tractor | Craftsman | 1000 |
IDENTIFICATION DIVISION.
PROGRAM-ID.INSERT-BEFORE-1.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT OPTIONAL ASSET-FILE ASSIGN TO "asset.isq" ORGANIZATION IS INDEXED ACCESS MODE IS DYNAMIC RECORD KEY IS ASSET-ID.
DATA DIVISION.
FILE SECTION.
FD ASSET-FILE.
01 ASSET-RECORD.
03 ASSET-ID PIC 9(8) COMP.
03 ASSET-DESCRIPTION PIC X(32).
03 ASSET-ASSETTYPE PIC 9(8) COMP.
03 TRUCK-ASSET.
05 TRUCK-MODEL PIC X(16).
05 TRUCK-LICENSE PIC X(8).
05 TRUCK-TOWCAPACITY PIC 9(8) COMP.
05 FILLER PIC X(8).
03 TRAILER-ASSET REDEFINES TRUCK-ASSET.
05 TRAILER-OWNWEIGHT PIC 9(8) COMP.
05 TRAILER-MAXCARGO PIC 9(8) COMP.
05 TRAILER-ROOF PIC 9(8) COMP.
03 TOOL-ASSET REDEFINES TRUCK-ASSET.
05 TOOL-TOOLTYPE PIC X(16).
05 TOOL-NAME PIC X(16).
05 TOOL-WEIGHT PIC 9(8) COMP.
WORKING-STORAGE SECTION.
01 TRUCK PIC 9(8) COMP VALUE 1.
01 TRAILER PIC 9(8) COMP VALUE 2.
01 TOOL PIC 9(8) COMP VALUE 3.
01 PERMOPEN PIC 9(8) COMP VALUE 1.
01 COVERABLE PIC 9(8) COMP VALUE 2.
01 REALROOF PIC 9(8) COMP VALUE 3.
PROCEDURE DIVISION.
MAIN-PARAGRAPH.
OPEN I-O ASSET-FILE
MOVE 1 TO ASSET-ID
MOVE "Red truck" TO ASSET-DESCRIPTION
MOVE TRUCK TO ASSET-ASSETTYPE
MOVE "GMC Sierra" TO TRUCK-MODEL
MOVE "AB1234" TO TRUCK-LICENSE
MOVE 6000 TO TRUCK-TOWCAPACITY
PERFORM INSERT-PARAGRAPH
MOVE 2 TO ASSET-ID
MOVE "Small trailer" TO ASSET-DESCRIPTION
MOVE TRAILER TO ASSET-ASSETTYPE
MOVE 500 TO TRAILER-OWNWEIGHT
MOVE 3000 TO TRAILER-MAXCARGO
MOVE REALROOF TO TRAILER-ROOF
PERFORM INSERT-PARAGRAPH
MOVE 3 TO ASSET-ID
MOVE "Lawn tracctor #1" TO ASSET-DESCRIPTION
MOVE TOOL TO ASSET-ASSETTYPE
MOVE "Lawn tractor" TO TOOL-TOOLTYPE
MOVE "Craftsman" TO TOOL-NAME
MOVE 1000 TO TOOL-WEIGHT
PERFORM INSERT-PARAGRAPH
CLOSE ASSET-FILE
STOP RUN.
INSERT-PARAGRAPH.
WRITE ASSET-RECORD
INVALID KEY DISPLAY "Error writing"
NOT INVALID KEY CONTINUE
END-WRITE.
Build and run:
$ cob insert_before_1
$ link insert_before_1
$ run insert_before_1
asset_isam.pas:
const
TRUCK = 1;
TRAILER = 2;
TOOL = 3;
const
PERMOPEN = 1;
COVERABLE = 2;
REALROOF = 3;
type
asset = record
id : [key(0)]unsigned;
description : packed array [1..32] of char;
assettype : integer;
case integer of
TRUCK:
(
model : packed array[1..16] of char;
license : packed array[1..8] of char;
towcapacity : integer;
);
TRAILER:
(
ownweight : integer;
maxcargo : integer;
roof : integer;
);
TOOL:
(
tooltype : packed array[1..16] of char;
name : packed array[1..16] of char;
weight : integer;
);
end;
program insert_before_2(input, output);
%include 'asset_isam.pas'
var
a : asset;
db : file of asset;
begin
open(db, 'asset.isq', unknown, organization := indexed, access_method := keyed);
a.id := 4;
a.description := 'Blue truck';
a.assettype := TRUCK;
a.model := 'Ford F-250';
a.license := 'CD5678';
a.towcapacity := 10000;
db^ := a;
put(db);
a.id := 5;
a.description := 'Large trailer';
a.assettype := TRAILER;
a.ownweight := 1000;
a.maxcargo := 6000;
a.roof := PERMOPEN;
db^ := a;
put(db);
a.id := 6;
a.description := 'Lawn tractor #2';
a.assettype := TOOL;
a.tooltype := 'Lawn tractor';
a.name := 'Craftsman';
a.weight := 1000;
db^ := a;
put(db);
close(db);
end.
Build and run:
$ pas insert_before_2
$ link insert_before_2
$ run insert_before_2
IDENTIFICATION DIVISION.
PROGRAM-ID.LIST-BEFORE-1.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT OPTIONAL ASSET-FILE ASSIGN TO "asset.isq" ORGANIZATION IS INDEXED ACCESS MODE IS DYNAMIC RECORD KEY IS ASSET-ID.
DATA DIVISION.
FILE SECTION.
FD ASSET-FILE.
01 ASSET-RECORD.
03 ASSET-ID PIC 9(8) COMP.
03 ASSET-DESCRIPTION PIC X(32).
03 ASSET-ASSETTYPE PIC 9(8) COMP.
03 TRUCK-ASSET.
05 TRUCK-MODEL PIC X(16).
05 TRUCK-LICENSE PIC X(8).
05 TRUCK-TOWCAPACITY PIC 9(8) COMP.
05 FILLER PIC X(8).
03 TRAILER-ASSET REDEFINES TRUCK-ASSET.
05 TRAILER-OWNWEIGHT PIC 9(8) COMP.
05 TRAILER-MAXCARGO PIC 9(8) COMP.
05 TRAILER-ROOF PIC 9(8) COMP.
03 TOOL-ASSET REDEFINES TRUCK-ASSET.
05 TOOL-TOOLTYPE PIC X(16).
05 TOOL-NAME PIC X(16).
05 TOOL-WEIGHT PIC 9(8) COMP.
WORKING-STORAGE SECTION.
01 TRUCK PIC 9(8) COMP VALUE 1.
01 TRAILER PIC 9(8) COMP VALUE 2.
01 TOOL PIC 9(8) COMP VALUE 3.
01 PERMOPEN PIC 9(8) COMP VALUE 1.
01 COVERABLE PIC 9(8) COMP VALUE 2.
01 REALROOF PIC 9(8) COMP VALUE 3.
01 EOF-FLAG PIC X.
01 ID PIC 9(8) DISPLAY.
01 TOWCAPACITY PIC 9(8) DISPLAY.
01 OWNWEIGHT PIC 9(8) DISPLAY.
01 MAXCARGO PIC 9(8) DISPLAY.
01 ROOF PIC 9(8) DISPLAY.
01 WEIGHT PIC 9(8) DISPLAY.
PROCEDURE DIVISION.
MAIN-PARAGRAPH.
OPEN I-O ASSET-FILE
MOVE 'N' TO EOF-FLAG
PERFORM UNTIL EOF-FLAG = 'Y'
READ ASSET-FILE NEXT
AT END MOVE 'Y' TO EOF-FLAG
NOT AT END PERFORM SHOW-PARAGRAPH
END-READ
END-PERFORM
CLOSE ASSET-FILE
STOP RUN.
SHOW-PARAGRAPH.
EVALUATE ASSET-ASSETTYPE
WHEN TRUCK PERFORM SHOW-TRUCK-PARAGRAPH
WHEN TRAILER PERFORM SHOW-TRAILER-PARAGRAPH
WHEN TOOL PERFORM SHOW-TOOL-PARAGRAPH.
SHOW-TRUCK-PARAGRAPH.
MOVE ASSET-ID TO ID
MOVE TRUCK-TOWCAPACITY TO TOWCAPACITY
DISPLAY ID " " ASSET-DESCRIPTION " " TRUCK-MODEL " " TRUCK-LICENSE " " TOWCAPACITY.
SHOW-TRAILER-PARAGRAPH.
MOVE ASSET-ID TO ID
MOVE TRAILER-OWNWEIGHT TO OWNWEIGHT
MOVE TRAILER-MAXCARGO TO MAXCARGO
MOVE TRAILER-ROOF TO ROOF
DISPLAY ID " " ASSET-DESCRIPTION " " OWNWEIGHT " " MAXCARGO " " ROOF.
SHOW-TOOL-PARAGRAPH.
MOVE ASSET-ID TO ID
MOVE TOOL-WEIGHT TO WEIGHT
DISPLAY ID " " ASSET-DESCRIPTION " " TOOL-TOOLTYPE " " TOOL-NAME " " WEIGHT.
Build and run:
$ cob list_before_1
$ link list_before_1
$ run list_before_1
asset_isam.pas:
const
TRUCK = 1;
TRAILER = 2;
TOOL = 3;
const
PERMOPEN = 1;
COVERABLE = 2;
REALROOF = 3;
type
asset = record
id : [key(0)]unsigned;
description : packed array [1..32] of char;
assettype : integer;
case integer of
TRUCK:
(
model : packed array[1..16] of char;
license : packed array[1..8] of char;
towcapacity : integer;
);
TRAILER:
(
ownweight : integer;
maxcargo : integer;
roof : integer;
);
TOOL:
(
tooltype : packed array[1..16] of char;
name : packed array[1..16] of char;
weight : integer;
);
end;
program list_before_2(input, output);
%include 'asset_isam.pas'
var
a : asset;
db : file of asset;
begin
open(db, 'asset.isq', unknown, organization := indexed, access_method := keyed);
resetk(db, 0);
while not eof(db) do begin
a := db^;
write(a.id, ' ', a.description, ' ');
case a.assettype of
TRUCK:
begin
write(a.model, ' ', a.license, ' ', a.towcapacity);
end;
TRAILER:
begin
write(a.ownweight, ' ', a.maxcargo, ' ', a.roof);
end;
TOOL:
begin
write(a.tooltype, ' ', a.name, ' ', a.weight);
end;
end;
writeln;
get(db);
end;
close(db);
end.
Build and run:
$ pas list_before_2
$ link list_before_2
$ run list_before_2
The variants within a record require a new feature in the annotations:
import dk.vajhoej.isam.KeyField;
import dk.vajhoej.record.Alignment;
import dk.vajhoej.record.Endian;
import dk.vajhoej.record.FieldType;
import dk.vajhoej.record.Selector;
import dk.vajhoej.record.Struct;
import dk.vajhoej.record.StructField;
import dk.vajhoej.record.SubType;
@Struct(endianess=Endian.LITTLE, alignment=Alignment.ALIGN1)
public class AssetISAM {
@KeyField(n=0)
@StructField(n=0, type=FieldType.INT4)
private int id;
@StructField(n=1, type=FieldType.FIXSTR, length=32)
private String description;
@StructField(n=2, type=FieldType.INT4)
@Selector(subtypes={@SubType(value=1,type=TruckAssetISAM.class),
@SubType(value=2,type=TrailerAssetISAM.class),
@SubType(value=3,type=ToolAssetISAM.class)})
private int assetType;
public AssetISAM() {
this(0, "", 0);
}
public AssetISAM(int id, String description, int assetType) {
this.id = id;
this.description = description;
this.assetType = assetType;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getAssetType() {
return assetType;
}
public void setAssetType(int assetType) {
this.assetType = assetType;
}
}
import dk.vajhoej.record.Alignment;
import dk.vajhoej.record.Endian;
import dk.vajhoej.record.FieldType;
import dk.vajhoej.record.Struct;
import dk.vajhoej.record.StructField;
@Struct(endianess=Endian.LITTLE, alignment=Alignment.ALIGN1)
public class TruckAssetISAM extends AssetISAM {
@StructField(n=3, type=FieldType.FIXSTR, length=16)
private String model;
@StructField(n=4, type=FieldType.FIXSTR, length=8)
private String license;
@StructField(n=5, type=FieldType.INT4)
private int towcapacity;
public TruckAssetISAM() {
this(0, "", "", "", 0);
}
public TruckAssetISAM(int id, String description, String model, String license, int towcapacity) {
super(id, description, 1);
this.model = model;
this.license = license;
this.towcapacity = towcapacity;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getLicense() {
return license;
}
public void setLicense(String license) {
this.license = license;
}
public int getTowcapacity() {
return towcapacity;
}
public void setTowcapacity(int towcapacity) {
this.towcapacity = towcapacity;
}
}
import dk.vajhoej.record.Alignment;
import dk.vajhoej.record.Endian;
import dk.vajhoej.record.FieldType;
import dk.vajhoej.record.Struct;
import dk.vajhoej.record.StructField;
@Struct(endianess=Endian.LITTLE, alignment=Alignment.ALIGN1)
public class TrailerAssetISAM extends AssetISAM {
@StructField(n=3, type=FieldType.INT4)
private int ownWeight;
@StructField(n=4, type=FieldType.INT4)
private int maxCargo;
@StructField(n=5, type=FieldType.INT4)
private int roof;
public TrailerAssetISAM() {
this(0, "", 0, 0, 0);
}
public TrailerAssetISAM(int id, String description, int ownWeight, int maxCargo, int roof) {
super(id, description, 2);
this.ownWeight = ownWeight;
this.maxCargo = maxCargo;
this.roof = roof;
}
public int getOwnWeight() {
return ownWeight;
}
public void setOwnWeight(int ownWeight) {
this.ownWeight = ownWeight;
}
public int getMaxCargo() {
return maxCargo;
}
public void setMaxCargo(int maxCargo) {
this.maxCargo = maxCargo;
}
public int getRoof() {
return roof;
}
public void setRoof(int roof) {
this.roof = roof;
}
}
import dk.vajhoej.record.Alignment;
import dk.vajhoej.record.Endian;
import dk.vajhoej.record.FieldType;
import dk.vajhoej.record.Struct;
import dk.vajhoej.record.StructField;
@Struct(endianess=Endian.LITTLE, alignment=Alignment.ALIGN1)
public class ToolAssetISAM extends AssetISAM {
@StructField(n=3, type=FieldType.FIXSTR, length=16)
private String toolType;
@StructField(n=4, type=FieldType.FIXSTR, length=16)
private String name;
@StructField(n=5, type=FieldType.INT4)
private int weight;
public ToolAssetISAM() {
this(0, "", "", "", 0);
}
public ToolAssetISAM(int id, String description, String toolType, String name, int weight) {
super(id, description, 3);
this.toolType = toolType;
this.name = name;
this.weight = weight;
}
public String getToolType() {
return toolType;
}
public void setToolType(String toolType) {
this.toolType = toolType;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
The inheritance requires two new features in the annotations:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
@Entity
@Table(name="asset")
@Inheritance(strategy=InheritanceType.JOINED)
public class AssetJPA {
public static final int TRUCK = 1;
public static final int TRAILER = 2;
public static final int TOOL = 3;
private int id;
private String description;
private int assetType;
public AssetJPA() {
this(0, "", 0);
}
public AssetJPA(int id, String description, int assetType) {
this.id = id;
this.description = description;
this.assetType = assetType;
}
@Id
@Column(name="id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name="description")
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Column(name="assettype")
public int getAssetType() {
return assetType;
}
public void setAssetType(int assetType) {
this.assetType = assetType;
}
}
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
@Entity
@Table(name="truckasset")
@PrimaryKeyJoinColumn(name="id")
public class TruckAssetJPA extends AssetJPA {
private String model;
private String license;
private int towcapacity;
public TruckAssetJPA() {
this(0, "", "", "", 0);
}
public TruckAssetJPA(int id, String description, String model, String license, int towcapacity) {
super(id, description, TRUCK);
this.model = model;
this.license = license;
this.towcapacity = towcapacity;
}
@Column(name="model")
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
@Column(name="license")
public String getLicense() {
return license;
}
public void setLicense(String license) {
this.license = license;
}
@Column(name="towcapacity")
public int getTowcapacity() {
return towcapacity;
}
public void setTowcapacity(int towcapacity) {
this.towcapacity = towcapacity;
}
}
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
@Entity
@Table(name="trailerasset")
@PrimaryKeyJoinColumn(name="id")
public class TrailerAssetJPA extends AssetJPA {
private int ownWeight;
private int maxCargo;
private int roof;
public TrailerAssetJPA() {
this(0, "", 0, 0, 0);
}
public TrailerAssetJPA(int id, String description, int ownWeight, int maxCargo, int roof) {
super(id, description, TRAILER);
this.ownWeight = ownWeight;
this.maxCargo = maxCargo;
this.roof = roof;
}
@Column(name="ownweight")
public int getOwnWeight() {
return ownWeight;
}
public void setOwnWeight(int ownWeight) {
this.ownWeight = ownWeight;
}
@Column(name="maxcargo")
public int getMaxCargo() {
return maxCargo;
}
public void setMaxCargo(int maxCargo) {
this.maxCargo = maxCargo;
}
@Column(name="roof")
public int getRoof() {
return roof;
}
public void setRoof(int roof) {
this.roof = roof;
}
}
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
@Entity
@Table(name="toolasset")
@PrimaryKeyJoinColumn(name="id")
public class ToolAssetJPA extends AssetJPA {
public static final int PERMOPEN = 1;
public static final int COVERABLE = 2;
public static final int REALROOF = 3;
private String toolType;
private String name;
private int weight;
public ToolAssetJPA() {
this(0, "", "", "", 0);
}
public ToolAssetJPA(int id, String description, String toolType, String name, int weight) {
super(id, description, TOOL);
this.toolType = toolType;
this.name = name;
this.weight = weight;
}
@Column(name="tooltype")
public String getToolType() {
return toolType;
}
public void setToolType(String toolType) {
this.toolType = toolType;
}
@Column(name="name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name="weight")
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class AutoMap<TFROM,TTO> {
public static class MethodPair {
private Method getter;
private Method setter;
private boolean trim;
public MethodPair(Method getter, Method setter, boolean trim) {
this.getter = getter;
this.setter = setter;
this.trim = trim;
}
public Method getGetter() {
return getter;
}
public Method getSetter() {
return setter;
}
public boolean getTrim() {
return trim;
}
}
private List<MethodPair> conv;
public AutoMap(Class<TFROM> from, Class<TTO> to) throws IntrospectionException {
this(from, to, false);
}
public AutoMap(Class<TFROM> from, Class<TTO> to, boolean trim) throws IntrospectionException {
conv = new ArrayList<MethodPair>();
for(PropertyDescriptor pdfrom : Introspector.getBeanInfo(from).getPropertyDescriptors()) {
for(PropertyDescriptor pdto : Introspector.getBeanInfo(to).getPropertyDescriptors()) {
if(pdfrom.getName().equals(pdto.getName())) {
Method getter = pdfrom.getReadMethod();
Method setter = pdto.getWriteMethod();
if(getter != null && setter != null) {
conv.add(new MethodPair(getter, setter, trim && pdfrom.getPropertyType().equals(String.class)));
}
}
}
}
}
public void convert(TFROM from, TTO to) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
for(MethodPair mp : conv) {
if(mp.getTrim()) {
mp.getSetter().invoke(to, ((String)mp.getGetter().invoke(from)).trim());
} else {
mp.getSetter().invoke(to, mp.getGetter().invoke(from));
}
}
}
}
# stuff for JPA
from java.util.logging import Level
from java.util.logging import Logger
from javax.persistence import Persistence
# stuff for ISAM
from dk.vajhoej.isam import Key0
from dk.vajhoej.isam.local import LocalIsamSource
#input class
import AssetISAM
import TruckAssetISAM
import TrailerAssetISAM
import ToolAssetISAM
#output class
import AssetJPA
import TruckAssetJPA
import TrailerAssetJPA
import ToolAssetJPA
# auto map
import AutoMap
# open JPA
Logger.getLogger("org.hibernate").setLevel(Level.OFF)
emf = Persistence.createEntityManagerFactory("Asset")
em = emf.createEntityManager()
# open ISAM
db = LocalIsamSource('asset.isq', 'dk.vajhoej.vms.rms.IndexSequential', False)
# process all records
truckmapper = AutoMap(TruckAssetISAM, TruckAssetJPA, True)
trailermapper = AutoMap(TrailerAssetISAM, TrailerAssetJPA, True)
toolmapper = AutoMap(ToolAssetISAM, ToolAssetJPA, True)
it = db.readGE(AssetISAM, Key0(0))
em.getTransaction().begin()
while it.read():
oldrec = it.current()
if oldrec.assetType == 1:
newrec = TruckAssetJPA()
truckmapper.convert(oldrec, newrec)
if oldrec.assetType == 2:
newrec = TrailerAssetJPA()
trailermapper.convert(oldrec, newrec)
if oldrec.assetType == 3:
newrec = ToolAssetJPA()
toolmapper.convert(oldrec, newrec)
em.persist(newrec)
it.close()
em.getTransaction().commit()
# close ISAM
db.close()
# close JPA
em.close()
emf.close()
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="Asset">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>TruckAssetJPA</class>
<class>TrailerAssetJPA</class>
<class>ToolAssetJPA</class>
<exclude-unlisted-classes/>
<properties>
<!--<property name="show_sql" value="true"/>-->
<property name="hibernate.connection.driver_class" value="org.sqlite.JDBC"/>
<property name="hibernate.connection.url" value="jdbc:sqlite:asset.db"/>
<property name="hibernate.connection.username" value=""/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.dialect" value="org.hibernate.dialect.SQLiteDialect"/>
</properties>
</persistence-unit>
</persistence>
Database structure:
CREATE TABLE asset (
id INTEGER NOT NULL,
description VARCHAR(32),
assettype INTEGER,
PRIMARY KEY(id)
);
CREATE TABLE truckasset (
id INTEGER NOT NULL,
model VARCHAR(16),
license VARCHAR(8),
towcapacity INTEGER,
PRIMARY KEY(id)
);
CREATE TABLE trailerasset (
id INTEGER NOT NULL,
ownweight INTEGER,
maxcargo INTEGER,
roof INTEGER,
PRIMARY KEY(id)
);
CREATE TABLE toolasset (
id INTEGER NOT NULL,
tooltype VARCHAR(16),
name VARCHAR(16),
weight INTEGER,
PRIMARY KEY(id)
);
asset.h:
#define TRUCK 1
#define TRAILER 2
#define TOOL 3
#define PERMOPEN 1
#define COVERABLE 2
#define REALROOF 3
struct truckasset
{
char model[17];
char license[9];
int towcapacity;
};
struct trailerasset
{
int ownweight;
int maxcargo;
int roof;
};
struct toolasset
{
char tooltype[17];
char name[17];
int weight;
};
struct asset
{
int id;
char description[33];
int assettype;
union
{
struct truckasset truck;
struct trailerasset trailer;
struct toolasset tool;
} u;
};
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sqlite3.h"
#include "asset.h"
int main()
{
sqlite3 *con;
sqlite3_stmt *ins;
sqlite3_stmt *toolins;
char *sqlstr = "INSERT INTO asset VALUES(?,?,?)";
char *toolsqlstr = "INSERT INTO toolasset VALUES(?,?,?,?)";
int stat;
struct asset a;
stat = sqlite3_open("asset.db", &con);
stat = sqlite3_prepare(con, sqlstr, strlen(sqlstr), &ins, NULL);
stat = sqlite3_prepare(con, toolsqlstr, strlen(toolsqlstr), &toolins, NULL);
a.id = 7;
strcpy(a.description, "Shovel");
a.assettype = TOOL;
strcpy(a.u.tool.tooltype, "Shovel");
strcpy(a.u.tool.name, "Noname");
a.u.tool.weight = 5;
sqlite3_bind_int(ins, 1, a.id);
sqlite3_bind_text(ins, 2, a.description, strlen(a.description), NULL);
sqlite3_bind_int(ins, 3, a.assettype);
stat = sqlite3_step(ins);
sqlite3_finalize(ins);
sqlite3_bind_int(toolins, 1, a.id);
sqlite3_bind_text(toolins, 2, a.u.tool.tooltype, strlen(a.u.tool.tooltype), NULL);
sqlite3_bind_text(toolins, 3, a.u.tool.name, strlen(a.u.tool.name), NULL);
sqlite3_bind_int(toolins, 4, a.u.tool.weight);
stat = sqlite3_step(toolins);
sqlite3_finalize(toolins);
sqlite3_close(con);
return 0;
}
Build and run:
$ cc/include=sqlite3_include: insert_after_1
$ link insert_after_1 + sys$input/opt
sqlite3shr/share
$
$ run insert_after_1
asset.pas:
const
TRUCK = 1;
TRAILER = 2;
TOOL = 3;
const
PERMOPEN = 1;
COVERABLE = 2;
REALROOF = 3;
type
asset = record
id : unsigned;
description : varying[32] of char;
assettype : integer;
case integer of
TRUCK:
(
model : varying[16] of char;
license : varying[8] of char;
towcapacity : integer;
);
TRAILER:
(
ownweight : integer;
maxcargo : integer;
roof : integer;
);
TOOL:
(
tooltype : varying[16] of char;
name : varying[16] of char;
weight : integer;
);
end;
[inherit('psqlitedir:sqlite', 'psqlitedir:psqlite')]
program insert_after_2(input, output);
%include 'asset.pas'
var
con : sqlite_ptr;
ins, toolins : sqlite_stmt_ptr;
a : asset;
begin
con := psqlite_open('asset.db');
ins := psqlite_prepare(con, 'INSERT INTO asset VALUES(?,?,?)');
toolins := psqlite_prepare(con, 'INSERT INTO toolasset VALUES(?,?,?,?)');
a.id := 8;
a.description := 'Rake';
a.assettype := TOOL;
a.tooltype := 'Rake';
a.name := 'Noname';
a.weight := 5;
psqlite_bind_int(ins, 1, a.id);
psqlite_bind_text(ins, 2, a.description);
psqlite_bind_int(ins, 3, a.assettype);
psqlite_step_nonquery(ins);
psqlite_bind_int(toolins, 1, a.id);
psqlite_bind_text(toolins, 2, a.tooltype);
psqlite_bind_text(toolins, 3, a.name);
psqlite_bind_int(toolins, 4, a.weight);
psqlite_step_nonquery(toolins);
psqlite_finalize(ins);
psqlite_finalize(toolins);
psqlite_close(con);
end.
Build and run:
$ pas insert_after_2
$ link insert_after_2 + sys$input/opt + psqlitedir:sqlite/opt
psqlitedir:psqlite
psqlitedir:sqlite
$
$ run insert_after_2
asset.py:
TRUCK = 1
TRAILER = 2
TOOL = 3
PERMOPEN = 1
COVERABLE = 2
REALROOF = 3
class Asset(object):
def __init__(self, _id = 0, _description = '', _assettype = 0):
self.id = _id
self.description = _description
self.assettype = _assettype
class TruckAsset(Asset):
def __init__(self, _id = 0, _description = '', _model = '', _license = '', _towcapacity = 0):
super(TruckAsset, self).__init__(_id, _description, TRUCK)
self.model = _model
self.license = _license
self.towcapacity = _towcapacity
class TrailerAsset(Asset):
def __init__(self, _id = 0, _description = '', _ownweight = 0, _maxcargo = 0, _roof = 0):
super(TrailerAsset, self).__init__(_id, _description, TRAILER)
self.ownweight = _ownweight
self.maxcargo = _maxcargo
self.roof = _roof
class ToolAsset(Asset):
def __init__(self, _id = 0, _description = '', _tooltype = '', _name = '', _weight = 0):
super(ToolAsset, self).__init__(_id, _description, TOOL)
self.tooltype = _tooltype
self.name = _name
self.weight = _weight
import sqlite3
from asset import *
con = sqlite3.connect('asset.db')
c = con.cursor()
a = ToolAsset(9, 'Craftsman snowblower', 'Snowblower', 'Craftsman', 200)
c.execute('INSERT INTO asset VALUES(?,?,?)', (a.id, a.description, a.assettype))
c.execute('INSERT INTO toolasset VALUES(?,?,?,?)', (a.id, a.tooltype, a.name, a.weight))
con.commit()
con.close()
asset.php:
<?php
define('TRUCK', 1);
define('TRAILER', 2);
define('TOOL', 3);
define('PERMOPEN', 1);
define('COVERABLE', 2);
define('REALROOF', 3);
class Asset {
public $id;
public $description;
public $assetType;
public function __construct($id = 0, $description = '', $assetType = '') {
$this->id = $id;
$this->description = $description;
$this->assetType = $assetType;
}
}
class TruckAsset extends Asset {
public $model;
public $license;
public $towcapacity;
public function __construct($id = 0, $description = '', $model = '', $license = '', $towcapacity = 0) {
parent::__construct($id, $description, TRUCK);
$this->model = $model;
$this->license = $license;
$this->towcapacity = $towcapacity;
}
}
class TrailerAsset extends Asset {
public $ownWeight;
public $maxCargo;
public $roof;
public function __construct($id = 0, $description = '', $ownWeight = 0, $maxCargo = 0, $roof = 0) {
parent::__construct($id, $description, TRAILER);
$this->ownWeight = $ownWeight;
$this->maxCargo = $maxCargo;
$this->roof = $roof;
}
}
class ToolAsset extends Asset {
public $toolType;
public $name;
public $weight;
public function __construct($id = 0, $description = '', $toolType = '', $name = '', $weight = 0) {
parent::__construct($id, $description, TOOL);
$this->toolType = $toolType;
$this->name = $name;
$this->weight = $weight;
}
}
?>
<?php
include '/disk2/arne/migr/inher/asset.php';
$con = new PDO('sqlite:/disk2/arne/migr/inher/asset.db');
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$con->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$stmt = $con->prepare('INSERT INTO asset VALUES(:ID,:DESCRIPTION,:ASSETTYPE)');
$toolstmt = $con->prepare('INSERT INTO toolasset VALUES(:ID,:TOOLTYPE,:NAME,:WEIGHT)');
$a = new ToolAsset(10, 'Normal wheelbarrow', 'Wheelbarrow', 'Noname', 25);
$stmt->execute(array(':ID' => $a->id, ':DESCRIPTION' => $a->description, ':ASSETTYPE' => $a->assetType));
$toolstmt->execute(array(':ID' => $a->id, ':TOOLTYPE' => $a->toolType, ':NAME' => $a->name, ':WEIGHT' => $a->weight));
?>
public class Asset {
public static final int TRUCK = 1;
public static final int TRAILER = 2;
public static final int TOOL = 3;
private int id;
private String description;
private int assetType;
public Asset() {
this(0, "", 0);
}
public Asset(int id, String description, int assetType) {
this.id = id;
this.description = description;
this.assetType = assetType;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getAssetType() {
return assetType;
}
public void setAssetType(int assetType) {
this.assetType = assetType;
}
}
public class TruckAsset extends Asset {
private String model;
private String license;
private int towcapacity;
public TruckAsset() {
this(0, "", "", "", 0);
}
public TruckAsset(int id, String description, String model, String license, int towcapacity) {
super(id, description, TRUCK);
this.model = model;
this.license = license;
this.towcapacity = towcapacity;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getLicense() {
return license;
}
public void setLicense(String license) {
this.license = license;
}
public int getTowcapacity() {
return towcapacity;
}
public void setTowcapacity(int towcapacity) {
this.towcapacity = towcapacity;
}
}
public class TrailerAsset extends Asset {
private int ownWeight;
private int maxCargo;
private int roof;
public TrailerAsset() {
this(0, "", 0, 0, 0);
}
public TrailerAsset(int id, String description, int ownWeight, int maxCargo, int roof) {
super(id, description, TRAILER);
this.ownWeight = ownWeight;
this.maxCargo = maxCargo;
this.roof = roof;
}
public int getOwnWeight() {
return ownWeight;
}
public void setOwnWeight(int ownWeight) {
this.ownWeight = ownWeight;
}
public int getMaxCargo() {
return maxCargo;
}
public void setMaxCargo(int maxCargo) {
this.maxCargo = maxCargo;
}
public int getRoof() {
return roof;
}
public void setRoof(int roof) {
this.roof = roof;
}
}
public class ToolAsset extends Asset {
public static final int PERMOPEN = 1;
public static final int COVERABLE = 2;
public static final int REALROOF = 3;
private String toolType;
private String name;
private int weight;
public ToolAsset() {
this(0, "", "", "", 0);
}
public ToolAsset(int id, String description, String toolType, String name, int weight) {
super(id, description, TOOL);
this.toolType = toolType;
this.name = name;
this.weight = weight;
}
public String getToolType() {
return toolType;
}
public void setToolType(String toolType) {
this.toolType = toolType;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.PreparedStatement;
public class InsertAfter5 {
public static void main(String[] args) throws Exception {
Class.forName("org.sqlite.JDBC");
Connection con = DriverManager.getConnection("jdbc:sqlite:asset.db");
PreparedStatement pstmt = con.prepareStatement("INSERT INTO asset VALUES(?,?,?)");
PreparedStatement toolpstmt = con.prepareStatement("INSERT INTO toolasset VALUES(?,?,?,?)");
ToolAsset a = new ToolAsset(11, "Echo edger", "Edger", "Echo", 25);
pstmt.setInt(1, a.getId());
pstmt.setString(2, a.getDescription());
pstmt.setInt(3, a.getAssetType());
pstmt.executeUpdate();
toolpstmt.setInt(1, a.getId());
toolpstmt.setString(2, a.getToolType());
toolpstmt.setString(3, a.getName());
toolpstmt.setInt(4, a.getWeight());
toolpstmt.executeUpdate();
pstmt.close();
toolpstmt.close();
con.close();
}
}
Build and run:
$ javac InsertAfter5.java Asset.java TruckAsset.java TrailerAsset.java ToolAsset.java
$ java -cp .:/javalib/sqlite-jdbc-3_14_1-vms.jar "InsertAfter5"
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
@Entity
@Table(name="asset")
@Inheritance(strategy=InheritanceType.JOINED)
public class AssetJPA {
public static final int TRUCK = 1;
public static final int TRAILER = 2;
public static final int TOOL = 3;
private int id;
private String description;
private int assetType;
public AssetJPA() {
this(0, "", 0);
}
public AssetJPA(int id, String description, int assetType) {
this.id = id;
this.description = description;
this.assetType = assetType;
}
@Id
@Column(name="id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name="description")
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Column(name="assettype")
public int getAssetType() {
return assetType;
}
public void setAssetType(int assetType) {
this.assetType = assetType;
}
}
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
@Entity
@Table(name="truckasset")
@PrimaryKeyJoinColumn(name="id")
public class TruckAssetJPA extends AssetJPA {
private String model;
private String license;
private int towcapacity;
public TruckAssetJPA() {
this(0, "", "", "", 0);
}
public TruckAssetJPA(int id, String description, String model, String license, int towcapacity) {
super(id, description, TRUCK);
this.model = model;
this.license = license;
this.towcapacity = towcapacity;
}
@Column(name="model")
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
@Column(name="license")
public String getLicense() {
return license;
}
public void setLicense(String license) {
this.license = license;
}
@Column(name="towcapacity")
public int getTowcapacity() {
return towcapacity;
}
public void setTowcapacity(int towcapacity) {
this.towcapacity = towcapacity;
}
}
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
@Entity
@Table(name="trailerasset")
@PrimaryKeyJoinColumn(name="id")
public class TrailerAssetJPA extends AssetJPA {
private int ownWeight;
private int maxCargo;
private int roof;
public TrailerAssetJPA() {
this(0, "", 0, 0, 0);
}
public TrailerAssetJPA(int id, String description, int ownWeight, int maxCargo, int roof) {
super(id, description, TRAILER);
this.ownWeight = ownWeight;
this.maxCargo = maxCargo;
this.roof = roof;
}
@Column(name="ownweight")
public int getOwnWeight() {
return ownWeight;
}
public void setOwnWeight(int ownWeight) {
this.ownWeight = ownWeight;
}
@Column(name="maxcargo")
public int getMaxCargo() {
return maxCargo;
}
public void setMaxCargo(int maxCargo) {
this.maxCargo = maxCargo;
}
@Column(name="roof")
public int getRoof() {
return roof;
}
public void setRoof(int roof) {
this.roof = roof;
}
}
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
@Entity
@Table(name="toolasset")
@PrimaryKeyJoinColumn(name="id")
public class ToolAssetJPA extends AssetJPA {
public static final int PERMOPEN = 1;
public static final int COVERABLE = 2;
public static final int REALROOF = 3;
private String toolType;
private String name;
private int weight;
public ToolAssetJPA() {
this(0, "", "", "", 0);
}
public ToolAssetJPA(int id, String description, String toolType, String name, int weight) {
super(id, description, TOOL);
this.toolType = toolType;
this.name = name;
this.weight = weight;
}
@Column(name="tooltype")
public String getToolType() {
return toolType;
}
public void setToolType(String toolType) {
this.toolType = toolType;
}
@Column(name="name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name="weight")
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
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 InsertAfter6 {
public static void main(String[] args) throws Exception {
Logger.getLogger("org.hibernate").setLevel(Level.OFF);
EntityManagerFactory emf = Persistence.createEntityManagerFactory("Asset");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
AssetJPA a = new ToolAssetJPA(12, "Echo blower", "Blower", "Echo", 50);
em.persist(a);
em.getTransaction().commit();
em.close();
emf.close();
}
}
Build and run:
$ javac -cp 'hibpath' InsertAfter6.java AssetJPA.java TruckAssetJPA.java TrailerAssetJPA.java ToolAssetJPA.java
$ java -cp .:'hibpath':/javalib/sqlite-jdbc-3_14_1-vms.jar:/javalib/sqlitehib.jar "InsertAfter6"
asset.h:
#define TRUCK 1
#define TRAILER 2
#define TOOL 3
#define PERMOPEN 1
#define COVERABLE 2
#define REALROOF 3
struct truckasset
{
char model[17];
char license[9];
int towcapacity;
};
struct trailerasset
{
int ownweight;
int maxcargo;
int roof;
};
struct toolasset
{
char tooltype[17];
char name[17];
int weight;
};
struct asset
{
int id;
char description[33];
int assettype;
union
{
struct truckasset truck;
struct trailerasset trailer;
struct toolasset tool;
} u;
};
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sqlite3.h"
#include "asset.h"
int main()
{
sqlite3 *con;
sqlite3_stmt *trucksel;
sqlite3_stmt *trailersel;
sqlite3_stmt *toolsel;
char *trucksqlstr = "SELECT asset.id,asset.description,asset.assettype,truckasset.model,truckasset.license,truckasset.towcapacity FROM asset JOIN truckasset ON asset.id = truckasset.id";
char *trailersqlstr = "SELECT asset.id,asset.description,asset.assettype,trailerasset.ownweight,trailerasset.maxcargo,trailerasset.roof FROM asset JOIN trailerasset ON asset.id = trailerasset.id";
char *toolsqlstr = "SELECT asset.id,asset.description,asset.assettype,toolasset.tooltype,toolasset.name,toolasset.weight FROM asset JOIN toolasset ON asset.id = toolasset.id";
int stat;
int count;
struct asset res[1000];
int i;
stat = sqlite3_open("asset.db", &con);
count = 0;
stat = sqlite3_prepare(con, trucksqlstr, strlen(trucksqlstr), &trucksel, NULL);
while(sqlite3_step(trucksel) == SQLITE_ROW)
{
count++;
res[count-1].id = sqlite3_column_int(trucksel, 0);
strcpy(res[count-1].description, (char *)sqlite3_column_text(trucksel, 1));
res[count-1].assettype = sqlite3_column_int(trucksel, 2);
strcpy(res[count-1].u.truck.model, (char *)sqlite3_column_text(trucksel, 3));
strcpy(res[count-1].u.truck.license, (char *)sqlite3_column_text(trucksel, 4));
res[count-1].u.truck.towcapacity = sqlite3_column_int(trucksel, 5);
}
sqlite3_finalize(trucksel);
stat = sqlite3_prepare(con, trailersqlstr, strlen(trailersqlstr), &trailersel, NULL);
while(sqlite3_step(trailersel) == SQLITE_ROW)
{
count++;
res[count-1].id = sqlite3_column_int(trailersel, 0);
strcpy(res[count-1].description, (char *)sqlite3_column_text(trailersel, 1));
res[count-1].assettype = sqlite3_column_int(trailersel, 2);
res[count-1].u.trailer.ownweight = sqlite3_column_int(trailersel, 3);
res[count-1].u.trailer.maxcargo = sqlite3_column_int(trailersel, 4);
res[count-1].u.trailer.roof = sqlite3_column_int(trailersel, 5);
}
sqlite3_finalize(trailersel);
stat = sqlite3_prepare(con, toolsqlstr, strlen(toolsqlstr), &toolsel, NULL);
while(sqlite3_step(toolsel) == SQLITE_ROW)
{
count++;
res[count-1].id = sqlite3_column_int(toolsel, 0);
strcpy(res[count-1].description, (char *)sqlite3_column_text(toolsel, 1));
res[count-1].assettype = sqlite3_column_int(toolsel, 2);
strcpy(res[count-1].u.tool.tooltype, (char *)sqlite3_column_text(toolsel, 3));
strcpy(res[count-1].u.tool.name, (char *)sqlite3_column_text(toolsel, 4));
res[count-1].u.tool.weight = sqlite3_column_int(toolsel, 5);
}
sqlite3_finalize(toolsel);
sqlite3_close(con);
for(i = 0; i < count; i++)
{
switch(res[i].assettype)
{
case TRUCK:
printf("%d %s %s %s %d\n", res[i].id, res[i].description, res[i].u.truck.model,res[i].u.truck.license, res[i].u.truck.towcapacity);
break;
case TRAILER:
printf("%d %s %d %d %d\n", res[i].id, res[i].description, res[i].u.trailer.ownweight,res[i].u.trailer.maxcargo, res[i].u.trailer.roof );
break;
case TOOL:
printf("%d %s %s %s %d\n", res[i].id, res[i].description, res[i].u.tool.tooltype,res[i].u.tool.name, res[i].u.tool.weight );
break;
}
}
return 0;
}
Build and run:
$ cc/include=sqlite3_include: list_after_1
$ link list_after_1 + sys$input/opt
sqlite3shr/share
$
$ run list_after_1
asset.pas:
const
TRUCK = 1;
TRAILER = 2;
TOOL = 3;
const
PERMOPEN = 1;
COVERABLE = 2;
REALROOF = 3;
type
asset = record
id : unsigned;
description : varying[32] of char;
assettype : integer;
case integer of
TRUCK:
(
model : varying[16] of char;
license : varying[8] of char;
towcapacity : integer;
);
TRAILER:
(
ownweight : integer;
maxcargo : integer;
roof : integer;
);
TOOL:
(
tooltype : varying[16] of char;
name : varying[16] of char;
weight : integer;
);
end;
[inherit('psqlitedir:sqlite', 'psqlitedir:psqlite')]
program list_after_2(input, output);
%include 'asset.pas'
var
con : sqlite_ptr;
sel : sqlite_stmt_ptr;
count : integer;
res : array [1..1000] of asset;
i : integer;
begin
con := psqlite_open('asset.db');
count := 0;
sel := psqlite_prepare(con, 'SELECT asset.id,asset.description,asset.assettype,truckasset.model,truckasset.license,truckasset.towcapacity FROM asset JOIN truckasset ON asset.id = truckasset.id');
while psqlite_step_query(sel) do begin
count := count + 1;
res[count].id := psqlite_column_int(sel, 0);
res[count].description := psqlite_column_text(sel, 1);
res[count].assettype := psqlite_column_int(sel, 2);
res[count].model := psqlite_column_text(sel, 3);
res[count].license := psqlite_column_text(sel, 4);
res[count].towcapacity := psqlite_column_int(sel, 5);
end;
psqlite_finalize(sel);
sel := psqlite_prepare(con, 'SELECT asset.id,asset.description,asset.assettype,trailerasset.ownweight,trailerasset.maxcargo,trailerasset.roof FROM asset JOIN trailerasset ON asset.id = trailerasset.id');
while psqlite_step_query(sel) do begin
count := count + 1;
res[count].id := psqlite_column_int(sel, 0);
res[count].description := psqlite_column_text(sel, 1);
res[count].assettype := psqlite_column_int(sel, 2);
res[count].ownweight := psqlite_column_int(sel, 3);
res[count].maxcargo := psqlite_column_int(sel, 4);
res[count].roof := psqlite_column_int(sel, 5);
end;
psqlite_finalize(sel);
sel := psqlite_prepare(con, 'SELECT asset.id,asset.description,asset.assettype,toolasset.tooltype,toolasset.name,toolasset.weight FROM asset JOIN toolasset ON asset.id = toolasset.id');
while psqlite_step_query(sel) do begin
count := count + 1;
res[count].id := psqlite_column_int(sel, 0);
res[count].description := psqlite_column_text(sel, 1);
res[count].assettype := psqlite_column_int(sel, 2);
res[count].tooltype := psqlite_column_text(sel, 3);
res[count].name := psqlite_column_text(sel, 4);
res[count].weight := psqlite_column_int(sel, 5);
end;
psqlite_finalize(sel);
psqlite_close(con);
for i := 1 to count do begin
write(res[i].id, ' ', res[i].description, ' ');
case res[i].assettype of
TRUCK:
begin
write(res[i].model, ' ', res[i].license, ' ', res[i].towcapacity);
end;
TRAILER:
begin
write(res[i].ownweight, ' ', res[i].maxcargo, ' ', res[i].roof);
end;
TOOL:
begin
write(res[i].tooltype, ' ', res[i].name, ' ', res[i].weight);
end;
end;
writeln;
end;
end.
Build and run:
$ pas list_after_2
$ link list_after_2 + sys$input/opt + psqlitedir:sqlite/opt
psqlitedir:psqlite
psqlitedir:sqlite
$
$ run list_after_2
asset.py:
TRUCK = 1
TRAILER = 2
TOOL = 3
PERMOPEN = 1
COVERABLE = 2
REALROOF = 3
class Asset(object):
def __init__(self, _id = 0, _description = '', _assettype = 0):
self.id = _id
self.description = _description
self.assettype = _assettype
class TruckAsset(Asset):
def __init__(self, _id = 0, _description = '', _model = '', _license = '', _towcapacity = 0):
super(TruckAsset, self).__init__(_id, _description, TRUCK)
self.model = _model
self.license = _license
self.towcapacity = _towcapacity
class TrailerAsset(Asset):
def __init__(self, _id = 0, _description = '', _ownweight = 0, _maxcargo = 0, _roof = 0):
super(TrailerAsset, self).__init__(_id, _description, TRAILER)
self.ownweight = _ownweight
self.maxcargo = _maxcargo
self.roof = _roof
class ToolAsset(Asset):
def __init__(self, _id = 0, _description = '', _tooltype = '', _name = '', _weight = 0):
super(ToolAsset, self).__init__(_id, _description, TOOL)
self.tooltype = _tooltype
self.name = _name
self.weight = _weight
import sqlite3
from asset import *
con = sqlite3.connect('asset.db')
c = con.cursor()
res = []
c.execute('SELECT asset.id,asset.description,asset.assettype,truckasset.model,truckasset.license,truckasset.towcapacity FROM asset JOIN truckasset ON asset.id = truckasset.id')
for row in c.fetchall():
res.append(TruckAsset(row[0], row[1], row[3], row[4], row[5]))
c.execute('SELECT asset.id,asset.description,asset.assettype,trailerasset.ownweight,trailerasset.maxcargo,trailerasset.roof FROM asset JOIN trailerasset ON asset.id = trailerasset.id')
for row in c.fetchall():
res.append(TrailerAsset(row[0], row[1], row[3], row[4], row[5]))
c.execute('SELECT asset.id,asset.description,asset.assettype,toolasset.tooltype,toolasset.name,toolasset.weight FROM asset JOIN toolasset ON asset.id = toolasset.id')
for row in c.fetchall():
res.append(ToolAsset(row[0], row[1], row[3], row[4], row[5]))
con.commit()
con.close()
for o in res:
if isinstance(o, TruckAsset):
print('%d %s %s %s %d' % (o.id, o.description, o.model, o.license, o.towcapacity))
if isinstance(o, TrailerAsset):
print('%d %s %d %d %d' % (o.id, o.description, o.ownweight, o.maxcargo, o.roof))
if isinstance(o, ToolAsset):
print('%d %s %s %s %d' % (o.id, o.description, o.tooltype, o.name, o.weight))
asset.php:
<?php
define('TRUCK', 1);
define('TRAILER', 2);
define('TOOL', 3);
define('PERMOPEN', 1);
define('COVERABLE', 2);
define('REALROOF', 3);
class Asset {
public $id;
public $description;
public $assetType;
public function __construct($id = 0, $description = '', $assetType = '') {
$this->id = $id;
$this->description = $description;
$this->assetType = $assetType;
}
}
class TruckAsset extends Asset {
public $model;
public $license;
public $towcapacity;
public function __construct($id = 0, $description = '', $model = '', $license = '', $towcapacity = 0) {
parent::__construct($id, $description, TRUCK);
$this->model = $model;
$this->license = $license;
$this->towcapacity = $towcapacity;
}
}
class TrailerAsset extends Asset {
public $ownWeight;
public $maxCargo;
public $roof;
public function __construct($id = 0, $description = '', $ownWeight = 0, $maxCargo = 0, $roof = 0) {
parent::__construct($id, $description, TRAILER);
$this->ownWeight = $ownWeight;
$this->maxCargo = $maxCargo;
$this->roof = $roof;
}
}
class ToolAsset extends Asset {
public $toolType;
public $name;
public $weight;
public function __construct($id = 0, $description = '', $toolType = '', $name = '', $weight = 0) {
parent::__construct($id, $description, TOOL);
$this->toolType = $toolType;
$this->name = $name;
$this->weight = $weight;
}
}
?>
<?php
include '/disk2/arne/migr/inher/asset.php';
$con = new PDO('sqlite:/disk2/arne/migr/inher/asset.db');
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$con->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_NUM);
$res = array();
$stmt = $con->prepare('SELECT asset.id,asset.description,asset.assettype,truckasset.model,truckasset.license,truckasset.towcapacity FROM asset JOIN truckasset ON asset.id = truckasset.id');
$stmt->execute(array());
while($row = $stmt->fetch()) {
$res[] = new TruckAsset($row[0], $row[1], $row[3], $row[4], $row[5]);
}
$stmt = $con->prepare('SELECT asset.id,asset.description,asset.assettype,trailerasset.ownweight,trailerasset.maxcargo,trailerasset.roof FROM asset JOIN trailerasset ON asset.id = trailerasset.id');
$stmt->execute(array());
while($row = $stmt->fetch()) {
$res[] = new TrailerAsset($row[0], $row[1], $row[3], $row[4], $row[5]);
}
$stmt = $con->prepare('SELECT asset.id,asset.description,asset.assettype,toolasset.tooltype,toolasset.name,toolasset.weight FROM asset JOIN toolasset ON asset.id = toolasset.id');
$stmt->execute(array());
while($row = $stmt->fetch()) {
$res[] = new ToolAsset($row[0], $row[1], $row[3], $row[4], $row[5]);
}
foreach($res as $o) {
if($o instanceof TruckAsset) {
echo sprintf('%d %s %s %s %d', $o->id, $o->description, $o->model, $o->license, $o->towcapacity) . "\r\n";
}
if($o instanceof TrailerAsset) {
echo sprintf('%d %s %d %d %d', $o->id, $o->description, $o->ownWeight, $o->maxCargo, $o->roof) . "\r\n";
}
if($o instanceof ToolAsset) {
echo sprintf('%d %s %s %s %d', $o->id, $o->description, $o->toolType, $o->name, $o->weight) . "\r\n";
}
}
?>
public class Asset {
public static final int TRUCK = 1;
public static final int TRAILER = 2;
public static final int TOOL = 3;
private int id;
private String description;
private int assetType;
public Asset() {
this(0, "", 0);
}
public Asset(int id, String description, int assetType) {
this.id = id;
this.description = description;
this.assetType = assetType;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getAssetType() {
return assetType;
}
public void setAssetType(int assetType) {
this.assetType = assetType;
}
}
public class TruckAsset extends Asset {
private String model;
private String license;
private int towcapacity;
public TruckAsset() {
this(0, "", "", "", 0);
}
public TruckAsset(int id, String description, String model, String license, int towcapacity) {
super(id, description, TRUCK);
this.model = model;
this.license = license;
this.towcapacity = towcapacity;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getLicense() {
return license;
}
public void setLicense(String license) {
this.license = license;
}
public int getTowcapacity() {
return towcapacity;
}
public void setTowcapacity(int towcapacity) {
this.towcapacity = towcapacity;
}
}
public class TrailerAsset extends Asset {
private int ownWeight;
private int maxCargo;
private int roof;
public TrailerAsset() {
this(0, "", 0, 0, 0);
}
public TrailerAsset(int id, String description, int ownWeight, int maxCargo, int roof) {
super(id, description, TRAILER);
this.ownWeight = ownWeight;
this.maxCargo = maxCargo;
this.roof = roof;
}
public int getOwnWeight() {
return ownWeight;
}
public void setOwnWeight(int ownWeight) {
this.ownWeight = ownWeight;
}
public int getMaxCargo() {
return maxCargo;
}
public void setMaxCargo(int maxCargo) {
this.maxCargo = maxCargo;
}
public int getRoof() {
return roof;
}
public void setRoof(int roof) {
this.roof = roof;
}
}
public class ToolAsset extends Asset {
public static final int PERMOPEN = 1;
public static final int COVERABLE = 2;
public static final int REALROOF = 3;
private String toolType;
private String name;
private int weight;
public ToolAsset() {
this(0, "", "", "", 0);
}
public ToolAsset(int id, String description, String toolType, String name, int weight) {
super(id, description, TOOL);
this.toolType = toolType;
this.name = name;
this.weight = weight;
}
public String getToolType() {
return toolType;
}
public void setToolType(String toolType) {
this.toolType = toolType;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
public class ListAfter5 {
public static void main(String[] args) throws Exception {
Class.forName("org.sqlite.JDBC");
List<Asset> res = new ArrayList<Asset>();
Connection con = DriverManager.getConnection("jdbc:sqlite:asset.db");
Statement stmt = con.createStatement();
ResultSet rs;
rs = stmt.executeQuery("SELECT asset.id,asset.description,asset.assettype,truckasset.model,truckasset.license,truckasset.towcapacity FROM asset JOIN truckasset ON asset.id = truckasset.id");
while(rs.next()) {
int id = rs.getInt(1);
String description = rs.getString(2);
int assettype = rs.getInt(3);
String model = rs.getString(4);
String license = rs.getString(5);
int towcapacity = rs.getInt(6);
res.add(new TruckAsset(id, description, model, license, towcapacity));
}
rs.close();
rs = stmt.executeQuery("SELECT asset.id,asset.description,asset.assettype,trailerasset.ownweight,trailerasset.maxcargo,trailerasset.roof FROM asset JOIN trailerasset ON asset.id = trailerasset.id");
while(rs.next()) {
int id = rs.getInt(1);
String description = rs.getString(2);
int assettype = rs.getInt(3);
int ownweight = rs.getInt(4);
int maxcargo = rs.getInt(5);
int roof = rs.getInt(6);
res.add(new TrailerAsset(id, description, ownweight, maxcargo, roof));
}
rs.close();
rs = stmt.executeQuery("SELECT asset.id,asset.description,asset.assettype,toolasset.tooltype,toolasset.name,toolasset.weight FROM asset JOIN toolasset ON asset.id = toolasset.id");
while(rs.next()) {
int id = rs.getInt(1);
String description = rs.getString(2);
int assettype = rs.getInt(3);
String tooltype = rs.getString(4);
String name = rs.getString(5);
int weight = rs.getInt(6);
res.add(new ToolAsset(id, description, tooltype, name, weight));
}
rs.close();
stmt.close();
con.close();
for(Asset o : res) {
if(o instanceof TruckAsset) {
TruckAsset o2 = (TruckAsset)o;
System.out.printf("%d %s %s %s %d\n", o2.getId(), o2.getDescription(), o2.getModel(), o2.getLicense(), o2.getTowcapacity());
}
if(o instanceof TrailerAsset) {
TrailerAsset o2 = (TrailerAsset)o;
System.out.printf("%d %s %d %d %d\n", o2.getId(), o2.getDescription(), o2.getOwnWeight(), o2.getMaxCargo(), o2.getRoof());
}
if(o instanceof ToolAsset) {
ToolAsset o2 = (ToolAsset)o;
System.out.printf("%d %s %s %s %d\n", o2.getId(), o2.getDescription(), o2.getToolType(), o2.getName(), o2.getWeight());
}
}
}
}
Build and run:
$ javac ListAfter5.java Asset.java TruckAsset.java TrailerAsset.java ToolAsset.java
$ java -cp .:/javalib/sqlite-jdbc-3_14_1-vms.jar "ListAfter5"
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.Table;
@Entity
@Table(name="asset")
@Inheritance(strategy=InheritanceType.JOINED)
public class AssetJPA {
public static final int TRUCK = 1;
public static final int TRAILER = 2;
public static final int TOOL = 3;
private int id;
private String description;
private int assetType;
public AssetJPA() {
this(0, "", 0);
}
public AssetJPA(int id, String description, int assetType) {
this.id = id;
this.description = description;
this.assetType = assetType;
}
@Id
@Column(name="id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name="description")
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Column(name="assettype")
public int getAssetType() {
return assetType;
}
public void setAssetType(int assetType) {
this.assetType = assetType;
}
}
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
@Entity
@Table(name="truckasset")
@PrimaryKeyJoinColumn(name="id")
public class TruckAssetJPA extends AssetJPA {
private String model;
private String license;
private int towcapacity;
public TruckAssetJPA() {
this(0, "", "", "", 0);
}
public TruckAssetJPA(int id, String description, String model, String license, int towcapacity) {
super(id, description, TRUCK);
this.model = model;
this.license = license;
this.towcapacity = towcapacity;
}
@Column(name="model")
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
@Column(name="license")
public String getLicense() {
return license;
}
public void setLicense(String license) {
this.license = license;
}
@Column(name="towcapacity")
public int getTowcapacity() {
return towcapacity;
}
public void setTowcapacity(int towcapacity) {
this.towcapacity = towcapacity;
}
}
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
@Entity
@Table(name="trailerasset")
@PrimaryKeyJoinColumn(name="id")
public class TrailerAssetJPA extends AssetJPA {
private int ownWeight;
private int maxCargo;
private int roof;
public TrailerAssetJPA() {
this(0, "", 0, 0, 0);
}
public TrailerAssetJPA(int id, String description, int ownWeight, int maxCargo, int roof) {
super(id, description, TRAILER);
this.ownWeight = ownWeight;
this.maxCargo = maxCargo;
this.roof = roof;
}
@Column(name="ownweight")
public int getOwnWeight() {
return ownWeight;
}
public void setOwnWeight(int ownWeight) {
this.ownWeight = ownWeight;
}
@Column(name="maxcargo")
public int getMaxCargo() {
return maxCargo;
}
public void setMaxCargo(int maxCargo) {
this.maxCargo = maxCargo;
}
@Column(name="roof")
public int getRoof() {
return roof;
}
public void setRoof(int roof) {
this.roof = roof;
}
}
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
@Entity
@Table(name="toolasset")
@PrimaryKeyJoinColumn(name="id")
public class ToolAssetJPA extends AssetJPA {
public static final int PERMOPEN = 1;
public static final int COVERABLE = 2;
public static final int REALROOF = 3;
private String toolType;
private String name;
private int weight;
public ToolAssetJPA() {
this(0, "", "", "", 0);
}
public ToolAssetJPA(int id, String description, String toolType, String name, int weight) {
super(id, description, TOOL);
this.toolType = toolType;
this.name = name;
this.weight = weight;
}
@Column(name="tooltype")
public String getToolType() {
return toolType;
}
public void setToolType(String toolType) {
this.toolType = toolType;
}
@Column(name="name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name="weight")
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
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 ListAfter6 {
public static void main(String[] args) throws Exception {
Logger.getLogger("org.hibernate").setLevel(Level.OFF);
EntityManagerFactory emf = Persistence.createEntityManagerFactory("Asset");
EntityManager em = emf.createEntityManager();
TypedQuery<AssetJPA> q = em.createQuery("SELECT o FROM AssetJPA AS o", AssetJPA.class);
List<AssetJPA> res = q.getResultList();
for(AssetJPA o : res) {
if(o instanceof TruckAssetJPA) {
TruckAssetJPA o2 = (TruckAssetJPA)o;
System.out.printf("%d %s %s %s %d\n", o2.getId(), o2.getDescription(), o2.getModel(), o2.getLicense(), o2.getTowcapacity());
}
if(o instanceof TrailerAssetJPA) {
TrailerAssetJPA o2 = (TrailerAssetJPA)o;
System.out.printf("%d %s %d %d %d\n", o2.getId(), o2.getDescription(), o2.getOwnWeight(), o2.getMaxCargo(), o2.getRoof());
}
if(o instanceof ToolAssetJPA) {
ToolAssetJPA o2 = (ToolAssetJPA)o;
System.out.printf("%d %s %s %s %d\n", o2.getId(), o2.getDescription(), o2.getToolType(), o2.getName(), o2.getWeight());
}
}
em.close();
emf.close();
}
}
Build and run:
$ javac -cp 'hibpath' ListAfter6.java AssetJPA.java TruckAssetJPA.java TrailerAssetJPA.java ToolAssetJPA.java
$ java -cp .:'hibpath':/javalib/sqlite-jdbc-3_14_1-vms.jar:/javalib/sqlitehib.jar "ListAfter6"
We started by making the claim that a relational database is much better for complex queries.
The queries so far has been very simple. But let us show an example demonstrating some of the power of SQL.
Create database structure:
CREATE TABLE customer (
id INTEGER NOT NULL,
name VARCHAR(32),
address VARCHAR(64),
PRIMARY KEY(id)
);
CREATE TABLE myorder (
id INTEGER NOT NULL,
customerid INTEGER,
ordertime DATE,
PRIMARY KEY(id)
);
CREATE TABLE orderline (
id INTEGER NOT NULL,
orderid INTEGER NOT NULL,
item VARCHAR(32),
itemprice NUMERIC(10,2),
qty INTEGER,
PRIMARY KEY(id)
);
INSERT INTO customer VALUES(1, 'A A', 'A Road 11');
INSERT INTO customer VALUES(2, 'B B', 'B Road 22');
INSERT INTO customer VALUES(3, 'C C', 'C Road 33');
INSERT INTO myorder VALUES(1, 1, '2021-04-04');
INSERT INTO myorder VALUES(2, 1, '2021-05-05');
INSERT INTO myorder VALUES(3, 1, '2021-06-06');
INSERT INTO myorder VALUES(4, 2, '2021-05-01');
INSERT INTO myorder VALUES(5, 3, '2021-06-01');
INSERT INTO orderline VALUES(1, 1, 'Something', 10.00, 1);
INSERT INTO orderline VALUES(2, 2, 'Something else', 20.00, 1);
INSERT INTO orderline VALUES(3, 3, 'Something different', 30.00, 1);
INSERT INTO orderline VALUES(4, 4, 'Something', 10.00, 1);
INSERT INTO orderline VALUES(5, 4, 'Something else', 20.00, 1);
INSERT INTO orderline VALUES(6, 5, 'Something different', 30.00, 3);
Note that the database structure is actually just a combination and extension of the first two examples!
Let us say that we want to show customers, their total sale and the time of the last sale.
Python:
import sqlite3
con = sqlite3.connect('order.db')
c = con.cursor()
c.execute('SELECT customer.name,SUM(orderline.itemprice*orderline.qty) AS sale,MAX(myorder.ordertime) AS lastorder\
FROM (myorder JOIN orderline ON myorder.id = orderline.orderid) JOIN customer ON myorder.customerid = customer.id\
GROUP BY customer.name\
ORDER BY sale DESC;')
for row in c.fetchall():
print('%s %10.2f %s' % (row[0], row[1], row[2]))
con.commit()
con.close()
I will not even try to create this example with index-sequential files and Cobol/Pascal. It can obviously be done, but it will be a lot more lines.
And this is non-trivial SQL but it is not complex SQL - it is possible to make much more complex queries in SQL.
With index-sequential files operations like:
read record X read record Y ... update record X update record Y
are not safe in multi-process (or multi-threaded) context.
It is necessary to do something like:
lock record X lock record Y read record X read record Y ... update record X update record Y unlock record X unlock record Y
(VMS index-sequential files has excellent support for that)
The same problem exist for relational databases.SELECT * FROM mytable WHERE id=X;
SELECT * FROM mytable WHERE id=Y;
...
UPDATE mytable SET somefield=somevalue WHERE id=X;
UPDATE mytable SET somefield=somevalue WHERE id=Y;
is not safe in multi-process or multi-threaded context.
But in a relational database one does not use explicit locking - one use transactions and and approriate transaction isolation level.
First ensure that transaction isolation level is serializable and then bundle the statements in a transaction.
BEGIN
SELECT * FROM mytable WHERE id=X;
SELECT * FROM mytable WHERE id=Y;
...
UPDATE mytable SET somefield=somevalue WHERE id=X;
UPDATE mytable SET somefield=somevalue WHERE id=Y;
COMMIT;
then the relational database will ensure proper synchronization.
For some databases that will mean that the database locks the involved rows similar to how one did it manually for index-sequential files.
So what can we conclude from the above examples?
It is possible to migrate from index-sequential files to SQLite. No surprise.
It is possible to do data convertion by mapping both records in index-sequential files and tables in relational database to classes which allows to write the conversion programs in Java and Python instead of a traditional native language (Cobol, Pascal, Basic). Whether that is a real advantage depends on the available skills.
What to expect regarding code complexity by the change?
type of operation | traditional native language -> traditional native language or Java with JDBC (*) |
traditional native language -> scripting language or Java with JPA (*) |
---|---|---|
simple operations | similar code | less code |
complex operations | less code | lot less code |
*) Not counting Java getter and setter code that usually will be autogenerated.
Version | Date | Description |
---|---|---|
1.0 | July 5th 2021 | Initial version |
See list of all articles here
Please send comments to Arne Vajhøj