Showing posts with label Ruby. Show all posts
Showing posts with label Ruby. Show all posts

Saturday, September 26, 2009

More on globals and classes in Caché

Interesting - it seems that "dynamic languages" have been around for much longer than (us) Ruby users would think. Here's Caché's own version of it at work:



Class Definition: TransactionData


/// Test class - Julian, Sept 2009
Class User.TransactionData Extends %Persistent
{
Property Message As %String;
Property Token As %Integer;
}


Routine: test.mac

Set ^tdp = ##class(User.TransactionData).%New()
Set ^tdp.Message = "XXXX^QPR^JTX"
Set ^tdp.Token = 131

Write !, "Created: " _ ^tdp


Terminal:

USER> do ^test
... Created 1@User.TransactionData

Studio: Globals

tdp
^tdp = "1@User.TransactionData"
tdp.Message
^tdp.Message = "XXXX^QPR^JTX"
tdp.Token
^tdp.Token = 131


The order of creation is:
  1. create the class
  2. this will create the SQL objects
  3. populating the SQL table will instantiate the globals
  4. the globals are: classD for data, classI for index

Objects can be created (%New)/opened(%OpenId) from code, but to be saved (%Save: which will update the database), the restrictions must be met (required properties, unique indexes, etc).

Also, I finally got the .NET gateway generator to work: it creates native .NET classes that can communicate with Cache objects. Here is a sample of the client code:

InterSystems.Data.CacheClient.CacheConnection cn = new InterSystems.Data.CacheClient.CacheConnection("Server=Irikiki; Port=1972;" +
"Log File = D:\\CacheNet\\DotNetCurrentAccess.log; Namespace = USER;" +
"Password = ______; USER ID = ____");
cn.Open();
PatientInfo pi = new PatientInfo(cn);
pi.PatientName = "New Patient";
pi.PatientID = new byte[1]{6};
InterSystems.Data.CacheTypes.CacheStatus x = pi.Save();
Console.WriteLine(x.Message);

PatientInfo is a class defined in Cache, as follows:


Class User.PatientInfo Extends %Persistent
{

Property PatientName As %String [ Required ];
Property PatientDOB As %Date;
Property PatientID As %ObjectIdentity;

Method getVersion() As %String
{
Quit "Version 1.0"
}

Index IndexPatientName On PatientName;
Index IndexPatientId On PatientID [ IdKey, PrimaryKey, Unique ];

}

Easy enough, the getVersion() method is available to the C# code, as are the persistence and all the other methdods natively available in ObjectScript. The generated code is here.

Friday, March 21, 2008

Ruby and SQLite3 in Windows

If you need to run Ruby with SQLite in Windows, since you cannot set up the environment in the script like you can in Unix (#!), make sure you have the sqlite3.rb and sqlite3.dll in the same directory where the Ruby script is. Figuring this out caused me much grief.

Thursday, March 13, 2008

Postgres and Ruby







On Mac OS X the Postgres binaries are saved in /usr/local/bin. Here is a handy Postgres launcher that can be saved in the user’s directory (as postgres_start.sh for example):

su -l postgres -c "/usr/local/bin/pg_ctl start -D /Users/postgres/datadir"

Where datadir is the directory (owned by the postgres user) where Postgres has the data files.

To create a custom tablespace in Postgres, make an empty directory first and use that as the location for the tablespace in pgAdmin3.

Sample Ruby code to access Postgres; notice that the first line is needed to set up the environment; without it the require fails.

#! /usr/bin/env ruby
#
# original file src/test/examples/testlibpq.c
# Modified by Razvan
# Calls PL/SQL function in Postgres

require 'postgres'

def main
norecs = 0
pghost = "localhost"
pgport = 5432
pgoptions = nil
pgtty = nil
dbname = "razvan"

begin
conn = PGconn.connect(pghost,pgport,pgoptions,pgtty,dbname)

res = conn.exec("BEGIN")
res.clear
res = conn.exec("SELECT * FROM insertrt('another row')")

if (res.status != PGresult::TUPLES_OK)
raise PGerror,"RB-Error executing command.\n"
end

printf("\nRB-Results\n")
res.result.each do |tupl|
tupl.each do |fld|
printf("RB-%-15s",fld)
norecs = norecs + 1
end
end

res = conn.exec("END")
printf("\nRB-Records: %i\n", norecs)
res.clear
conn.close

rescue PGError
if (conn.status == PGconn::CONNECTION_BAD)
printf(STDERR, "RB-Connection lost.")
else
printf(STDERR, "RB-Error:" )
printf(STDERR, conn.error)
end
exit(1)
end #rescue
end #end def main

main #invoke code

This calls the following Postgres plpgsql function:

CREATE OR REPLACE FUNCTION insertrt(data character varying)
RETURNS bigint AS
$BODY$
DECLARE
id bigint;
BEGIN
id := 0;
IF EXISTS(SELECT * FROM "RTable") THEN
SELECT MAX("Id") INTO id FROM "RTable";
END IF;
id := id + 1;
INSERT INTO "RTable" ("Data", "Id")
VALUES(data, id);
RAISE NOTICE 'New id is %', id;
RETURN id;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
ALTER FUNCTION insertrt(character varying) OWNER TO postgres;
GRANT EXECUTE ON FUNCTION insertrt(character varying) TO postgres;


To execute this function do a SELECT * FROM insertrt( ‘parameter’ ). Interesting in the function, SELECT INTO variable. Also notice “ ‘s used to enclose field names and table names. The output of RAISE NOTICE is displayed by the Ruby console.

Since gems does not work with OS X Tiger’s Ruby, the Postgres adapter has to be built manually.