Find

Article
· Jan 23, 2023 2m read

Global-Streams-to-SQL #2

Some technical background information

There is not just one class in this package:  rcc.gstream.cls but also rcc.gstreamT.cls

While rcc.gstream works with direct access to the stream globals, the *T version uses
a Process Private Global (PPG) as Temporary storage.
using  SELECT * FROM RCC.gstreamT WHERE RCC.useT('^jpgS')=1 and similar.

This might be an advantage for multiple access to the same stream in sequence,
The advantage is obvious: You have a personal snapshot in memory and no risk of
a conflict in access. This might be interesting if you work just on 1 specific stream.
The disadvantage is also evident: The merge from Stream Global to PPG takes time. 
 
As a side effect I learned that the compression of stream variants GblChrCompress,
and GblBinCompress only affects the global size on disk. Once in memory, it consumes
the full size, and therefore with xDBC the full uncompressed stream gets sent over the
connection.
Differently, inside IRIX/Caché/Ensemble you only get to the stream's OID. Which makes
sense as streams typically exceed the maximum String length. To visualize this I did
something unusual as I mixed flat and compressed data into the same global.
So all even IDs are compressed streams.  

The code in the repo is written for IRIS.
But using it in Caché/Ensemble/... only requires changing the stream storage type from  
<Type>%Storage.SQL</Type> in IRIS to  <Type>%CacheSQLStorage</Type> for C/E

The base for both classes is Global mapping with SQL Storage.
And it was quite an exercise to make it dynamic.
My personal thanks go to Mike LaRocca who created a presentation about 20 years ago
that I found in my personal archives together with a related similar aged document
"Mapeo de Clases persistentes en Globales"  from a Spanish engineer
who's name was not mentioned there.

As a bonus for those who try the package, there is a medical jpeg not shown in the video.
I guess you will recognize the person immediately.




Hoping for your votes in the tools contest  !

Video

GitHub

Discussion (0)1
Log in or sign up to continue
Article
· Jan 23, 2023 2m read

Global-Streams-to-SQL

In general Global Streams are data objects embedded in Classes / Tables.
Using and viewing them with SQL is normally a part of the access to the containing tables.

SO WHAT?

During debugging or searching for strange or unexpected behavior there could be the need to 
get closer to the stored stream. No big problem with direct access to Globals with SMP or Terminal.
But with SQL you are lost.
So my tool provides dynamic access to Global Streams wherever you may need this
Special thanks to  @Oliver Wilms  for the inspiration for this tool.    

Mapping of globals to SQL is a rather traditional art from past.
Though Global Streams are somehow specialized.
But even as their Object classes have changed their representation in Global is the same.

The tricky point is that we see 4 different types of Global Streams in a common structure
Only the embedding Class /Table knows the meaning of the content.

  • %Stream.GlobalCharacter   -  raw text
  • %Stream.GblChrCompress - zipped text
  • %Stream.GlobalBinary - raw binary sequence
  • %Stream.GblBinCompress - zipped binary sequence

The Global itself has no indication, of what format it holds.
Dumping the Global just helps for raw text, the rest needs special treatment.
In combination with SQL you meet the problem of maximum field lengths.

I cover this issue by mapping all 4 types over the same stream and the user decides.
In addition, the total size and number of subnodes is also available.
For string manipulation, the first subscript level is also available as "body" VARCHAR
The Global Stream to examine is provided by a static where clause like this:

select * from rcc.gstream where rcc.use('^txtS')=1

  

WinSQL is friendly enough to let you see the full content. eg. for id=1  chr
 

and czip

with SQL the compressed data can be viewed unzipped.

Video

GitHub

1 Comment
Discussion (1)1
Log in or sign up to continue
Question
· Jan 10, 2023

Como saber o tamanho (quantidade de linhas) de uma global com comando direto

Existe algum comando que retorna a quantidade de linhas de uma global?

Exemplo:

^test(1)="aa"
^test(2)="aa"
^test(3)="aa"
^test(4)="aa"

Total de linhas = 4

2 Comments
Discussion (2)2
Log in or sign up to continue
Please note that this post is obsolete.
Question
· Dec 14, 2022

Does InterSystems has CDS Hook implementations?

Does InterSystems has CDS Hook implementations?
if yes, where I could get the details.

7 Comments
Discussion (7)3
Log in or sign up to continue
Article
· Nov 28, 2022 2m read

IRIS SQLでは LIMIT/OFFSET句のような機能をサポートしていますか?

Question:

IRISでは、PostgreSQLやMySQLで使うことができる、開始位置や取得件数を指定する LIMIT句やOFFSET句をサポートしているでしょうか?


Answer:

※2025/4/17更新:IRIS2025.1 以降のバージョンでは、LIMIT/OFFSET句をサポートするようになりました。ご参考

残念ながらサポートしていません。
ただ、代わりに使える同様の方法がありますのでご紹介します。

以下のようなSQLクエリをIRIS SQLで行うとします。

SELECT *
  FROM Sample.Person
ORDER BY Name
 LIMIT 3 OFFSET 5


---------------------------------------------------------------------------------
1. サブクエリとビュー ID (%VID)を使用する方法
---------------------------------------------------------------------------------

IRISでは、ビューまたは FROM 節のサブクエリで返される各行に整数のビュー ID (%VID) を割り当てることができます。
%VIDを使用すると、以下のサンプルのようにして同様のことが実現できます。
※%vidについて

SELECT *, %vid FROM (SELECT top all ID, Name
                     FROM Sample.Person
                     ORDER BY Name) v
WHERE %vid BETWEEN 6 AND 8
// 6番目から3つ分 --> 8番目まで


---------------------------------------------------------------------------------
2. OFFSET目までのデータを除いて TOP する方法
---------------------------------------------------------------------------------

SELECT TOP 3 ID, Name FROM Sample.Person WHERE ID NOT IN (SELECT TOP 5 ID
                 FROM Sample.Person
                 ORDER BY Name)
ORDER BY Name

 

---------------------------------------------------------------------------------
3.row_number() 関数を使用する方法
---------------------------------------------------------------------------------

IRIS 2021.1以降でサポートされるようになった ウィンドウ関数の ROW_NUMBER() を使用して実現することも可能です。

SELECT * FROM (
  SELECT row_number() OVER (ORDER BY Name) AS rn, ID, Name
  FROM Sample.Person 
) AS e 
WHERE e.rn BETWEEN 6 AND 8 ORDER BY Name


是非お試しください。

Discussion (0)0
Log in or sign up to continue