Zigzag Language

1. Relational Database Application

1.1. Dissimilarity from SQL
1.2. Declaring database
$base "..." =; $base "..." ~; = $base "..."; ~ $base "..."; $base "..."; $"..."; $"..."*
1.3. Creating table relations
R (A1, ...); R: r(A1:a1, ...); {E1, ...}; S*
1.4. Selecting table relations
= E; =A:a; = R(E1, ...); = {E1 =/~/, ...}; = A: a^b; *S; *S*
1.5. Printing database contents
$printX($file "F", Q1, ...); $printX(Q1, ...); = *; = *:; = :*
1.6. Updating relation
=E = (A1:a1, ...); E ~ (A1:a1, ...); R: #n
1.7. Coping and deleting relation
R0 =/~ R1; R: {r0 =/~ r1}; R:r ~ ( ); R:r ~
1.8. Exporting and importing table data
$readTable($file "F", N0, N1, ...); $printTable($file "F", Q, A0, A1, ...)
1.9. Quoting and numbering
R("A"); R(#n); A:'...'; A:"..."; A:#n; '...'*'...'; "..."*"..."; #*
2. Object-oriented Database Application
2.1. Dissimilarity from relational database
2.2. Multilevel classification
C1: C2: ...; C1(E11, ...): C2(E21, ...): ...
2.3. Class passing
E / ; E / E1; / E; / E / ; E / / E1
2.4. Class analysis
C():c; E:c | ; E:c \ ; | {C, C:c}; \ C:c
2.5. Class manipulation
C : [C1/]; C: = C1:; C: ~ C1:
2.6. Multitude variable
$mul S; $S =/~ E; $S ~; = [$S]; [$S] ~; [$S] =; $S*
2.7. XML data
$rd($file "F", C:...), $pd($file "F", Q, Q1),
$rk($file "F", C:...), $pk($file "F", Q, Q1)
3. Administrating
3.1. User account
$User:"..." ($Password:"...", $Service:"...", $Info:"..."); $login("...", "...", "...")
3.2. Database navigation
$Content:E ($Attribute:E1, ...); E ($WebPage:"...")
4. Language Reference

Zigzag Language

1. Relational Database Application

1.1. Dissimilarity from SQL

The main merit of Zigzag (or Z, pronounced "zi") language is its conciseness. Zigzag language makes possible working with relational database that features multiple values of field and dynamic structure (schema independent data). There is integrity control for a field of many tables, so the trigger procedure is not required for Zigzag. Moreover, attribute name (not only value) may be expressed via request in a description or another request. These (and others) unique possibilities are not provided by SQL or XML/XSL!!!

1.2. Declaring database

Considered structure:
$base "..." = ; Opens modifiable database with "..." name.

$base "..." ~ ; Opens "..." database as new modifiable.

= $base "..." ; Opens "..." database as non-modifiable (only readable).

~ $base "..." ; Closes "..." database.

$base "..." ; Sets "..." database as current. If database is not opened yet, opens it as modifiable.

Considered auxiliary structure:
$"..." ;
$"..."* ; Contractions of specification. If S1 specific name was declared by $base "S1" before, the $"S"* suggests S1 database.

Database type is specified by base key word immediately after $. The name of the current database may be missing. It needs to be careful with $"..." . If a specification is used without type, system tries to remember type or otherwise suggests multitude ($mul "...").



See the following example.
< Tests multibase working >
$base "Notes/Test" =;
B;
$base "Notes/RelDB";
=A;
= $"Notes/T"*; < Apparently Notes/Test >
=B;
$base ~; < Clears current database >;
The < ... > construction is a Zigzag comment.

1.3. Creating table relations

Considered description structure:
Note: Here and further left sentences are Zigzag statements, right sentences - literal translation and commentary.

R (A1, ...) - an R relation of an A1, ... .
R:r (A1:a1, ...) - an R class namely r relation of an A1 class namely a1, ... .
R:(A:a, ...) (A1:a1, ...) - an R class namely relation of an A: a, ... , which is relation of A1: a1, .... The attributes of first relation, A:a,..., are key.

The R and A are denotes of relational model: Relation, Attribute. Really for Zigzag, if R(A1, A2) exists, it suggests existence of A1(R) and A2(R).

Considered auxiliary structure:
{E1, ...} - a set of E1, ... expressions.

For example A: {a1, a2}, or equal {A:a1, A:a2}.
S* . S denotes sequence of non-key symbols and blanks. The S* is simple names of database beginning with S.
For example a* in place of {a1, a2, ... an}.


Look at the table with the multiple valued fields.
note  workfellow      telephone     address
#1    Ringer Michael  415 506-0111  4 Broadway Av
                      503 743-5226
#2    Smith Anne      400 297-0752  10 Seventh Av
      Smith Robert
Let us create new empty Notes/RelDB database.
$base "Notes/RelDB" ~;
Now input the table information. Description of schema, first statement, is optional!!!. ZBase deduces schema automatically.
note (workfellow, telephone, address);
note:#1 ( workfellow:Ringer Michael,
          telephone:{415 506-0111,503 743-5226},
          address:4 Broadway Av
        );
note:#2 ( w*:Smith Anne,
          t*:400 297-0752,
          a*:10 Seventh Av
        );
We can use some attributes as key without preliminary declaration. Assume the telephone is key. The following statement will not add new note, because the note: (telephone:400 297-0752) exists, it is note:#2. However it adds workfellow: Smith Robert attribute to note:#2.
note:( t*:400 297-0752
     )  ( w*:Smith Robert,
          a*:10 Seventh Av
        );
There are more flexible possibilities to enter new data.
workfellow:Smith Robert (note:#2);
Moreover, we can describe attributes via request, for example note: #2, in last statement, might be expressed via Smith Anne =note:(:Smith*). Even the note attribute name, itself, we can express via another attribute name = (telephone). So the workfellow:Smith Robert (note:#2) may be expressed via: workfellow:Smith Robert (=(telephone):(:Smith *)). See following section.

1.4. Selecting table relations

Considered request structure:
= E - anything equal to the E expression (or the E).
= A:a.
For example:
= A: -  the A class;
= :a - the a of an arbitrary class;
Important note: if database includes only {A}, then =A: equals indefinitude, the =:A equals A, and the =A(): equals A.

= R:(E1, ...).

For example:
= R:r (A:a) - the R class namely r relation of the A: a ;
= (A:a, B:b) - the relation of the A: a and B: b ;
= ({A:a,B:b}) - the relation of the A: a or B: b ;
= {A,B}: (R:#1) - the A, B classes namely relation of the R: #1
= {E1=/~/, ...} - the set of the E1 expression and/no/or the ... . Such important expressions define algebraic operations on the sets. The ={E1=E2} is a intersection, the ={E1~E2} is a difference, the ={E1,E2} is a union.
For example:
= {R: ~ (B:)} - anything of the R class no the relation of the B class;
= {:a=A:, B:} - the union of the ={:a = A:} intersection and ={B:}. Evidently = {:a = A:} equals = A: a.
= A:a^b - the A class namely range from a to b.

Considered auxiliary structure:
*S . Denotes element names of database ending with S.
*S* . Element names of database containing S.

All the complete expressions separated by the ';' are statements. Expression may be description or request. If Zigzag expression begins with '=' or with '~' symbol, its operand (and itself expression) is a request. For '= Q;' and '~ Q;' the Q is a request, whereas for 'D;' the D is description. Operands are descriptions for D=, D=D1. For '~' operator of negation the operands are request, Q~Q1, Q~. Look at these combinations: D = =Q; = {Q, D=};.

See 4.Reference... about all the Zigzag operators, ordered from highest to lowest precedence. Consecution of operators is executed from left to the right. For example, A = B = C is equal to { A = B } = C.



Return back at previous example. Note that all examples from any division are continuation of previous (from previous division) in this article.
note  workfellow      telephone     address
#1    Ringer Michael  415 506-0111  4 Broadway Av
                      503 743-5226
#2    Smith Anne      400 297-0752  10 Seventh Av
      Smith Robert
Following request reports some objects that belong to the telephone class with values in the range from 415* .
= telephone:415*^;
Result in the Report area (in Report window for Sav ZBase Interpreter, or in Report buffer for Sav ZAPI):
telephone:{
            415 506-0111,
            503 743-5226
          };
We can image relations with address containing 'way' and with one of the 0111 or 0752 phones.
= (address:*way*,*phone:{*0111,*0752});
Result:
note:#1;
Finally let's output all the notes that have relation with 4... phone or address, but no relation with Anne.
= {note:({*phone,addr*}:4*)~(:*Anne)};

-----
note:#1;

1.5. Printing database contents

Considered procedure structure:
$printX($file "F", Q1, ...) – print X of the Q1, ... in F file.

$printX(Q1, ...) – print X of the Q1, ... . Missing of the $file parameter denotes output in the Report area (window or buffer).

We can use: print, printObject, printRelation, printClass, or a abbreviation thereof p, po, pr, pc. The F is an output file. The Q1, ... are requests or "..." string, or #n number.

Considered * requests:
= * - simple objects (elements)

= *: - simple class names

= :* - simple class values

To understand expressions, review example for database that consists of {A:a, B}:

Statement   Result
$pc();         A:a, B;
$pc(*)        A, B;
$pc(*:)       A;
$pc(:*)        a;
$pc({*}:)    A:a;


Try to print all the "schema relations" from 1.3. Creating....

$p("SCHEMA OF ", *);
$p("------------------------------------------------------");
$pr(*);

SCHEMA OF address, note, telephone, workfellow
------------------------------------------------------
address ( note
        ),
note ( address,
       telephone,
       workfellow
     ),
telephone ( note
          ),
workfellow ( note
           );
If you want to print contents of the workfellow class related with the notes of the 415* telephone in the Notes/wf415.txt, type
$pc($file "Notes/wf415.txt",
        workfellow: (note: (telephone: 415*) ) );
If you need to print all the objects of two level class in the Notes/test.txt, type
$po($file "Notes/test.txt", *:*);

1.6. Updating relation

Considered structure:
=E = (A1:a1, ...) - the E is a relation of an A1 class a1 and .... The {=a} (b) is the same as =a=(b).

E ~ (A1:a1, ...) - E is not relation of the A1 class a1 and .... The a(~b2) is not correct!  The a~(b) is the same as =a~(b).

R: #n - R class namely n number. Here n is positive number, 1073741823 maximum by default.
Look at the R: # expression. The indefinite number is last number if the R: # request, and is new number if the R: # description.



Suppose that Smith couple split. Anne lives in another place. (See 1.3. Creating...).
=note:(:Smith*) ~ (:Smith Anne);
note:# (:Smith Anne);
=note:# = (t*:503 743-5226);
Take a look at the result using
$pr( (:Smith*) );
note:{


       #2 ( address:10 Seventh Av,
            telephone:400 297-0752,
            workfellow:Smith Robert
          ),
       #3 ( telephone:503 743-5226,
            workfellow:Smith Anne
          )
     };

1.7. Coping and deleting relation

Considered structure:
R0 =/~ R1R0 is equal/unequal to R1. The R1 relation is copied to/deleted from R0.

R: {r0 =/~ r1}R namely r0 is equal/unequal to R namely r1. Expression might transform to R: r0 =/~ R: r1. It copies relations from R: r1 to R: r0 or deletes relations of R: r1 from R: r0.

R:r ~ ( ) - R class namely r is not relation. Deletes relations.

R:r ~ - R class namely r is not. Deletes objects.



We have new sample information. Anne Smith is daughter of Michael Ringer. Michael died and Anne has father's address. Remember contents of database.
$pr(note:#3);
-----
note:{ 
       #1 ( address:4 Broadway Av,
            telephone:{ 415 506-0111,
                        503 743-5226
                      },
            workfellow:Ringer Michael
          ),
       #2 ( address:10 Seventh Av,
            telephone:400 297-0752,
            workfellow:Smith Robert
          ),
       #3 ( telephone:503 743-5226,
            workfellow:Smith Anne
          )
     };
Set data of Michael Ringer (#1 record) to #3 record.
note: {=#3 = =(:Ringer Michael)};
$pr(note:#3);
-----
note:#3 ( address:4 Broadway Av,
          telephone:{
                      415 506-0111,
                      503 743-5226
                    },
          workfellow:{
                       Ringer Michael,
                       Smith Anne
                     }
        );
Following fragment demonstrates integrity control. To delete Ringer Michael, we need not point records (#1, #3) with this field and we may not use triggers or like SQL CONSTRAINT statements.
:Ringer Michael ~;
$pr(note:{#1,#3});
-----
note:{
       #1( address:4 Broadway Av,
           telephone:{
                       415 506-0111,
                       503 743-5226
                     }
         ),
       #3( address:4 Broadway Av,
           telephone:{
                       415 506-0111,
                       503 743-5226
                     },
           workfellow:Smith Anne
         )
     };
The #1 record does not have workfellow value, so we can delete and it.
note:#1 ~ ();
$pr(note:);
-----
note:{
       #1,
       #2 ( address:10 Seventh Av,
            telephone:400 297-0752,
            workfellow:Smith Robert
          ),
       #3 ( address:4 Broadway Av,
            telephone:{
                        415 506-0111,
                        503 743-5226
                      },
            workfellow:Smith Anne
          )
     };

1.8. Exporting and importing table data

Considered structure:
$readTable($file "F", N0, N1, ...) - read table from F file with column numbers N0 key, N1, ....  The contraction, $rt(...), is able. If F file parameter is missing, imported tabular data are located immediately after procedure expression, in <> brackets. If there are not N0, N1, ..., all the columns will be input.
For example, we can import R(A, B) table directly from script:
$rt() <
R ; A ; B
#1; a1; b1
#2; a2; b2
>
$printTable($file "F", Q, A0, A1, ...) - print table in F file from Q with column names A0 key, A1, .... There are procedure name contraction, $pt(...). The Q is a request. The A0, A1, ... may be requests. If F file parameter is missing, Report area is suggested. The $printTableRows($file "F", Q, A0, A1, ...) procedure, $ptr(...) contraction, prints only table rows, without first line determining column names. If the A0, A1, ... are absent, attributes entered by $readTable(...) will be output in alphabet order.

Notice large profit of these procedures for database archiving. The F file may be directory, without extension ( .tab). For example: If database consists of R1, R2 tables, $pt($file "Tables") exports all the tables in Tables/R1.tab and Tables/R2.tab accordingly; Then we can import all the files from Tables by $rt($file "Tables").

A first input line of tabular data must define the names of columns. Only ";" semicolon may be delimiter of the table fields. Values of the field are separated by the ','. The words with the $ * # " ' { [ ( } ] ) ^ : / | \ ~ = , ; < > key symbols need be enclosed in the quotes. The price may be without quotes, $10.2. See distinction of the "..." and '...' in the 1.9 section.



Consider creating workfellow (address, telephone) class relation in Notes/ObjDB.ass database. It needs to output relations note (address, telephone, workfellow) in a Notes/Note.tab file, then to input so that #4 column would be key.
$pt($file "Notes/Note.tab", note:, note, address, telephone, workfellow);
$base "Notes/ObjDB" ~;
$rt($file "Notes/Note.tab", #4, #2, #3);
$pt($file "Notes/Workfellow.tab", workfellow: );
$pt(workfellow:);
-----
workfellow; telephone; address
Smith Anne; 415 506-0111, 503 743-5226; 4 Broadway Av
Smith Robert; 400 297-0752; 10 Seventh Av

1.9. Quoting and numbering

Considered structure:
A: '...'
A: "..."
A: #n
R ("A")
R (#n)
Considered auxiliary structure:
"..."*"..."
'...'*'...'
#*
The ... denotation is an any sequence of symbols. Notice that '...', "..." names and #n number may end up space combination, for example a "b", whereas "a" b and "a" "b" are not correct. System tests existing of "..." and #n objects in a database only when needs to test its connection or presence. For example "a" will be tested in database for "a"*, "a":, *:"a", or ["a"] expression, but not for { "a" } or $print("a").

Using A: "...", as A: #n, reduces the required database size and accelerates running, but a price must be paid in loss of the system wits and possibility of contractions: =:"...", =:#n . The R("...") and R(#n) also reduce memory. The =("A") and =(#n) contractions are not attainable. Quoting and numbering may be fit for a big database. Particularly it may be useful to express repeating class levels: "A": "A" or #1: #1. Single quotes like usual words does not express repeat, the 'A':'A' equals 'A' like A:A equals A. Single quotes may be helpful only to use special symbols as non-special, for instance A: '2*3'. The '2'*'3' denotes '...' quote in database starting with 2 and ending with 3. The same is for "2"*"3". The #* combination is used to select only all the numbers from current class level.



Let us create "Note/Test" base.
$base "Notes/Test" ~;
"office":'#10' (employer:#10, "company":"Unknown");
$pr();
-----
"company":"Unknown",
"office"( "company",
          employer
        ):'#10'( "company":"Unknown",
                 employer:#10
               ),
employer( "office"
        ):#10( "office":'#10'
             );


We can test now its contents.

= "***ELLIPSIS***";
= ""*"ff"*:'#'*'0';
= employer:#*;
= "company":*"know"*;
= "ATTAINABLE EXPRESSIONS";
= :'#10';
= "company":"Unknown";
= "office":("company":"Unknown");
Derivable result:
"***ELLIPSIS***";
"office":'#10';
employer:#10;
"company":"Unknown";
"ATTAINABLE EXPRESSIONS";
"office":'#10';
"company":"Unknown";
"office":'#10';
Following fragment produces Failure messages.
= "UNATTAINABLE EXPRESSIONS"*;
= :#10;
= :"Unknown";
=("company":"Unknown")


2. Object-oriented Database Application

2.1. Dissimilarity from relational database

Zigzag language maps related objects on database and vice versa, whereas SQL maps objects' relations. These general definitions (equal at the first sight) disclose essentially different data models of both languages. Connections of the Zigzag objects make up new type of data - association, which may be either relation or class. So Zigzag language manipulates with relations and classes. The relations feature relational database, while classes, for example its inheritance, adds to database object-oriented nature.

2.2. Multilevel classification

Considered structure:
C1: C2: ...

C1(E11, ...): C2(E21, ...): ...

Mark that R1(A1): R2(A2) expression equals to {R1(A1): R2} (A2) and equals to R1(A1):  {R2(A2)}. The R1: {:R2} is allowable, but it is the same as R1: R2. It may be useful to know: the R1: expression assumes all the levels of R1 class, R1: R2: ..., but R1:* only one level - R1: R2.



Let us classify by Zigzag language the objects of the telephone notebook with necessary properties: telephone, and address.
category: acquainted (property: telephone,
                      property: address
                     ): { relative (property: propinquity
                                   ),
                          workfellow (property: position,
                                      property: function
                                     )
                        };
Execute the queries.
$pc(category:relative);
$p("-----");
$pc(:acquainted:(property:telephone, property:propinquity));
$p("-----"); 
$pc(category:~:workfellow);
Report window will have three equal Zigzag statements separated by the "-----"; string.
category:acquainted:relative;
Additional test:
$p("category:*");
$pr(category:*);
Result:
category: *
category ( property

         ):acquainted ( property:{ 
                                   address,
                                   telephone
                                 }
                      );

2.3. Class passing

Considered structure:
E /  - value of E class (value of E:).

E / E1 - E1 value of E class (E1 value of E: ).

/ E - name of class with E value.

/ E / - value of class with E value.

E / / E1 - intermediate levels of class between E name and E1 value.



We are going to complicate category of 2.2 section namely add unacquainted relative.
category:{unacquainted:relative = =:relative};
$pr(category:);
category:{
           acquainted( property:{
                                  address,
                                  telephone
                                }
                     ):{
                         relative( property:propinquity
                                 ),
                         workfellow( property:{
                                                function,
                                                position
                                              }
                                   )
                       },
           unacquainted():relative( property:propinquity
                                  )
         };
It is left to enter many of '/' request combinations and look at result.
= "= category:unacquainted/";
= category:unacquainted/;
= "= category:*/";
= category:*/;
= "= category/relative";
= category/relative;
= "= category/(property:propinquity, property:address)";
= category/(property:propinquity, property:address);
= "= /relative";
= /relative;
= "= category:acquainted:{/relative}";
= category:acquainted:{/relative};
= "= {/relative = /workfellow}";
= {/relative = /workfellow};
= "= /relative/";
= /relative/;
= "= category//relative";
= category//relative;
Result:
"= category:unacquainted/";
relative;
"= category:*/";
{
  relative,
  workfellow
};
"= category/relative";
{

  acquainted:relative,
  unacquainted:relative
};
"= category/(property:propinquity, property:address)";
acquainted:relative;
"= /relative";
category:{
           acquainted,
           unacquainted
         };
"= category:acquainted:{/relative}";
category:acquainted;
"= {/relative = /workfellow}";
category:acquainted;
"= /relative/";
{
  relative,
  workfellow
};
"= category//relative";
{
  acquainted,
  unacquainted
};

2.4. Class analysis

Considered structure:
C():c - C and C:c objects. It is equal to {C, C:c} expression.

E:c | - simple value of E:c expression. Result is lower level, c. It is allowed to use ...|..., result of E:{c1,c2}|c will be c.

E:c \ - name of E:c expression. Result is E. It is allowed to use ...\..., result of {C1,C2}:c\C1 will be C1.

| {C, C:c} -  normal (proper) objects of {C, C:c} expression. Result is C:c.

\ C:c - all objects of C:c expression. Result is a {C, C:c} or equal C():c.



Let us return to the category class. Firstly we delete category:unacquainted: class and category:unacquainted itself object.
category:unacquainted():~;
= category:;
category:acquainted():{
                        relative,
                        workfellow
                      };
Now test '|' and '\' combinations.
$po("", "CURRENT (CONSIDERED) OBJECTS", category:);
$po("", "CURRENT IDENTIFIERS", category:|);
$po("", "CURRENT CATEGORIES", category:\);
$po("", "NORMAL OBJECTS", |category:);
$po("", "ALL OBJECTS", \category:);
$po("", "NORMAL IDENTIFIERS", |category:|);
$po("", "NORMAL CATEGORIES", |category:\);
$po("", "NORMAL GENERAL CATEGORIES", |category:\*);
$po("", "ALL IDENTIFIERS", \category:|);
$po("", "ALL CATEGORIES", \category:\);
Result:
CURRENT (CONSIDERED) OBJECTS
category:acquainted
category:acquainted:relative
category:acquainted:workfellow

CURRENT IDENTIFIERS
acquainted
relative
workfellow

CURRENT CATEGORIES
category
category:acquainted

NORMAL OBJECTS
category:acquainted:relative
category:acquainted:workfellow

ALL OBJECTS
category
category:acquainted
category:acquainted:relative
category:acquainted:workfellow

NORMAL IDENTIFIERS
relative
workfellow

NORMAL CATEGORIES
category:acquainted

NORMAL GENERAL CATEGORIES
category

ALL IDENTIFIERS
acquainted
category
relative
workfellow

ALL CATEGORIES
category
category:acquainted

2.5. Class manipulation

Considered structure:
C: [C1/] - C class namely value of C1. The C: { C1 / } expression has other meaning and is equal to { C:C1 / } - the set of values of the C: C1.

C: = C1: - C class is equal to C1 class. Relations of C1: objects are copied to C: with identical values.

C: ~ C1: - C class is unequal to C1 class. Relations of C1: are removed from C: with identical values.

Assume that C: {c, c1}, C1(A): {c1(A:a1), c2(A:a2)} are available. Consequently, the C: = C1: entails C(A): { c, c1(A:a1)}.


Remember about workfellow class.
$pt(workfellow:);
workfellow  ; address      ; telephone
Smith Anne  ; 4 Broadway Av; 415 506-0111, 503 743-5226
Smith Robert; 10 Seventh Av; 400 297-0752
Assume we face the need of transmitting workfellow class relation to
object:workfellow class relation. Look at the workfellow class values.
= workfellow/;
{
  Smith Anne,
  Smith Robert
};
Make value of the object:workfellow class initially.
object:workfellow: [=workfellow/];
$pr(object:);
object:workfellow():{
                      Smith Anne,
                      Smith Robert
                    };
Now we can copy class relations from workfellow:.
object:workfellow: = workfellow:;
$pr(object:);
object:workfellow():{
                      Smith Anne ( address:4 Broadway Av,
                                   telephone:{
                                               415 506-0111,
                                               503 743-5226
                                             }
                                 ),
                      Smith Robert ( address:10 Seventh Av,
                                     telephone:400 297-0752
                                   )
                    };
Let's print all the objects with Smith* simple class values.
$po(:Smith*);
object:workfellow:Smith Anne
object:workfellow:Smith Robert
workfellow:Smith Anne
workfellow:Smith Robert
Let us print now name of class with Smith* values.
$po(/Smith*);
object:workfellow
workfellow
The old workfellow (not object:workfellow) class relation should be deleted.
workfellow(): ~;
Lastly we can print information about objects through property/ attributes.
$pt(object:, :workfellow, property/);
object:workfellow; address      ; telephone
Smith Anne       ; 4 Broadway Av; 415 506-0111, 503 743-5226
Smith Robert     ; 10 Seventh Av; 400 297-0752

2.6. Multitude variable

Considered structure:
$mul S - S multitude. Declares S specification name as multitude variable.

$S =/~ E - S is equal/unequal to E. It includes/excludes objects to set denoted by S.

$S ~ . It excludes all objects from S set.

= [$S] . Expression extracts the objects, equal to S set, from a database.

[$S] ~ . It deletes objects of S from database.

[$S] = . It creates objects of S in a current database.

$S* . Using ellipsis for multitude name.

The mul key word is optional and needed only if a variable of other type with the same name was declared earlier. For example, if $base "s1", $mul s1 were declared, the $s1 implies "Ambiguous" error. Type or name of variable must follow immediately after $.

System supposes that objects of multitude variable are in a current database and therefore tests the multitude existing only if variable is in [] brackets, or defines connection. For example contents of $x will be tested in ($x), [$x], $x: , but not in =$x, {$x}, $print($x). Constructions $x (...) and $x: ... may be used for creating new connections in database.



Previously declared variable name may be with '*' ellipsis, see $tel*.
$mul telephone ~;
$tel* = =tel*:(:Smith Anne);
= $tel*;
Result:
telephone:{
            415 506-0111,
            503 743-5226
          };
=====
$x ~;
$x = $tel*;
$x ~ tel*:415*;
= $x;
Result:
telephone:503 743-5226;
=====
$x = ={telephone:~(:Smith Anne)};
= $x;
Result:
telephone:{
            400 297-0752,
            503 743-5226
          };
The following fragment illustrates using the variable data in another database.
$p("Test New Database");
$base "Notes/Test" ~;

= {"current DB", [$x]};
[$x] =;
= {"DB after [$x]=", [$x]};
[$x] ~;
= {"DB after [$x]~", [$x]};
Result:
Test New Database
"current DB";
{
  "DB after [$x]=",
  telephone:{
              400 297-0752,
              503 743-5226
            }
};
"DB after [$x]~";

2.7. XML data

Considered structure:
$readXmlDocument($file "F", C:...). Contraction: $rd(...) or $rxd(...).
$printXmlDocument($file "F", Q, Q1). Contraction: $pd(...) or $pxd(...).
$readXmlKnowledge($file "F", C:...). Contraction: $rk(...) or $rxk(...).
$printXmlKnowledge($file "F", Q, Q1). Contraction: $pk(...) or $pxk(...).

F is name of either XML file or directory of XML files. Directory is supposed for F name without point. Q request and Q1, C:... roots (paths in database) may be missed in all the procedures. The $file parameter may be missed in printXmlKnowledge and printXmlDocument. If $file is absent, output is a Report area (string buffer for Sav ZAPI).

The XML knowledge differs from XML document in that the knowledge does not suppose repeatable data (tags or texts) in one class (in one tag). Internal Zigzag representation of XML data is different for $rd(...) and $rk(...). For example, test this f.xml file.
<R1>
  r1
  <r2 A="a"/>
  <r2/>
  <_1/>
</R1>

Zigzag data for $rd($file "f.xml", C1):
C1:R1:{
       #1(@T:"r1"),
       #2(@N:r2,A:"a"),
       #3(@N:r2),
       #4(@N:_1)
      }
For $rk($file "f.xml", C2) Zigzag data will be more general:
C2:R1:{
       "r1",
       r2(A:"a"),
       #1
      }



Let us see p1.xml XML file representing paragraph with two sentences.

<!--
XML is a subset of SGML.
XML enables SGML to be processed on the Web.
-->
<paragraph>
  <sentence>
    <phrase>
      <noun>XML</noun>
      <phrase>
        <verb>is</verb>
        <phrase>
          <noun>subset</noun>
          <preposition>of</preposition>
          <noun>SGML</noun>
        </phrase>
      </phrase>
    </phrase>
  </sentence>
  <sentence>
    <phrase>
      <noun>XML</noun>
      <phrase>
        <verb>enables</verb>
        <phrase>
          <noun>SGML</noun>
          <phrase>
            <particle>to</particle>
            <verb group="auxiliary">be</verb>
           <verb>processed</verb>
            <preposition>on</preposition>
            <phrase>
              <article>the</article>
              <noun>Web</noun>
            </phrase>
          </phrase>
        </phrase>
      </phrase>
    </phrase>
  </sentence>
</paragraph>

We can read XML file by rd(...) procedure in document root.

$base "Notes/xml"~;
< XML Data >
$rd($file "Notes/p1.xml", document);

Now we will assign path for is and be text to $x variable. Before declare current database as non-modifiable. Lastly, print $x as XML document.

=$base;
$x ~;
$x = =document:(@T:{"is","be"},@N:verb);
$pd($x, document);
-----
<paragraph>
  <sentence>
    <phrase>
      <phrase>
        <verb>
          is
        </verb>
      </phrase>
    </phrase>
  </sentence>
  <sentence>
    <phrase>
      <phrase>
        <phrase>
          <phrase>
            <verb>
              be
            </verb>
          </phrase>
        </phrase>
      </phrase>
    </phrase>
  </sentence>
</paragraph>

Reflect $x value. It is tree of position numbers of texts and tags in XML. To define $x1 variable as grandparents of $x, we need to ascend two levels up. It will be positions of phrase tags.

$pr($x);
$x1 ~;
$x1 = $x\\;
$pr($x1);
-----
document:#1:{
              #1:#1:#2:#1:#1( @T:"is"
                            ),
              #2:#1:#2:#2:#2:#2:#1( @T:"be"
                                  )
        };
document:#1:{
              #1:#1:#2( @N:phrase
                      ),
              #2:#1:#2:#2:#2( @N:phrase
                            )
            };

To print in XML format phrases directly belonged to $x1, we can use this.

$pd(={$x1:#*=(@N:phrase)}:, $x1);
-----
<phrase>
  <noun>
    subset
  </noun>
  <preposition>
    of
  </preposition>
  <noun>
    SGML
  </noun>
</phrase>
<phrase>
  <article>
    the
  </article>
  <noun>
    Web
  </noun>
</phrase>

Fragment below selects paths of $x non-having group attribute with value "auxiliary". Then it defines near phrase ancestors and prints its last child.

$x2 ~;
$x2 = ={$x~$x(group:"auxiliary")};
$x3 ~;
$x3 = =|{\$x2=(@N:phrase)};
$pr($x3);
$pd(={$x3}:#:, $x3);
-----
document:#1:#1:#1:#2( @N:phrase
                    );
<phrase>
  <noun>
    subset
  </noun>
  <preposition>
    of
  </preposition>
  <noun>
    SGML
  </noun>
</phrase>

By next statement we print all document's descendants from #1 to #3 grandchildren of document in directory "Notes/paragraph". Result will be XML files

$pd($file "Notes/paragraph", document:, document:#*:#1^#3);
-----

Finally let us to make sense of XML knowledge.

$pk(={$x3}:#:, $x3);
$base=;
$rk($file "Notes/p1.xml", combinations);
$pk(combinations:);
-----
<_2>
  <_1 _N="noun">
    <_1 _T="subset"/>
  </_1>
  <_2 _N="preposition">
    <_1 _T="of"/>
  </_2>
  <_3 _N="noun">
    <_1 _T="SGML"/>
  </_3>
</_2>
<combinations>
  <paragraph>
    <sentence>
      <phrase>
        <article>
          the
        </article>
        <noun>
          SGML
          Web
          XML
          subset
        </noun>
        <particle>
          to
        </particle>
        <preposition>
          of
          on
        </preposition>
        <verb group="auxiliary">
          be
          enables
          is
          processed
        </verb>
      </phrase>
    </sentence>
  </paragraph>
</combinations>
 

3. Administrating

3.1. User account

Resource control is important for database that is shared by many users. Zigzag is comfortable language for making a user account. It allows taking proper user's name, password and service. Service is additional but very useful property. It corresponds to some procedure or task that user may execute.

Considered expression
$User:"..." ($Password:"...", $Service:"...", $Info:"..."). Only administrator has to enter this expression. The $User:"" and $Service:"" denote arbitrary user and service. If there are some $User:"...", then database has limit access.

$login("...", "...", "..."). The $l is a contraction of procedure name. First parameter - a service name, second - a password, third - user name. Parameters may be missed, then its are assumed from previous $login or "".

Current version of Sav Z has 4 system services:
Service Class
navigate Sav.Base.Navigator, Sav.Server.Navigator
import Sav.Base.Importer, Sav.Server.Importer
export Sav.Base.Exporter, Sav.Server.Exporter
record Sav.Server.Recorder



Fragment declares users and prints specific data about its.
$base "Notes/Resource";
$User:"Administrator" ($Password:"123456", $Service:"");
$User:"Serg" ($Password:"123123", $Service:"navigate");
$User:"" ($Service:"record");
$pr($User:);
-----
$User:{
        ""( $Service:"record"
          ),
        "Administrator"( $Password:"123456",
                         $Service:""
                       ),
        "Serg"( $Password:"123123",
                $Service:"navigate"
              )
      };
After login with others properties statements will be rejected.
$l("navigate", "123456", "Mole");
$pr();

3.2. Database navigation

The Sav ZServer and Sav ZBase systems have navigator tool that lightens viewing of database content. Design of navigation may be adjusted.

Considered expression
$Content:E ($Attribute:E1, ...). ZBase's or ZServer's navigator will have a chance of observing only E: and E1,.... Note that $Content:R ($Attribute:A1, ...) is made automatically by $rt() <R; A1; ...> procedure.

E ($WebPage:"..."). ZServer's navigator uses $WebPage:"...". The "..." is a URL reference.



Return at the previous example and print specific classes.
$pr($*:);
-----
$Password:{
            "123123"( $User:"Serg"
                    ),
            "123456"( $User:"Administrator"
                    )
          },
$Service:{
           ""( $User:"Administrator"
             ),
           "navigate"( $User:"Serg"
                     ),
           "record"( $User:""
                     )
         },
$User:{
        ""( $Service:"record"
          ),
        "Administrator"( $Password:"123456",
                         $Service:""
                       ),
        "Serg"( $Password:"123123",
                $Service:"navigate"
              )
      };
We need to read table to make automaticly $Content class.
$rt() <
A ; B ; C ; D ; $WebPage
a1; b1; c1; d1; "http://www.org.com"
a2; b2; c2; d2;
>;
$pr($Content:);
-----

$Content:A( $WebPage,
            B,
            C,
            D
          );
Let's change $Content:.
$Content:A ~ ($Attribute:D);
$Content:D ($Attribute:A);
$pr($Content:);
$pt();
-----
$Content:{
           A( $WebPage,
              B,
              C
            ),
           D( A
            )
         };
A; $WebPage; B; C
a1; "http://www.org.com"; b1; c1
a2; ; b2; c2

D; A
d1; a1
d2; a2
It remains only to see as navigator is working.

4. Language Reference

Symantec designations ('|' separator and '...' trailing ellipsis are special symbols):
E                   Expression
Q                   Request in =Q | ~Q | Q~ | Q~Q | $print(Q,...)
D                   Description in D; | D = | D = D
R|R:r               Relation name in R(E) | R:r(E)
A|A:a               Relation attribute in E(A,...) | E(A:a,...)
C:c                 Object (or class instance) in {C:{c,...},...}
C                   Class name in C:E
c                   Class value in E:c
A|B|C|...|R|...     Element (or Simple object)
a|b|c|...|r|...     Element (or Simple object)
S                   Symbol sequence in element's name (simple name)
Syntax designations:
Z     Key symbol         $ | * | # | " | ' |   | { | [ | ( | } | ] | ) | ^ | : | / | | | \ | ~ | = | , | ; | < | >
C     Non-key character
L     Letter
D     Digital
N     Number             D...
S     String             "..." 
Q     Quote              '...'
W     Word               C...
NN    Number name        #N | # | #*
SN    String name        S | S* | S*SN | *SN
QN    Quote name         Q | Q* | Q*QN | *QN
WW    Word sequence      W | W WW
WN    Word name          WW | WW* | WW*WN | *WN
DN    Determinate name   NN | SN | QN | WN | WN Nm
IN    Indeterminate name *
Nm    Element name       DN | IN
SNm   Specific name      WW | S | WW* | S*
Sp    Specification      $W SNm | $SNm
Exp   Expression         Nm | Sp | Exp Z | Z Exp
Stm   Statement          Exp, ...
Scr   Script             Stm; ...
Expressions ordered by priority:
 1  Sp | Sp(Exp, ...)
    $base SNm             1.2
    $file SNm             1.5, 1.8
    $mul SNm              2.6
    $Sp(Exp,...)          1.5, 1.8, 2.7, 3.1
    $W                    3.1, 3.2
 1  Nm
    SN | QN               1.9
    NN                    1.6, 1.9
    ...*...               1.3, 1.4, 1.9
    *                     1.5, 2.2
 1  <...>                 1.2, 1.8
 1  [Exp, ...]            2.5, 2.6
 1  {Exp, ...}            1.3, 1.4
 1  (Exp, ...)            1.4
 2  ^Exp | Exp^Exp | Exp^ 1.4
 3  Exp(Exp, ...)         1.3, 1.4
 4  Exp:Exp               1.3, 1.9, 2.2
 4  :Exp | Exp:           1.4
 5  /Exp | Exp/           2.3
 5  Exp/Exp | Exp//Exp    2.3
 6  |Exp | \Exp           2.4
 6  Exp|Exp | Exp\Exp     2.4
 6  Exp| | Exp\           2.4
 7  =Exp                  1.4, 1.6
 7  ~Exp                  1.2
 8  Exp~Exp               1.4, 1.6, 1.7, 2.5, 2.6
 9  Exp=Exp               1.4, 1.6, 1.7, 2.5, 2.6
10  Exp~ | Exp=           1.2, 1.7
11  Exp,Exp               1.3, 1.4
12  Stm;Stm               1.3