发布新帖

查找

文章
· 四月 25, 2020 阅读大约需 2 分钟

Semi-Persistent Classes and Tables

If you define a Persistent Class / Table the class compiler generates for you an appropriate Storage definition.
A different option is to define a SQL mapping for an already existing Global storage.  This has been excellently
explained already in a different series of articles.   The Art of Mapping Globals to Classes 1 of 3

Once your storage map is defined it might be extended by the class compiler but the fundamental
storage parameters will not change.
This does not mean that you can't change it manually yourself.

My article on The adopted Bitmap includes such a case. And in combination with some 
Static WHERE Conditions as described earlier you make it available also to SQL.

The typical definition of your storage globals may look like this example:

<DataLocation>^User.PersonD</DataLocation>
<IdLocation>^User.PersonD</IdLocation>
<IndexLocation>^User.PersonI</IndexLocation>
<StreamLocation>^User.PersonI</StreamLocation
>

Now we change this definition into a dynamic one

<DataLocation>@%MyData</DataLocation>
<IdLocation>@%MyId</IdLocation>
<IndexLocation>@%MyIndex</IndexLocation>
<StreamLocation>@%MyStream</StreamLocation>

and we add some comfort

Parameter MANAGEDEXTENT As INTEGER = 0;

ClassMethod SetStorage(ref As %String) As %Integer [ SqlName = SetStorage, SqlProc ]
{
    set %MyData=ref_"D"
      , %MyId=%MyData
      , %MyIndex=ref_"I"
      , %MyStream=ref_"S"
    quit $$$OK
}

For object access we direct our storage and fill it

write ##class(Person).SetStorage("^mtemp.Person")
write ##class(Person).Populate(5)

and in SQL:

SELECT  from Person where SetStorage('^mtemp.Person')=1

It works with PPG  (^||Person)
across namespace  (^|"USER"|Person)
also subscripted as used for The adopted Bitmap   with another variant of ClassMethod SetStorage() 

For object access (without SQL) it even works for local variables.
It's not the intended use but it demostrates how much flexibility is in this feature. 

But take care. It will NOT work with Sharding. But that should  not be surprising.

7 Comments
讨论 (7)1
登录或注册以继续
文章
· 四月 25, 2020 阅读大约需 2 分钟

Static WHERE Conditions

The typical WHERE condition in SQL relates mostly to some content of the rows you work on.
So it needs to be calculated and checked for each row you access.
Differently (and that's why I named it STATIC) is a WHERE condition that is independent of the rows you access.


The nice thing about it:
It is accessed and evaluated only once before anything else happens.
You could interpret it as a kind of main switch to your table.
In the past, this was often used as a workaround for simple SQL access rules.
A more tricky use is the combination with a SQLprocedure like this very simple example:

Class User.Hack
{ ClassMethod chk(any As %String) As %Boolean [ SqlName = mychk, SqlProc ]
  set if=$get(any)#2 ;; just a placeholder for a complex condition
    break              ;; for interactive examination
    quit if
  } }

and to get all lines and check only once (!!) you run:

SELECT id,name,Home_State from sample.person where home_State %startswith 'A'
       and MYCHK('rcc')=1  

differently, dynamic use (with ID)  it will be evaluated for each line
- line with odd ID 

SELECT id,name,Home_State from sample.person where home_State %startswith 'A'
       and MYCHK(id)=1 

- lines with even IDs

SELECT id,name,Home_State from sample.person where home_State %startswith 'A'
       and MYCHK(id)=0 


The important point is you have a backdoor to your SQLstatement to pass your specific parameters into a query
before any access to your data.
I have used this already inside notes for various replies.
A further article will demonstrate a practical use case.

2 Comments
讨论 (2)2
登录或注册以继续
InterSystems 官方
· 四月 12, 2020

InterSystems joins the open source ObjectScript for VS Code effort

I’m excited to announce that InterSystems will be joining the open source community for InterSystems ObjectScript extension to Visual Studio Code. Early this year I posted that we were on a journey to redefine the future of our IDE strategy, and what came out of that is Visual Studio Code is the IDE that can support that future.

3 Comments
讨论 (3)3
登录或注册以继续
文章
· 四月 4, 2020 阅读大约需 3 分钟

Websocket Client IRIS internal

IRIS 2010.1 brought us a new feature: %Net.WebSocket.Client

As a continuation of my series of WS Clients I just couldn't resist to try it.
Well, this is the result and it was rather simple in the end.

  • After I succeeded in my personal fight against Windows Firewall ;-)

You basically need to prepare 3 classes:

  • Credentials for User, PW, SSL
  • an Event Listener
  • the Client (Could be a .MAC routine as well)

The example uses the WSS.EchoServer (a derivate from former SAMPLES in Caché).
The default assumption is to have Client and Server on the same system & namespace.
But if you have some other echo server (e.g. ws://echo.websocket.org)
you just pass the URL as param.

You start it
by DO ##CLASS(WSCI.Client).Try()
or DO ##CLASS(WSCI.Client).Try(server_url)

USER>DO ##CLASS(WSCI.Client).Try()   
OPEN  
MESSAGE:10@%Stream.TmpCharacter   
Welcome to Cache WebSocket. NameSpace: USER   
--------------- next ---------------  
new message (*=exit):MESSAGE:8@%Stream.TmpCharacter  
2020-04-04 18:33:53.319: received 'hallo WS demo server' (length=20)  
--------------- next ---------------  
new message (*=exit):MESSAGE:10@%Stream.TmpCharacter  
2020-04-04 18:34:03.320: Timeout after 10 seconds  
--------------- next ---------------  
new message (*=exit):this is my demo  
--------------- next ---------------  
new message (*=exit):MESSAGE:5@%Stream.TmpCharacter  
2020-04-04 18:34:09.851: received 'this is my demo' (length=15)  
--------------- next ---------------  
--------------- next ---------------  
new message (*=exit):MESSAGE:10@%Stream.TmpCharacter  
2020-04-04 18:34:19.866: Timeout after 10 seconds  
--------------- next ---------------  
new message (*=exit):longer timeout  
MESSAGE:8@%Stream.TmpCharacter  
2020-04-04 18:34:29.132: received 'lange' (length=5)  
--------------- next ---------------  
new message (*=exit):MESSAGE:11@%Stream.TmpCharacter  
2020-04-04 18:34:39.132: Timeout after 10 seconds  
--------------- next ---------------  
new message (*=exit):MESSAGE:8@%Stream.TmpCharacter  
2020-04-04 18:34:41.132: received 'longer timeout' (length=14)  
--------------- next ---------------  
new message (*=exit):MESSAGE:11@%Stream.TmpCharacter  
2020-04-04 18:34:51.148: Timeout after 10 seconds  
--------------- next ---------------  
new message (*=exit):to=17  
--------------- next ---------------  
new message (*=exit):MESSAGE:5@%Stream.TmpCharacter  
2020-04-04 18:34:55.866: received 'to=17' (length=5)  
--------------- next ---------------  
--------------- next ---------------  
new message (*=exit):MESSAGE:11@%Stream.TmpCharacter  
2020-04-04 18:35:12.882: Timeout after 17 seconds  
--------------- next ---------------  
--------------- next ---------------  
new message (*=exit):*  
--------------- next ---------------  
    
ERROR #28000: Connection closed  
USER>  

GitHub

讨论 (0)1
登录或注册以继续
文章
· 四月 4, 2020 阅读大约需 1 分钟

Websocket Echo server IRIS

In Caché you had an example of a WebSocket Server in namespace SAMPLES
With IRIS the samples are gone and require additional installation effort.

So I refurbished the code with some useful additions:

  • independent of namespace
  • timeout control from client
  • readable communication log

This contains 2 classes:

The server is essential for the 'native' WebSocket Client Demo

GitHub

讨论 (0)1
登录或注册以继续