[Info-vax] Calling $CREPRC in COBOL
Arne Vajhøj
arne at vajhoej.dk
Sat Jul 9 20:15:24 EDT 2022
On 7/9/2022 8:06 PM, Arne Vajhøj wrote:
> On 7/4/2022 10:34 AM, seasoned_geek wrote:
>> On Sunday, July 3, 2022 at 7:22:57 PM UTC-5, Arne Vajhøj wrote:
>>> On 7/3/2022 4:05 PM, seasoned_geek wrote:
>>>> On Thursday, June 23, 2022 at 9:14:07 AM UTC-5, osuv... at gmail.com
>>>> wrote:
>>>>> On Tuesday, June 21, 2022 at 12:08:21 AM UTC-4, Dave Froble wrote:
>>>> At any rate, there is no SQL that will let you put multi-typed
>>>> records in a table. The "best" you could hope for is to have the
>>>> primary key fields then a BLOB object one had to hack like we did in
>>>> BASIC. You would be right back to CVT$% and RSET logic. (Didn't they
>>>> drop RSET and LSET from the DEC BASIC specification at some point?)
>>> Not true.
>>>
>>> You define a super class and sub classes and your ORM framework
>>> transparently stores and retrieved the different classes.
>>>
>>> That is basic persistence knowledge. Any young developer would
>>> know that.
>>
>> Well, we will ask Dave to post the TOLAS invoice (or order) record
>> layouts for a defunct
>> customer and you create a functioning VAX BASIC program using SQLite
>> along with Superclass
>> and Subclass and post it here.
>
> It is techniques used by hundreds of thousands maybe millions of
> applications.
>
> VMS Basic would be a problem as I am not aware of any ORM
> framework for VMS Basic.
>
> (and I also suspect that VMS Basic would need some new features
> to be able to create a good one)
But let me show something. Not TOLAS - just hello world level.
Obvious choices would be Java + Hibernate, C# + Entity Framework
or PHP + Doctrine, but since Groovy and Basic are part of the
thread then Groovy + Hibernate and VB.NET + Entity Framework.
Database definition and a few rows:
CREATE TABLE p (
id INTEGER NOT NULL,
typ INTEGER NOT NULL,
PRIMARY KEY(id)
);
CREATE TABLE c1 (
id INETGER NOT NULL,
ival INTEGER,
PRIMARY KEY(id)
);
CREATE TABLE c2 (
id INETGER NOT NULL,
sval VARCHAR(50),
PRIMARY KEY(id)
);
INSERT INTO p VALUES(1, 1);
INSERT INTO c1 VALUES(1, 123);
INSERT INTO p VALUES(2, 2);
INSERT INTO c2 VALUES(2, 'ABC');
First Groovy + Hibernate.
What is needed:
* Java
* Groovy
* Hibernate
* SQLite dialect for Hibernate version
* JDBC driver for SQLite
Data classes:
package mt
import javax.persistence.*
// parent class
@Entity @Inheritance(strategy=InheritanceType.JOINED)
class P {
@Id int id
int typ
}
// child class 1
@Entity @PrimaryKeyJoinColumn(name="id")
class C1 extends P {
@Id int id
int ival
@Override String toString() {
return "C1: $id -> $ival"
}
}
// child class 2
@Entity @PrimaryKeyJoinColumn(name="id")
class C2 extends P {
@Id int id
String sval
@Override String toString() {
return "C2: $id -> $sval"
}
}
Config file with database connection:
<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="testdb">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>mt.P</class>
<class>mt.C1</class>
<class>mt.C2</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:test.db"/>
<property name="hibernate.connection.username" value=""/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.dialect"
value="org.sqlite.hibernate.dialect.SQLiteDialect"/>
</properties>
</persistence-unit>
</persistence>
And it is all ready.
Demo:
package mt
import java.util.logging.*
import javax.persistence.*
// disable logging
Logger.getLogger("org.hibernate").setLevel(Level.OFF)
// open connection
emf = Persistence.createEntityManagerFactory("testdb")
em = emf.createEntityManager()
// add a C1 and C2
em.getTransaction().begin()
em.persist(new C1(id:3, typ:1, ival:456))
em.persist(new C2(id:4, typ:2, sval:"DEF"))
em.getTransaction().commit()
// find by PK
println(em.find(P.class, 2))
// list all
for(o in em.createQuery("SELECT o FROM P AS o", P.class).getResultList()) {
println("${o}")
}
// list all C2
for(o in em.createQuery("SELECT o FROM C2 AS o", P.class).getResultList()) {
println("${o}")
}
// list some
for(o in em.createQuery("SELECT o FROM P AS o WHERE o.id BETWEEN 2 and
3", P.class).getResultList()) {
println("${o}")
}
// close connection
em.close()
emf.close()
Note that: this should run on VMS Itanium as all the pieces
needed are available.
Now VB.NET + Entity Framework.
What is needed:
* .NET
* Entity Framework
* ADO.NET provider for SQLite (includes Entity Framework support)
Data classes:
Imports System
Imports System.ComponentModel.DataAnnotations
Imports System.ComponentModel.DataAnnotations.Schema
Imports System.Data.Entity
Namespace MT
' parent class
<Table("P")> Public Class P
<Key> <DatabaseGenerated(DatabaseGeneratedOption.None)> Public
Property Id() As Integer
Public Property Typ() As Integer
End Class
' child class 1
<Table("C1")> Public Class C1
Inherits P
Public Property Ival() As Integer
Public Overrides Function ToString() As String
Return $"C1: {id} -> {ival}"
End Function
End Class
' child class 2
<Table("C2")> Public Class C2
Inherits P
Public Property Sval() As String
Public Overrides Function ToString() As String
Return $"C2: {id} -> {sval}"
End Function
End Class
' database context
Public Class TestDbContext
Inherits DbContext
Public Sub New(constrkey As String)
MyBase.New(constrkey)
End Sub
Public Property P() As DbSet(Of P)
Public Property C1() As DbSet(Of C1)
Public Property C2() As DbSet(Of C2)
End Class
End Namespace
Config file with database connection:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="entityFramework"
type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection,
EntityFramework" requirePermission="false" />
</configSections>
<connectionStrings>
<add name="TestDB" connectionString="Data Source=.\test.db"
providerName="System.Data.SQLite"/>
</connectionStrings>
<entityFramework>
<providers>
<provider invariantName="System.Data.SQLite"
type="System.Data.SQLite.EF6.SQLiteProviderServices,
System.Data.SQLite.EF6"/>
<provider invariantName="System.Data.SQLite.EF6"
type="System.Data.SQLite.EF6.SQLiteProviderServices,
System.Data.SQLite.EF6"/>
</providers>
</entityFramework>
<startup>
<supportedRuntime version="v4.0"
sku=".NETFramework,Version=v4.5.1" />
</startup>
<system.data>
<DbProviderFactories>
<remove invariant="System.Data.SQLite" />
<remove invariant="System.Data.SQLite.EF6" />
<add name="SQLite Data Provider (Entity Framework 6)"
invariant="System.Data.SQLite.EF6" description=".NET Framework Data
Provider for SQLite (Entity Framework 6)"
type="System.Data.SQLite.EF6.SQLiteProviderFactory,
System.Data.SQLite.EF6" />
<add name="SQLite Data Provider"
invariant="System.Data.SQLite" description=".NET Framework Data Provider
for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
</DbProviderFactories>
</system.data>
</configuration>
And it is all ready.
Demo:
Imports System
Imports System.Data.Entity
Imports System.Linq
Namespace MT
Public Class Program
Public Shared Sub Main(args As String())
' open and close connection
Using ctx As TestDbContext = new TestDbContext("TestDB")
' add a C1 and C2
ctx.P.Add(New C1 With { .Id = 3, .Typ = 1, .Ival = 456 })
ctx.P.Add(New C2 With { .Id = 4, .Typ = 2, .Sval = "DEF" })
ctx.SaveChanges
' find by PK
Console.WriteLine((From o In Ctx.P Where o.Id = 2
Select o).FirstOrdefault)
' list all
For Each ox In (From o In Ctx.P Select o)
Console.WriteLine(ox)
Next
' list all C2
For Each ox In (From o In Ctx.C2 Select o)
Console.WriteLine(ox)
Next
' list some
For Each ox In (From o In Ctx.P Where 2 <= o.Id And
o.Id <= 3 Select o)
Console.WriteLine(ox)
Next
End Using
End Sub
End Class
End Namespace
Arne
More information about the Info-vax
mailing list