XQuery Update Facility: insert as first vs. insert as last

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

XQuery Update Facility: insert as first vs. insert as last

Roel Vercammen

There seems to be something odd in the specification of insert in
Section 2.3 of the XQuery Update Facility WD. According to 4.a "insert
as last" is compiled into update primitives of the form
"upd:insertIntoAsLast", while "insert as first" does not have a
designated update primitive.

Consider the following input bound to a variable $x := <a><b/></a>
If I'm not mistaken, the XQuery expression
  insert <c/> into $x as first, insert <d/> before $x/b
signals an incompatibility, while the expression
  insert <c/> into $x as last, insert <d/> after $x/b
does not. The reasoning for this conclusion is as follows. Suppose n_a,
n_b, n_c and n_d are the nodes that correspond to the nodes with the
corresponding tag name. The first expression yields the following
pending update list:
  { upd:insertBefore(n_b, n_c), upd:insertBefore(n_b, n_d) }
The second expression yields the following pending update list:
  { upd:insertIntoAsLast(n_a, n_c), upd:insertAfter(n_b, n_d) }
According to the compatibility matrix, the first pending update list
contains a conflict, while the second doesn't. The result of the second
expression is <a><b/><d/><c/></a> (no matter in which order the two
primitives are evaluated).

I don't think that this asymmetry is desired and see two ways to solve
this issue:
(1) Add an upd:insertAsFirst primitive.
(2) If "as last" is specified in an insert statement, do something
similar to "as first" when there is a child, i.e., insert after the last
child node. When there are no children, perform upd:insertInto. This
would remove the need for an upd:insertAsLast primitive, but would cause
the second expression to signal a conflict.

Roel


Reply | Threaded
Open this post in threaded view
|

Re: XQuery Update Facility: insert as first vs. insert as last

Jonathan Robie

Roel Vercammen wrote:
> There seems to be something odd in the specification of insert in
> Section 2.3 of the XQuery Update Facility WD. According to 4.a "insert
> as last" is compiled into update primitives of the form
> "upd:insertIntoAsLast", while "insert as first" does not have a
> designated update primitive.

I don't think there is an error here, but I agree that the specification
is asymmetrical here. We were trying to keep the number of primitives
small, but adding upd:insertIntoAsFirst() would not be a big step in
complexity, and would make the description more orderly.  For instance,
it would have made the asymmetry you note ore obvious. We always prefer
to keep the number of primitives small, but this one might be worth
adding. (Personal opinion only, as is the rest of this reply.)

> Consider the following input bound to a variable $x := <a><b/></a>
> If I'm not mistaken, the XQuery expression
>   insert <c/> into $x as first, insert <d/> before $x/b
> signals an incompatibility, while the expression
>   insert <c/> into $x as last, insert <d/> after $x/b
> does not. The reasoning for this conclusion is as follows. Suppose n_a,
> n_b, n_c and n_d are the nodes that correspond to the nodes with the
> corresponding tag name. The first expression yields the following
> pending update list:
>   { upd:insertBefore(n_b, n_c), upd:insertBefore(n_b, n_d) }
> The second expression yields the following pending update list:
>   { upd:insertIntoAsLast(n_a, n_c), upd:insertAfter(n_b, n_d) }
> According to the compatibility matrix, the first pending update list
> contains a conflict, while the second doesn't. The result of the second
> expression is <a><b/><d/><c/></a> (no matter in which order the two
> primitives are evaluated).I don't think that this asymmetry is desired and see two ways to solve
> this issue:
> (1) Add an upd:insertAsFirst primitive.
> (2) If "as last" is specified in an insert statement, do something
> similar to "as first" when there is a child, i.e., insert after the last
> child node. When there are no children, perform upd:insertInto. This
> would remove the need for an upd:insertAsLast primitive, but would cause
> the second expression to signal a conflict.

I just checked the compatibility table:

http://www.w3.org/TR/2006/WD-xqupdate-20060127/#id-compatibility

I get the same results you do:

insert <c/> into $x as first, insert <d/> before $x/b
=  { upd:insertBefore(n_b, n_c), upd:insertBefore(n_b, n_d) }
=> conflict

insert <c/> into $x as last, insert <d/> after $x/b
=  { upd:insertIntoAsLast(n_a, n_c), upd:insertAfter(n_b, n_d) }
=> <a><b/><d/><c/></a>

Now suppose we had a primitive upd:insertIntoAsFirst, with compatibility
similar to upd:insertIntoAsLast: I suppose the primitive
insAsFirst(t1,r1) would probably have the following compatibility table
entries:
   
insAsFirst(t1,r1)
--------------------------------------------------
delete(t2): yes
rename(t2,r2): yes
repVal(t2,r2): yes
insBef(t2,r2): yes
insAft(t2,r2): yes
insInto(t2,r2): no(1) - not compatible if t1 is t2
insAsFirst(t2,r2): no(1) - not compatible if t1 is t2
insAsLast(t2,r2): yes
insAttrs(t2,r2): yes

And we could change the mapping to:

insert <c/> into $x as first, insert <d/> before $x/b
=  { upd:insertAsFirst(n_a, n_c), upd:insertBefore(n_b, n_d) }
=> <a><c/><d/><b/></a>

I think this would be an improvement for precisely the reasons you give.

Jonathan
(personal opinion only)

--
Read my Blog: http://blogs.datadirect.com/jonathan_robie/
Learn XQuery: http://media.datadirect.com/download/docs/ddxquery/tutorial_query.html
Learn XQJ (the JDBC for XQuery): http://www.datadirect.com/developer/xquery/topics/xqj_tutorial/
Get DataDirect XQuery: http://www.datadirect.com/products/xquery/