[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