tDOM

Check-in [69c262ef77]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Still working on digest local key constraint specification: Now support union "Path ( '|' Path )*" for selector and fields. Distinct between element and attribute selecting steps because of the distict spaces of the names.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | localkey
Files: files | file ages | folders
SHA3-256: 69c262ef77b5d563a14710a291deae7d2a3a023448f0c22cf16a0b230d644052
User & Date: rolf 2019-05-16 22:25:02
Original Comment: still working on digest local key constraint specification: Now support union "Path ( '|' Path )*" for selector and fields. Distinct between element and attribute selecting steps because of the distict spaces of the the names.
Context
2019-05-17
00:02
Now start to actually use the local key constraint info. check-in: 120c8294a0 user: rolf tags: localkey
2019-05-16
22:25
Still working on digest local key constraint specification: Now support union "Path ( '|' Path )*" for selector and fields. Distinct between element and attribute selecting steps because of the distict spaces of the names. check-in: 69c262ef77 user: rolf tags: localkey
2019-05-15
00:16
Enhanced the unique schema contraint: the fields argument is now expected to be a proper tcl list with their elements as the field XPath expressions. check-in: abc0715900 user: rolf tags: localkey
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to generic/schema.c.

   374    374   /* DBG end */
   375    375   
   376    376   static void freeKeyConstraints (
   377    377       KeyConstraint *kc
   378    378       )
   379    379   {
   380    380       KeyConstraint *knext;
   381         -    KeyStep *step, *snext;
          381  +    KeyStep *step, *snext, *child, *nchild;
   382    382       int i;
   383         -    
          383  +
   384    384       while (kc) {
   385    385           knext = kc->next;
   386    386           if (kc->name) FREE (kc->name);
   387    387           step = kc->selector;
   388    388           while (step) {
   389    389               snext = step->next;
   390         -            FREE (step);
          390  +            child = step;
          391  +            while (child) {
          392  +                nchild = child->child;
          393  +                FREE (child);
          394  +                child = nchild;
          395  +            }
   391    396               step = snext;
   392    397           }
   393    398           for (i = 0; i < kc->nrFields; i++) {
   394    399               step = kc->fields[i];
   395    400               while (step) {
   396    401                   snext = step->next;
   397         -                FREE (step);
          402  +                child = step;
          403  +                while (child) {
          404  +                    nchild = child->child;
          405  +                    FREE (child);
          406  +                    child = nchild;
          407  +                }
   398    408                   step = snext;
   399    409               }
   400    410           }
   401    411           FREE (kc->fields);
   402    412           FREE (kc);
   403    413           kc = knext;
   404    414       }
................................................................................
  3451   3461   extern void printAst (int depth, ast t);
  3452   3462   
  3453   3463   static int
  3454   3464   processSchemaXPath (
  3455   3465       Tcl_Interp *interp,
  3456   3466       SchemaData *sdata,
  3457   3467       KeyConstraint *kc,
  3458         -    KeyStep *lastStep,
  3459   3468       StepType nextType,
  3460   3469       ast t,
  3461   3470       int field,
  3462   3471       int toplevel
  3463   3472       )
  3464   3473   {
  3465   3474       ast child, savedt;
  3466         -    KeyStep *step;
         3475  +    KeyStep *step, *curstep;
         3476  +    Tcl_HashTable *table;
  3467   3477       Tcl_HashEntry *h;
  3468         -    int hnew;
         3478  +    int rc, hnew;
  3469   3479       SchemaCP *cp;
  3470   3480       
  3471   3481       /* if (toplevel) printAst (0, t); */
  3472   3482       while (t) {
  3473   3483           switch (t->type) {
  3474   3484           case GetContextNode:
  3475   3485               if (!toplevel) {
  3476   3486                   SetResult ("Not a reduced XPath expression.");
  3477         -                return TCL_ERROR;
         3487  +                return 0;
  3478   3488               }
  3479   3489               t = t->next;
  3480   3490               continue;
  3481   3491           case CombineSets:
  3482         -            SetResult ("CombineSets to be done.");
  3483         -            return TCL_ERROR;
  3484         -                
  3485         -            if (!toplevel) {
  3486         -                SetResult ("Not a reduced XPath expression.");
  3487         -                return TCL_ERROR;
         3492  +            child = t->child;
         3493  +            if (child->type == EvalSteps) {
         3494  +                savedt = NULL;
         3495  +                child = child->child;
         3496  +            } else {
         3497  +                savedt = child->next;
         3498  +                child->next = NULL;
         3499  +            }
         3500  +            if (field) {
         3501  +                step = kc->fields[field-1];
         3502  +                kc->fields[field-1] = NULL;
         3503  +            } else {
         3504  +                step = kc->selector;
         3505  +                kc->selector = NULL;
         3506  +            }
         3507  +            if (!processSchemaXPath (interp, sdata, kc, SCHEMA_STEP_NONE,
         3508  +                                     child, field, toplevel)) {
         3509  +                if (savedt) child->next = savedt;
         3510  +                if (field) kc->fields[field-1] = step;
         3511  +                else kc->selector = step;
         3512  +                return 0;
         3513  +            }
         3514  +            if (step) {
         3515  +                if (field) {
         3516  +                    curstep = step;
         3517  +                    while (curstep->next) curstep = curstep->next;
         3518  +                    curstep->next = kc->fields[field-1];
         3519  +                } else {
         3520  +                    curstep = step;
         3521  +                    while (curstep->next) curstep = curstep->next;
         3522  +                    step->next = kc->selector;
         3523  +                }
         3524  +            } else {
         3525  +                if (field) {
         3526  +                    step = kc->fields[field-1];
         3527  +                } else {
         3528  +                    step = kc->selector;
         3529  +                }
  3488   3530               }
  3489         -            for (child = t->child; child != NULL; child = child->next) {
  3490         -                if (processSchemaXPath (interp, sdata, kc, NULL,
  3491         -                                        SCHEMA_STEP_NONE, child, field, 0)
  3492         -                    != TCL_OK) {
  3493         -                    return TCL_ERROR;
         3531  +            if (field) kc->fields[field-1] = NULL;
         3532  +            else kc->selector = NULL;
         3533  +            if (savedt) child->next = savedt;
         3534  +            child = t->child->next;
         3535  +            if (child->type == EvalSteps) child = child->child;
         3536  +            rc = processSchemaXPath (interp, sdata, kc, SCHEMA_STEP_NONE,
         3537  +                                     child, field, toplevel);
         3538  +            if (field) {
         3539  +                if (kc->fields[field-1]) {
         3540  +                    curstep = step;
         3541  +                    while (curstep->next) curstep = curstep->next;
         3542  +                    curstep->next = kc->fields[field-1];
         3543  +                }
         3544  +                kc->fields[field-1] = step;
         3545  +            } else {
         3546  +                if (kc->selector) {
         3547  +                    curstep = step;
         3548  +                    while (curstep->next) curstep = curstep->next;
         3549  +                    curstep->next = kc->selector;
  3494   3550                   }
         3551  +                kc->selector = step;
  3495   3552               }
  3496         -            break;
         3553  +            return rc;
  3497   3554           case AxisDescendant:
  3498   3555               if (!toplevel) {
  3499   3556                   SetResult ("Not a reduced XPath expression.");
  3500         -                return TCL_ERROR;
         3557  +                return 0;
  3501   3558               }
  3502   3559               nextType = SCHEMA_STEP_DESCENDANT_ELEMENT;
  3503   3560               break;
  3504   3561           case IsNSAttr:
  3505   3562           case IsAttr:
  3506   3563               if (!field) {
  3507   3564                   SetResult ("Attribute selection is only possible in reduced "
  3508   3565                              "XPath expression for field selectors.");
  3509         -                return TCL_ERROR;
         3566  +                return 0;
  3510   3567               }
  3511   3568               /* Fall through */
  3512   3569           case IsElement:
  3513   3570           case IsFQElement:
  3514   3571           case IsNSElement:
  3515   3572               savedt = t;
  3516   3573               step = TMALLOC (KeyStep);
  3517   3574               memset (step, 0, sizeof (KeyStep));
  3518   3575               step->type = nextType;
         3576  +            if (t->type == IsAttr || t->type == IsNSAttr) {
         3577  +                table = &sdata->attrNames;
         3578  +            } else {
         3579  +                table = &sdata->element;
         3580  +            }
  3519   3581               if (t->type == IsFQElement || t->type == IsNSAttr) {
  3520   3582                   h = Tcl_CreateHashEntry (&sdata->namespace, t->strvalue,
  3521   3583                                            &hnew);
  3522   3584                   step->ns = Tcl_GetHashKey (&sdata->namespace, h);
  3523   3585                   t = t->child;
  3524   3586               }
  3525         -            h = Tcl_CreateHashEntry (&sdata->element, t->strvalue, &hnew);
  3526         -            if (hnew) {
         3587  +            h = Tcl_CreateHashEntry (table, t->strvalue, &hnew);
         3588  +            if (hnew && (table == &sdata->element)) {
  3527   3589                   cp = initSchemaCP (SCHEMA_CTYPE_NAME, step->ns,
  3528   3590                                      Tcl_GetHashKey (&sdata->element, h));
  3529   3591                   cp->flags |= PLACEHOLDER_PATTERN_DEF;
  3530   3592                   REMEMBER_PATTERN (cp);
  3531   3593                   Tcl_SetHashValue (h, cp);
  3532   3594               }
  3533         -            step->name = Tcl_GetHashKey (&sdata->element, h);
  3534         -            if (lastStep) {
  3535         -                lastStep->next = step;
         3595  +            step->name = Tcl_GetHashKey (table, h);
         3596  +            if (field) {
         3597  +                if (kc->fields[field-1]) {
         3598  +                    curstep = kc->fields[field-1];
         3599  +                    while (curstep->child) curstep = curstep->child;
         3600  +                    curstep->child = step;
         3601  +                } else {
         3602  +                    kc->fields[field-1] = step;
         3603  +                }
  3536   3604               } else {
  3537         -                if (field) kc->fields[field-1] = step;
  3538         -                else kc->selector = step;
         3605  +                if (kc->selector) {
         3606  +                    curstep = kc->selector;
         3607  +                    while (curstep->child) curstep = curstep->child;
         3608  +                    curstep->child = step;
         3609  +                } else {
         3610  +                    kc->selector = step;
         3611  +                }
  3539   3612               }
  3540         -            lastStep = step;
  3541   3613               t = savedt;
  3542   3614               break;
  3543         -        case AxisChild:
  3544         -            nextType = SCHEMA_STEP_ELEMENT;
  3545         -            break;
  3546   3615           case AxisAttribute:
  3547   3616               if (!field) {
  3548   3617                   SetResult ("Attribute selection is only possible in reduced "
  3549   3618                              "XPath expression for field selectors.");
  3550         -                return TCL_ERROR;
         3619  +                return 0;
  3551   3620               }
  3552         -            nextType = SCHEMA_STEP_ATTRIBUTE;
         3621  +            /* Fall through */
         3622  +        case AxisChild:
         3623  +            if (t->type == AxisChild) nextType = SCHEMA_STEP_ELEMENT;
         3624  +            else nextType = SCHEMA_STEP_ATTRIBUTE;
         3625  +            if (!processSchemaXPath (interp, sdata, kc, nextType,
         3626  +                                     t->child, field, 0)) {
         3627  +                return 0;
         3628  +            }
  3553   3629               break;
  3554   3630           default:
  3555   3631               SetResult ("Not a reduced XPath expression.");
  3556         -            return TCL_ERROR;
         3632  +            return 0;
  3557   3633           }
  3558   3634           toplevel = 0;
  3559   3635           t = t->next;
  3560   3636       }
  3561         -    return TCL_OK;
         3637  +    return 1;
  3562   3638   }
  3563   3639   
  3564   3640   static int
  3565   3641   uniquePatternCmd (
  3566   3642       ClientData clientData,
  3567   3643       Tcl_Interp *interp,
  3568   3644       int objc,
................................................................................
  3592   3668       }
  3593   3669   
  3594   3670       if (Tcl_ListObjLength (interp, objv[2], &nrFields) != TCL_OK) {
  3595   3671           SetResult ("The <fieldlist> argument must be a valid tcl list");
  3596   3672           xpathFreeAst (t);
  3597   3673           return TCL_ERROR;
  3598   3674       }
         3675  +    if (nrFields == 0) {
         3676  +        SetResult ("Non empty fieldlist arugment expected.");
         3677  +        xpathFreeAst (t);
         3678  +        return TCL_ERROR;
         3679  +    }
  3599   3680       
  3600   3681       kc = TMALLOC (KeyConstraint);
  3601   3682       memset (kc, 0, sizeof (KeyConstraint));
  3602   3683       kc->fields = MALLOC (sizeof (KeyStep*) * nrFields);
  3603         -
  3604         -    if (processSchemaXPath (interp, sdata, kc, NULL, SCHEMA_STEP_NONE, t, 0, 1)
  3605         -        != TCL_OK) {
         3684  +    memset (kc->fields, 0, sizeof (KeyStep*) * nrFields);
         3685  +    kc->nrFields = nrFields;
         3686  +    
         3687  +    if (!processSchemaXPath (interp, sdata, kc, SCHEMA_STEP_NONE, t,
         3688  +                             0, 1)) {
  3606   3689           xpathFreeAst (t);
  3607   3690           freeKeyConstraints (kc);
  3608   3691           return TCL_ERROR;
  3609   3692       }
  3610   3693       xpathFreeAst (t);
  3611   3694   
  3612   3695       for (i = 0; i < nrFields; i++) {
................................................................................
  3615   3698                           sdata->prefixns, NULL, &t, &errMsg) < 0) {
  3616   3699               SetResult3 ("Error in field xpath: '", errMsg, "");
  3617   3700               FREE (errMsg);
  3618   3701               xpathFreeAst (t);
  3619   3702               freeKeyConstraints (kc);
  3620   3703               return TCL_ERROR;
  3621   3704           }
  3622         -        if (processSchemaXPath (interp, sdata, kc, NULL, SCHEMA_STEP_NONE, t, i+1, 1)
  3623         -            != TCL_OK) {
         3705  +        if (!processSchemaXPath (interp, sdata, kc, SCHEMA_STEP_NONE, t,
         3706  +                                 i+1, 1)) {
  3624   3707               xpathFreeAst (t);
  3625   3708               freeKeyConstraints (kc);
  3626   3709               return TCL_ERROR;
  3627   3710           }
  3628   3711           xpathFreeAst (t);
  3629   3712       }
  3630   3713       if (objc == 4) {

Changes to generic/schema.h.

    88     88   
    89     89   typedef struct KeyStep 
    90     90   {
    91     91       StepType type;
    92     92       char    *name;
    93     93       char    *ns;
    94     94       struct KeyStep *next;
           95  +    struct KeyStep *child;
    95     96   } KeyStep;
    96     97   
    97     98   typedef struct KeyConstraint {
    98     99       char     *name;
    99    100       KeyType   type;
   100    101       KeyStep  *selector;
   101         -    KeyStep  **fields;
          102  +    KeyStep **fields;
   102    103       int       nrFields;
   103    104       struct KeyConstraint *next;
   104    105   } KeyConstraint;
   105    106   
   106    107   typedef struct SchemaCP
   107    108   {
   108    109       Schema_CP_Type    type;

Changes to tests/schema.test.

  4683   4683       } {
  4684   4684           tdom::schema s
  4685   4685           lappend result [catch {s define $schema} errMsg]
  4686   4686           #puts $errMsg
  4687   4687           s delete
  4688   4688       }
  4689   4689       set result
  4690         -} {0 1 1 0 1 1 1 1 0 1 1 0 1 1 0 1 1 1 1}
         4690  +} {0 1 1 0 0 0 1 0 0 1 1 0 1 1 0 1 1 1 1}
         4691  +
         4692  +test schema-19.2a {unique} {
         4693  +    set schema {
         4694  +        prefixns {ns1 http://tdom.org/test}
         4695  +        defelement doc {
         4696  +            unique ${::schema-19.2} {{@ref | div/@id} @lang}
         4697  +        }
         4698  +    }
         4699  +    set result [list]
         4700  +    foreach ::schema-19.2 {
         4701  +        {e/b | a/b | e/f }
         4702  +    } {
         4703  +        tdom::schema s
         4704  +        lappend result [catch {s define $schema}]
         4705  +        s delete
         4706  +    }
         4707  +    set result
         4708  +} 0
  4691   4709   
  4692   4710   test schema-19.3 {unique} {
  4693   4711       tdom::schema s
  4694   4712       s define {
  4695   4713           defelement doc {
  4696   4714               unique item @lang
  4697   4715               element item * {