Headless Stored Objects: A Simple Example of Working with Caché Objects in ObjectScript and Python
Neuschwanstein Castle
In June 2020, there are exactly 50 years of tabular data warehouses or, formally speaking, a relational data model. Here is an official document -
the most famous article . For what we say thank you so much to Dr. Edgar Frank Codd. And by the way, the relational data model is on the list of the most important global innovations of the last 100 years, according to Forbes.
On the other hand, oddly enough, Codd considered relational databases and SQL a distorted implementation of his theory. As a guide, he even developed 12 rules that each relational database management system must satisfy (in fact, these are 13 rules). And, to tell the truth, for today, there is no way in the world to find DBMS satisfying at least Codd's “Rule 0” and, therefore, no one can call their DBMS 100% relational :) Maybe there are exceptions, tell me?
The relational model is not very complex and has been studied far and wide. It may even be too deeply studied. Meanwhile, in this year 2019, we will also celebrate another anniversary - exactly 10 years ago, the hashtag #NoSQL, which later also “not only SQL” appeared on Twitter and began its rapid penetration into the practice of developing database models.
')
Why such a long preface? To the fact that the programming universe consists of data (and algorithms of course), and the monopolistic position of the relational model leads to a split in the consciousness of the programmer. Because the work objects in the developer’s head (OOP is also total, isn’t it?), All these lists, queues, trees, heaps, dictionaries, streams and so on to infinity are far from being tables.
And if you continue and recall the storage architecture in modern DBMS? Let's talk straight, no one in their right mind stores data in the form of tables. DBMS developers often use B-tree variants (in PostrgeSQL, for example) or, what happens much less often, dictionary-based storage. On the other hand, barricades, developers using DBMS for storage, do not operate tables either. And this forces programmers to bridge the semantic gap with the help of a clumsy intermediate layer of data. And, thereby, cause in itself internal dichotomous tension, system discomfort and debug insomnia.
That is, if briefly, there is a contradiction - the data is packed into the appropriate objects for the task, and when saved, it should take care of some tables.
Hopelessness? No :) But what about the object-relational mapping, is it in the common people of ORM? Let's leave
this holy war to Egor Bugayenko and his comrades. And this whole story from the last century, as
according to the version of Uncle Bob, should not worry us .
Certainly worth mentioning that the "bag of bytes" (Robert Martin "Pure Architecture") can be serialized and dropped into a file or pushed into some other suitable stream. But, first, it will immediately limit us in the language, and secondly, we will now only worry about storage in the DBMS.
In these twists and turns with the "bags of bytes" there is a pleasant exception - the Intersystems Caché DBMS (and now the InterSystems IRIS data platform). This is probably the only DBMS in the world that does not hide the obvious from the developer and even goes further - it frees you from the idea of ​​“how to keep everything properly”. Suffice it to say that the class continues the Persistent genus and
is in the bag ,
that is, in globals (not to be confused with global variables!).
You can store all types of data, including character and binary streams. Here is the simplest example:
// - // : , , , , Class FW.Events Extends %Persistent { Property "My name" As %String; } // // «» set haJS = ##class(FW.Events).%New() // write haJS.%Id()
Moreover, and this is great, you can communicate with stored objects not only in ObjectScript, native to Caché, but by receiving and saving them directly in programs in Python, Java, JavaScript, C ++, C #, Perl. And even, oh, horror :). it is also possible to draw information from the same objects directly through SQL queries, and it is also possible to call own methods of objects. More precisely, the methods in this case by themselves (and the magic word SqlProc) turn into stored procedures. All the magic is already under the hood of the Caché DBMS.
How to get free test access to Intersystems Caché DBMS?
It is absolutely real, that would not say evil tongues! :) You can download and install a single-user full-featured version of Caché here (you will need to register for free). Available builds for MacOS, Windows and Linux.
The most convenient way is to work with ObjectScript code and direct access directly to the Caché DBMS server (and the InterSystems IRIS platform too) using IDE Atelier, which is based on Eclipse. All
download and installation instructions are
here .
To whom it is more convenient and familiar, you can use a comfortable and simple Visual Studio Code, complementing it with community-developed plug-in ObjectScript.
And now a few practical examples. Let's try to create a pair of related objects and work with them in ObjectScript and in Python. Integration with other languages ​​implemented very similar. Python is chosen for reasons of “maximum relationship” with ObjectScript - both are scripting languages, support OOP and do not have strict typing :)
For ideas for examples, we turn to vigorous Khabarovsk (not to be confused with Habrovsk!) Projects "Framework-gathering." The ideological source code lies on
github.com/Hajsru/framework-weekend And our source code is lower in the text.
Important nuance for macOS users. When running Python support modules, you need to remember that you need to specify the path DYLD_LIBRARY_PATH to the directory where you installed Caché. For example:
export DYLD_LIBRARY_PATH = / application / Cache / bin: $ DYLD_LIBRARY_PATH
The documentation specifically states this .
Create stored classes in ObjectScript
So let's go. Classes in Caché will be very simple. You can do without the IDE - copy the code of the classes directly through the portal of your instance of the Caché platform (yes, the Caché DBMS is not only the DBMS): System Explorer> Classes> Import (Namespace USER).
Objects after saving appear in globals with names that match the names of the corresponding classes. Search also in the Caché management portal: Systemspace Browser> Globals (Namespace USER).
// , , Class FW.Event Extends %Persistent { Property title as %String; Property description as %String; Property date as %Date; Property visitors as list of FW.Attendee; } // / Class FW.Attendee Extends %Persistent { Property name As %String; }
Accessing objects in Caché from Python
First, connect to the database database Caché. We repeat as
in the documentation .
Just a useful fact for work. A free, educational version of the Caché DBMS will allow you to do everything that is available in the full-featured version, but only allows two active connections. Therefore, at the same time keep the connection from the IDE and try to run another code to interact with the server will not succeed. The simplest solution found is to close the IDE while the Python code is running.
And now we will make an object database of IT events and their participants. Very, very simple. First we will create a class for registering and storing information about the event participant. For simplicity to class only the name of the participant.
As you can see, we use ready-made wrapper functions for accessing fields of objects in Caché: set and in the parameters we pass the property name in quotes and openid with the name of the package and class. About the similar function get there are examples below. For access to any other methods, including those inherited by the ancestor class, the run_obj_method () function is used with the method name and call parameters, if needed.
The most important magic in the line: self.att.run_obj_method ("% Save", [])
This is how we can save objects with direct instructions and without the need to use additional libraries and frameworks / frameworks, such as the ubiquitous and unsightly ORM.
In addition, given the object-oriented nature of ObjectScript, along with the methods of our class (in our example, we did not do them), we gain access from Python to the entire set of methods inherited from the Persistent class and its ancestors as a bonus.
Here is a complete list , if that.
Create the first member:
att = Attendee() att.new("")
After running this code, a global with the name FW.AttendeeD and the contents of the object just saved will appear in the database as in the screenshot:
This object after saving has its own id (with the number 1). Therefore, you can download it to our program by this id:
att = Attendee() att.use(1) print (att.att.get("name"))
And now, again, knowing the id, if necessary, you can delete the object from the database of participants:
att = Attendee() att.use(1) att.clean()
Check, after running this example, the record of the object should disappear in the global. Although the downloaded data is still “in memory” of your object until the program ends.
Take the next step. Create your own records of events.
The class structure is almost the same as the class for the participant. Most importantly, the addAttendee (att) method of adding participants to the list of participants for this event has appeared.
We try to create an object-record about a new event and save it in the database:
haJS = Event() haJS.new("haJS", " ", "2019-01-19")
It should look something like this (note that the date is automatically converted to ObjectScript and when loaded back to the Python object will be returned in the originally specified format):
It remains to add a participant to the event:
So, in these examples it is clear that it is not necessary to think simultaneously about your data model and its tabular storage scheme. You can use more obvious tools for their tasks.
Detailed instructions for connecting and using Caché with Python and other languages ​​are always
available to you in the documentation and on the InterSystems developer community portal - this is not a few, and 5,000 members of
community.intersystems.com
Reference: InterSystems Caché multi-model DBMS remains the undisputed world leader in object databases.