In the last decade XML became one of the main standards for data storage and exchange on the Web. Detecting XML query-update independence is crucial to efficiently perform data management tasks, like those concerning view-maintenance, concurrency control, and security. This thesis presents a novel static analysis technique to detect XML queryupdate independence, in the presence of a schema. Rather than types, the presented system infers chains of types. Each chain represents a path that can be traversed on a valid document during query/update evaluation. The resulting independence analysis is precise, although it raises a challenging issue: recursive schemas may lead to infer infinitely many chains. This thesis presents a sound and complete approximation technique ensuring a finite analysis in any case, together with an efficient implementation performing the chain-based analysis in polynomial space and time.

iii iv

Résumé

Pendant la dernière décennie, le format de données XML est devenu l'un des principaux moyens de représentation et d'échange de données sur le Web. La détection de l'indépendance entre une requête et une mise à jour, qui a lieu en absence d'impact d'une mise à jour sur une requête, est un problème crucial pour la gestion efficace de tâches comme la maintenance des vues, le contrôle de concurrence et de sécurité. Cette thèse présente une nouvelle technique d'analyse statique pour détecter l'indépendance entre requête et mise à jour XML, dans le cas où les données sont typées par un schéma. La contribution de la thèse repose sur une notion de type plus riche que celle employée jusqu'ici dans la littérature. Au lieu de caractériser les éléments d'un document XML utiles ou touchés par une requête ou mise à jour en utilisant un ensemble d'étiquettes, ceux-ci sont caractérisés par un ensemble de chaînes d'étiquettes, correspondants aux chemins parcourus pendant l'évaluation de l'expression dans un document valide pour le schéma. L'analyse d'indépendance résulte du développement d'un système d'inférence de type pour les chaînes. Cette analyse précise soulève une question importante et difficile liés aux schémas récursifs: un ensemble infini de chaînes pouvant être inférées dans ce cas, est-il possible et comment se ramener à une analyse effective donc finie. Cette thèse présente donc une technique d'approximation correcte et complète assurant une analyse finie. L'analyse de cette technique a conduit à développer des algorithmes pour une implantation efficace de l'analyse, et de mener une large série de tests validant à la fois la qualité de l'approche et son efficacité. v vi Chapter 1 Chapter 2

Preliminaries

In this chapter we define the formal framework on top of which we build our work. We begin by presenting XML and DTDs, as the data model and the type language of semistructured databases. Then, we present the XML query and update languages that we consider, together with their formal semantics, which is used to prove the correctness of our analysis. We conclude by defining the XML query-update independence problem.

XML

XML [BPSM + 06] is a W3C-recommended language for representing data on the Web. XML has been designed to facilitate information exchange across different systems, thus overcoming the limits of its predecessor HTML, that was purposely conceived for displaying. XML is capable of wrapping many different kinds of data, because the data is represented in a textual form, organized hierarchically in a tree, and the document structure is self-describing by means of markup tags.

.1. It is a fragment of a bibliography, containing a single book, with its own title and author. Textual nodes here are written as the text they represent, for instance "B. Pierce". Element nodes are denoted by pairs of open and closing markup-tags, for instance <book>< book>, and are possibly nested inside other elements.

An XML document in its textual form must be well-formed. This essentially means that it defines a tree structure, the labels of open and closing tags match, and are also properly nested, so that the closing tag of a node appears always before the close-tag of its parent. The document t 1 is well-formed.

The abstract model underlying XML documents is tree-based. In its textual form, an XML document looks like the linearization of a tree. In this work, we represent an 1 2 CHAPTER 2. PRELIMINARIES

Introduction

In the last decade, XML has established itself as one of the main standards for data storage and exchange on the Web. Along with XML, a family of languages for querying and manipulating XML data have been devised, such as W3C standards XPath, XQuery and XSLT languages [SCF + 07]. The recent W3C standardization of an update facility for XML [RCD + 11] attracted a big deal of attention by the database community. Many old questions related to update optimization, already recognized as of crucial importance for relational databases, are open again for XML. Three central issues related to XML updates are view-maintenance, concurrency, and security.

View-maintenance Materialized views are precomputed queries from the database, that are used to expedite query answering. Materialized views have been shown to improve query evaluation performance by up to several orders of magnitude. Viewmaintenance is the problem of propagating into a materialized view the changes in the base data made by updates. View maintenance is a non-trivial process. Incremental re-computations of the view can take time proportional to the database size just to determine that no operation has to be done on the view and, in general, the problem is non-trivial even for XPath based queries and updates [START_REF] Björklund | Incremental XPath evaluation[END_REF].

Concurrency It is well known that, for ensuring high performances in the execution of concurrent query and update expressions, it is fundamental to evaluate them in parallel. Parallel evaluations, with a proper level of safety, can be ensured once one is able to define concurrency control mechanisms, locking schemes and schedulers which guarantee serializability of transactions on XML documents. All of this could be achieved, for instance, by means of a commutativity analysis, able to check if two expressions can be safely executed on a database independently of their order. Such an analysis would permit also to optimize logical plans for query languages with side effects, as shown in [START_REF] Ghelli | XML query optimization in the presence of side effects[END_REF].

Security Security views are a well studied framework to provide controlled access to data XML [START_REF] Fan | Secure XML querying with security views[END_REF]. The idea is that each user-group is provided with an XML view ix x CHAPTER 1. INTRODUCTION consisting of all and only the information that the users of that group are authorized to access or to update. It is of crucial importance to verify that updates coming from a user-group are executed respecting access control policies.

A way to entail an advance of technology in all such contexts, is to provide an efficient solution to the problem of detecting XML query-update independence. Query-update independence holds when a query and an update over a database do not interact, and therefore the update does not alter query result.

How can independence detection help tasks of view-maintenance, concurrency and security control? Intuitively, when a view is specified as a query, being able to determine that there is no interaction between a query and and update, allows to skip the whole view maintenance phase. Concerning concurrency control, if a query and an update do not interact, then they commute, meaning that they can be safely executed in any order, or even in parallel. Concerning security views, when these specify the part of data that cannot be accessed or modified, independence can be used to ensure that updates can be executed without violating the security policy expressed by the views.

A query and an update are independent when the query result is not affected by update execution, on any possible input database. In all contexts where detecting queryupdate independence is of crucial importance, benefits are amplified when query-update independence can be checked statically. In order to be useful, every static analysis technique must be sound: if query-update independence is statically detected, then independence does hold. The inverse implication (completeness) cannot be ensured in the general case, since static independence detection is undecidable (see [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF]). This means that if a static analyzer is used, for instance, in a view maintenance system, sometimes views are re-materialized after updates even if not needed, because the analysis has not been smart enough to statically detect a view-update independence. Useless view re-materialization frequently occurs if a static analyzer with low precision is adopted. This can lead to great waste of time, since view materialization cost can be proportional to the database size.

High precision of static independence analysis can be ensured by taking into account schema information. In many contexts, schemas are defined by users, mainly by means of the DTD or XML Schema languages, while in other contexts quite precise schemas, in the form of a DTD, can be automatically inferred, by using accurate and efficient existing techniques like the one proposed by Bex et al. in [START_REF] Geert | Inference of concise regular expressions and DTDs[END_REF]. Schema-based detection of XML query-update independence has been recently investigated. The state of the art technique has been presented by Benedikt and Cheney in [BC09a]. This technique infers from the schema the set of node types traversed by the query, and the set of node types impacted by the update. The query and the update are then deemed as independent if the two sets do not overlap. This technique is effective since the static analysis i) is able to manage a wide class of XQuery queries and updates, ii) can be performed in a negligible time, and iii) as a consequence, even on small documents, can avoid expensive query recomputation when independence wrt an update is detected. However, the technique has xi some weaknesses. As illustrated in [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF], in some cases, independence is not detected by the static analysis, due to some over-approximation made by the type inference rules.

Contributions

In this dissertation we propose a novel schema-based approach for detecting XML queryupdate independence. Differently from [BC09a, Che08, CGMS06], our system infers sequences of labels, hereafter called chains, to perform a static analysis of the data accessed by the queries and the updates. Intuitively, for each node that can be selected by a query/update path in a schema instance, the system infers a chain recording i) all labels that are encountered from the root to the node and ii) the order of traversal. This information is at the basis of a precise static independence analysis.

The main contribution of this work is a precise algorithm to detect independence for a query-update pair q-u knowing that documents are valid wrt a DTD d. It strongly relies on the following developments.

• Chain-based independence for queries and updates, a static notion, is the foundation of our algorithm: starting from the set of all possible chains associated with a DTD, our inference system extracts subsets of chains for the query and the update, capturing the navigation through valid documents made by the evaluation of the query and the update, respectively. Our inference system is cautiously specified for dealing with all XPath axes. Chain-based independence is the result of the absence of overlapping pair of chains for the query and the update. Our inference system is formally proved to be sound.

• A major step of our work concerns recursive schemas, for which chain-based independence analysis may cripplingly involve to deal with an infinite number of chains.

Our technique enabling the restriction of the analysis to finite subsets of query and update chain is a key contribution, and the core of our algorithm is the resulting finite analysis. It is proved to be equivalent to the infinite analysis

• Aiming at designing a tractable analysis, we show that by using a DAG-based representation of inferred chains, the finite analysis can run in polynomial space and time. Our technique has been carefully implemented, and extensive tests have been performed to validate our claim of precision and efficiency. Concerning precision, our results show that our technique outperforms [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF] to a large extent.

This work has been published in the International Conference of Very Large Databases 2012 [START_REF] Bidoit-Tollu | Type-based detection of XML query-update independence[END_REF], while preliminary versions have been presented in the 26ème Journée des Bases de Données Avancées 2010 [START_REF] Bidoit-Tollu | Detecting XML query-update independence. 26ème journée des Bases des données Avancées[END_REF] and in the International Formal Methods Workshop 2010 [START_REF] Bidoit-Tollu | Detecting XML query-update independence[END_REF].

The thesis is organized as follows. Chapter 2 introduces basic definitions about XML, schemas, queries and updates. Chapter 3 revises the state-of-the-art for detecting XML xii CHAPTER 1. INTRODUCTION query-update independence, and provides motivations for the work here presented. Chapter 4 presents our static independence analysis based on schemas and chains. Chapter 5 describes how the chain analysis can be efficiently implemented. Chapter 6 presents experiments validating our method. Chapter 7 discusses extensions, while Chapter 8 draws conclusions and discusses future perspectives.

Figure 2.1: Document t 1 and store (σ, l t 1 ) XML document as a store σ, which is an environment associating each node location l with either an element node a[L] or a text node "txt". In a[L], a is the element tag (or label), while L = (l 1 , . . . , l n ) is the ordered sequence of children locations in σ. We denote by dom(σ) the set of locations of σ. A tree is a pair t = (σ, l t ) where l t is the root location. With a little abuse of notation, we denote by dom(t) the domain of t, which consists of l t together with all locations connected to l t . We denote by σ@l the tree t in σ rooted at l. We denote by t ∼ t ′ two isomorphic trees t and t ′ ; they may differ only in terms of names of node locations. The empty sequence of locations is denoted by (). The concatenation of two sequences of locations L and L ′ is denoted by L ⋅ L ′ , and defined such that L ⋅ () = () ⋅ L = L.

In Figure 2.1 we draw the store associated to the XML document t 1 ; this store is a driving example for most of the definitions provided in the chapter. As already mentioned, each element tag of t 1 corresponds to a single node in the store, and vice versa. As a subtlety, notice that each node is referenced by a location. A location can be simply seen as the identifier of the node.

The XML data model has many features, but in this work we consider only element and textual nodes, since they are the most relevant ones. Most of the missing features, e.g., string attribute nodes, can be straightforwardly encoded in our model. We consider tree instances without document-node [BPSM + 06] (an unlabeled node which is the parent of the root). Other mechanisms such as key referencing (ID/IDREF) require to extend our model, by adding further constraints. We discuss extensions in Chapter 7.

SCHEMA LANGUAGES

Schema Languages

The concept of schema is standard in databases: it is a set of constraints defining a collection of data. XML documents are self-describing, hence a schema is an optional feature of XML databases. Nevertheless, any data collection is likely to follow a structure, and schemas are a very powerful means to express structural constraints. In all the context where a schema is available, it can be exploited to ensure safe and efficient XML processing [START_REF] Colazzo | Schemas for Safe and Efficient XML Processing[END_REF].

Many formalisms for writing XML schemas have been proposed, with the notable distinction of Document Type Defition (DTD) and XML Schema (XSD) as W3C standards, and RelaxNG as OASIS standard [START_REF] Clark | RELAX NG specification[END_REF]. In this work we will focus on the widely used DTDs. DTDs embody all of the main features of XML schema languages, whilst still allowing to keep the formalization concise. The extension of DTDs to more powerful languages such as XSD, by means of extended DTDs [START_REF] Papakonstantinou | DTD inference for views of XML data[END_REF] will be also discussed.

A DTD essentially consists of a list of declarations of elements. As an example, consider the schema bibliography.dtd reported in Figure 2.2. The declaration of elements follows a specific syntax like <!ELEMENT bib (book * ) > stating that an element tag is defined, that the name of the element is bib, and that the content of the element is modeled by the regular expression book * . The reserved word #PCDATA denotes the string type.

DTDs can be formally defined along the line of [START_REF] Murata | Taxonomy of XML schema languages using formal language theory[END_REF].

Definition 2.2.1 (DTD). A DTD is a 3-tuple (d, s, Σ) where • Σ is a finite alphabet for element tags, denoted by a, a 2 , a ′ ;

• s ∈ Σ is a non-recursive root-type;

• d is a function from Σ to regular expressions over Σ∪{String}, where String denotes the string base-type.

For convenience, in this work we assume that the root-type of a DTD is non-recursive. This implies that the root-element tag is never re-used inside a valid document, as happens in most practical scenarios. As we will discuss in Chapter 4, Section 4.4.2, this assumption is made for the sake of formalizations of the finite analysis, and is not restrictive. From now on we will use only the d component to specify a DTD, and we will write Σ S to denote the set Σ ∪ {String}.

In Figure 2.2 we show how a DTD is encoded in our formalism. The verbose declarations are denoted in our formalism in a simpler way, by associating each element tag with a regular expression modeling the element tag content.

An XML database compliant with all of the structural constraints defined by a schema is said to be valid against the schema. where Lang(r) denotes the language generated by the regular expression r.

As an example, the document t 1 in Figure 2.1 is valid wrt the DTD d 1 in Figure 2.2, because there exists a mapping λ such that • for the root l t 1 , we have λ(l t 1 ) = bib

• for all textual nodes, namely l ′ 2 and l ′′ 3 , we have λ(l ′ 2 ) = λ(l ′′ 3 ) = String ∈ Lang(String) • for all the sequences of children locations, namely (l 1 ), (l 2 , l 3 ) and (l ′

3 ) we have λ(l 1 ) = book ∈ Lang(book * ) λ(l 2 , l 3 ) = title author ∈ Lang(title, author+) λ(l ′ 3 ) = name ∈ Lang(name)

A recursive DTD d may not have any XML tree t such that t ∈ d. This is because the content description of some element a in d is non-terminating, i.e., there exists no finite subtree rooted at a that satisfies all constraints of d. A DTD d may also feature the content description of some elements that are unreachable from the root. No subtree of a valid tree is typed with an unreachable type definition, because there is a unique root type, and each element type definition is unique.

One can determine whether an element type a in d is non-terminating or unreachable in linear time (in the size of d). These problems can be reduced to the emptiness problem for context-free grammars, which can be solved in linear time [START_REF] Hopcroft | Introduction to Automata Theory, Languages and Computation[END_REF]. To simplify the discussion, in the sequel we assume that all element types in a DTD are terminating, and that all types in Σ S are reachable from the root.

DTDs capture all of the main features of XML schema languages. The principal restriction a DTD imposes is that each element tag definition must be unique. This is partially relaxed in XSDs, where a tag can have multiple type definitions, but at a specific condition: two type definitions for the same element tag, are never used in the same element content description. This is the single type restriction.

To illustrate, a legal fragment of XSD containing two element tag definitions that cannot be expressed by DTDs, is the following one. <xs∶element name = "author"> <xs∶complexType> <xs∶element name = "name" type = "AuthorName" > < xs∶complexType> < xs∶element> <xs∶element name = "publisher"> <xs∶complexType> <xs∶element name = "name" type = "PublisherName" > < xs∶complexType> < xs∶element> Notice that XSDs and DTDs have different syntax (XSDs are written as XML documents). The command xs∶element defines a new element tag, while xs∶complexType is used here to define the type structure of the element tag. In the example, two element tags are defined, namely author and publisher. Both have a common child element, name, specifying the name of the author and that of the publisher.

In DTDs, the definition of name must be unique while, in XSDs, we can use multiple type definitions. In this case, the schema refers to distinct type definitions AuthorName and PublisherName (defined elsewhere in the schema) depending on wether name is nested in author and publisher, respectively. What is powerful here is that the two types can define completely different structures of the name element.

A fragment of XSD that does not respect the single type restriction is the following. <xs∶element name = "person"> <xs∶complexType> <xs∶choice> <xs∶element name = "name" type = "AuthorName" > <xs∶element name = "name" type = "PublisherName" > < xs∶choice> < xs∶complexType> < xs∶element> Here xs∶choice says that only one between the elements is the list can be chosen. In particular, one between the two name element definitions can be used. This definition is illegal in XML Schema, since it is illegal to have two element types with the same name (i.e., name) but different types (i.e., AuthorName, PublisherName) in the same regular expression. Indeed, this breaks the single type restriction, and it is not expressible in DTDs nor in XSDs. Nevertheless it is expressible in RelaxNG.

A formalism that goes beyond that of DTDs and captures the expressivity of XML Schemas is that of Extended DTDs (EDTDs).

Definition 2.2.3 (Extended DTD and Validation [START_REF] Papakonstantinou | DTD inference for views of XML data[END_REF]). An Extended DTD is a triple (Σ, d ′ , µ) where

• d ′ is a DTD defined over the tag alphabet Σ ′ • µ ∶ Σ ′
S ↦ Σ S is a function, that is the identity on input String A tree A over Σ is valid wrt the extended DTD (Σ, d ′ , µ) if and only if there exists a tree t ′ over Σ ′ such that µ(t ′ ) = t and t ′ is valid wrt the DTD d ′ .

The crux of the definition is to interpret the two tag alphabets Σ and Σ ′ in a way such that Σ represents all element tags found in the tree instance, while Σ ′ contains a different tag for each type definition in the schema. In case of a tag with multiple definitions, such as name in the last example, we would have Σ ⊇ {name} and Σ ′ ⊇ {AuthorName, PublisherName} with µ(PublisherName) = name and µ(AuthorName) = name. The validation of the tree t over Σ wrt the extended DTD is then defined in terms of validation of a tree t ′ over Σ ′ wrt a DTD over a "type" alphabet Σ ′ .

It is worth noticing that EDTDs do not make any assumption on the use of types in the regular expressions, and hence they are strictly more expressive than XML Schemas, and roughly correspond to RelaxNG (without interleaving and counting operators). In this work, we will develop a static analysis relying on DTDs, and in Chapter 7 we will show that it can be lifted to EDTDs very easily.

XML types are founded on regular tree grammars [START_REF] Hosoya | Regular expression types for XML[END_REF]. Indeed, a schema language (e.g., DTD) roughly corresponds to a class of regular tree grammars [START_REF] Murata | Taxonomy of XML schema languages using formal language theory[END_REF]. This is needed for designing typed XML query and update language, where types of input and output expressions can be checked and type safety possibly ensured. However, our ultimate goal is to develop an access analysis based on schema informations, which is a problem radically different from that of type-checking. To avoid any confusion, in this work we adopt the following definition of XML type. Definition 2.2.4 (XML Type). Let d be a DTD, a type τ ∈ Σ S stands for the set of nodes A such that • if τ is the label a then A is the set of all nodes labeled with a belonging to some tree t ∈ d • if τ is String then A is the set of all textual nodes belonging to some tree t ∈ d

SCHEMA LANGUAGES

From this definition, it follows that the tag of each element definition in a DTD is a type. As an example, consider the bibliographic DTD d 1 . The type author stands for all nodes labeled as author belonging to a tree valid wrt the DTD d 1 .

A DTD induces a type dependency graph, defined as follows.

Definition 2.2.5 (Dependency graph). Let d be a DTD, the dependency graph of d, denoted by G d , is a directed graph defined as G d = (Σ S , ⇒ d ).

The vertex-set of G d coincides with Σ S , which is the tag-alphabet of the schema together with the String type. The edge-set of G d is ⇒ d , therefore two (immediately) reachable types in Σ S are two adjacent vertex in G d . The root of the graph is s d . The graph is connected because all types in Σ S are reachable from s d . A DTD d is recursive if and only if G d has a cycle. Proposition 2.2.6. Let G d be a type dependency graph with n vertices and m edges.

i) n-1 ≤ m ≤ n(n-1) ii) if m > n(n-1) 2 then G d is cyclic Proof. i) If G d has
n vertices, the number of edges in G d varies from n-1, because the graph is connected, to n(n-1), because all types can be recursive, except for the root that we assumed to be non-recursive. ii) An acyclic dependency graph of n vertices with the maximum number of edges, is such that only one type (the root) is connected with at most n-1 types, only one type is connected with at most with n -2 types, and so on until a single type with no children (e.g., String). This is ∑ n i=1 (i -1) = n(n-1) 2. We call saturated a DTD d that maximizes the number of edges in the dependency graph G d . Saturated DTDs are defined as follows.

Definition 2.2.7. (Saturated DTDs) A recursive DTD d is said to be saturated if G d has n vertexes and n(n-1) edges. A non-recursive DTD d is said to be saturated if G d has n vertexes and n(n-1) 2 edges.

An example of a saturated and non-recursive DTD and relative dependency graph is depicted in Figure 2.3. The DTD d 2 features 5 elements. The root type a 1 is defined in terms of all other types a 2 , . . . , a 5 , the type a 2 is defined in terms of all other types except the root and itself, namely a 3 , . . . , a 5 , and so on until the singleton type a 5 that has empty content. Note that no edge can be added in G d 2 without introducing recursion. a 1 ← a 2 , a 3 , a 4 , a 5 a 2 ← a 3 , a 4 , a 5 a 3 ← a 4 , a 5 a 4 ← a 5

Inference and Derivations

Throughout this dissertation we will describe several inference systems for checking properties of XML queries and updates. Inference systems have been nicely formalized in [START_REF] Grall | Deux critères de sécurité pour l'exécution de code mobile[END_REF].

Definition 2.2.8 (Inference System). Let J be a set of predicates called judgments. An inference system I is a set of rules defined over judgments. A rule R is of the form

Υ β
where Υ ⊆ J is a set of premises and β ∈ J is a judgment called the goal of the rule.

An inference system proves properties (ground judgments) by repeated backward application of inference rules, in Prolog style. The whole proof is called derivation tree, that is a tree whose nodes are judgements and edges denote the application of inference rules. In particular, the root of the derivation tree is the property one aims to prove and the leafs are axioms. A set of rules is said to be deterministic if for each judgement created, at most one rule can be applied. This property is necessary to ease the derivation of an algorithm from the rules. In this dissertation, we will present only deterministic inference systems.

Query and Update Languages

XQuery is the XML query language standardized by the W3C [SCF + 07]. XQuery stands to XML databases as SQL stands to relational databases. Nevertheless, the two languages are deeply different, because they are conceived for different data-models (trees vs. relations), and different deployments (the web vs. mainframes applications).

XQuery and SQL are both declarative languages. This is a crucial requirement for any query language in order to ensure logical and physical data independence. XQuery is a Turing-complete language, while SQL (without advanced features) is not. This just means that XQuery provides sufficient -perhaps, superabundant -expressive query power.

XQuery and SQL are both typed languages, this means that a type representing the result of an expression can be inferred. XQuery is a functional language, while SQL is not. This means that XQuery expressions are functions that can be nested or composed, and that the evaluation of each expression always returns a value with no side effect.

To illustrate, consider the following XQuery expression, where y is a free variable bound to the root of a bibliographic XML document and x is a bound variable of the query.

for x in y book return (x title, x author)

The expression iterates over book nodes in the document. At each iteration step, it binds the current node to the variable x, and then it returns a sequence of title and author of the book.

Being declarative, XQuery allows to retrieve all books in the document, by invoking the XPath navigation y book, independently from how they are effectively stored and retrieved.

Being functional, expressions can be composed in a sequence, to form the return clause, or nested to form the whole iterative construct.

Being typed, it is possible to infer the regular expression type (title * , author * ) * , to capture the fact that the result of the query is a possibly empty sequence of title and author lists.

XQuery is built on top of XPath. XPath is a language designed for navigating tree structures, along the axes of ancestors, descendants and siblings of a node. XQuery wraps-up XPath expressions, by introducing programming-language style constructs such as iteration, let binding, conditional expression, sequence construction, element construction, type-switching, etc.

The W3C working group has published a rich documentation on the XML query and update languages [SCF + 07, RCD + 11]. There is a large amount of details to consider in a rich language such as XQuery, hence it is a common practice to focus on a subset of the language that capture the most interesting constructs, so as to make the formal development intelligible yet effective.

In this work we deal with a large fragment of XQuery considered also in related approaches [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF][START_REF] Benedikt | Destabilizers and independence of XML updates[END_REF], which is defined by the grammar of Table 2.1.

We comment on the main constructs of the language.

(Empty) The empty query is an expression performing no operation.

(Concatenation) A concatenation of queries is used to build new sequences of trees.

CHAPTER 2. PRELIMINARIES q ∶∶= () (Empty) q, q (Concatenation)
<a>q< a> (ElementNode)

"txt" (TextNode)

x axis∶∶φ (Step) for x in q return q (For) let x ∶= q return q (Let) if (q) then q else q (If) The importance of node element and text constructions stems from the fact that they are the only query expression that extend the input store with new data. Their use is twofold. They can be used in order to re-structure nodes of the base data, and then present it to the user (e.g. output a node changing the order of its children). They can be used by update expressions, in order to create new forests to be added to the store (e.g., insert a fresh textual node "txt" in a given position).

axis ∶∶= self (Axes)
(XPath Steps) Navigational capabilities are at the heart of all query languages for semi-structured and, in general, for hierarchical data. Our language grammar includes downward, upward and sibling XPath navigational axis. This is a large fragment, considered also by related studies such as [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF][START_REF] Benedikt | Destabilizers and independence of XML updates[END_REF].

Preceding and following axes, are not included. They can be easily encoded by standard rewriting As we will show later, this can be done in a both correct and complete way. Therefore, the language we consider simulates all XPath navigational axes.

(Iteration, Let binding and Conditional) Iteration (For), let binding (Let) and conditional expression (If) represent the most powerful constructs of the language, in terms of expressivity. This set of constructs subsumes the standard FLWR XQuery fragment [SCF + 07], that features the where clause instead of the conditional if. Indeed, while the where clause nested in a let or for expression can be simulated by using an if-then-else expression, the converse is not always true since the where clause can express only an if-then condition. Therefore the language is strictly more expressive than its FLWR version.

For the sake of presentation, we adopt some minor syntactic deviation from the W3C specification [SCF + 07]. In XQuery variables are always prefixed by $, in order to avoid ambiguity during the parsing phase. However, in this work variables will be always clear from the context and thus, we avoid to prefix them with a reserved symbol. Also, element construction is denoted by <a>q< a>, without enclosing the inner query q into brackets, as defined in [SCF + 07].

XPath node tests are denoted by φ. In the grammar, a stands for a tag name. We will use φ as a shortcut for child ∶∶ φ while φ is a (strict) descendant navigation that, according to the W3C, stands for descendant-or-self ∶∶ node() child ∶∶ φ

In the following we will use step to indicate an XPath step. The node filter node() is often denoted by the wildcard * . XPath expressions of the form

x step 1 step 2 . . . step n u ∶∶= () (Empty) u, u (Concatenation)
for x in q return u (For)

let x ∶= q return u (Let) if (q) then u 1 else u 2 (If)
delete q 0 (Delete) rename q 0 as a (Rename) insert q pos q 0 (Insert) replace q 0 with q (Replace)

pos ∶∶= into (as first as last)? (Positions) after before

for x 1 in x step 1 return for x 2 in x 1 step 2 return ⋮ for x n in x n-1 step n return x n self ∶∶ node()
Recently the W3C standardized an update language for XML called XQuery Update Facility [RCD + 11]. This includes a set of commands that can be used to modify instances of the XML data model, thus introducing effects to the query language.

As for queries, update commands are declarative and typed. This means that it is possible to modify an XML document, independently from how this is stored or retrieved, and also to compute a type describing the modified document. However, XML updates are not written in a functional way. They are not true functions with a return value that can be arbitrarily composed or nested.

An example of XML update is the following.

insert < book > into x bib which inserts a fresh node labeled as book below the root labeled with bib.

XQuery Update Facility is built on XQuery and XPath, that are indeed used to fill the arguments of update commands.

The subset of XQuery Update Facility [RCD + 11] which we consider is defined in Table 2.2. It is essentially composed of two parts, one of programming constructs shared with the query language, and one of commands modifying the input store.

(Basic Programming) Like for queries, updates can be composed sequentially or can be composed by means of let/for statements, where only the return part can contain update operations. The conditional expression allows to apply different updates, depending on the boolean value of a conditional query.

(Side-effects) In this work we consider all main constructs of the XQuery Update Facility, namely node deletion, renaming, insertion and replacement. We consider only replace update affecting node locations. The extension to the replace node-value command is straightforward1 , as well as that to the remaining update commands.

Other extensions to the update language are discussed in Chapter 7.

Formal Semantics

In this section we give the formal semantics of XQuery and XQuery Update Facility. This will be used in the proofs to show the correctness of our independence analysis. We begin by defining the semantics of XPath steps as they are the building blocks of both languages.

Semantics of XPath Steps

Tree relations The semantics of axis navigation and text filtering is defined in [DFF + 10].

If σ is a store, the binary parent-child relation among store locations is denoted by Child σ ⊆ dom(σ) × dom(σ), and (l, l ′ ) ∈ Child σ when l = a[L ⋅ l ′ ⋅ L ′ ] ∈ σ. We denote by Parent σ the inverse of Child σ , by Descendant σ the transitive closure of Child σ , and by Ancestor σ the inverse of Descendant σ . Finally, Self σ denotes the identity function on dom(σ). The binary relation that holds between a location and its immediate-rightsibling is denoted by NextSibling σ ⊆ dom(σ)×dom(σ). We have that (l, l ′ ) ∈ NextSibling σ when l a ← a[L ⋅ l ⋅ l ′ ⋅ L ′ ] ∈ σ, for some a. We denote by FollowingSibling σ the transitive closure of NextSibling σ , and by PrecedingSibling σ the inverse of FollowingSibling σ . If R is one of the binary relations defined above, provided a location l, we write R(l) for the set of locations l ′ such that (l, l ′ ) ∈ R. For instance Child σ (l) denotes the set of children of l and FollowingSibling σ (l) the set of following sibling nodes of l. Of course, it holds Self σ (l) = { l }. Finally docOrder σ ⊆ dom(σ) × dom(σ) denotes the partial documentorder among store locations, that is total for locations belonging to the same tree, but is undefined for locations belonging to distinct trees of the store. If R σ is a relation over σ defined above, we denote by R t ⊆ R σ its subset concerning all and only the locations belonging to the tree t = (σ, l t ).

Axis Semantics

The semantics of an XPath step is given by the composition of the semantics of a navigational axis axis and that of a test filtering φ. The semantics of a navigation axis axis wrt a store σ and an input location l, is denoted by [[axis]] l σ and defined as follows.

[[self]] l σ def = Self σ (l) [[child]] l σ def = Child σ (l) [[descendant]] l σ def = Descendant σ (l) [[descendant-or-self]] l σ def = Descendant σ (l) ∪ Self σ (l) [[parent]] l σ def = Parent σ (l) [[ancestor]] l σ def = Ancestor σ (l) [[ancestor-or-self]] l σ def = Ancestor σ (l) ∪ Self σ (l) [[following-sibling]] l σ def = FollowingSibling σ (l) [[preceding-sibling]] l σ def = PrecedingSibling σ (l)
The semantics of a test filtering wrt a store σ and an input location l, is denoted by

[[φ]] l
σ and defined by the following equations.

[[a]] l σ def = { l l ← a[L] ∈ σ } [[text()]] l σ def = { l l ← "txt" ∈ σ } [[node()]] l σ def = { l l ∈ σ }
Notice that this rules output either input location, when it satisfies the filtering condition, or the empty set.

The following examples illustrate the above definitions. Consider the store σ in Figure 2.1.

[[descendant-or-self]] lt 1 σ = dom(σ) [[following-sibling]] l 2 σ = {l 3 } [[text()]] l ′ 2 σ = {l ′ 2 } [[author]] l ′ 2 σ = ∅
An XPath axis axis is said to be downward if it is either child, descendant or descendant-or-self, backward if it is parent, ancestor or ancestor-or-self, and horizontal if it is preceding-sibling or following-sibling.

Step Semantics An XPath step is evaluated by composing axis navigation and step filtering. An axis navigation results in a set of locations L. This set is explicitly casted into a sequence L that respects document order. We model this by using an abstract predicate order σ

(L) = L that holds iff (i) l ∈ L ⇐⇒ l ∈ L and (ii) L = (L 1 ⋅ l ⋅ l ′ ⋅ L 2 ) ⇒ (l, l ′ ) ∈ docOrder σ . Finally, L is filtered according to φ. Provided that [[axis]] l σ = L and order σ (L) = (l 1 , . . . , l n ) step semantics is defined as follows. [[axis ∶∶ φ]] l σ def = ([[φ]] l 1 σ , [[φ]] l 2 σ , . . . , [[φ]] ln σ ) When [[φ]] l σ = ∅ it is treated as the empty sequence.
Notice that this definition slightly differs from the one in [SCF + 07] where sequences obtained by the evaluation of backward and preceding-sibling axes are returned in inverse document order. Of course, this detail has no impact on our static analysis.

The following examples illustrate the above definition. Consider the store σ in Fig-

ure 2.1. [[descendant-or-self ∶∶ node()]] lt 1 σ = dom(σ) [[descendant-or-self ∶∶ text()]] lt 1 σ = (l ′ 2 , l ′′ 3 ) [[following-sibling ∶∶ author]] l 2 σ = (l 3 ) Notice that [[axis ∶∶ φ]] l
σ produces a sequence of nodes without duplicates.

XQuery Semantics

Query semantics is specified in [DFF + 10], while we are highly inspired by the succinct and elegant formalization made in [START_REF] Benedikt | Semantics, types and effects for XML updates[END_REF], from which we borrow some notions that are needed for our own presentation.

Query semantics is denoted by the following judgment

σ, γ ⊧ q ⇒ σ ′ , L
meaning that the execution of the query q over σ outputs a sequence of locations L and a new store σ ′ , including σ plus new elements built by q. The dynamic environment γ binds each free variable of q to a sequence of locations L in σ, this is denoted by γ

[x ↦ L] or simply by γ[x ↦ l] when L = (l).
Query semantics is reported in Table 2.3. In the rules we also make use of two auxiliary judgements ⊧ copy and ⊧ ⋆ that model the copy of a sequence of elements and the iteration over a sequence of elements. These are defined by rule (SQ-Copy) and (SQ-Iter), respectively. We illustrate the semantics of the language through some running examples. Consider for instance the following iteration, that returns all parents of textual nodes, evaluated over the tree t 1 in Figure 2.1, wrt the environment γ

CHAPTER 2. PRELIMINARIES σ, γ ⊧ () ⇒ σ, () (SQ-Empty) σ, γ ⊧ q 1 ⇒ σ 2 , L 1 σ 2 , γ ⊧ q 2 ⇒ σ 3 , L 2 σ, γ ⊧ q 1 , q 2 ⇒ σ 3 , L 1 ⋅ L 2 (SQ-Concat) σ, γ ⊧ q copy ⇒ σ 2 , L l ∈ dom(σ 2 ) σ, γ ⊧ <a>q< a> ⇒ σ 2 [l ∶= a[L]], l (SQ-Elt) l ∈ dom(σ) σ, γ ⊧ "txt" ⇒ σ 2 [l ∶= "txt"], l (SQ-Text) σ, γ ⊧ q ⇒ σ 0 , L 0 (L ′ , σ 1 ) = copy(L 0 , σ 0 ) σ ′ = σ 0 ∪ σ 1 σ, γ ⊧ q copy ⇒ σ ′ , L ′ (SQ-Copy) σ, γ ⊧ q 1 ⇒ σ 2 , L σ 2 , γ[x ↦ L] ⊧ ⋆ q 2 ⇒ σ 3 , L ′ σ, γ ⊧ for x in q 1 return q 2 ⇒ σ 3 , L ′ (SQ-For) σ, γ[x ↦ ()] ⊧ ⋆ q ⇒ σ, () (SQ-IterBase) σ, γ[x ↦ l] ⊧ q ⇒ σ 2 , L 1 σ 2 , γ[x ↦ L] ⊧ ⋆ q ⇒ σ 3 , L 2 σ, γ[x ↦ l ⋅ L] ⊧ ⋆ q ⇒ σ 3 , L 1 ⋅ L 2 (SQ-Iter) σ, γ ⊧ q 1 ⇒ σ 2 , L σ 2 , γ[x ↦ L] ⊧ q 2 ⇒ σ 3 , L ′ σ, γ ⊧ let x ∶= q 1 return q 2 ⇒ σ 3 , L ′ (SQ-Let) σ, γ ⊧ q ⇒ σ 2 , l ⋅ L σ 2 , γ ⊧ q 1 ⇒ σ 3 , L 1 σ, γ ⊧ if (q) then q 1 else q 2 ⇒ σ 3 , L 1 (SQ-If1) σ, γ ⊧ q ⇒ σ 2 , () σ 2 , γ ⊧ q 2 ⇒ σ 3 , L 2 σ, γ ⊧ if (q) then q 1 else q 2 ⇒ σ 3 , L 2 (SQ-If2) γ(x) = l ⋅ () [[axis ∶∶ φ]] l σ = L σ, γ ⊧ x axis ∶∶ φ ⇒ σ, L (SQ-Step)
= { x ↦ l t 1 }. 1 σ, γ ⊧ x descendant ∶∶ text() ⇒ σ, L 2 σ, γ[y ↦ L] ⊧ ⋆ y parent ∶∶ node() ⇒ σ, L ′ σ, γ ⊧ for y in x descendant ∶∶ text() return y parent ∶∶ node() ⇒ σ, L ′
The semantics of iteration is standard and modeled by rule (SQ-For). The resulting sequence of the left subexpression L is bound with variable y and then used for iterating over the right subexpression. Notice that the evaluation does not change the store σ.

Let us explore more in detail the derivation.

1 The left branch is derived by applying rule (SQ-Step) as follows

[[descendant ∶∶ text()]] lt 1 σ = (l ′ 2 , l ′′ 3 ) σ, γ ⊧ x descendant ∶∶ text() ⇒ σ, (l ′ 2 , l ′′ 3 )
The result sequence is composed of all textual nodes that are descendants of the root.

2 The right branch is derived by applying rule (SQ-Iter) as follows

[[parent ∶∶ node()]] l ′ 2 σ = (l 2 ) σ, γ[y ↦ l ′ 2 ] ⊧ y parent ∶∶ node() ⇒ σ, (l 2 ) [[parent ∶∶ node()]] l ′′ 3 σ = (l ′ 3 ) σ, γ[y ↦ l ′′ 3 ] ⊧ y parent ∶∶ node() ⇒ σ, (l ′ 3 ) σ, γ[y ↦ (l ′ 2 , l ′′ 3 )] ⊧ ⋆ y parent ∶∶ node() ⇒ σ, (l 2 , l ′ 3 )
Here step evaluation is performed for each location bound to y. The results of the evaluations are concatenated and then returned.

The construction of new elements is the only command that extends the input store during query evaluation.

To illustrate, consider the following query listing all books of tree t 1 in Figure 2.1, wrt the environment

γ = { x ↦ l t 1 }. σ, γ ⊧ x descendant ∶∶ book ⇒ σ, (l 1 ) (l c , σ c ) = copy(l 1 , σ) σ ′ = σ ∪ σ c σ, γ ⊧ x descendant ∶∶ book copy ⇒ σ ′ , (l c ) l ∉ dom(σ ′ ) σ, γ ⊧ <list>x descendant ∶∶ book< list> ⇒ σ ′ [l ∶= list[l c ]], l c
In this case rule (SQ-Elt) is applied. First, the inner query selecting all books in the store is evaluated, resulting in the only location l 1 . Second, the whole subtree rooted at l 1 is copied to a fresh isomorphic tree σ c @l c , by means of rule (SQ-Copy). This operation is modeled here by using an abstract predicate copy(l 1 , σ). The output store σ ′ is the extension of σ with σ c . Finally, l c becomes the child of a fresh node location l representing the element node labeled with list.

Rewriting of preceding and following axes As said before, following and preceding axes are not directly dealt with by our system, but they can be expressed by means of rewriting. We can show that the rewriting is complete, in the sense that it gives the same result set as the standard semantics.

We show the case of the following axis, since preceding is analogous. Below σ is a fixed store, while l, l a and l f are locations belonging to σ. The W3C semantics for the axis is as follows.

[[following ∶∶ φ]] l σ def = order σ (L) (2.1) where L is ⋃ l a ∈ [[ancestor-or-self ∶∶ node()]] l σ l f ∈ [[following-sibling ∶∶ node()]] la σ l ′ ∈ [[descendant-or-self ∶∶ φ]] l f σ { l ′ }
Step x following ∶∶ φ is rewritten in our language in the following way

x following ∶∶ φ ≈ q f (φ)
where q f (φ) = for x a in x ancestor-or-self ∶∶ node() for x f in x a following-sibling ∶∶ node() return x f descendant ∶∶ φ Hence, provided that the judgment σ, x ↦ l ⊧ q f (φ) ⇒ σ, L holds, we have that L is

(l a 1 , . . . , l an ) = order σ ([[ancestor ∶∶ node()]] l σ ) (l f i,1 , . . . , l f i,m ) = order σ ([[following-sibling ∶∶ node()]] la i σ ) L (i,j) = order σ ([[descendant-or-self ∶∶ φ]] l f i,j σ ) L (i,j) (2.2)
where ∏ denotes sequence concatenation, with i = 1..n and j = 1..m.

We claim that a location is in the result of (2.1) if and only if it is in the result of (2.2). This holds since the resulting locations of all intermediate steps are the same. Furthermore, if one also wants to enforce that resulting sequences of both (2.1) and (2.2) are output in the same order (that is, document order), it is sufficient to impose that locations in the result of step [[ancestor ∶∶ node()]] l σ in (2.2) are iterated in inverted document order, for instance by imposing i = n..1.

XQuery Update Semantics

In this section we formally define the semantics of update expressions.

As a convention in update expressions, we write q 0 for the target expression that is retrieving the nodes in the input document that are target of the update (e.g. deleted nodes are target nodes). We simply write q for the source update subexpression, that is retrieving or producing elements to insert in the database by means of insert or replace commands. According to the W3C semantics [RCD + 11] the target expression q 0 is required to output a single node otherwise a run time error occurs.

In the W3C specification update evaluation is split into three phases.

1. Creation of an update pending list (UPL) of atomic update commands; 2. Execution of a sanity check on this list, and reorder of atomic updates; 3. Application of the UPL on the input store so as to update the document.

An update pending list ω is a sequence of atomic update commands. An atomic update commands ι in of the following form.

ι ∶∶ = del(l) ren(l, a) ins(L, pos, l) repl(l, L)
where l is the target location, L the sequence of roots of source elements to be inserted, and pos is an insertion position defined as before.

Creation of the UPL The creation of the UPL from an update u is denoted as follows

σ, γ ⊧ u ⇒ σ ω , ω
As usual, γ binds u free variables to locations in σ and the store σ ω that extends σ contains newly created locations potentially used in the UPL ω.

σ, γ ⊧ () ⇒ σ, ǫ (SU-Empty) Application of the UPL Applying the UPL ω to the input store σ ω produces the updated store σ u . This is denoted by

σ 1 , γ ⊧ u 1 ⇒ σ 2 , ω 1 σ 2 , γ ⊧ u 2 ⇒ σ 3 , ω 2 σ 1 , γ ⊧ u 1 , u 2 ⇒ σ 3 , ω 1 ; ω 2 (SU-Concat) σ 1 , γ ⊧ q ⇒ L, σ 2 σ 2 , γ[x ↦ L] ⊧ ⋆ u ⇒ σ 3 , ω σ 1 , γ ⊧ for x in q return u ⇒ σ 3 , ω (SU-For) σ 1 , γ ⊧ q ⇒ L, σ 2 σ 2 , γ[x ↦ L] ⊧ u ⇒ σ 3 , ω σ 1 , γ ⊧ let x ∶= q return u ⇒ σ 3 , ω (SU-Let) σ 1 , γ ⊧ q ⇒ σ 2 , l ⋅ L σ 2 , γ ⊧ u 1 ⇒ σ 3 , ω 1 σ 1 , γ ⊧ if (q) then u 1 else u 2 ⇒ σ 3 , ω 1 (SU-If1) σ 1 , γ ⊧ q ⇒ σ 2 , () σ 2 , γ ⊧ u 2 ⇒ σ 3 , ω 2 σ 1 , γ ⊧ if (q) then u 1 else u 2 ⇒ σ 3 , ω 2 (SU-If2) σ 1 , γ ⊧ q copy ⇒ σ 2 , L σ 2 , γ ⊧ q 0 ⇒ σ 3 , l 0 σ 1 , γ ⊧ insert q pos q 0 ⇒ σ 3 , ins(L, pos, l 0 ) (SU-Insert) σ 1 , γ ⊧ q 0 ⇒ σ 2 , l 0 σ 1 , γ ⊧ delete q 0 ⇒ σ 2 , del(l 0 ) (SU-Delete) σ 1 , γ ⊧ q 0 ⇒ σ 2 , l 0 σ 2 , γ ⊧ q copy ⇒ σ 3 , L σ 1 , γ ⊧ replace q 0 with q ⇒ σ 3 , repl(l 0 , L) (SU-Replace) σ 1 , γ ⊧ q 0 ⇒ σ 2 , l σ 1 , γ ⊧ rename q 0 as b ⇒ σ 2 , ren(l 0 , b) (SU-Rename) σ, γ[x ↦ ()] ⊧ ⋆ u ⇒ σ, ǫ (SU-IterBase) σ 1 , γ[x ↦ l] ⊧ u ⇒ σ 2 , ω 1 σ 2 , γ[x ↦ L] ⊧ ⋆ u ⇒ σ 3 , ω 2 σ 1 , γ[x ↦ l ⋅ L] ⊧ ⋆ u ⇒ σ 3 , ω 1 ; ω 2 (SU-Iter)
σ(l ′ ) = a[L 1 ⋅ l ⋅ L 2 ] σ⊧ del(l) ↝ σ[l ′ ∶= a[L 1 ⋅ L 2 ]] (SAU-Delete) σ(l) = a[L] σ⊧ ren(l, b) ↝ σ[l ∶= b[L]] (SAU-Rename) σ(l ′ ) = a[L 1 ⋅ l ⋅ L 2 ] σ⊧ ins(L, before, l) ↝ σ[l ′ ∶= a[L 1 ⋅ L ⋅ l ⋅ L 2 ]] (SAU-InsertBefore) σ(l ′ ) = a[L 1 ⋅ l ⋅ L 2 ] σ⊧ ins(L, after, l) ↝ σ[l ′ ∶= a[L 1 ⋅ l ⋅ L ⋅ L 2 ]] (SAU-InsertAfter) σ(l) = a[L 1 ⋅ L 2 ] σ⊧ ins(L, into, l) ↝ σ[l ∶= a[L 1 ⋅ L ⋅ L 2 ]] (SAU-InsertInto) σ(l) = a[L 1 ] σ⊧ ins(L, into as first, l) ↝ σ[l ∶= a[L ⋅ L 1 ]] (SAU-InsertFirst) σ(l) = a[L 1 ] σ⊧ ins(L, into as last, l) ↝ σ[l ∶= a[L 1 ⋅ L]] (SAU-InsertLast) σ(l ′ ) = a[L 1 ⋅ l ⋅ L 2 ] σ⊧ repl(l, L) ↝ σ[l ′ ∶= a[L 1 ⋅ L ⋅ L 2 ]] (SAU-Replace) σ⊧ ǫ ↝ σ (SAU-Empty) σ⊧ ω j ↝ σ ′ σ ′ ⊧ ω k ↝ σ ′′ {j, k} = {1, 2} σ⊧ ω 1 , ω 2 ↝ σ ′′ (SAU-Iter)
σ ω ⊧ ω ↝ σ u
Of course, all locations used in ω are contained in σ ω .

The composition of all phases of update semantics is denoted by

σ, γ ⊧ u ∶ σ u
and it is defined as follows

σ, γ ⊧ u ⇒ σ ω , ω sanitycheck(ω) σ ω ⊧ ω ↝ σ u σ, γ ⊧ u ∶ σ u
As for queries, we explain the semantics of updates through some examples. Let us consider the execution of the update below that deletes all textual nodes in the tree t 1 of Figure 2.1, wrt the environment γ = { x ↦ l t 1 }.

for y in x descendant ∶∶ text() return delete y

The end-to-end semantics of the update consists of generating the UPL of nodes to delete, and then doing the sanity check on the UPL and of applying the update pending list so as to obtain the updated store σ ′ .

1 σ, γ ⊧ for y in x descendant ∶∶ text() return delete y ⇒ σ, (del(l ′ 2 ), del(l ′′ 3 )) sanitycheck(del(l ′ 2 ), del(l ′′ 3 )) 2 σ⊧ del(l ′ 2 ), del(l ′′ 3 ) ↝ σ ′ σ, γ ⊧ for y in x descendant ∶∶ text() return delete y ∶ σ ′
1 The derivation of the branch generating the UPL with locations to be deleted is the following.

σ, γ ⊧ x descendant ∶∶ text() ⇒ σ, (l ′ 2 , l ′′ 3 ) σ, γ[y ↦ l ′ 2 ] ⊧ delete y ⇒ σ, (del(l ′ 2 )) σ, γ[y ↦ l ′′ 3 ] ⊧ delete y ⇒ σ, (del(l ′′ 3 )) σ, γ[y ↦ (l ′ 2 , l ′′ 3 )] ⊧ ⋆ delete y ⇒ σ, (del(l ′ 2 ), del(l ′′ 3 )) σ, γ ⊧ for y in x descendant ∶∶ text() return delete y ⇒ σ, (del(l ′ 2 ), del(l ′′ 3 ))
Here the UPL is computed by first evaluating the navigational expression selecting all textual nodes, and then by iterating over the resulting sequence of locations.

2 The derivation of the branch applying the UPL is the following.

σ(l ′ 3 ) = name[l ′′ 3 ] σ ′′ = σ[l ′ 3 ∶= name[]] σ⊧ del(l ′′ 3 ) ↝ σ ′′ σ ′′ (l 2 ) = title[l ′ 2 ] σ ′ = σ[l 2 ∶= title[]] σ ′′ ⊧ del(l ′ 2 ) ↝ σ ′ σ⊧ del(l ′ 2 ), del(l ′′ 3 ) ↝ σ ′
Here the application of the UPL consists of removing the use of the target locations by means of rule (SAU-Iter) and (SAU-Delete). As mentioned before, in this semantics we do not explicitly take into account order of update application, in fact rule (SAU-Iter) specifies that two update pending lists can be executed in any order. In order to stress this, in the example, we chose to remove first location l ′′ 3 and then l 2 , while the input UPL presents them in inverse order. For instance for all valid sequences of updates targeting the same locations like for x in y a return ( delete x , rename x as b)

the semantics allows to apply non-deterministically the atomic delete and rename commands in any order. Whatever order of application is chosen, the result of the update is to delete all nodes labeled as a. Notice that once atomic updates are collected, we may have that a location is both target of an insert and of a rename. In fact, the sanity check just enforces that no location is target of multiple rename or replace.

Another interesting point to stress is that for deleted and replace updates, no node is destroyed in the store. In fact, if σ, γ ⊧ u ⇒ σ ω , ω and σ ω ⊧ ω ↝ σ u then dom(σ) ⊆ dom(σ u ). For a tree t=(σ, l t ), u(t) denotes the tree (σ u @l t , l t ). Note that dom(σ) ⊆ dom(σ u @l t ) may not hold anymore, since σ u @l t does not keep locations disconnected to the root l t after the update.

To see how the input store is extended by updates such as insert and replace, we consider the following expression on the tree t 1 in Figure 2.1, wrt the environment γ = { x ↦ l t 1 }. The update inserts a new tree listing all books as a child of the root.

1 σ, γ ⊧ insert <list>x descendant ∶∶ book< list> into x self ∶∶ bib ⇒ ins(L, into, l t 1 ) sanitycheck(ins(L, into, l t 1 )) 2 σ⊧ ins(L, into, l 0 ) ↝ σ ′ σ, γ ⊧ insert <list>x descendant ∶∶ book< list> into x self ∶∶ bib ∶ σ ′
We explore a possible derivation tree of the update semantics, by means of an example.

1 The derivation for the branch generating the UPL is the following.

σ, γ ⊧ x self ∶∶ bib ⇒ σ, (l t 1 ) σ, γ ⊧ x descendant ∶∶ book ⇒ σ 1 , l 1 (l c , σ c ) = copy(l 1 , σ 1 ) σ ′ = σ 1 ∪ σ c σ, γ ⊧ <list>x descendant ∶∶ book< list> copy ⇒ σ ′ , l c σ, γ ⊧ insert <list>x descendant ∶∶ book< list> into x self ∶∶ bib ⇒ ins(l c , into, l t 1 )
Here the UPL is composed by a single atomic insert update command. The arguments of the atomic update are taken from the outputs of the target and the source query. From one hand, the target query simply returns the root of the document.

From the other hand, the source query returns the copy of a fresh tree listing all books.

2 The derivation concerning the application of the UPL is the following.

σ(l t 1 ) = bib[l 1 ] σ ′ = σ[l t 1 ∶= bib[l 1 , l c ]] σ⊧ ins(l c , into, l t 1 ) ↝ σ ′
Here the root location receives one more child. In this example we chose to insert the new location in last position. It is worth noticing that when position into is specified, our semantics, as well as the W3C one, allows to insert the node nondeterministically, in any position.

QUERY-UPDATE INDEPENDENCE 25

Assumptions on the Query Language In order to simplify the formal treatment, we do some assumptions on the query language.

(Node Element Construction) We assume that node element construction <a>q< a> is not used in the left-hand side expression of a for/let-expression. This restriction is met by a very large class of queries used in practice, while queries like let x ∶= <a>q< a> return <b>x< b> can be rewritten by simple variable substitution into <b><a>q< a>< b> (Text Element Construction) Given that a constant query is independent of any update, we assume that "txt" is either nested in a for expression.

Updates Preserving the Schema We assume also that the updates are preserving the schema, in the sense that they do not introduce new chains. Delete updates that break schema constraints are however allowed. As we show later in Chapter 3, schema evolution is an issue that goes beyond the scope of detecting independence.

Query-Update Independence

We now formalize query-update independence. To this end we need a notion of equivalence over XML stores.

Definition 2.5.1 (Equivalence). Given two stores σ and σ ′ , two locations l ∈ σ and l ′ ∈ σ ′ are said to be value equivalent, written (σ, l) ≅ (σ ′ , l ′ ), iff the two trees σ@l and σ ′ @l ′ are isomorphic (they possibly differ only in terms of locations). We write (σ, L) ≅ (σ ′ , L ′ ) to denote the value equivalence on location sequences L = (l 1 , . . . , l n ) and L ′ = (l ′ 1 , . . . , l ′ n ), with l i ∈ σ and l ′ i ∈ σ ′ , and holding iff (σ, l i ) ≅ (σ ′ , l ′ i ) for i = 1..n.

Definition 2.5.2 (Independence: q ⊧ u, q ⊧ d u). Let σ be a store and γ a variable environment over σ.

A query q and an update u are said to be independent wrt (σ, γ) if

σ, γ ⊧ q ⇒ σ q , L q σ, γ ⊧ u ∶ σ u σ u , γ ⊧ q ⇒ σ ′ q , L ′ q implies (σ q , L q ) ≅ (σ ′ q , L ′ q )
. Also, q and u are independent, written q ⊧ u, iff they are independent for any pair (σ, γ).

Finally, q and u are independent wrt the DTD d, written q ⊧ d u, iff for every tree t = (σ, l t ) ∈ d and γ, they are independent for (σ, γ).

As a natural consequence of the fact that XML data are typed by a schema, we assume that our independence analysis is run in a context where all data remain consistent wrt the schema after each update. In case an update triggers schema evolution, then a larger task of schema maintenance has to be carried on. This task may imply existing views (queries) to be reformulated in order to be correct wrt the new schema, and thus it is likely to exclude any other kind of schema-based analysis until its completion.

Conclusions

In this chapter we presented the formal framework on top of which we build our work. We presented XML databases, schemas, query and update languages, and defined the problem we study: XML query update independence. In the next chapter we will revise the state of the art for detecting independence via static analysis.

Chapter 3

Query Update Independence: State of the Art

In this chapter we present the state of the art techniques for checking XML query-update independence. In the first part, we report on the theoretical background that is relevant to detecting independence via static analysis, and outline the intractability of the problem for practical cases. In the second part, we present a family of approximate algorithms developed for checking independence that, being sound but not complete, try to ensure a tractable analysis.

Decidability and Complexity of Exact Static Independence Analysis

Former studies by Benedikt and Cheney [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF] and by Raghavachari and Shmueli [START_REF] Raghavachari | Conflicting XML updates[END_REF] provided the theoretical background of checking independence via static analysis. These works show that independence essentially inherits its computational difficulty from more fundamental problems such as query equivalence and containment. Because of this, the problem is challenging.

The following results give a flavor on how checking independence ranges from undecidability to tractability. Below, boolean atomic queries and updates are expressions without aggregates and tests on data values returning either the empty sequence or a constant value [START_REF] Benedikt | Interpreting tree-to-tree queries[END_REF].

Theorem 3.1.1 ([BC09a]). Independence is undecidable for XQuery queries and updates.

Theorem 3.1.2 ([BC09a]). For boolean atomic XQuery queries and updates, independence is decidable but non-elementary.

Theorem 3.1.3 ([RS06]). For queries and updates defined by using XPath expressions featuring descendant navigation, * wildcard operator and predicates, independence is NP-Complete.

CHAPTER 3. QUERY UPDATE INDEPENDENCE: STATE OF THE ART

Theorem 3.1.4 ([RS06]). Independence is polynomial for queries and updates defined by downward XPath expressions using at most two of the following features: descendant axis, * wildcard and predicates.

In the following, we discuss the main steps of the proofs of the above theorems, with the aim of giving more details on the links between independence, equivalence and containment.

The main observation for relating independence with equivalence suggested in [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF] is that we can solve independence if we can solve the equivalence problem for compositions of queries and updates. Equivalence means that two programs always agree on their output, once evaluated on the same input database. That is, a query q is independent from an update u if the equivalence q ≡ q ○ u holds, provided that the composition q ○ u and the notion of equivalence ≡ are properly defined. Results on the decidability of independence follow from this idea, as we now illustrate.

General Undecidability of Independence Benedikt and Cheney showed that independence is undecidable with a reduction to the satisfiability problem for queries expressed as first order logic formulas over data trees (corresponding to XQuery expressions) [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF]. It is well known that satisfiability of first order logic is undecidable, and this is also true in the signature of trees. With signature of trees, we mean the binary and unary relations that allow to define trees (see [START_REF] Benedikt | From XQuery to relational logics[END_REF] for more details). The idea is that we could solve independence if we had solved satisfiability of first order logic over data trees. Fix an XQuery query q, and define a query update pair in the following way

q ′ = if ( root a) then q else () u = insert <a > into root
Then, q is unsatisfiable for all σ, γ if and only if q ′ is independent of u for all σ, γ

In fact, query q ′ outputs constantly the empty sequence (before and after u) on any σ, γ, if and only if q is not satisfiable on any σ, γ. Since the satisfiability problem for XQuery queries is undecidable, we conclude that independence for XQuery queries and updates is generally undecidable. This is stated by Theorem 3.1.1.

Decidability of Boolean Independence for Core Atomic XQuery Benedikt and Cheney showed also that independence is decidable for a relevant subset of XML queries and updates [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF], as stated by Theorem 3.1.2. Again, the result is obtained from decidability of satisfiability of first order logic over trees. This result is interesting because it sheds light on the links between independence and query equivalence.

Each step of the proof is quite dense, and will be detailed next.

1. Define independence using a weaker notion of equivalence.

DECIDABILITY AND COMPLEXITY OF EXACT STATIC INDEPENDENCE ANALYSIS29

2. Restrict the query and update languages.

3. Show that, with such restrictions, queries and updates correspond to first order interpretations.

4. Show that first order interpretations can be composed and tested to be equivalent, thus conclude decidability of independence.

1) Define independence using a weaker notion of equivalence. Several notions of equivalence can be used to define independence (i.e., q ≡ q ○ u), notably, boolean equivalence, node equivalence or subtree equivalence. They naturally differ on the test they do. Boolean equivalence checks if the results of two expressions always agrees on non-emptiness. Node equivalence checks if node ids in result sequences are isomorphic. Subtree equivalence checks if forests of the two expressions are isomorphic. Decidability of boolean query equivalence has been showed in [START_REF] Benedikt | Interpreting tree-to-tree queries[END_REF] for the class of atomic queries. Differently, decidability of node-equivalence and subtree-equivalence are still open problems. Consequently, in [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF] the authors studied the analogous problem of boolean independence. Boolean independence just checks if the result of a query changes from empty to non empty or vice-versa, after update. Now, for testing boolean independence it is sufficient to translate a query q in a boolean-query of the form if (q) then 1 else 0.

2) Restrict the query and update language. Benedikt and Cheney [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF] considered XML queries and updates without aggregates and tests on data values, which is originally referred as Core Atomic XQuery in [START_REF] Benedikt | Interpreting tree-to-tree queries[END_REF]. This is roughly equivalent to the language defined in Section 2.3. Because we want to check boolean independence, we will consider Boolean Core Atomic XQuery queries of the form if (q) then 1 else 0, and Core Atomic XQuery updates built on such expressions 3) Show that queries and updates correspond to first order interpretations. Benedikt and Koch [START_REF] Benedikt | Interpreting tree-to-tree queries[END_REF] showed that Boolean Core Atomic XQuery queries of XQuery are given by first-order queries in the signature of trees. First order interpretations are formulas that define the output structure in function of a given input. First order interpretations model queries. The crucial point is the following. It can be shown (see [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF]) that the addition of updates to Core Atomic XQuery still yields first order interpretations. This means that, while in general it is true that updates are more expressive than queries, this is not the case for Core Atomic XQuery. For this fragment queries and updates have the same expressive power, and they precisely correspond to first order interpretations. 4) Conclude decidability of independence. Since first-order interpretations are closed under composition (Theorem 5.1 of [START_REF] Benedikt | From XQuery to relational logics[END_REF]), the composition of a query and an update is again a first order interpretation. So the

CHAPTER 3. QUERY UPDATE INDEPENDENCE: STATE OF THE ART

goal now is to test equivalence of first order interpretations. In the special case of a boolean query, a first-order interpretation is just a first-order sentence (a formula with no variables). First-order sentences can be translated into tree automata. Equivalence of automata obtained by first order sentences can be decided. Therefore, equivalence of first order interpretations for boolean queries can be decided. Hence, equivalence of a query against the composition of a query and an update can be decided. Hence, independence can be effectively decided. It is worth noticing that it is critical for decidability that data value comparisons are disallowed.

Benedikt and Cheney also give the complexity of the problem when the tag alphabet is fixed. This captures the case where a schema is available. In this case, because the satisfiability problem for first order logic over labeled trees (with fixed alphabet) is non-elementary [START_REF] Vorobyov | An improved lower bound for the elementary theories of trees[END_REF] we obtain that the independence problem in the presence of the schema is non-elementary. As outlined in [START_REF] Benedikt | Analysis of declarative updates: invited talk[END_REF], decidability of equivalence, and hence independence, when considering powerful notions of equivalence such as node and subtree equivalence is still an open question.

NP-Completeness for XPath( , * , []) fragment Another contribution to the study of XML independence comes from the work of Raghavachari and Shmueli [START_REF] Raghavachari | Conflicting XML updates[END_REF]. This work investigates the complexity of detecting conflicting query and update expressions. A query and an update conflict when a node accessed by the query is also impacted by the update. This is a dual notion of independence, that indeed holds in the absence of conflicts. Detecting conflicting expressions has been proved NP-complete for XML queries and updates expressed in the downward fragment of XPath featuring * wildcard and branching, and a notion of delete/insert node-conflict reminiscent of node-equivalence (are the ids of resulting sequences isomorphic?). NP-completeness follows from a reduction to the complement of the containment problem for XPath. Actually, it follows from the dual non-containment problem. The non-containment problem for XPath asks wether two expressions disagrees on the emptiness of the result, for some trees. In brief, it turns out that detecting this property is enough to detect if the result of a query may change after update. For instance, by taking an instance for which query result is empty and adding some data so as to get a non-empty query result. This operation is possible if the expressions are not in the containment relation. Updates are defined in terms of queries, hence solving non-containment between query-paths and update-paths would solve the problem of determining if the expressions conflict. Miklau and Suciu previously showed that non-containment is NP-hard [START_REF] Miklau | Containment and equivalence for a fragment of XPath[END_REF], that in turn determines the hardness of independence.

Polynomial fragments of XPath( , * , []) Along the line of the previous result, Ravagachari and Shmueli also showed that by further restricting the query and update language polynomial time algorithms for independence can be given [START_REF] Raghavachari | Conflicting XML updates[END_REF]. This is stated by Theorem 3.1.3. This holds for queries and updates written with path expressions belonging to a subset of XPath( , * , []) which is employing at most two features among descendant navigation "//", * wildcard and branching "[ ]". The authors in [START_REF] Raghavachari | Conflicting XML updates[END_REF] showed the relationship with query containment of XPath expressions for such languages [START_REF] Miklau | Containment and equivalence for a fragment of XPath[END_REF][START_REF] Amer-Yahia | Minimization of tree pattern queries[END_REF]. This shows that tractable algorithms for independence can be given only by substantially restricting the query and update language. These subsets of XPath are quite restrained and may not support realistic XQuery workloads.

The results we discussed show that independence is not tractable in practical cases. Its general undecidability and hardness suggest that in order to do static analysis one is obliged to proceed with approximate algorithms, trading completeness with tractability, and then devise analysis that can be useful in practice. This is what motivated recent research efforts towards approximate techniques discussed next.

Approximate Algorithms

The hardness of independence leads to attack the problem with approximate solutions. Approximate algorithms are sound but not complete methods, that is, they either correctly detect an independence or conservatively raise a conflict. As we will see throughout this dissertation, approximate solutions can be extremely effective by exploiting structural properties of queries and updates.

The state-of-the-art techniques for detecting independence reformulate the problem in terms of an intersection problem. Precisely, testing independence is made by checking whether the data needed by a query intersects with the data affected by an update. The techniques now decompose the problem in two parts: 1) providing an abstract representation of the data that is accessed by the query and impacted by the update, and 2) defining the intersection test. Before illustrating the state-of-the-art, we discuss the problem of providing an abstract representation of the data and show a link with XML projection.

The problem of computing a subset of the input database that is accessed by a query, and that is sufficient for its execution, is known as XML data-projection [START_REF] Marian | Projecting XML documents[END_REF][START_REF] Véronique Benzaken | Type-based XML projection[END_REF]. This problem has been studied also for updates in [BBC + 11]. The set of nodes involved by query/update execution is usually captured via static analysis. XML projection has developed the ideas of using either XPath navigational paths or XML types (when a schema is available) in order to abstract over the collection of data. These ideas gave birth to a series of works showing how projection can be used to optimize query execution [START_REF] Marian | Projecting XML documents[END_REF][START_REF] Véronique Benzaken | Type-based XML projection[END_REF] or for locally updating a database [BBC + 11]. Indeed, all approaches in the current literature dealing with independence [GRS08, BC09a, BC10, BTCU12] are likely to follow these ideas. However, substantial technical differences arise between methods for projection and independence, as we will see next.

In the following, we present the state-of-the-art techniques for independence in detail. We begin by presenting the analysis based on XML types [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF] which are the closest to our work since they use schema information. Then we present the analysis based on XPath paths [START_REF] Ghelli | Commutativity analysis for XML updates[END_REF] and then the approach with destabilizers [BC10].

Schema-based independence analysis for XML updates [BC09a]

This work is the first to propose a static analysis for detecting independence, in the presence of a schema. The idea at the basis of the schema-based analysis of [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF] is to infer type-names of nodes that are accessed by a query and impacted by an update, and then check that these do not overlap. The main contribution of [BC09a] is a type system that features very low complexity and which is able to detect a consistent number of independencies statically.

The technique targets a fragment of XQuery that is essentially the one presented in Section 2.3. Mild differences comes from the fact that queries can navigate on constructed data, and updates do not need to preserve the schema.

The independence analysis relies on three inference systems.

(RES) An inference system for typing the result (RES) of a query expression. The judgment d, Γ ⊢ (RES) q ∶ τ stands for a relation between the schema d, the static variable environment Γ, the query q and the set of types τ where τ contains at least all types of nodes, defined in d, that can be in the result sequences of q.

(SAC) An inference system for typing the data accessed by a query, that is called static access cover (SAC). The judgment d, Γ ⊢ (SAC) q ∶ τ is a relation between the schema d, the static variable environment Γ, the query q and the set of types τ where τ contains at least all types of nodes, defined in d, that are needed to evaluate q.

(IMP) An inference system for typing the data impacted by the update (IMP). The judgment d, Γ ⊢ (IMP) q ∶ τ is a relation between the schema d, the static variable environment Γ, the query u and the set of types τ where τ contains at least all types of nodes, defined in d, that are updated by u.

We now illustrate through some examples how these three systems work, and how type inference is done.

Consider the bibliographic DTD d 3 and the following query and update pair, for which we want to verify independence. q = for x in doc descendant ∶∶ book return x author u = delete doc title

We always assume that the context of the first navigational step of a query or update is the schema root type, thus in all of the examples of this chapter we assume that Γ is a static environment such that Γ(doc) = { bib }. The derivation tree for the inference of types accessed by q is the following.

1 d 3 , Γ ⊢ (SAC) doc descendant ∶∶ book ∶ τ 1 2 d 3 , Γ ⊢ (RES) doc descendant ∶∶ book ∶ τ 2 3 d 3 , Γ[x ↦ τ 2 ] ⊢ (SAC) x author ∶ τ 3 d 3 , Γ ⊢ (SAC) for x in doc descendant ∶∶ book return x author ∶ τ 1 ∪ τ 3
The set of types accessed by q is the union of types accessed by its subexpressions, i.e. τ 1 ∪ τ 3 . Types are inferred by calling system SAC as shown by derivations 1 and 3 . What is inferred for the query in τ 1 and τ 3 ? Because doc descendant ∶∶ book selects all book nodes in a store, in τ 1 we expect to find book and all of its ancestor types defined in d 1 . Because x author selects all author children of nodes bound to x, and x is only bound to book nodes, in τ 3 we expect to find types book and author. Derivation 2 shows also the role of the inference system RES in the process. It is used in order to provide types for variable x in the subsequent SAC derivation.

By exploring the next level of derivation we can understand more peculiarities of type inference.

1 The judgment d 3 , Γ ⊢ (SAC) doc descendant ∶∶ book ∶ τ 1 is developed as follows

Γ(doc) = { bib } d 3 , Γ ⊢ (RES) doc descendant ∶∶ * ∶ Σ d 3 S ∖ { bib } d 3 , Γ ⊢ (SAC) doc descendant ∶∶ book ∶ Σ d 3

S

The judgment infers the static access cover for doc descendant ∶∶ book. The inference result is the whole set of types of d 3 . This is obtained as a union of the root type (that is the context type for the step descendant ∶∶ * ), together with all descendant types of the root (that type the result of the step descendant ∶∶ * ). This last one is obtained by calling the RES system.

The first peculiarity of the system SAC we can observe is how the static access cover is computed. As said before, a sound static access cover would contain types for book nodes and their ancestors. To accomplish this, the navigational step descendant ∶∶ book is approximated by replacing the book label with the * wildcard (denoting any node). This of course makes the analysis sound but imprecise, because all schema types are inferred, and thus also all types unrelated with the step. As a consequence of this, the query is likely to be deemed dependent wrt almost all updates. We stress that this is always the case, for all queries starting with a descendant navigation.

2 The judgment d 3 , Γ ⊢ (RES) doc descendant ∶∶ book ∶ τ 2 is developed as follows.

Γ(doc) = {bib} τ 2 = { book book is a descendant type of bib in d 3 } d 3 , Γ ⊢ (RES) doc descendant ∶∶ book ∶ { book }
It infers types for the result of doc descendant ∶∶ book, this time for providing input to the next inference step. The derivation stresses that schema information is used in order to check if type book is a descendant of type bib. If this is not the case then τ 2 = ∅.

3 The judgment d 3 , Γ[x ↦ τ 2 ] ⊢ (SAC)
x author ∶ τ 3 is developed in the following way

d 3 , Γ[x ↦ { book }] ⊢ (RES) x * ∶ { title, author, publisher } d 3 , Γ[x ↦ { book }] ⊢ (SAC)
x author ∶ { book, title, author, publisher } This infers the static access cover for x author. The result is constituted by the union of types bound to variable x with the types of nodes in the result of step x * .

Once again we observe that the child step is approximated, by replacing the label author with * . This means that all children types of book are inferred namely title, author and publisher. Once again, the typing is sound but is not precise since while type author is needed by step x author, types title and publisher are not. Analogously to the previous case, the query is likely to be deemed as dependent wrt all updates impacting a node related to book.

Once types are inferred for the query, the update is analyzed.

The types of a node impacted by u are inferred by the system IMP as follows.

d 3 , Γ ⊢ (RES) doc title ∶ { title } d 3 , Γ[x ↦ { title }] ⊢ (RES) x parent ∶∶ * ∶ { book } d 3 , Γ ⊢ (IMP) delete doc title ∶ { book }
The set of types deleted by the update is computed in two steps. First, system RES infer types for nodes effectively deleted, that are those returned by the target expression doc price. Second, a parent navigation for such types is performed. This is the second peculiarity of the system, and it is meant to state that a node whose children are modified by the update is considered as impacted by the update as well. For the DTD d 3 , this means that the data type impacted by the update is book. As a consequence of this, the update is deemed dependent with all queries accessing book or one of its children. The same approximation is done for rename, insert and replace updates.

After type inference is done, for the analysis to be sound, all descendant types of nodes in the result of the query are also added to the set of types accessed by the query. For instance, because author types the root of a subtree output by q, all descendant types of author, namely name and String, are included in the result of the analysis.

Once type inference is done for q and u, providing sets of accessed and updated types τ q and τ u , static independence holds iff

τ q ∩ τ u = ∅
Another peculiarity of this method is that by basing an analysis on type-names, even if type inference is precise, independence cannot be detected in many cases. In fact, when a type is reused in several definitions, it may be difficult, or even impossible, to disambiguate it.

To illustrate, consider again the DTD d 3 , the environment Γ, and the following pair of query and update expressions. q = doc author name and u = delete doc publisher name Assume that the type name is inferred for both expressions. This type captures both nodes returned by the query and nodes impacted by the update, that are labeled with name. However, the sets of accessed and updated nodes here are disjoint, because the query accessed nodes labeled with name nested into nodes labeled with author while the update deletes nodes labeled with name nested into nodes labeled with publisher.1 By using sets of type names, without recording any information on ancestor types, independence cannot be detected in many cases such as this one.

So far, we have seen a running example of the independence analysis based on types, and the use of inference system RES, SAC and IMP. Now we discuss how this technique supports updates that do not preserve the schema.

As said before, not assuming schema preservation is a nice property of the typebased analysis. However, when flows of updates (possibly violating the initial schema) are evaluated this property alone does not ensure the success of the analysis: one needs to maintain the schema after each update which does not preserve the schema2 . Indeed, a flow of updates may change completely the structure of the schema thus making the static analysis unsound.

To see this, consider the following update renaming all labels of the schema, provided the DTD d 3 and the environment Γ. u 1 = for x in doc book rename x as "livre" rename x title as "titre" rename x author as "auteur" rename x name as "nom"

How does the analysis detect that a query like q = doc livre, whose result is empty over any document valid wrt the DTD, is now drawing some data from this renaming? This case is covered since, while computing the static access cover of the query, system SAC approximates doc livre with doc * . This makes the analysis sound, despite the fact that u 1 does not preserve the schema. Indeed, in the intersection of type-names inferred from q and u 1 is non-empty.

At this point, if the DTD d 3 is not maintained, the analysis may turn to be unsound. Consider an update u 2 possibly conflicting with q over the (invalid) document instance obtained after u 1 such as

u 2 = delete doc livre
Because no definition of livre is found in d 3 , the set of types inferred from u 2 over d 3 is empty, and thus independence of q and u 2 is assumed, while it should not. Therefore, after an update breaking schema constraints the schema needs to be maintained if one aims at a sound analysis. This short discussion shows that preservation of schema constraints is a problem orthogonal to that of independence. Schema evolution has been studied in [START_REF] Benedikt | Semantics, types and effects for XML updates[END_REF][START_REF] Cavalieri | Updating XML schemas and associated documents through exup[END_REF] and it is out of the scope of our work.

We conclude this section by discussing simplicity and complexity of the type analysis of [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF] which are the most important features of the system. The approximations made by the type system discussed are motivated by avoiding a complex analysis and providing a simple inference system. The advantages of a simple type system are that it can be easily understood, implemented and proved correct. Proofs of the type systems have been provided and worst case complexity studied. The independence analysis runs in O(( d 2 + q ) 2 + u ) and it turns out to be very fast in practice.

Commutativity analysis for XML updates [GRS08]

Another approach for detecting independence can be drawn from the commutativity analysis of XML updates proposed by Ghelli, Rose and Siméon in [START_REF] Ghelli | Commutativity analysis for XML updates[END_REF]. This technique relies on an extension of the path-based analysis proposed in [START_REF] Marian | Projecting XML documents[END_REF] that overapproximates the nodes accessed and modified by a given expression, by means of simple XPath expressions for which disjointness is decidable.

This work on commutativity distinguishes itself by two main aspects. First, it studies commutativity of updates, a different problem from that of independence. Second, and more importantly, this study considers XML languages with an iterative semantics, thus different from languages with a snapshot semantics like the one introduced in Section 2.3. As we discuss next, these two differences can be actually levelled out since commutativity allows to detect independence and the path-based approach suits to both kinds of semantics.

We discuss first the links between independence and commutativity. Roughly speaking, independence asks wether the result of a query is preserved after updating, while commutativity asks if the application order of two updates is irrelevant. Deciding commutativity allows to decide independence. Conceptually, this is true because updates are written in terms of queries. This implies that, an instance of the independence problem for q, u can be reduced to a commutativity one by rewriting q as a new update u ′ = replace q with q, and then check that u ′ commutes with u. This reduction also shows that checking commutativity is at least as hard as checking independence.

The commutativity analysis of [START_REF] Ghelli | Commutativity analysis for XML updates[END_REF] has been developed for query languages with side-effects (i.e., updates) such as of XQuery! [START_REF] Ghelli | XQuery!: An XML query language with side effects[END_REF] and XQueryP [CCF + 06]. These languages have a so called iterative semantics, they support immediate update application and explicit left-to-right evaluation order. This is a main difference with the languages considered in [BC09a, BC10, BTCU12], that have a snapshot semantics. Iterative languages have a strict left to right evaluation order, while languages with snapshot semantics reorder their updates before application: insert and replace are executed first, then rename and finally delete. Iterative languages allow to see the effects of updates during evaluation.

While iterative languages seem more intuitive, they have a more involved semantics. This is because any expression can read data that it previously inserted. To illustrate, a (possibly) non terminating update such as the following can easily be written in an iterative language.

for x in doc name return insert <name > af ter x Assuming that the base data contains at least one node labeled with name (that is also a descendant of the node bound to doc), the expression keeps on extending the iterating sequence of name nodes forever.

Much more machinery effort has to be done in order to prove the soundness of the commutativity analysis for a language with iterative semantics, with respect to languages with snapshot semantics. Many expressions that do not commute in iterative languages do commute in snapshot language (simply because they do not have the same effect), so an analysis for an iterative language is likely to work also for a language with snapshot semantics. Of course, it is possible to define a more general (and less precise) static analysis that works for both kinds of languages.

CHAPTER 3. QUERY UPDATE INDEPENDENCE: STATE OF THE ART

We proceed now with the description of the path-based analysis, thus illustrating its characteristics.

The path-based analysis relies on a system of simple path inference. Simple paths are expressions belonging to the fragment of XPath composed by downward and upward navigation, plus the wildcard *. Predicates, as well as data values and sibling axis, are not allowed.

The analysis relies on an inference system (PATH) for inferring the simple paths of an expression. The judgment Γ ⊢ (PATH) q ∶ (rt, ac, up) is a relation between the static variable environment Γ, the query q and the sets of paths (rt, ac, up) where rt is the set of path leading to returned subtrees of q, ac is the set of path representing nodes accessed but possibly not returned by q, and up is the set of path representing nodes that are updated by q.

Distinguishing among these three kinds of paths allows to capture two main aspects of the language. First, side-effects, by distinguishing between update paths from the rest. Second, query semantics, by distinguishing between accessed and return paths.

Note that here the analysis is supported by a single inference system, and most importantly, the analysis does not depend on an input schema. In the following examples the steps navigating from the root of a tree are written without an explicit variable.

To illustrate the (PATH) inference system, we consider again the following queryupdate pair. q = for x in descendant ∶∶ book return x author u = delete price Inference of return, used and update paths for q is derived in the following way.

1 Γ ⊢ (PATH) descendant ∶∶ book ∶ (rt, ac, up) 2 Γ[x ↦ rt] ⊢ (PATH) x author ∶ (rt ′ , ac ′ , up ′ ) Γ ⊢ (PATH) for x in descendant ∶∶ book return x author ∶ ( rt ′ , ac ∪ ac ′ , up ∪ up ′ )
Accessed and updated paths inferred for the whole expression are those inferred from each subexpression only. Return paths for the whole expression are naturally those on the right subexpression. Next we will see how the static environment Γ helps in reconstructing navigational paths by following variable bindings.

Notice that the rule for path extraction introduces a bit of imprecision since all accessed and updated paths of the left subexpressions are kept in the final result, independently of the right subexpression. This means that, for instance, when the right branch of the iteration query performs no operation, and thus the query does nothing, the set of inferred paths for the whole expression may not be empty, while it should. This is the case for the following query for x in book return () for which path book is inferred, despite the fact that inferring an empty set of returned and accessed path would still be sound.

Let us explore further derivations and comment on other peculiarities of the analysis.

1 The judgment Γ ⊢ (PATH) descendant ∶∶ book ∶ (rt, ac, up) is developed as follows rt = { descendant ∶∶ book} Γ ⊢ (PATH) descendant ∶∶ book ∶ (rt, rt, ∅)
In this case path inference is a simple path extraction. Notice that return and accessed paths coincide, and of course no update path is inferred.

2 The judgment Γ[x ↦ rt] ⊢ (PATH) x author ∶ (rt ′ , ac ′ , up ′ ) is developed as follows Γ[x ↦ rt] ⊢ (PATH) x ∶ (rt, ∅, ∅) rt ′ = rt × { author} ac ′ = prefixes(rt ′ ) Γ[x ↦ rt] ⊢ (PATH) x author ∶ (rt ′ , ac ′ , ∅)
Here the system first reconstructs simple paths by following variable bindings. Indeed, the path descendant ∶∶ book that is bound to x is combined in a cartesian product with step author in order to infer rt ′ = { descendant ∶∶ book author }.

Accessed paths are defined as prefixes of inferred paths. Of course, no update path is inferred since the operation has no side-effect.

The application of the rule may lead to infer exponentially many paths for some rare expressions such as the following one.

for x 1 in ( x 0 a , x 0 b ) . . . x n in ( x n-1 a , x n-1 b ) return x n
this expression would produce exactly 2 n return paths and O(n2 n ) accessed paths. This kind of expressions are however very rare in practice.

Now that paths are inferred from the query, we focus on the update. Path inference for the update expression is derived as follows

Γ ⊢ (PATH) price ∶ ({ price }, ∅, ∅) ac = { price } up = { price } × { descendant-or-self ∶∶ * } Γ ⊢ (PATH) delete price ∶ (∅, ac, up)
Here nodes deleted by the expression are captured by combining return paths of price with a descendant-or-self ∶∶ * step, denoting that whole subtrees rooted at prices are deleted. Return paths for the target query become also accessed paths for the whole expression. No return path is inferred for the whole update.

Notice that the path analysis precisely capture only the deleted subtrees without including their parent, as is done by the type analysis.

Another characteristics of the analysis is how updates paths are extracted from insert and replace commands. To illustrate, consider the following update.

insert author into site book Paths for the update are extracted in the following way.

Γ ⊢ (PATH) author ∶ (rt 1 , ac 1 , up 1 ) Γ ⊢ (PATH) site book ∶ (rt 2 , ac 2 , up 2 ) ac = rt 1 × { descendant-or-self ∶∶ * } up = rt 2 × {descendant ∶∶ * } Γ ⊢ (PATH) insert author into site book ∶ (∅ , ac 1 ∪ ac 2 ∪ ac , up 1 ∪ up 2 ∪ up)
Accessed paths extracted from the two subexpressions become accessed paths for the whole update. Moreover, return paths for the source expression author are combined with a self or descendants axis, and become accessed paths for the whole update, mimicking the fact that an entire subtree is copied.

Update paths extracted from the subexpressions (if any) become update paths for the whole update. Notice that the set of inserted paths is inferred by combining path site book with a descendant step, mimicking that the whole subtree rooted at book is updated. This of course is sound, but not complete. For instance, the update is deemed as non-commuting with query site book title, while it does.

Once return, accessed and update paths are inferred from the expressions, an intersection test is run. The subset of XPath considered for inference includes downward and backward navigational axes, and * wildcard. Branching is excluded. For this language intersection is decidable. While results in [START_REF] Hidders | Satisfiability of XPath expressions[END_REF] show that the intersection problem for downward XPath expressions is NP-complete, [START_REF] Beda | On the intersection of XPath expressions[END_REF] approach shows that intersection is solvable in quadratic time for the downward fragment only.

One of the most important features of the path analysis, is that it works independently without requiring a schema. However, in all the cases where schema is available, schema constraints cannot be easily plugged into the path-based analysis. Soundness of the pathbased commutativity analysis has been proved in [START_REF] Ghelli | Commutativity analysis for XML updates[END_REF], and also its benefits have been showed when used for optimizing logical plans of queries with side-effects [START_REF] Ghelli | XML query optimization in the presence of side effects[END_REF].

Destabilizers and independence of XML updates [BC10]

Destabilizers [START_REF] Benedikt | Destabilizers and independence of XML updates[END_REF] are a generalization of the idea of statically approximating the set of accessed nodes found in some prior work [BCCN06, MS03, GRS08] and then testing intersection, combined with the concrete use of the data. The destabilizer framework can work in principle for any language and data-model, in [START_REF] Benedikt | Destabilizers and independence of XML updates[END_REF] they are formally implemented for XML queries and updates.

The formal definition of destabilizers is quite technical, thus here we provide just a gentle introduction to the approach, discuss the problematics in computing destabilizers and outline how they are concretely used.

Given a query q, the destabilizer of q, denoted by ∆(q), is defined as the set of updates that may change the answer of q. From this follows that an update u is independent wrt a query q when u does not overlap with ∆(q). In the following we will distinguish between dynamic or static, and exact or approximate destabilizers. Dynamic destabilizers are composed by atomic update commands, while static ones are update expressions. Exact destabilizers are minimal, in the sense that they produce no false negative (updates that do not change the answer of q), while approximated ones may produce false negatives.

An exact dynamic destabilizer is a minimal set of atomic update commands that can affect the result of a query q evaluated over the tree t. We recall that an atomic update command is an operation of del(_) ins(_, _, _) ren(_, _) repl(_, _)

As an example, consider the document t = (σ, l t ) with two nodes

σ = l t ← bib[l 1 ] l 1 ← book[]
Let q be the query bib book. The exact dynamic destabilizer of q wrt t, denoted by ∆ d (q, t), is composed by all atomic update commands targeting either l t or l 1 in t. The atomic updates that can alter l t are the followings

del(l t ) ren(l t , "a") repl(l t , l ′ )
where l ′ is a location not isomorphic to l t , and a is a string different from bib.

The atomic updates that can alter l 1 are the followings.

del(l 1 ) ins(L i , pos, l t ) ins(L i , pos ′ , l 1 ) ren(l 1 , "b") repl(l 1 , L i )
where L i is a non empty sequence of locations containing a node not labeled with book, pos is one of {into, into as first, into as last}, pos ′ is one of {before, after}, and b is a string different from book.

CHAPTER 3. QUERY UPDATE INDEPENDENCE: STATE OF THE ART

An update u is independent of a query q if the UPL produced by u over t does not overlap with ∆ d (q, t). Consider the update

u 1 = insert < new > into bib
u 1 over t generates the atomic update ins(l new , into, l t ). Because l new is not labeled with book, q is independent of u 1 . Differently, the update u 2 = delete bib * is not independent with q because it generates the atomic update del(l 1 ) which also belongs to ∆ d (q, t).

Benedikt and Cheney [START_REF] Benedikt | Destabilizers and independence of XML updates[END_REF] illustrate that it is not feasible to deal with dynamic destabilizers as concrete sets of atomic update sequences. Therefore, destabilizers are treated at a symbolic level. The set of nodes involved in atomic updates in ∆ d (q, t) is approximated by any update expression targeting those locations. Since updates are defined in terms of queries, it turns out that the destabilizer set is defined as a set of query expression targeting all nodes that are arguments of the atomic updates. For q = bib book, the exact static destabilizer ∆ s (q, t) approximating the dynamic one, is simply

∆ s (q, t) = { bib, bib book }
In developing a static destabilizer, there is a trade-off between the precision (how close it is to the dynamic analog) and the complexity of analyzing the resulting query. The generic static destabilizer defined as above is frequently a significant over-approximation of the runtime destabilizer. For example, a query may be sensitive to update sequences that can only affect a node via a particular update operation. In its simplest form, the static destabilizer cannot capture this aspect. The authors presented a query-rewriting technique that provides a useful, sound approximation. Destabilizers sensitive to update operations (precise for each update), as well as destabilizers sensitive to different equalities (precise for boolean, node and subtree equivalence) are also defined in [START_REF] Benedikt | Destabilizers and independence of XML updates[END_REF].

Benedikt and Cheney showed that calculating an exact static destabilizers is not feasible even for a core XML query language, hence the analysis needs to abstract away from some features in order to be effectively executed. This is stated by the following theorem.

Theorem 3.2.1 ([BC10]

). There is no elementary time algorithm for constructing an operation-sensitive minimal static destabilizer.

The formal definition of a destabilizer is reminiscent of a path analysis. The main difference with the path-based approach is that destabilizers also consider the source document for the overlapping test. To illustrate, consider the following query q and update u over the previous document t. q = for x in bib return <list>x book< list> u = delete book title

APPROXIMATE ALGORITHMS

43

The destabilizer for the query is

∆ s (q, t) = { bib , bib book descendant-or-self ∶∶ * }
Now, while running the intersection test between u and ∆ s (q, t), we consider also the actual data of t.

The intersection tests of the destabilizers approach is more accurate that the one of previous techiques. While the path analysis (and also the type analysis) would exclude independence, the destabilizer analysis correctly deem the independence, because there is no data in the store corresponding to title nodes. In fact, the path analysis (and also the type analysis) does not take into account the document. This is because the path analysis would see that the path targeting delete nodes book title descendant-or-self ∶∶ * intersects with path bib book descendant-or-self ∶∶ * (inferred for q). The source document is taken into account by translating queries into logical formulas, and then transforming the intersection test of query and update paths to a satisfiability problem, solved with SAT-solvers. Several exact and approximate translation are proposed. These allow to trade between precision and efficiency of the analysis. In the following, we limit ourselves to discuss translations, without reporting the formal development, that can be found in [START_REF] Benedikt | Destabilizers and independence of XML updates[END_REF].

We discuss now exact solutions. Queries without element construction can be translated to first-order formulas over the child, descendant and sibling relations, and then disjointness analysis for these queries reduces to satisfiability for first-order formulas over trees FO(Trees). However it follows from results of [START_REF] Vorobyov | An improved lower bound for the elementary theories of trees[END_REF] that there is a non-elementary lower bound on the complexity of satisfiability. The solver used for resolution of this formulas is Yices [START_REF] Dutertre | The Yices SMT solver[END_REF]. Another strategy is to convert expression into monadic second order logic (MSO). It follows from results in [START_REF] Stockmeyer | Word problems requiring exponential time[END_REF] that there is a non-elementary lower bound on the complexity of satisfiability of MSO over trees. The solver used for M SO resolution is MONA [START_REF] Klarlund | MONA version 1.4 user manual[END_REF].

We discuss approximate solutions. To check intersection of query expressions on database instances, the authors propose first a reduction to existential second order logic (ESO) which uses as support an arithmetic encoding of the input document. This solution has an overhead that depends on the document to analyze, and this could not be reasonable for large documents. We recall that path intersection is NP-hard in general, even if for downward-only paths, overlapping is exactly decidable in quadratic time.

In [START_REF] Junedi | XML query-update independence analysis revisited[END_REF] Junedi, Genevès and Layïda showed that the efficiency of destabilizer can be enhanced wrt the work of [START_REF] Benedikt | Destabilizers and independence of XML updates[END_REF] by checking satisfiability of logical formulas using their µ-solver [START_REF] Genevès | Efficient static analysis of xml paths and types[END_REF][START_REF] Genevès | XML reasoning solver user manual[END_REF]. Their approach is based on translating XPath expressions into µ-calculus formulas. As outlined above, the theoretical complexity of satisfiability on MSO formulas is known to be non-elementary, whereas it is exponential for simplex based linear arithmetic satisfiability. The complexity of satisfiability on µ-formulas is simple exponential. The resulting approach resulted to be far more competitive wrt solver such as MONA and Yices. An evidence from experiments in [START_REF] Junedi | XML query-update independence analysis revisited[END_REF] is that the dominant inference cost does not necessarily reside in the resolution procedure, but mostly in constructing destabilizers, parsing formulas and initializing the auxiliary libraries for resolution. The time spent in the resolution procedure better reflects the intrinsic difficulty of each problem instance.

In conclusion, the merit of destabilizers is twofold. It is a modular framework that generalizes concepts of all previous approaches to independence. It promotes the practical use of SAT-solvers for intersection analysis. The approach does not require a schema, even if they can be handled by adding schema constraints in the satisfiability test. While former experiments in [START_REF] Benedikt | Destabilizers and independence of XML updates[END_REF] showed some limits of the approach concerning the cost of the destabilizer analysis, recent works of [START_REF] Junedi | XML query-update independence analysis revisited[END_REF] showed that destabilizers can be implemented efficiently.

Conclusions

In this chapter we presented the theoretical background and the state-of-the-art techniques for checking XML query update independence. We discussed theoretical results that show the computational difficulty of the problem. Then we discussed three approximated analysis that, being sound but not complete, try to make the analysis tractable. All approaches distinguish for simplicity, precision and complexity. The type-based analysis [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF] requires a schema in order to be executed, it is simple to implement and it runs in polynomial time, but it may be not precise. The path-based analysis [START_REF] Ghelli | Commutativity analysis for XML updates[END_REF] works without requiring a schema but when structural constraints are available they cannot be easily integrated. It is also simple to implement but for some expression the path extraction may occur in blowups, and also exact checking of path disjunction turns out to be NP-hard. The destabilizer analysis [START_REF] Benedikt | Destabilizers and independence of XML updates[END_REF] is a modular framework that generalizes all previous ideas, and allow to perform an independence analysis varying precision and complexity of the approach. The method works without schemas, but it can easily integrate structural constraints.

In the next chapters we present our technique for detecting independence based on schemas, showing how it can ensure a precise analysis while still keeping inference polynomial in time and space.

Chapter 4

Independence Analysis based on Schema-Chains

This chapter presents the main contribution of this thesis: a novel method for detecting XML query update independence, in the presence of a schema. We present an inference system for computing the set of navigational paths accessed by queries and updates, called chains. We prove the chain-based inference system to be sound and more precise than the related approach based on types. We present a static notion of independence, based on chains, that we show to be decidable, even for recursive schemas which can generate infinite sets of chains.

The chapter is organized in four parts. In the first part, we present a system for chain inference. In the second part, we show the correctness of the type system. In the third part, we present a static notion of independence based on chains. In the fourth part, we show the decidability of the notion of static independence.

Introduction

As explained in the previous chapter, the type analysis for checking independence defined in [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF] is designed so as to infer information about accessed data, by abstracting away from some of the structural properties expressed by queries and updates. This is done in order to keep the systems relatively simple, and to make the inference fast. Actually, the main structural information which is traded is data-nesting, that defines the way in which types interact. Data-nesting is a synonym of hierarchical information. Together with document order, it entails that the semantics of a subtree depends on its position in the document. Describing a collection of accessed and updated trees with a set of types-names, is equivalent to consider all possible trees with fixed tag alphabet, ignoring any constraint on the hierarchy of data. Unfortunately, in many cases this causes lack of precision because of the tree shape of XML data.

The goal of this work is to improve the precision of the method proposed in [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF] by exploiting schema information in a different way. Rather than inferring sets of typenames accessed by the expressions, our goal is to infer sequences of accessed types, called chains, that essentially correspond to navigational paths traversed by query and update expressions on valid schema instances. Chains will form the basis of an extremely precise independence analysis.

We present now formal definitions about chains. We begin by defining the notion of type and chain of types for a node location belonging to a store. Definition 4.1.1 (Node Type and Chain). Given a store σ, the type of a location l ∈ dom(σ), denoted by type(l) is defined as

type(l) = a if σ(l) = a[L] String otherwise
The chain associated to location l, denoted by c σ l , is defined by

c σ l = type(l) if l has no parent c σ parent(l)
.type(l) otherwise If t = (σ, l t ) and l ∈ dom(t) then we denote by c t l the chain c t l = c σ l . To illustrate, consider the tree t 2 in Figure 4.1. Here the type of the root location l t 2 is type(l t 2 ) = bib, and it also coincides with its own chain c σ Notice that since the store coincides with the tree, we have that c σ l = c t 2 l for all l ∈ dom(σ). As a convention in the notation, we use "." to separate two consecutive labels in a chain. Notice also that this definition considers only rooted chains, where the starting symbol is always the root.

We stress that the above definition works for any XML tree and node location, independently from schema constraints. However, dealing with schemas is our ultimate goal. Hence in order to develop a static analysis which is correct we need to ensure that, if a document is compliant with a schema, then all node chains in the document are induced by the schema.

To formalize this property, we define the set of chains induced by a schema relying on a reachability relation between types.

< publisher> < book> < bib> σ = ⎧ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎨ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎩ l t2 ← bib[ l 1 ] l 1 ← book[ l 2 , l 3 l 4 ] l 2 ← title[ l ′ 2 ] l ′ 2 ← "Types and ..." l 3 ← author[ l ′ 3 ] l ′ 3 ← name[ l ′′ 3 ] l ′′ 3 ← "B. Pierce" l 4 ← publisher[ l ′ 4 ] l ′ 4 ← name[ l ′′ 4 ] l ′′ 4 ← "MIT Press" Figure 4.1: Document t 2 and store (σ, l t 2 )
The set of chains associated with the DTD d is denoted by C d . Observe that chains in C d are of finite length and may start with any DTD symbol. The set C d is infinite only if d is a vertical-recursive schema (i.e., some type is defined in terms of the type itself). The empty chain is denoted by ǫ, and we assume, as a convention, that it is never induced by any schema. Given two chains c 1 and c 2 , the concatenation of c 1 and Relation ⇒ d is both sound and complete. Soundness means that for any pair of parent-child locations belonging to a valid tree, there exists a correspondent pair of types in ⇒ d . Completeness means that the relation is also minimal, thus removing one pair from ⇒ d we beak soundness. This is stated by the following lemmas. Proofs are reported in Chapter 9. At this point, we can reconcile chains associated to node locations (Definition 4.1.1) and chains induced by a schema (Definition 4.1.2) by stating that, when we consider a document valid against a schema, all node-chains are schema-chains. The converse of this proposition is not true. Not all of the schema-chains are nodechains of a tree, for all valid schema instance. This is because some elements may be optional. Therefore, what can be proved is that for all rooted schema chain there exists a document instance including a node with that chain. This, as a corollary of Lemma 4.1.4.

c 2 is denoted c 1 .c 2 , of course c 1 .ǫ = c 1 . We write c 1 ⪯ c 2 to indicate that c 1 is a prefix of c 2 , that is c 2 = c 1 .c for some chain c.
At this point, we formally defined types and chains for documents and schemas. We have shown that schema chains can be safely used in order to abstract over tree chains (Proposition 4.1.5), as a corollary of validity. The sequel of the chapter is dedicated to define an independence analysis based on schema-chains.

Chain Inference

We begin by defining chain inference for XPath navigational steps, we then generalize to queries and updates.

Step Chain Inference

The definition of our chain inference system makes the assumption that the inference is made starting from an input set of chains C. Given a DTD d, this set can be either C d (possibly infinite analysis) or a finite subset of C d (finite analysis). We would like to stress that assuming a pre-computed chain set is only made to ease the formal presentation. Any reasonable implementation can avoid this, by inferring chains in C on the fly (see Chapter 5).

The first ingredient for query/update chain inference is chain inference for a single XPath step. We first define chain inference for axes, and then for node tests. Axis chain inference aims at inferring all chains that can be generated by axis navigation, in a d instance, starting from a node typed by a chain c ∈ C. Chain inference for XPath axes is defined below, where we assume that c ′ , c ′′ ≠ ǫ.

A C (c, self) def = { c } A C (c, child) def = { c.a c.a ∈ C } A C (c, descendant) def = { c.c ′ c.c ′ ∈ C } A C (c, parent) def = { c ′ c = c ′ .a } A C (c, ancestor) def = { c ′ c = c ′ .c ′′ }

CHAIN INFERENCE

49

Chain inference rules strictly mimic XPath semantics of axes. It is worth noticing that all navigations follows from the reachability relation ⇒ d . Notice also that

A C (c, axis-or -self) = A C (c, axis) ∪ A C (c, self)
for axis ∈ {descendant, ancestor}.

We illustrate step chain inference over the DTD d 3 in Figure 3 Chain inference for sibling axes has a slightly more involved definition. First we need to define a relation between sibling types. This is needed in order to deal with horizontal axis.

Definition 4.2.1 (Sibling-type relation). Two types a, b are said to be siblings wrt a regular expression r, denoted by a < r b if there exists a word u belonging to the language generated by r in which a letter a occurs before a letter b. The relation < r is inductively defined as follows

< () def = ∅ < a def = ∅ < r 1 r 2 def = < r 1 ∪ < r 2 < r 1 ,r 2 def = < r 1 ∪ < r 2 ∪ Sym(r 1 ) × Sym(r 2 ) < r + 1 def = < r 1 ,r 1 < r * 1 def = < r 1 ,r 1
where Sym(r) is the set of symbols used in the regular expression r.

In the following rules, with a little abuse of notation, given a chain c on d, we use d(c) to indicate either the regular expression d(a), when c = c ′ .a, or the empty regular expression ǫ, when c = c ′ .String. Chain inference for preceding/following-sibling axes is defined as follows.

A C (c, following-sibling) def = { c ′ .b ∈ C c = c ′ .a, a < d(c ′ ) b } A C (c, preceding-sibling) def = { c ′ .a ∈ C c = c ′ .b, a < d(c ′ ) b }
It is worth noticing that this sibling typing is very precise, since the sibling relation is evaluated for a particular regular expression. To illustrate, let r 1 , r 2 be two regular expressions in d. It may be that a < r 1 b but a < r 2 b, and this difference can be captured using chains. This is not the case for the type analysis in [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF] that would consider a and b as sibling types in all cases.

Step chain inference for sibling axes over DTD d 3 is exemplified below.

< a,(b f)+,g = {(b, b), (b, f), (f, b), (f, f), (a, b), (a, f), (a, g), (b, g), (f, g)} since < a,(b f)+,g = < a,(b f)+ ∪ < g ∪ {a, b, f} × {g} = < a ∪ < (b f)+ ∪ {a} × {b, f} ∪ {a, b, f} × {g} = < (b f),(b f) ∪ {a} × {b, f} ∪ {a, b, f} × {g} = < b f ∪ {b, f} × {b, f} ∪ {a} × {b, f} ∪ {a, b, f} × {g} = < b ∪ < f ∪ {b, f} × {b, f} ∪ {a} × {b, f} ∪ {a, b, f} × {d} = {b, f} × {b, f} ∪ {a} × {b, f} ∪ {a, b, f} × {g} = {(b, b), (b, f), (f, b), (f, f), (a, b), (a, f), (a, g), (b, g), (f, g)}
It the development we assumed left associativity for union and concatenation, that implies r 1 , r 2 , r 3 = (r 1 , r 2 ), r 3 . It is worth noticing that the relation < r considers all following siblings of a given type, like (a, g), and not just the immediate ones. Also,

< a = < b = < f = < g = ∅.
The following two lemmas state that the relation < r is both sound and complete.

CHAIN INFERENCE

51

Rules for node-test chain inference are easier and defined below.

T C ( c, node() ) def = { c } T C ( c, a ) def = { c c = c ′ . a } T C ( c, text() ) def = { c c = c ′ . String }
Composition of axis and node-filters is noted as In this section we defined chain inference for XPath steps, the building blocks of our analysis. We will define next chain inference for query and update expressions. It is worth noting that in the above examples we considered only rooted chains, where the first symbol is the root type. This is because these chains are the ones that make sense for the access analysis, despite the fact that all definitions work also for non-rooted chains.

T C ( A C (c, axis), φ ) that stands for ⋃ c ′ ∈A C (c,axis) T C ( c ′ ,

Query Chain Inference

The analysis of query and update chains requires to further structure the inference process, in order to better describe the behavior of query and update expression, and prepare for a more precise independence analysis. For this aim, we introduce several classes of chains that we use to capture accessed and updated data.

As output of inference, our system produces chains of different kinds. The classification resembles that of Marian and Simeon in [START_REF] Marian | Projecting XML documents[END_REF] for query path extraction, and of Ghelli et al. in [START_REF] Ghelli | Commutativity analysis for XML updates[END_REF] for update path extraction, and is needed in order to reflect different way a query manipulates nodes during its evaluation. Reflecting this distinction is crucial for soundness and precision of the independence analysis.

In our framework, a query chain belongs to one of the following three disjoint classes.

• Return chains type input document nodes (return nodes) that are roots of subtrees outputted by the query. All descendants of a return node are in the query result, thus a return chain c implicitly embodies these descendants. Now, if a change made by an update u targets a return node or some of its ancestors or descendants, query-update independence is not guaranteed.

• Used chains type nodes (used nodes) belonging to the input document and participating to the query evaluation, without necessarily being part of the result itself.

Clearly, if a change of an update u targets a used node or some of its ancestors, then query-update independence is not guaranteed. However, if it targets a used node descendant then independence may still hold.

• Element chains type newly constructed elements; an element chain is of the form a.c, where a is the tag of the constructed a element, while c traverses nodes belonging to the subtree rooted at the a element. Extracting these chains is important to record the structure of forests built and inserted by update expressions.

For updates, we have one class of chains:

Γ ⊢ C () ∶ (∅, ∅, ∅) (Empty) Γ ⊢ C q i ∶ (r i , v i , e i ) i=1, 2 Γ ⊢ C q 1 , q 2 ∶ (r 1 ∪ r 2 , v 1 ∪ v 2 , e 1 ∪ e 2 ) (Conc) axis ∈ {self, child, descendant-or-self} r c = T C ( A C (c, axis), φ ) for any c ∈ Γ(x) Γ ⊢ C x axis∶∶φ ∶ ( ⋃ c∈Γ(x) r c , ∅, ∅) (StepF)
axis ∈ {parent, ancestor, ancestor-or-self, following-sibling, preceding-sibling}

r c = T C ( A C (c, axis), φ ) for any c ∈ Γ(x) Γ ⊢ C x axis ∶∶ φ ∶ ( ⋃ c∈Γ(x) r c , ⋃ c ∈ Γ(x) rc ≠ ∅ {c}, ∅) (StepUH) Γ ⊢ C q 1 ∶ (r 1 , v 1 , e 1 ) Γ[x ↦ c] ⊢ C q 2 ∶ (r c , v c , e c ) for any c ∈ r 1 Γ ⊢ C for x in q 1 return q 2 ∶ ( ⋃ c∈r 1 r c , v 1 ∪ ⋃
The following examples are made on the DTD d 3 in Figure 3.1, and we assume that variable doc is always bound to bib in Γ.

To illustrate rules (StepF) and (StepUH), consider , and the query doc title following-sibling ∶∶ author Chain inference for this expression is done by analyzing the two steps in sequence. Rule (StepF) infers chain bib.book.title for the step doc title. By applying rule (StepUH) on the step following-sibling ∶∶ author, provided that Γ ′ = Γ ∪ { x ↦ bib.book.title }, we obtain the following derivation.

T C d 3 ( A C d 3 (bib.book.title, following-sibling), author ) = {bib.book.author} Γ ′ ⊢ C d 3 x following-sibling ∶∶ author ∶ ({bib.book.author}, {bib.book.title}, ∅)
The rule produces a return chain, namely bib.book.author, that is typing subtrees rooted at author returned by the query, but also a used chain, namely bib.book.title, that is typing locations accessed before getting to the result. Rules (For) and (Let) are very similar, thus we mainly comment on the former. According to query semantics, rule (For) performs an iteration on the set of return chains inferred for q 1 and, at each iteration step, it evaluates q 2 . We illustrate this process through an example. Consider the DTD d 3 and the following query for x in doc descendant ∶∶ name return x parent ∶∶ *

The expression iterates on the sequence of document nodes labeled with name, and outputs the parent of the each node. Here, chain inference for the left subexpression descendant ∶∶ name produces two return chains c a = bib.book.author.name and c p = bib.book.publisher.name. Accordingly, chain inference for the right subexpression x parent ∶∶ * is done twice, with x bound to c a and c p respectively. Moreover, three other operations are necessary in order to perform a correct and precise analysis. First, return chains for q 1 are converted into used chains for the whole expression. This is needed because chain inference is a bottom-up process: inside q 1 a path expression is seen as a query producing a result (and as such it locally produces return chains), while it only selects nodes to be used in the outer iteration for x in q 1 return q 2 . To illustrate, consider the query for x in doc publisher return for y in doc name return y

In this case the return chain bib.book.publisher inferred for the step publisher, should not be considered as a return chain for the whole expression, since the descendants of nodes labeled with publisher are not accessed by the expression. Rather, it should be considered as a used chain for the whole expression.

Second, return chains for q 1 that are irrelevant for q 2 are filtered out. To illustrate, consider the query for x in doc node() return if ( x title ) then x author else () Chain inference for the expression doc node() returns all rooted chains of the schema. If these are all kept in the final result, the analysis is jeopardized since the query would be consider as dependent wrt almost every update. Our system avoids this, by discarding all return chains of doc node() that do not further satisfy x title. Chain inference for the whole expression only produces the used chain bib.book.title and the return chain bib.book.author.

Third, used chains for q 1 become chains for the whole expression. This operation is needed in order to ensure a sound analysis. Consider the DTD d 3 and following query for x in doc title following-sibling ∶∶ author return x here the left query doc title following-sibling ∶∶ author makes the system inferring a return chain bib.book.author and a used chain bib.book.title. Now, in order to have a sound analysis, the chain bib.book.title should be inferred as a used chain for the whole expression.

Rule (If) is similar to rule (Concat). It invokes chain inference for each subexpression, and then outputs the proper union of sets inferred for the subexpressions. As an example consider the query for x in doc book return if (x price) then x author else x title This case illustrates well that a correct analysis needs the chains inferred for all subexpressions, namely bib.book.price, bib.book.author, bib.book.title. Return chains for the then-branch (bib.book.author) and the else-branch (bib.book.title) become return chains for the whole expression. Differently, the return chain inferred for the boolean conditional-query (bib.book.price) is converted into a used chains for the whole expression, since this is just needed to perform boolean tests on the existence of some nodes, without requiring the whole subtrees.

Element queries <a>q< a> are dealt with by rule (Elt). In the element construction rule, τ denotes all descendant chains of chains in the set τ wrt C.

τ def = { c.c ′ ∈ C c ∈ τ }
This rule infers element chains of the form a.c, where c is obtained from either an element or return chain of q. The rule also infers a set of used chains, composed by i) used chains of q and ii) return chains of q converted into used chains for the whole expression. To this end r is used to extend returned chains of the inner query. This return-to-used chain conversion is needed to correctly handle nested element construction. For instance, consider the following query q = for x in doc book return <livre>q ′ < livre> where

q ′ = x title , <auteur> x author name < auteur>
The expression restructures the result of a query selecting some informations on the books in the bibliography, changing both the structure and the label of nodes of a tree labeled with book. Element chains for q are inferred in terms of chains for q ′ . So, element chains for q are livre.title and livre.auteur.name, given that for q ′ the return chain is bib.book.title (for x title) and the element chain is auteur.name (for <auteur>x author name< auteur>).

In order to avoid ending up with a wrong element chain for q, i.e., title.name the return chain bib.book.author.name inferred for x author name does not have to belong to the set of return chains for q ′ . At the same time, we must record the fact that the whole subtree rooted at name is accessed. This is handled by the returnto-used conversion of the return chain bib.book.author.name when inferring chains for <auteur>x author name< auteur>. The return-to-used conversion extends r, the set of return chains of the inner query x author name, with all possible continuations by means of r and then it converts chains in r to used chains for the whole expression.

It is worth stressing that if we just convert return chains to used ones without the extension r, then we loose their semantic property of representing entire subtrees of data. Notice that this extension is needed for the purpose of the formal presentation although any efficient implementation can avoid performing these extensions by using intensional representations.

Rule (Text) deals with expressions building new text nodes. The rule simply infers String as an element chain for the built textual node. With a little abuse of notation, for simplicity, we preferred not to use another class of chains.

In this section we illustrated chain inference rules for for query expressions. As update expressions are defined in terms of queries, we will see, in the next section, that chain inference rules for updates rely on the rules for query chain inference.

Update Chain Inference

Rules for update chain inference are presented in Table 4.2. These rules prove judgments of the form Γ ⊢ C u ∶ U meaning that starting from a static variable environment Γ and a set of chains C, the chain inference for the update u produces the set of update chains U.

As seen before, update chains are of the form c ∶ c ′ . Essentially, the prefix c types updated nodes, that are nodes whose children are modified by the update, while the suffix c ′ types modified children or new inserted/replaced descendants.

The most important inference rules are the ones corresponding to delete, rename, insert and replace operations, which are explained in the sequel. The following examples are made on the DTD d 4 , and again we assume that variable doc is always bound to bib in Γ. We recall that when the update target query returns a sequence with more than one location, this has to be bound to a variable and then the update command has to applied by means of iteration, otherwise a dynamic error is raised. However for the sake of conciseness, and w.l.o.g., in the following examples we do not make iteration explicit and assume that the update target query returns only one location.

Inference for delete expressions is defined by the (Delete) rule, which simply puts the separator ":" just before the last symbol of each return chain of the target query. A delete chain c ∶ a captures the fact that a node typed by c has a child labeled by a which may be deleted. As an example, consider the update delete doc publisher By applying rule (Delete) we obtain the following derivation

Γ ⊢ C d 4 doc publisher ∶ ({bib.book.publisher}, ∅, ∅) Γ ⊢ C d 4 delete doc publisher ∶ {bib.book ∶ publisher}
showing how return chains inferred for the target query become update chains.

For rename updates, the process is similar. Rule (Rename) infers chains c ∶ a where a is the tag of the target node before renaming, but it also produces chains c ∶ b, where b is the tag of the target node after renaming. Recall that textual nodes are never target of rename commands. As an example, consider the DTD d 4 and the rename update In this case the update chains capture both the fact that subtrees rooted at author disappear and that subtrees rooted at publisher appear.

Chain inference for insert-into expressions (position ranges over into, first and last) is specified by the rule (Insert-1). For any chain c ∶ c ′ inferred, the prefix c is a return chain of the target query q 0 (typing the insertion point), while the suffix c ′ is either a return or element chain of the source expression q typing a branch of a node element returned by q itself; this element can either be a new one or a sub-element of the input document; in both cases the suffix chain corresponds to inserted data. As an example, consider the DTD d 4 and the update expression insert <name > into doc self ∶∶ bib book. By applying rule (Insert-1) we obtain the following.

Γ ⊢ C d 4 <name > ∶ (∅, ∅, {name}) Γ ⊢ C d 4 doc self ∶∶ bib book ∶ ({bib.book}, ∅, ∅) Γ ⊢ C d 4 insert <name > into doc self ∶∶ bib book ∶ {bib.book ∶ name}
Rule (Insert-2) is similar, and deals with insert-before/after updates.

The two rules for insert updates rely on the fact that element chains can be extracted in source queries. The fact that we opportunely attach element chains of the sourceexpression to result chains of the target-expression, allow us to have a precise analysis. It is worth saying that related update analysis of [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF] and [START_REF] Ghelli | Commutativity analysis for XML updates[END_REF] define as updated everything below the parent of the source location. This design choice has a strong impact for this case, since it is likely to make the analysis deem the update as dependent with almost all queries accessing information concerning the book, while it should only raise conflicts on name elements. This last case suggests also that element chains are necessary for a precise independence analysis, when dealing with updates. To illustrate, consider the following update over the DTD in Figure 4.2.

for x in doc book return insert <author>q ′ < author> into x
Here the source expression is an element query, for which we infer element chains of the form author.c ′ , with c ′ a chain inferred for q ′ . The update chain bib.book ∶ author.c ′ is obtained by concatenation of the chain bib.book associated with the target expression x, and the chain author.c ′ . This allows one to conclude independence wrt the query Now, let us do the analysis without considering element chains: for the source expression <author>q ′ < author>, the best that can be done is to infer the chain bib.book ∶ _ telling that something happens beneath book elements. As a consequence, we would not deduce the independence. As said in the introduction, for similar reasons [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF] wrongly excludes independence for similar cases.

Γ ⊢ C let x ∶= q return u ∶ U (TU-Let) Γ ⊢ C q ∶ (r, v, e) Γ ⊢ C u i ∶ U i i = 1, 2 Γ ⊢ C if (q) then u 1 else u 2 ∶ U 1 ∪ U 2 (TU-If)
In the presence of nested element construction, the same remark holds. In the previous example, if q ′ is <f irst>U mberto< f irst>, <second>Eco< second> then by composing element chains during the inference, we end up with the following update chains bib.book ∶ author.first.String, bib.book ∶ author.second.String, bib.book ∶ author, bib.book ∶ author.first and bib.book ∶ author.second. Indeed, this is necessary to exclude independence wrt the query doc author email (assuming the DTD allows for email elements into author elements).

The rule for replace expressions (Replace) is built on the same principles as (Insert-2) and (Delete) rules. The chains produced by the expression capture the fact that replaced subtrees are now missing, and that replacing subtrees can now be retrieved. As an example, consider the DTD d 4 and the rename update replace doc author name with doc publisher name By applying rule (Replace) we obtain the following. Once again the update chain is obtained by the concatenation of the target and the source expression. Notice that the update chain contains also the expansion of the return chain for the source query. This is done in order to completely trace inserted structures.

Remaining rules for the empty update, concatenation, iteration, let-binding and conditional expressions are formulated in the same spirit as for query chain inference.

In this section we presented rules for update chain inference, showing also that they are built on top of rules for query chain inference. We illustrated the precision of the chain inference with examples compared with related work. In the next section, we will formally prove that query and update chain inference rules are correct, in the sense that they allow to infer types capturing all data which are accessed and updated by query and update expression.

Correctness and Precision of Chain Inference

In this section we show the correctness of the chain inference system for queries and updates. We begin by showing correctness of XPath step chain inference, for which completeness also hold. Then, we state the correctness for queries and updates. The proofs of all statements of this section can be found in the appendix 9.

Soundness of axis and node-test chain inference wrt query semantics is stated below.

Lemma 4.3.1 (Soundness of Step Chain Inference). Let d be a DTD, t = (σ, l t ) ∈ d be a valid tree, and l ∈ dom(σ) be a location of the tree. If σ, (x ∶= l) ⊧ x axis ∶∶ φ ⇒ σ, L then for each location l ′ ∈ L we have that

c t l ′ ∈ T C ( A C (c t l , axis), φ )
A complete chain inference demands also the set of inferred chains to be minimal, so that each inferred chain is typing a result location belonging to some valid tree instance. The completeness of ⇒ d and < d(a) entails that step chain inference is minimal.

c ′ ∈ T C d ( A C d (c, axis), φ )
then there exists a valid tree t = (σ, l t ) ∈ d and a location l ∈ dom(t) such that c t l = c and, assuming that σ, (x ∶= l) ⊧ x axis ∶∶ φ ⇒ σ, L we have that c t l ′ = c ′ , for some l ′ ∈ L.

Showing that chain inference is complete for navigational axes is easy, since chains carry a navigational context that leads inference rules to strictly mimic axis semantics even with backwards and horizontal navigations.

Soundness of Query Chain Inference

Proving soundness of query chain rules consists of proving that, for any schema instance, any node used or built by the query q is captured (typed) by the chains inferred for q. The proof relies on the notion of projection for XML [START_REF] Marian | Projecting XML documents[END_REF][START_REF] Véronique Benzaken | Type-based XML projection[END_REF].

A tree t ′ is said to be a projection of t, denoted by t ′ ⪯ t, if t ′ is obtained from t by removing some subtrees of t. According to our formalism, we define the projection of a tree t induced by a set of locations L ⊆ dom(t), provided that L is non-empty and upward closed with respect to the node parent-child relationship in t. This simply means that if l ∈ L and l ′ is the parent of l in σ then l ′ ∈ L.

Given a sequence of locations L, we define the filtering of L wrt a set of node locations L, denoted by L L , as the subsequence of L that contains only identifiers in L and that preserves the order of L. The projection of a tree t = (σ, l t ) wrt a set of locations L ⊆ dom(σ), is defined as t L = (σ L , l t ), where

σ L def = { l ← a[L L ] l ∈ L, (l ← a[L]) ∈ σ } ∪ { l ← "txt" l ∈ L, (l←"txt") ∈ σ }
That is the store obtained by removing the use of all element and text node locations not in L.

Given a query q, we can define a notion of projection wrt q. We say that a store σ L is a q-projection of σ if, provided that σ, γ ⊧ q ⇒ σ, L and σ

L , γ ⊧ q ⇒ σ L , L ′ we can conclude (σ, L) ≅ (σ L , L ′ )
This definition enforces L to contain all locations needed in order to evaluate q, without altering the result of q. Given two trees t = (σ, l) and t ′ = (σ ′ , l), if σ ′ is a q-projection of σ then t ′ is a q-projection of t.

A tree t ′ is said to be a minimal q-projection of t if for all t ′′ strict projections of t ′ we have that t ′′ is not a q-projection of t ′ (or, equivalently, of t). Here strict means that dom(t ′′ ) ⊊ dom(t ′ ). Notice that, in general, a projection is not minimal. In the sequel we also show that a minimal projection is not unique, due to the query language considered.

To illustrate the above concepts, consider again the tree t 2 in Figure 4.1 that we report below. A projection of t 2 can be obtained by choosing the set of locations L = {l t 2 , l 1 , l 2 , l 3 , l 4 }, that induces the projection of the book element with its own children nodes. However the sets L 1 = {l 1 , l 2 } or L 2 = {l t 2 , l 2 } do not induce projections because they are not closed wrt the node parent-child relation, since L 1 misses l t 2 and L 2 misses l 1 . Neither L = ∅ induces a projection because it contains no location. Now, let us consider the query q = title, selecting all titles of book in the store. By evaluating q over t 2 , we get the subtree rooted at l 2 , since there is only one book in t 2 . <bib> <book> <title> Types and Programming Languages < title> <author> <name>B. Pierce< name>

< author> <publisher> <name>MIT Press< name> < publisher> < book> < bib> σ = ⎧ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎨ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎪ ⎩ l t2 ← bib[ l 1 ] l 1 ← book[ l 2 , l 3 l 4 ] l 2 ← title[ l ′ 2 ] l ′ 2 ← "Types and ..." l 3 ← author[ l ′ 3 ] l ′ 3 ← name[ l ′′ 3 ] l ′′ 3 ← "B. Pierce" l 4 ← publisher[ l ′ 4 ] l ′ 4 ← name[ l ′′ 4 ] l ′′ 4 ← "MIT Press" Figure 4.3: Document t 2 and store (σ, l t 2 )
Also, in order to reach the result, we need all ancestor locations of l 2 , namely l t and l 1 . The set of locations L q = {l t 2 , l 1 , l 2 , l ′ 2 } can be used in order to build a q-projection of t 2 . The result of q over t 2 Lq is equal to q over t 2 . In fact, all other locations in the store are not needed by the query because they concern complementary information such as authors and publishers of a book.

It is worth noticing that in the definition of projection we employed a notion of forestequivalence ≅, that checks only if the two resulting forests are isomorphic, regardless of the node identifiers. Above, we have an example of a stronger equivalence, since not only the structure of the results is the same, but also the node identifiers coincide.

To illustrate minimality of projection, consider again the tree t 2 , a dynamic environment γ = { doc ↦ l t 2 } and the query q = for x in doc book return if (x author, x publisher) then x title else () that returns the title of a book either if this has an author or a publisher child node (that is, if the sequence (x author, x publisher) is non-empty). For this expression, we have a number of q-projections, namely

L 1 = {l t 2 , l 1 , l 2 , l ′ 2 , l 3 , l 4 } L 2 = {l t 2 , l 1 , l 2 , l ′ 2 , l 3 } L 2 = {l t 2 , l 1 , l 2 , l ′ 2 , l 4 }
and all backward-closed supersets of L 1 , L 2 , L 3 . It could seem surprisingly that L 2 and L 3 are projections, because they both discard a node location that is used for building the sequence used by the conditional test. Anyway this is correct, since we need only one of l 3 and l 4 in order to ensure the conditional expression to be non-empty. In this case we have that L 1 is not minimal simply because L 2 , L 3 ⊊ L 1 . Differently, L 2 and L 3 are minimal, since by removing any of their locations we may either break backwardcloseness or alter the query result (by turning the value of the conditional expressions to empty). This shows that a minimal projection is not unique.

The goal of the chain analysis is to capture all nodes needed by all minimal projections of the query wrt all documents valid wrt a schema. To this end, we define how to connect chains with projections. Given a set of chains τ , the set L t τ of locations in t typed by chains in τ is defined as follows.

L t τ def = { l ∈ dom(t) c t l .c ∈ τ }
Dynamic and static variable environments have to link data and types in a consistent way, in order to ensure correctness of chain inference. This is stated next.

Definition 4.3.3 (Consistent environments). Let d be a DTD, t = (σ, l t ) ∈ d a valid tree, γ a dynamic environment binding variables to locations of σ and Γ a static environment binding variables to chains of C d . The environments γ and Γ are said to be consistent if l ∈ γ(x) implies c σ l ∈ Γ(x), for all l ∈ dom(σ). We denote this by σ ⊧ d γ ∶ Γ.

The following theorem formally states that chains inferred for a query q cover the structure of data relevant for the query, and newly constructed elements. Theorem 4.3.4 (Soundness of Query Chain Inference). Let d be a DTD, t = (σ, l t ) ∈ d a valid tree, q a query, γ a dynamic environment and Γ a static environment such that σ ⊧ d γ ∶ Γ. Provided σ, γ ⊧ q ⇒ σ new , L and Γ ⊢ C d q ∶ (r, v, e) the following hold.

1. if t min is a minimal q-projection of t then t min ⪯ t L t r∪v ⪯ t 2. if t new = (σ new , l new ) with l new ∈ L∖dom(σ) is a fresh subtree then dom(t new ) = L t new e
The first item of Theorem 4.3.4 states that chain inference is sound for used and return chains: a projection of any valid input tree made in terms of used and return chains includes every minimal q-projection, hence preserves query semantics (the projection contains all the query needs for its evaluation). The second item is dedicated to element chain inference which is one of the key feature of our query-update analysis as already illustrated. Intuitively, this statement says that if element chains are used to project newly constructed elements (notice that l ′ ∈ L∖dom(σ)) no node is pruned out, so element chains cover all possible chains in new elements of the query result. We conclude that our type inference system gives, as a side effect, a type-projector for the query [START_REF] Véronique Benzaken | Type-based XML projection[END_REF].

Soundness of Update Chain Inference

Proving update chain soundness consists of establishing a link between i) nodes in the stores t and u(t) that are involved in the changes (deletion, insertion, renaming, and replacements) made by u and ii) nodes in these trees which are typed by the chains statically inferred for u.

We stress that the evaluation of an update u on a tree t = (σ, l t ) ∈ d is a two phase process, that first generates the PUL ω together with an extended σ ω containing the arguments of atomic insert and replace updates, for which the following relations hold.

σ, γ ⊧ u ⇒ σ ω , ω σ ω ⊧ ω ↝ σ u
Recall that σ ω includes σ, and that u(t) denotes the tree (σ u @l t , l t ).

Definition 4.3.5 (Involved Location). We say that the update u involves the location l ∈ dom(σ ω ) if one of the following hold.

• l is the target location of an elementary delete command in ω

• l is the target location of an elementary rename command in ω

• l is a location, or the descendant of a location, in the source list L of a command ins(L, _, _) in ω

• l is the target location of an elementary replace command in ω

• l is a location, or the descendant of a location, in the source list L of a command repl(_, L) in ω

The static analysis for update expressions is correct if all involved locations are typed by some update chains. In the following, we present examples of involved locations and how they are typed by the analysis.

The following examples are made over the tree t 2 in Figure 4.1, which is valid against the DTD d 4 in Figure 4.2. As before, we assume that variable doc is bound to location l t 2 during dynamic evaluation and bound to type bib during static analysis.

Consider the following sequence of delete and rename updates delete doc title, rename doc publisher as "author"

The update produces a pending list composed of two atomic update commands ren(l 4 , "author" ) , del(l 2 ) meaning that the label of l 4 (the publisher node) has to be renamed as "author" and that the location l 2 has to be deleted. In this case both l 2 and l 4 are involved locations, since they are target locations of elementary update commands. Note first that an involved location may belong to the initial tree t but not to the updated tree u(t), for instance l 2 , and a location may also belong to both trees like for instance l 4 .

The static analysis for the delete updates over the DTD d 4 produces the chain c = bib.book ∶ title, that is the chain of the deleted location l 2 , in fact c t 2 l 2 = c. Concerning the rename expression, two chains are inferred c 1 = bib.book ∶ publisher and c 2 = bib.book ∶ author. These two chains type the renamed node in the original and in the updated tree respectively, since

c t 2 l 4 = c 1 c u(t 2 ) l 4 = c 2
Involved locations for insert expressions are illustrated by the following example. Consider the tree t 2 and the update insert <author > into doc self ∶∶ bib book

In this case, the first phase of the evaluation produces a PUL composed of the command ins(l ′ , into, l 1 ) together with the store σ extended with a fresh element node labeled as author, which is referenced by a fresh location l ′ . Then, applying the PUL attaches location l ′ as children of l 1 (which refers to the book node). The critical location for the PUL is l ′ . The static analysis for the update over the DTD d 4 returns the chain c = bib.book ∶ author and this is correct since c

u(t 2 ) l ′ = c.
Involved locations for replace expressions are illustrated by the following example. Consider tree t 2 and the update replace doc author name with doc publisher name here the update first build a fresh tree referenced by l c , which is a copy of the one rooted at l ′ 3 . Then l c replaces l ′ 4 (referencing to the publisher name). This results in the atomic update command repl(l ′ 4 , l c ) The critical locations are l ′ 4 , l c and all descendants of l c . l ′ 4 is a critical location because it is the target of the replace command. l c and all of its descendants are critical locations, because l c is the source locations of the update. We stress on the fact that descendants of l c are fresh locations as well.

The static analysis wrt the DTD d 4 returns chain c = bib.book.author ∶ name typing the replaced location l ′ 4 . Chain inference outputs also c = bib.book.publisher ∶ name and c = bib.book.publisher ∶ name.String that are the chains for l c and for the child of l c .

At this point we can state the correctness of the chain analysis for update expressions. The theorem below states that all locations involved by the update u are typed by chains inferred from u.

Theorem 4.3.6 (Soundness of Update Chain Inference). Let d be a DTD, t = (σ, l t ) ∈ d a valid tree, u an update, γ a dynamic environment and Γ a static environment such that

σ ⊧ d γ ∶ Γ. Provided that σ, γ ⊧ u ⇒ σ ω , ω σ ω ⊧ ω ↝ σ u Γ ⊢ C d u ∶ U it holds that • if l ∈ dom(σ)
is a location in t, and the update u involves l then there exists c ∶ c ′ ∈ U such that c σ l = c.c ′ , where c ′ ≠ ǫ. • if l is a location in u(t), i.e. l ∈ dom(σ u @l t ), and the update u involves l then there exists c ∶ c ′ ∈ U such that c σu l = c.c ′ , where c ′ ≠ ǫ. In the above statement, in case a location l belongs both to t and u(t), it may be that the chain typing l in t is different from the chain typing l in u(t) (e.g., due to renaming). Although we made the assumption that the update expression is preserving the schema, it is worth noticing that Theorem 4.3.6 holds also for updates violating schema constraints (u(t) ∉ d), since chains corresponding to deleted or inserted nodes are always traced by the system regardless of correctness wrt the schema.

In this section we showed the correctness of chain inference for query and updates. This will be used in the remaining of the chapter to define a notion of independence, and show its correctness.

Independence Analysis

In this section we define a notion of query update independence based on chain overlapping. We show that this static notion of independence is correct and implies independence on all schema instances. We show that, for recursive schemas, the notion of independence based on chains does not have a trivial terminating algorithm. To overcome this issue, we propose a finite analysis which is complete wrt the infinite analysis and terminates in all cases.

Infinite Analysis

The notion of query-update independence q ⊧ d u (Definition 2.5.2) is based on the semantics of q and u, and involves all possible d instances. The static counterpart of this notion is now proposed and is of course based on query and update chain inference. As chain inference depends on a set C of chains, we first introduce a general static notion of C-independence. Given two sets of chains τ 1 and τ 2 , the set of conflicting pairs of chains for τ 1 , τ 2 is defined as follows.

confl(τ 1 , τ 2 ) def = { (c 1 , c 2 ) c 1 ∈ τ 1 , c 2 ∈ τ 2 , c 1 ⪯ c 2 }

CHAPTER 4. INDEPENDENCE ANALYSIS BASED ON SCHEMA-CHAINS

Definition 4.4.1 (C-independence). Let d be a DTD, q a query and u an update, with at most only one free variable x, and Γ = { x ↦ s d } a static environment. The query q and the update u are C-independent, denoted by q ⊥ C u, if provided that Γ ⊢ C q ∶ (r, v, e) and Γ ⊢ C u ∶ U we have We illustrate the definition of C-independence throughout some examples. We consider DTD d 5 of Figure 4.4. In the queries and updates below, we assume as before that variable doc is bound to bib. We check independence of query q = for x in doc book return if (x price) then x author else x publisher against the following updates u 1 = delete doc title u 2 = rename doc publisher as "author"

confl(r, U) = ∅ confl(U, r) = ∅ confl(U, v) = ∅ C d -
u 3 = insert <price> 50 <price > into doc book u 4 = replace doc price text() with "10"
The static analysis infers, from the query, r q = { bib.book.author, bib.book.publisher } and v q = { bib.book, bib.book.price }. The following static independences hold.

q is C d 5 -independent of u 1 : the expressions are independent because the update does not delete any node that the query accesses or outputs. Hence it results that confl(U, v) ≠ ∅.

(r, U) = confl(U, r) = confl(U, v) = ∅. q is not C d 5 -independent
q is C d 5 -independent of u 4 : the expressions are independent because the update does not affect the result of the query. In fact, the update impacts the textual node below the price node which is accessed by the query, without changing the boolean value of the conditional expression. Let d be a DTD, q a query and u an update, with only one free variable. Then,

q ⊥ C d u implies q ⊧ d u
As already stated, updates are assumed to preserve the schema. The above theorem needs this assumption in order to correctly use query chains in the independence analysis. Actually, if deletions violate the schema (a mandatory node is deleted), the notion of static independence ⊥ C d is still sound. The problem comes from insertions creating new chains (not belonging to C d ) because they are not considered during chain inference for queries. As a consequence, the analysis made to check ⊥ C d could miss conflicting chains.

In this section we defined a notion of static independence based on chains which is sound. In the next section we will show how independence can be verified when recursive query and schemas may entail the inference of infinite sets of chains.

Finite Analysis

The notion of C d -independence (Definition 4.4.1) cannot be directly used to define a terminating decision algorithm, because for DTDs with vertical recursion the sets of inferred chains can be infinite. In this section we show how to finitely approximate sets of inferred chains so that C d -independence can be detected in finite time.

One feature of chains generated by a recursive DTD d is that some of them contain multiple occurrences of (recursively defined) tags. So one way to characterize a finite set of d-chains is to restrict to chains having at most k occurrences of each tag. Hereafter, these chains are called k-chains, and for any set of chains τ , its subset of k-chains is denoted by τ k . Thus, C k d denotes the set of k-chains generated by d.

As illustrated next, a multiplicity value k can be inferred from the query q and update u, so that independence according to chains in C d is equivalent to independence according to inferred chains in C k d . The value k is derived by a two-steps static analysis.

Given an expression e, being either a query q or an update u, the first step associates a value k e to e such that the set of k e -chains inferred for e is representative of all possible inferred chains for e. Intuitively, the representative set of inferred chains for an expression synthesizes all possible inferred chains: any possible inferred chain can be mapped to a chain in the representative set by some folding transformations, according to recursive definitions in the DTD.

The second step infers a value k from the values k q and k u , such that the search of conflicting chains decisive for statically detecting q-u independence can be safely done in the finite set of inferred k-chains.

Inferring the values k q and k u mainly depends on navigational properties of the XPath expressions occurring in the query and update. Thus, we start the discussion by focusing on XPath expressions p, and then consider FLWR expressions.

In the discussion, most of the examples are made on the following recursive DTD d 6 . As before, variable doc in the expressions is meant to be bound to the root of d 6 , that is store.

store ← component * component ← description, complist?, uselist? uselist ← component+ complist ← component+ description ← String
The inference of the k value depends on the navigational axes employed in the XPath steps.

Dealing with child, self and parent

The case where paths employ only the child, self or parent axis is a special one. In fact, such paths always generate a finite number of chains, hence a finite number of representative chains, and no folding is needed. What remains to do is to find a k value that fits all representative chains. The particularity of these paths is that they explicitly indicate how many times a single tag has to be matched: a good choice for k p is the maximal tag frequency in the path p.

To illustrate, consider the following downward path p doc self ∶∶ store component complist component description there are four tags in p, all but component have frequency 1, while component has frequency 2. Therefore, the maximal tag frequency is 2, and indeed 2-chains include the representative chain store.component.complist.component.description which is the only chain inferred for this path (for clarity, we over line the tag with k-frequency). It is worth noticing that, for the analysis to be correct, the query/update free variables have to be always bound to the schema root type. If we relax this assumption, the chain analysis may turn out to be unsound for recursive schemas. To see this, consider for instance the query doc component with doc initially bound to the chain store.component.description. The chain inferred for the query is store.component.description.component, which is a 2-chain. However, since for this expression k = 1, the analysis infers the empty set of used, return and element chains for the query, thus deeming it as independent of any update, while it should not.

Dealing with descendant and ancestor

When a path p makes use of the descendant axis, the number of chains inferred for an expression may not be finite, and the length of inferred chains totally unrelated to the length of p. For instance, the path doc descendant ∶∶ description makes the system inferring an infinite number of chains, of unbounded length.

This is what led us to reason in terms of tag frequency rather than path length. To generate a finite set of chains, the value k p is determined by taking into account the number of occurrences of descendant axes in p.

To illustrate this, we still consider the schema d 6 , and observe that the type component is defined in terms of description, uselist and complist, and the two latter are defined in terms of component. These mutual recursive definitions entail that, in a valid document instance, a node with type uselist can be a descendant of a node with type complist, and vice versa, along the same chain of the tree. In addition, a chain connecting uselist and complist nodes always contains an intermediate component label, which also occurs before the first occurrence of a description, uselist, and complist label.

As a consequence, for the following path p = doc descendant ∶∶ complist descendant ∶∶ uselist descendant ∶∶ description the shortest chain that is inferred is the 3-chain store.component.complist.component.uselist.component.description Simple tag frequency, like for the previous cases, would lead to k p = 1. This is not satisfactory because no 1-chain is inferred for p . To reflect the fact that each recursive axis may permit any tag to repeat once in inferred chains, the correct maximal tag frequency we have to consider for the path p is 3; in fact, 3-chains do allow to infer a non-empty set of representative chains -other inferred chains can be obtained by unfolding recursion.

Of course, an XPath expression may combine both recursive and non-recursive axes. In this case, for a path p we obtain k p as the sum of two components computed independently: the maximal tag frequency for non-recursive steps, and the number of recursive steps in p. As an example, for p = doc descendant ∶∶ component uselist component we have k p = 2 since the maximal tag frequency for the path suffix uselist component is 1, and there is 1 descendant step descendant ∶∶ component.

Recursive backward axes are handled similarly. Here we have to pay attention to the fact that chains navigated by an ancestor step are prefixes of some chains generated by previous steps. Consider p = doc descendant ∶∶ uselist ancestor ∶∶ complist Here k p has to be such that the used chain store.component.complist.component.uselist can be generated. Thus, we enforce ancestor steps to increment the tag frequency by 1. This is reminiscent of what we have seen before in the case of descendant; the way p is processed can be compared to the way would be processed the navigational path doc descendant ∶∶ complist descendant ∶∶ uselist and therefore chains containing complist as ancestor of uselist need to be generated for p.

Concerning paths p employing either descendant-or-self or ancestor-or-self, k p is computed as for the self-less axes. The same holds for shortcut expressions like p = φ, that stands for p ′ = descendant-or-self ∶∶ * φ, when φ ≠ * . It follows that k p = k p ′ simply because the sets of chains inferred for the two expressions are exactly the same.

It is worth noticing that by assuming that the root-type of a DTD is non-recursive we can provide a uniform the definition of the k value, and simplify proofs. To illustrate, consider the DTD d = { a ← a? }, the query q = x child ∶∶ a, and the static environment Γ = { x ↦ a }. Our system infers from q the 2-chain a.a. However, since k q = F(a, x child ∶∶ a) = 1 the chain a.a is ruled-out from inference, while it should not. The same happens if q = x descendant ∶∶ a. This of course can be captured by setting F(a, x axis ∶∶ φ) = 2 if i) x is bound to the singleton root-type, ii) the root-type is recursive, iii) the root-type satisfies φ, and of course iv) axis is downward. This would make the formal definition for the base case quite inelegant, while assuming a non-recursive root-type we have an uniform formalization of the tag frequency. This discrepancy is also caused by the fact that, as discussed in Chapter 2, we do not have the document-node in our data-model.

Dealing with sibling axes

Dealing with FLWR expressions and Updates

Based on concepts previously illustrated, we provide now formal definitions to deal with the general case of a FLWR expression e.

As seen before, the computation of k e is decomposed into two tasks. The first one determines via the function F(a, e) the frequency of each tag a ∈ Σ on the whole expression, in order to derive the maximal frequency. The second task computes via the function R(e) the maximal number of recursive steps used by a navigational path embodied in the whole expression. The value k e is the sum of these two values. Formally:

k e def = max{ F(a, e) a ∈ Σ } + R(e)
The functions F(a, e) and R(e) are defined by structural induction in Table 4.3 and 4.4, respectively.

When e is a for or a let expression, the value k e is specified by summing the subexpression values. This is captured by rules (F-For/Let) and (R-For/Let). This

F(a, ()) = 0 (F-Empty) F(a, "txt") = 0 (F-Text) f = F(a, q) F(a, <a>q< a>) = f + 1 (F-Element) axis is recursive F(a, axis ∶∶ φ) = 0 (F-Step1) φ ∉ {a, node()} F(a, axis ∶∶ φ) = 0 (F-Step2) axis is not recursive φ ∈ {a, node()} F(a, axis ∶∶ φ) = 1 (F-Step3) f 1 = F(a, q 1 ) f 2 = F(a, q 2 ) F(a, q 1 , q 2 ) = max(f 1 , f 2 ) (F-Concat) f 0 = F(a, q 0 ) f 1 = F(a, q 1 ) f 2 = F(a, q 2 ) F(a, if (q 0 ) then q 1 else q 2 ) = max(f 0 , f 1 , f 2 ) (F-If) f 1 = F(a, q 1 ) f 2 = F(a, q 2 ) F(a, for x in q 1 return q 2 ) = f 1 + f 2 (F-For) f 1 = F(a, q 1 ) f 2 = F(a, q 2 ) F(a, let x ∶= q 1 return q 2 ) = f 1 + f 2 (F-Let) f = F(a, q) F(a, delete q) = f (F-Delete) f = F(a, q) F(a, rename q as a) = 1 + f (F-Rename1) f = F(a, q) a ≠ b F(a, rename q as b) = f (F-Rename2) f = F(a, q) f 0 = F(a, q 0 ) F(a, insert q pos q 0 ) = f + f 0 (F-Insert) f 0 = F(a, q 0 ) f = F(a, q) F(a, replace q 0 with posq) = f 0 + f (F-Replace) f 1 = F(a, u 1 ) f 2 = F(a, u 2 ) F(a, u 1 , u 2 ) = max(f 1 , f 2 ) (F-UConcat) f 0 = F(a, q 0 ) f 1 = F(a, u 1 ) f 2 = F(a, u 2 ) F(a, if (q 0 ) then u 1 else u 2 ) = max(f 0 , f 1 , f 2 ) (F-UIf) f = F(a, q) f ′ = F(a, u) F(a, for x in q return u) = f + f ′ (F-UFor) f = F(a, q) f ′ = F(a, u) F(a, let x ∶= q return u) = f + f ′ (F-ULet) Table 4.3: F definition. R(()) = 0 (R-Empty) R("txt") = 0 (R-Text) r = R(q) R(<a>q< a>) = r (R-Element) axis is recursive R(axis ∶∶ φ) = 1 (R-Step1) axis is not recursive R(axis ∶∶ φ) = 0 (R-Step2) r 1 = R(q 1 ) r 2 = R(q 2 ) R(q 1 , q 2 ) = max(r 1 , r 2 ) (R-Concat) r 0 = R(q 0 ) r 1 = R(q 1 ) r 2 = R(q 2 ) R(if (q 0 ) then q 1 else q 2 ) = max(r 0 , r 1 , r 2 ) (R-If) r 1 = R(q 1 ) r 2 = R(q 2 ) R(for x in q 1 return q 2 ) = r 1 + r 2 (R-For) r 1 = R(q 1 ) r 2 = R(q 2 ) R(let x ∶= q 1 return q 2 ) = r 1 + r 2 (R-Let) r = R(q) R(delete q) = r (R-Delete) r = R(q) R(rename q as b) = r (R-Rename)
r = R(q) r 0 = R(q 0 ) R(insert q pos q 0 ) = r + r 0 (R-Insert) r 0 = R(q 0 ) r = R(q) R(replace q 0 with posq) = r 0 + r (R-Replace)

r 1 = R(u 1 ) r 2 = R(u 2 ) R(u 1 , u 2 ) = max(r 1 , r 2 ) (R-UConcat) r 0 = R(q 0 ) r 1 = R(u 1 ) r 2 = R(u 2 ) R(if (q 0 ) then u 1 else u 2 ) = max(r 0 , r 1 , r 2 ) (R-UIf) r = R(q) r ′ = R(u) R(for x in q return u) = r + r ′ (R-UFor) r = R(q) r ′ = R(u) R(let x ∶= q return u) = r + r ′ (R-ULet)
Table 4.4: R definition.

INDEPENDENCE ANALYSIS

77 is motivated by the fact that, for instance, for-expressions are usually used to encode nested iterations performed by XPath paths, like in the query for x in doc a for y in x b return y This definition leads in some cases to an overestimation of the value k e that would be actually sufficient for a finite analysis. For instance, for the query q = for x in doc a a for y in doc a b return x, y we have F(a, q) = 3, while the value 2 would be sufficient. It is worth saying that this overestimation raises the k q value. More precision can be obtained by tracing variable bindings in the definition of F. The same argument holds for R. However, this would make the formalization cumbersome without being a decisive factor for the analysis. Thus, our choice has been guided by simplicity and conciseness of F and R definitions.

The rules for element construction, (F-Element) and (R-Element), deserve some comment. Note that tags of constructed elements are taken into account. Indeed, these elements can be inserted by an update as children of existing elements, thus generating new chains pointing nodes that can be accessed by a query. Consider the recursive schema d 7 and the following update u.

for x in doc self ∶∶ store component return insert <component> <component> <description > < component> < component> into x
As already outlined, precision of the independence analysis relies (among other things) on the chains generated for element construction. The rules in Table 4.3 lead to infer k u = F(u, component) = 3, and thus the chain store.component ∶ component.component.description is inferred for the finite analysis. The inferred value is the same, if u is a replace update instead of an insert update.

Tag frequency for delete update expression is determined as for queries. For rename expressions tag frequency is determined by observing that for recursive schemas, after renaming, the frequency of the renaming label may increase of 1. To illustrate, consider the DTD d 7 update u = rename doc description as "component"

In this case, if we settle F(u, component) = 1 to capture the fact that a new node labeled with component appears. Together with R( description) = 1, this makes k u = 2, and indeed this is the multiplicity value needed to infer the 2-chains store.component ∶ description and store.component ∶ component Notice that if the frequency of component is not kept into account then k u = 1 and chain store.component ∶ component is wrongly excluded from inference.

Finite independence analysis

We see now how to use the values k q and k u in order to determine a k value such that C d -independence can be detected by restricting the analysis to k-chains.

Consider the following query and update pair over the DTD d 6 .

q = descendant ∶∶ complist u = delete descendant ∶∶ uselist
The two expressions are dependent because uselist is an ancestor of complist and they are both navigated by a recursive axis. It results that k q = 1 and k u = 1. At this point, we could argue that a sound choice is

k = max(k q , k u )
which allows the finite analysis to infer the query chain store.component.complist and the update chain store.component ∶ uselist Unfortunately, these chains do not conflict, and rule out dependence. The problem here comes from the fact that the update may change a descendant of a query returned node, and that k = max(k q , k u ) does not permit to capture this in the finite analysis. It may also occur that a query navigates descendants of nodes inserted/created by the update, and again such a definition rules out independence. To avoid this problem, it is necessary that representative chains that are inferred for the update cover query returned nodes, and vice versa. To this end, while inferring chains for the update u, structural properties of the query q have also to be taken into account. This is obtained by setting

k = k q + k u Now with k = 2 it

Soundness of the Finite Chain Analysis

In this section we state one of our main results, soundness of the finite analysis.

Theorem 4.4.3 (Soudness of C k d Independence). Let d be a DTD, q a query and u an update, with only one free variable. Let k = k q + k u as defined above, then

q ⊥ C k d u implies q ⊧ d u
We develop the main steps of the proof of the Theorem. The thesis follows by showing that q

⊥ C d u is equivalent to q ⊥ C k d u. Proving that q ⊥ C d u implies q ⊥ C k d u is straightforward since C k d ⊆ C d .
Also, we reason in terms of dependence, rather than independence. We prove that C d -dependence implies C k d -dependence (these notions directly follow from Definition 4.4.1) by showing that from any pair of chains in C d , witness of dependence, it is possible to identify a pair of k-chains in C k d , witness of dependence.

The proof is composed of three steps. First, we show that there exists a folding from query chains to k-query-chains, for any query q (Lemma 4.4.4). Then, we show that there exists a folding from query chains to k-query-chains also preserving the prefix relation ⪯, for any pair of queries (q, q ′ ) (Lemma 4.4.5). Finally, we show that such a folding exists for chains inferred for any query-update pair (q, u) (Theorem 4.4.3). Proofs are reported in Chapter 9. We state now the correctness of the k-folding for a single query. In the statements below we consider that, if c is a used (respectively return or element) chain, then c ′ is a used (respectively return or element) chain. Lemma 4.4.4 (Folding). Let d be a DTD, q a query with only one free variable x, and Γ = { x ↦ s d } a static environment. Assume that Γ ⊢ C d q ∶ (r, v, e) and τ = r ∪ v ∪ e. For each chain c ∈ τ there exists a chain c ′ ∈ τ such that c ↪ * d c ′ and c ′ is a k q -chain.

As an example, consider DTD d 6 and the query q = component. In this case k q = 1 and we have, for instance, the following 2-chain folding onto a 1-chain. store.component.uselist.component ↪ d store.component When q and u are C d -dependent, at least one of confl(U, v), confl(r, U), confl(U, r) is nonempty (see Definition 4.4.1). This implies that there exists a conflicting pair of inferred chains, witness of the C d -dependence of q and u. As updates are defined in terms of queries, the next lemma which focuses on "conflicting" query chains is needed to conclude the proof of Theorem 4.4.3. Lemma 4.4.5 (Folding and Conflict Preservation). Let d be a DTD, q 1 , q 2 two queries with only one free variable x, and

Γ = { x ↦ s d } a static environment. Assume that Γ ⊢ C d q i ∶ (r i , v i , e i ) and τ i = r i ∪ v i ∪ e i . For each pair of chains (c 1 , c 2 ) ∈ τ 1 × τ 2 such that c 1 ⪯ c 2 , there exists (c ′ 1 , c ′ 2 ) ∈ τ 1 ×τ 2 such that c ′ 1 ⪯ c ′ 2 and c i ↪ * d c ′ i with c ′ i a (k q 1 +k q 2 )-chain (i = 1, 2).
As an example, consider DTD d 6 and the query q = uselist and the update u = delete complist. In this case k = k q + k u = 2 and and we have, for instance, the following conflicting chains folding onto k-chains, and preserving the conflict. Below, for the sake of concision, st = store, co = component, ul = uselist, and cl = complist.

Conclusions

In this chapter we presented two of the main contributions of this thesis: a type system for chain inference and a static notion of independence based on chains. We proved also that both the type system and the independence analysis are correct. Moreover, we illustrated how to make the static notion of independence verifiable in a finite time, even in the case where inference entails an infinite number of query and update chain. In the next chapter we will discuss algorithms and data structures for efficiently implementing the chain-based independence.

Chapter 5

Implementing the Chain-based Independence Analysis

In this chapter we present algorithms for efficiently implementing the chain-based independence analysis. Chain inference poses significant challenges from the computational point of view. Because of the expressivity of the schema and of the query/update languages considered, it is easy to have exponential blowups of chains during inference. In light of this, we present a data-structure for storing chains based on DAGs, and algorithms implementing the chain-based independence analysis, that allow to run the independence analysis in polynomial space and time, whilst still retaining an high precision.

Introduction

Chain inference is a challenging problem not only from a formal point of view, but also from a computational point of view. In fact, the number of distinct chains inferred for a single expression may be exponential in the size of the input DTD. This happens for DTDs that make heavy use of recursive definitions, but also for non-recursive ones, like for DTD d 8 , that is defined by the following set of productions.

a ← b 1 , f 1 . . . b (i-1) ← (b i , f i )? f (i-1) ← (b i , f i )? with 1 ≤ i ≤ n.
The DTD d 8 employes 2n + 1 types, and a simple navigational query like b n makes the system inferring Ω(2 n ) chains. Namely, all chains of the form a x 1 x 2 . . . x (n-1) b n with x i ∈ {b i , f i }. This happens because types are heavily reused in the schema. If no type is reused, it turns out that, the DTD is non-recursive and the number of chains becomes linear in the size of the schema.

82CHAPTER 5. IMPLEMENTING THE CHAIN-BASED INDEPENDENCE ANALYSIS

This already demonstrates the expressive power of the constraints that can be defined by a non-recursive DTD. The situation is even exacerbated by the use of recursion, where it is possible to reproduce the previous situation with a schema featuring just three types. Consider the DTd d 9 defined as follows

a ← b, f b ← (b , f)? f ← (b , f)?
In this case, the chains of length h + 1 inferred for a navigational step like b, are again all chains of the form a x 1 x 2 . . . x (h-1) b with x i ∈ {b, f}. Again, we have an exponential blowup since the cardinality of the result is in Ω(2 h ). As we show later (see Proposition 5.1.5), when the multiplicity value k is considered instead of the chain length h, the quantity of inferred chains is still exponential.

These examples outline the hardness of chain inference already in terms of cardinality of the results. If chains are not stored efficiently, this may have a direct consequence on space occupancy. This is problematic because if the space complexity for intermediate computations has an exponential upper-bound, then time complexity is at least of the same order, thus compromising tractability of the analysis.

In the remainder of the chapter we will see that the crux in implementing the chain analysis is the choice of the data-structure to use for efficiently storing and retrieving chains. Unsurprisingly, the blowups outlined in the previous example imply that storing chains requires exponential space for instance if we use a trivial data-structure such as lists, or a less trivial one, such as trees. In light of this, we propose a compressed data structure based on DAGs that permits to store chains in polynomial space, paving the way to the tractability of the analysis.

Cardinality of Schema Chains

In this section, we investigate the cardinality of the set of chains induced by a schema, and relative issues concerning their space occupancy. We study both non-recursive and recursive DTDs, and storing chains on lists and trees. Our results show clearly that the static notion of independence we defined in Chapter 4 may require an exponential time to be checked.

Recall that given two functions f and g, we say that f is in O(g) or, equivalently, that g is in Ω(f ) if f ≤ Cg + C ′ , for two positive constants C, C ′ and all values of the variables. We say that f is in

Θ(g) if f is in O(g) and f is in Ω(g).
The cases when our system produces the larger number of chains are those relative to saturated schema (defined in Chapter 2).

Proposition 5.1.1. For a saturated non-recursive DTD d with n types, the cardinality of

C d is Θ(2 n ).
Proof. Because d is non-recursive and saturated, ⇒ d is a strict total order. It is total, because all pairs of types in d are adjacent in G d . It is strict, because d is non-recursive, and thus ⇒ d is irreflexive. This implies that any subset of types in d together with the order of ⇒ d corresponds to a chain in C d . The size of C d comes from the size of the powerset of types in d. This is 2 n -1, without counting the empty chain. Moreover, the number of rooted chains induced by d coincides with the number of subsets of types of d that contain at least the root-type. These are exactly 2 n-1 .

We compare the case of using lists and prefix-trees for storing chains.

List Lists are defined as sequences of objects. Storing chains on lists implies to store each time the full chain. For instance, chains bib.book.author and store.component are represented as [bib; book; author] and [store; component] respectively.

Prefix-Trees Prefix-trees are trees where all chain prefixes are stored only once. Each path in the tree is a chain. This optimizes chain inference wrt using lists. For instance, given two chains bib.book.title and bib.book.author the prefix-tree allow to store only the prefix bib.book on a single edge, even if it is shared by both chains.

Proposition 5.1.2. The set of rooted chains induced by a saturated non-recursive DTD d of n + 1 types requires, to be stored on lists, Θ(n2 n ) space.

Proof. The proof follows from some combinatorics. As discussed in the proof of Theorem 5.1.1, d being saturated and non-recursive, the power set of types in d is the equivalent of C d . Since we count rooted chains, we consider all subsets of types containing the root, and hence we count n types instead of n + 1. We model space occupancy by making a weighted sum of all subsets of types of size 1, 2, . . . , n. The number of sets of types of size i in d can be counted by using the number of combinations of i elements chosen from a set of n elements n i . Then we consider that, by using lists, a subset of size i would need space proportional to i + 1 (by re-considering also the root). Therefore, list space occupation is

n i=0 n i (i + 1) = n i=0 n i i + n i=0 n i = n2 n-1 + 2 n = (n + 2)2 n-1
and thus we obtain Θ(n2 n ).

Next statement shows that, even if we use an optimized data-structure such as prefixtrees for storing chains, we still need exponential space for storing all schema chains. 84CHAPTER

IMPLEMENTING THE CHAIN-BASED INDEPENDENCE ANALYSIS

Proposition 5.1.3. The set of rooted chains induced by a saturated non-recursive DTD d of n types, can be stored on a prefix tree in Θ(2 n ) space.

Proof. The result follows from defining the size of a tree as a recurrence relation. We consider the worst case where there is a maximum type dependency for the non-recursive DTD d. Let us denote by Size(i) the size of the prefix tree containing all rooted chains of a DTD with i types. For simplicity, we define the space occupancy of a node and of an edge as 1. The growth of the size of the tree is depicted in Figure 5.1. In general, for n > 0, we have the recurrence relation

Size(n) = 2 ⋅ Size(n -1) + 1
from which we conclude that the size of the tree is in Θ(2 n ).

a 0 a 0 a 1 a 0 a 1 a 2 a 2 a 0 a 1 a 2 a 3 a 3 a 2 a 3 a 3 (n = 1) (n = 2) (n = 3) (n = 4)
Figure 5.1: Prefix-tree for saturated non-recursive schemas with n types

From the previous results we have that trees are just linearly more succinct than lists for storing chains.

By considering recursive DTDs, the number of chains inferred for an expression augments substantially. We investigate the cardinality of sets of inferred chains for recursive schemas. To this end we adopt multisets, defined as follows.

Definition 5.1.4 (Multiset). A multiset (M, µ) is a set of (distinct) elements M together with a function µ that assigns to each element in M a non-negative integer value of multiplicity.

For instance, ({a, b} , {(a, 1), (b, 3)}) denotes the multiset in which the element a has one occurrence and b three occurrences. We say that (M ′ , µ ′ ) is a sub-multiset of (M, µ) if M ′ ⊆ M and µ ′ (m) ≤ µ(m), for all m ∈ M . For instance, let M = {a, b}, µ = {(a, 1), (b, 3)} and µ ′ = {(a, 0), (b, 1)}, the multiset (M, µ ′ ), corresponding to the set {b}, is a sub-multiset of (M, µ). In short, we denote by M k the multiset (M, µ) where each element of M has multiplicity k, so that µ(a) = k for all a ∈ M .

INTRODUCTION

85

Proposition 5.1.5. A saturated recursive DTD d with n + 1 types induces Ω(

(nk)! (k!) n ) and O( (nk+1)! (k!) n ) rooted k-chains.
Proof. Because d is saturated and recursive, a rooted k-chain is a sequence of types, whose length is upper bounded by 1 + nk. We model this by using multisets. Let M be the set of n mutual recursive types in d, and let M k be the multiset of M elements with multiplicity k each. A permutation of a multiset M is an ordered arrangement of objects of M . The set of rooted k-chains of d can be seen as the permutations with repetition of all sub-multisets of M k . For instance, let (M, µ ′ ) be the multiset with M = {m 1 , . . . , m n } and

µ ′ = { ( m 1 , k-1 ) , ( m 2 , k ) , . . . , ( m n , k ) }
We have that (M, µ ′ ) is a sub-multiset of M k . The permutations associated with (M, µ ′ ) can be seen as the set of all chains of length nk, where all types repeat exactly k times, but type m 1 repeats exactly k -1 times. Of course, if b 1 , b 2 are the first and second occurrence of b, respectively, then ab 1 b 2 and ab 2 b 1 denote the same permutation.

The number of k-chains for d can be computed exactly with the basic combinatorial formula for permutations with repetition, as the sum of all possible configurations of multiplicity values k 1 , . . . , k n (assigned to type-names m 1 , . . . , m n ) that are ranging from 0 to k. This is 0≤k 1 ,...,kn≤k

(k 1 + ⋅ ⋅ ⋅ + k n )! k 1 ! ⋅ ⋅ ⋅ ⋅ ⋅ k n !
also counting the singleton root-type.

A lower bound for this quantity can be given by computing just part of the inferred chains, namely the permutations of M k of maximum length nk (we ignore subsets for the moment). This can be done with the basic formula and results in

perm(M k ; nk) = (nk)! k 1 ! ⋅ ⋅ ⋅ ⋅ ⋅ k n ! with k 1 = ⋅ ⋅ ⋅ = k n = k.
This quantity is exactly the number of rooted k-chains of length nk, and thus we have the lower bound Ω(

(nk)! (k)! n ).
An upper bound for the set of k-chains induced by d is obtained in the following way. First, notice that the whole set of rooted k-chains of d is the set of prefixes of the chains of maximal length we computed above. Therefore, consider that each chain of length 1 + nk has nk prefixes. So as to obtain

nk (nk)! (k!) n which gives O( (nk+1)! (k!) n )
as upper bound of inferred chains. This upper bound is not tight, because we count twice a prefix shared by two chains, but still helpful in order to understand the result size. It is worth observing that perm(M k ; nk) is strictly smaller than the number of permutations with repetitions of length nk of n types, that is n nk .

86CHAPTER 5. IMPLEMENTING THE CHAIN-BASED INDEPENDENCE ANALYSIS

These results show that chain inference is much harder in the presence of recursive schemas. Once again, it is possible to show that by using both lists and prefix-trees for storing chains, the space occupancy is exponential in the size of the DTD and the value k; prefix trees are still polynomially more succinct than lists. Because space complexity has a direct impact on time complexity, this suggests that implementing the chain inference defined in Chapter 4 with one of these two data-structures may compromise scalability, as shown by the following result.

Theorem 5.1.6. Let d be a DTD with n types and e be a query or update expression of size m, exact k-chain inference for e is in EXPTIME.

Proof. By Lemma 5.1.5 the maximal number of chains one can infer from DTD d is in O( (nk+1)! (k!) n ). Consider now the case where each subexpression of e needs to process all of such chains. All inference rules perform a linear number of operations on a single chain, but rules for insert and replace updates perform a quadratic number of operations. Hence we say that each inference step does at most a polynomial number of operations on the set of input chains. In turn, each operation on a chain can be done in O(nk), that corresponds to the traversal of the whole chain. We conclude that exact chain inference for the whole expression of size m can be done in O(m ⋅ nk ⋅ poly(

(nk+1)! (k!) n )).
This theorem gives an upper bound to the complexity of the chain inference problem and it shows that exact chain inference may have an enormous worst-case cost by using data-structures such as lists or trees. Of course this does not means that for any instance of the problem, chain inference is expensive. However, in practice it turns out that for schemas featuring cliques of mutual recursive types, the k analysis works efficiently only if k is small, and rapidly becomes intractable. From this we can deduce also that, once chains are inferred from queries and updates (in exponential time), checking for a conflict may require an exponential time, because of the number of chains one has to consider.

Storing Chains on DAGs

To overcome the limits outlined in the previous section, we present now a data-structure for storing chains based on directed acyclic graphs (DAGs) which is exponentially more succinct than trees, and allows to store chains in polynomial space and makes the analysis tractable in practice.

The intuition behind the use of DAGs instead of trees is that rather than storing only once common-prefixes of chains, in many cases we can also store only once common suffixes of chains. This can be done in a particularly efficient way for XML schemas that, being regular tree grammars and generate regular trees-of-chains featuring a number of repeating subtrees.

To illustrate, consider the chains induced by the non-recursive DTD d 8 , which is defined by the following set of productions (below, we assume

1 ≤ i ≤ 3). a ← b 1 , f 1 . . . b (i-1) ← (b i , f i )? f (i-1) ← (b i , f i )?
In Figure 5.2.a we show how the chains of d are stored as a prefix-tree. From now on, we call CTREE a prefix-tree storing chains. The CTREE shows clearly that by unfolding schema chains we are unfolding regular subtrees. We stress this fact by marking repeated subtrees with different colors.

In Figures 5.2.(b-d) we show that repeated subtrees can be recursively compressed until obtaining a DAG that is equivalent to the CTREE. From now on, we call CDAG a DAG storing chains. In fact, when there is a path (equivalently, a chain) in the CTREE, there is a path in the CDAG, and vice-versa.

a b 1 b 2 b 3 b 4 f 4 f 3 b 4 f 4 f 2 b 3 b 4 f 4 f 3 b 4 f 4 f 1 b 2 b 3 b 4 f 4 f 3 b 4 f 4 f 2 b 3 b 4 f 4 f 3 b 4 f 4 (a) a b 1 f 1 b 2 f 2 b 3 f 3 b 3 f 3 b 4 f 4 b 4 f 4 b 4 f 4 b 4 f 4 (b) a b 1 f 1 b 2 f 2 b 3 f 3 b 4 f 4 b 4 f 4 (c) a b 1 f 1 b 2 f 2 b 3 f 3 b 4 f 4 (d)
Figure 5.2: Compression of a CTREE to an equivalent CDAG As suggested by the example, it is more convenient to perform the inference of the CDAG rather than the tree. Of course, we avoid to first infer prefix-trees and then compress them, because this again lead us to infer structures of exponential size. In the following, when speaking about CDAGs and CTREEs, we assume that they are inferred on a given DTD d.

A CDAG G is a directed acyclic graph rooted at the schema root-type, that contains no self-loop and meets the following property.

There is at most one node labeled a at depth h in G

(5.1) 88CHAPTER

IMPLEMENTING THE CHAIN-BASED INDEPENDENCE ANALYSIS

This means that, if two chains happen to have the same type in position h, they will share a common node in the CDAG at depth h. This property is for instance enjoyed by the tree in Figure 5.2.d. A CDAG is thus organized per levels. Property (5.1) makes the width of the CDAG upper-bounded by the number of types in the schema size. Also, the k-analysis makes the height of a CDAG linear in the size of the schema. Therefore the number of vertex of a CDAG is always finite, and polynomial in d and q.

Let us illustrate property (5.1) with some examples over recursive and non-recursive schemas.

Consider the saturated non-recursive schema d 2 previously defined.

a 1 ← a 2 , a 3 , a 4 , a 5 a 2 ← a 3 , a 4 , a 5 a 3 ← a 4 , a 5 a 4 ← a 5
In Figure 5.3 we compare a CTREE and a CDAG storing all chains of d 2 . Once again, we see the unfolding of the regular structure of the schema with the CTREE. By using DAGs instead of trees we can compress common chain-prefixes and store them only once. This is the case, for instance, for the subtrees rooted at a 4 and a 5 at level 2. In this case one could even compress more, by ignoring levels. However, this would substantially complicate not only the formal development, but also the implementation phase, thus resulting error prone for implementors. A chain in the graph is a rooted path ending with type b. Notice that a chain belongs to the CDAG if it belongs to the CTREE but, in this case, there are also some chains belonging to the CDAG that do not belong to the CTREE. The following chains are obtained as artifacts from the compression. While at first sight one could argue that, for the purpose of independence detection, a refined notion of completeness (wrt k-chains) may be needed, this is not the case. Indeed a k ′ -chain matching an expressions, with k ′ > k, cannot generate false negatives.

90CHAPTER 5. IMPLEMENTING THE CHAIN-BASED INDEPENDENCE ANALYSIS

To conclude the discussion on the size of CDAGs, we prove that they are always polynomial in d.

Lemma 5.2.1. Let d be a non-recursive DTD with n + 1 types. The size of a CDAG inferred for all chains of d is in O(n 3 ).

Proof. Assume that d is a saturated non-recursive schema featuring n + 1 types. The CDAG storing all d chains is organized in n + 1 levels where a) the root-level has one node and b) for the remaining n levels, level i has i nodes (1 ≤ i ≤ n). Therefore we conclude that the CDAG has 1 + n(n+1) 2

nodes. Concerning the number of edges, we notice first, that, at the root level, the root type is connected with all other n types. Then, as we said, level i has i types. Assume that a 2 , . . . , a i is the sequence of types at level i, ordered by the number of outgoing edges (ascending order). Because the schema is saturated, we have that type a j at level i is connected with j -1 types at level i + 1. We conclude that the size of the edge-set is n + ∑ n i=1 ∑ i-1 j=0 j, which is in O(n 3 ).

Lemma 5.2.2. Let d be a recursive DTD with n types and k a multiplicity value. The size of a CDAG inferred for k-chains of d is in O(kn 3 ).

Proof. Assume that d is a saturated recursive schema featuring n+1 types. First we notice that the CDAG storing the k-chains of d has at most kn levels. Therefore, because each of the n types can repeat in all kn levels, the CDAG has kn 2 nodes. Because there exists at most n 2 edges between two consecutive graph levels, the CDAG has O(kn 3 ) edges. We conclude since no edge crosses multiple levels.

Chain Inference and Edge-labeling

CDAGs do not allow only to reduce space occupancy, but also to reduce the number of operations needed by the inference. To illustrate, consider the query q = book * name and the DTD d 3 previously defined as bib ← book * book ← title, author+, publisher+ author, publisher ← name title, name ← String

The CTREE and the CDAG storing chains of q over d 3 are reported below. Now, assume a further inference step has to be done, such as for query

q ′ = q text()
Now, in order to extend the CTREE, two operations are needed (one for each node name) while, in order to extend the CDAG, only one operation is needed. This shows that, with CDAGs, we can also save computations by doing chain inference by groups of chains. The number of groups of chains is polynomial in the size of a schema and of a query (in fact, a group is represented by all chains terminating in one node). Thus this makes polynomial the number of input nodes for an intermediate inference operation.

92CHAPTER 5. IMPLEMENTING THE CHAIN-BASED INDEPENDENCE ANALYSIS

Another ingredient needed in the CDAG representation is a means to represent chains inferred for unrelated sub-expressions. Intuitively two expressions are related if one draws data from the other (e.g. by means of variable binding). If this does not happen, the expressions are unrelated. To illustrate, consider the bibliographic DTD d 3 and the following sequence q 1 , q 2 = book name text() , bib book publisher name f oo Here the whole expression is constituted of two unrelated queries q 1 and q 2 . It turns out that these may produce unneeded chains a consequence of overlapping.

The chains inferred for q 1 over d 3 are bib.book.author.name.String bib.book.publisher.name.String

The chain inferred for q 2 over d 3 is bib.book.publisher.name.foo

The naive CDAG representation of the chains for the two subexpressions is If the chains inferred for the two expressions are stored together, without any distinction, then the CDAG also encodes the chain bib.book.author.name.foo which is not a chain that should be inferred neither for q 1 nor q 2 . In order to overcome ambiguity in the CDAG, we introduce some marking for distinguishing among two chains inferred for distinct sub-expressions in the CDAG representation. We do this by putting on any edge connecting two CDAG-nodes a label identifying the query/update expressions that produced the chain during inference. These identifiers are necessary to precisely perform chain inference, and independence checking as well. The CDAG representation of chains for q 1 , q 2 is the following. q 1 , q 2 q 1 q 1 , q 2 q 1 q 1 , q 2 q 1 q 2

We see that the labelled CDAG allows for a more precise analysis, in this case for instance the chain bib.book.author.name.foo cannot be traced anymore. (through q 1 or q 2 identifiers).

Labels help also in dealing with backward navigations. We can observe that if in the above query q 1 , q 2 we replace q 2 by q 2 = bib book publisher f oo ancestor∶∶ * when inferring chains for the last step of q 2 , thanks to edge-labeling, avoids to navigate upward parts of the CDAG that have not been generated by q 2 (i.e., a author node), thus preserving the precision of the analysis in most of the cases.

Notice that backtracking on unvisited nodes does not affect the correctness of the analysis, but only its precision. The same observation holds for tracing unvisited chains. Removing labels, is a possibility if one wants to further lower the complexity of the analysis, that would result in dealing with a dimension less.

Chain Inference with CDAGs

In this section we present algorithms for implementing the chain inference with CDAGs. We first give some auxiliary definitions, and then we present chain inference. We begin with operators for XPath single steps, then treat navigational queries, element construction and, finally, we consider updates.

Preliminary definitions

Definition 5.3.1 (CDAGs). A CDAG is a directed acyclic rooted graph G = (V, E, s), where V ⊆ Σ S × N is a set of nodes that store a type in Σ S and an integer value denoting the distance of the node from the root in G, where node (s, 0) ∈ V denotes the root type, and E ⊆ V 2 × N is a set of edges among nodes recording the code of the query/update subexpression that produced that edge.

94CHAPTER 5. IMPLEMENTING THE CHAIN-BASED INDEPENDENCE ANALYSIS

In order to implement our analysis we need some auxiliary tools for managing chains inferred from queries and updates.

We first need an encoding of query and update expressions that is used for separating the chains inferred from unrelated subexpressions. The concept of subexpression is standard: e ′ is a subexpression of e, denoted by e ′ ∈ e, if the parse tree of e ′ is a subtree of the parse tree of e. Definition 5.3.2 (Query encoding). The encoding of a query or update expression e is an injective function id() mapping each subexpression of e to an integer in N. The encoding of a set of expressions {e 1 , . . . , e n } is a function obtained by the union of functions encoding each e i , with 1 ≤ i ≤ n, provided that this union is still injective.

The definition says that basically any coding would work for the inference task, provided that we are able to uniquely identify each subexpression. This is why the function is required to be injective. As an example, consider the sequence

q 0 = (q 1 , q 2 )
for which we can have the following encoding.

id (e) = ⎧ ⎪ ⎪ ⎪ ⎨ ⎪ ⎪ ⎪ ⎩ 1 if e = q 1 2 if e = q 2 12 if e = q 0
provided that there are no other subexpressions in q 1 , q 2 .

The second tool we need is a relation for capturing related expressions. As already said, two expressions are related if one draws data from the other. As an example, for the query for x in book return x author expressions book and x author are related because the first provides nodes that are bound to x, and the second accesses the content of x. As the example suggests, in the language we considered this relationship is established by the use of variables, and allows to reconstruct all navigational-paths embodied by a query or an update. We assume wlog that queries are written by using distinct variable-names for distinct variable-definitions.

To formalize this, we need a way to retrieve, given a variable x, the set of navigational steps that provide data to x. Assume that e = for let x in ∶= e 1 return e 2 then the set of navigational expressions providing data to x is defined as ret (e 1 ), where

ret (e) def = ⎧ ⎪ ⎪ ⎪ ⎪ ⎪ ⎨ ⎪ ⎪ ⎪ ⎪ ⎪ ⎩ {e} if e = y step ret(e 2 )
if e = for let y in ∶= e 1 return e 2 ret (e 1 ) ∪ ret (e 2 ) if e = if (e 0 ) then e 1 else e 2 or e = e 1 , e 2 ∅ otherwise

To illustrate function ret(), consider the following query q = for x in q 1 return q 2 with q 1 = ( title, author) and q 2 = x book. In this case we have that ret(q) = { x book } = ret(q 2 ) ret (q 1 ) = { title, author }

We now define expressions related by the use of variables.

Definition 5.3.3 (Variable-Reference). Let e be a query or update expression, and x a variable defined in e. The set of navigational steps referenced by x, denoted by vr (x), is defined as vr (x) = ret(e x ), provided that e x is a for/let expression introducing x.

To illustrate this definition, consider the query q = for x in (for y in a, d return y b)

return let z ∶= if ( b) then x else x parent ∶∶ * return x
The variable-reference relation, and its transitive closure, are graphed below.

→ d

With a little abuse of notation, we denote by vr (e), vr (i ) and vr (x) the same set, provided that e = x step and id(e) = i . The transitive closure of vr(x), vr (e) and vr (i ) are denoted by vr + (x), vr + (e) and vr + (i ), respectively.

The following property shows that an exponential number of sequences induced by the reference variable relation may arise.

96CHAPTER 5. IMPLEMENTING THE CHAIN-BASED INDEPENDENCE ANALYSIS

Proposition 5.3.4. Let e be a query or update expression and e 1 , . . . , e n be a sequence of subexpressions of e such that e (i+1) ∈ vr (e i ). The following holds.

1. the sequence size is bounded by the query size, n ∼ O( e ) 2. the number of such sequences is in the worst case exponential O(2 n ) 3. if no concatenation or conditional expression is nested in the left-branch of a for or let expression, then the number of such sequences is linear O(n).

The first item states that the length of a navigational path embodied in a query is upper bounded by the query size. The second item shows the succinctness of the query and update languages. It states that a query of size n can embody 2 n navigational paths. The third item states that this succinctness is given by two operators: query concatenation and conditional expressions. Proposition 5.3.4 suggests also that chain inference may lead to perform an exponential number of operations if the whole relation vr + () has to be visited. For instance, this may happen in the presence of backward navigations. Nevertheless, differently from trees and lists, CDAGs allow to design algorithms that are sound, that run in polynomial time and that are still precise, as we illustrate next.

Auxiliary Data-Structures

The CDAG inference algorithms make use of some global data structures that we define below. The role of such structures will be clarified during the presentation of inference algorithms.

• Ret() is an inverted index mapping an expression id i to a set of nodes M in the CDAG. The set of nodes N corresponds to terminal of return chains inferred for e.

• Upd() is an inverted index mapping an expression e to a set of nodes M in the CDAG. The set of nodes N corresponds to nodes in the suffix of an update chain inferred for e.

• Clean() is an inverted index mapping a step e to a set nodes representing dangling chains for which inference for e failed.

The input of the chain inference algorithm is a query or update expression e, a schema d and a multiplicity value k. The system outputs a CDAG G rv representing used and return chains, a CDAG G e representing element chains and a G U representing update chains inferred form e, respectively. Note that used and returned chains are put together in the same CDAG.

Given a CDAG G, and node v belonging to G is a pair v = (a, h), where a is the type of the node and h is the level of the node in the G. The type of a node v is denoted by v.type while its height is denoted by v.level . In the examples, a node is also denoted by v [type,height] .

Chain Inference Algorithms

Algorithm 1: Procedure Child Input : Node-set M ⊆ V rv , φ, id i Output: Infer chains for child ∶∶ φ, side-effect on Ret(), Clean(), V rv and

E rv 1 foreach v ∈ M do 2 new_edge ← false 3 if v.level + 1 does not exceeds the chain space then 4 foreach a child-type of v.type do 5 if a satisfies φ then 6 if (a, v.level + 1) ∉ V rv then 7 V rv ← V rv ∪ {(a, v.level + 1)} 8 v ′ ← (a, v.level + 1) 9 E rv ← E rv ∪ (v, v ′ , i ) 10 new_edge ← true 11 Ret(i ) ← Ret(i ) ∪ {v ′ } 12 if !new_edge then 13 Clean(i ) ← Clean(i ) ∪ {v}
The first procedure we present is the one to infer chains for a navigational expression of the form x child ∶∶ φ. Procedure Child is the most important procedure of the system, since it is the one responsible of extending the CDAGs. Other operators presented later on are defined in terms of the procedure Child.

The procedure takes as input a set of nodes M ⊆ V rv , and tries to connect each v ∈ M with a child node v ′ , provided that v ′ satisfies the filtering condition φ. If such v ′ is not a node of the CDAG, then v ′ is built and added to the vertex-set of the CDAG (line 7). Then v ′ becomes a terminal node of the expression invoking the child axis. The step expression x child ∶∶ φ, for which the procedure infers chains, is referred by identifier i , which is also part of the input.

In line 3, we have a condition that ensures the termination of the inference. It says that a child navigation could be performed, provided that chains do not exceed a certain length. The maximal length of a chain we infer is nk, provided that that n is the number of types in d, and k is the multiplicity value in input. This is a sufficient condition to ensure that all k chains are correctly inferred. Note also that this avoids to keep an hash table recording the frequency of each tag while doing the chain inference, thus ensuring better performances.

Finally, in the cases that the child extension for the input node v produces no new edges, then v is added to the list of possibly dangling nodes to backtrack (Lines 12-13).

98CHAPTER 5. IMPLEMENTING THE CHAIN-BASED INDEPENDENCE ANALYSIS

This happens, for instance, if v exceeds the chain space, or none of the children on v satisfy φ. A dangling node is later removed, provided that itself or one of its descendants are terminals of used or return chains in the CDAG. This essentially implements the chain filtering defined in chain inference rules of Chapter 4. For the sake of conciseness, we do not model this operation here.

Let us illustrate the workflow of the procedure with an example. Consider chain inference for the query x book over DTD d 3 , with x ↦ bib. Inference for the step takes in input the following CDAG

G rv = ({ v [bib,0] }, ∅)
and a set M = { v [bib,0] }. The procedure first checks that the chain space would not be exceeded by attaching a child to v [bib,0] , which is trivially true since

v [bib,0] .level < nk
where we recall that n is the number of types in d 3 (in this case n = 8) and k is the multiplicity value (in this case k = 1).

At this point, because book is the only child-type of bib, and book satisfies φ=book, the node v [book,1] is added to V and connected to v [bib,0] . Below, we assume id(x child ∶∶ φ) = i . Node v [book,1] is now the terminal of chains inferred for the query. The resulting G rv and Ret() are the following.

bib book i G rv = (V rv , E rv ) Ret(i ) = { v [book,1] } V rv = { v [bib,0] , v [book,1] } E rv = { (v [bib,0] , v [book,1] , i ) }
The second procedure defined is the one implementing the self axis. Procedure Self receives as input a set of nodes M ⊆ V rv and only checks if the type-name of each input node satisfies condition φ. If this is true, the input node becomes a terminal for the expression. This is captured by line 3.

Algorithm 2: Procedure Self Input : Node-set M ⊆ V rv , φ, id i Output: Infer chains for self axis, side-effect on Ret()

1 foreach v ∈ M do 2 if v.type satisfies φ then 3 Ret(i ) ← Ret(i ) ∪ {v}

CHAIN INFERENCE WITH CDAGS

99

Notice that, if a node does not satisfy φ, then no operation is performed here. This is made on purpose, nodes that do not satisfy the axis test should be dealt with by the external procedures calling Self.

Consider chain inference for query y self ∶∶ * over DTD d 3 , provided that y is bound to the result of x book and x ↦ bib, computed as in the previous example. Chain inference for y self ∶∶ * results in the following CDAG. As before, we assume that id(x book) = i and id(y

self ∶∶ * )=i ′ . bib book i G rv = (V, E) Ret(i ) = { v [book,1] } V = { v [bib,0] , v [book,1] } Ret(i ′ ) = { v [book,1] } E = { (v [bib,0] , v [book,1] , i ) }
Note that procedure Self adds no edge in the CDAG, but it just affects Ret(). In this case because node v [book,1] trivially satisfies φ = * we have

Ret(i ′ ) = { v [book,1] }.
The algorithm implementing the descendant axis is described in the following. We just describe the algorithm implementing axis descendant since descendant-or-self is similar.

Descendant-Rec is a recursive procedure that computes chains for navigational steps of the form x descendant ∶∶ φ. The descendant axis is computed by invoking the Child procedure. Because of this, in the pseudo-code, we use a fresh query-id i v for labeling edges obtained from the iteration of the procedure, that started from node v. This is simply needed to correctly perform set operations and clean the graph form artificial edges.

At each iteration step, the procedure tries to extend of one level each input node v, with all of its children-types (line 5), by calling procedure Child. Before calling procedure Child, the abstract predicate satisfies uses schema information to check if some descendant-type of v.type do satisfy the filter φ (line 4). When this is not true, any operation can be skipped and node v can be added to the backtrack list for the expression.

If some descendant-type of v.type do satisfy the filter φ but the result of the childnavigation with * -filter is empty, it simply means that the node is at the frontier of the chain space. In this case the node is added to the list of possibly dangling nodes (line 14). If the result of the child navigation is non-empty (line 6), then we record that some new labeled-edges has been created (line 7). All nodes in Ret(i v ) are saved in the set M ′ (line 8), and the descendant procedure is iterated on M ′ (line 15). Also, all nodes in Ret(i v ) that satisfy φ, are set as terminal nodes for the expression, by means of the 100CHAPTER

IMPLEMENTING THE CHAIN-BASED INDEPENDENCE ANALYSIS

Algorithm 3: Procedure Descendant-Rec Input : Node-set M ⊆ V rv , φ, id i Output: Infer chains for descendant axis, side-effect on Ret(), Clean(), V rv and E rv

1 M ′ ← ∅ 2 foreach v ∈ M do 3 new_edge ← false 4 if some descendant-type of v.type satisfies φ then 5 Child({v}, * , i v ) 6 if Ret(i v ) ≠ ∅ then 7 new_edge ← true 8 M ′ ← M ′ ∪ Ret(i v ) 9 Self(Ret(i v ), φ, i ) 10 foreach (v, v ′ , i v ) ∈ E do 11 E ← E ∖ (v, v ′ , i v ) 12 E ← E ∪ (v, v ′ , i ) 13 if !new_edge then 14 Clean(i ) ← Clean(i ) ∪ {v} 15 Descendant-Rec(M ′ , φ, i )
Self procedure (line 9). At this point, all edges produced by the Child procedure with the input code i v are re-labeled as i edges. Notice that i v is needed to perform this operation.

We illustrate chain inference for step x descendant ∶∶ bold with x bound to text over the recursive DTD d 12 defined as text ← ( bold emph ) * bold ← emph?, String emph ← bold?, String

In this case k q = 1 and thus we want to infer 1-chains for the query, namely text.bold and text.emph.bold. To this aim, procedure Descendant-Rec is iterated three times. In the first iteration, the procedure takes as input the triplet ({v [text,0] }, φ, i ). A child navigation from the root is then performed. This gives the following intermediate result.

Below, i 0 is used to denote i v [text,0] . text bold emph i 0 i 0 Ret(i 0 ) = { v [bold,1] , v [emph,1] }

CHAIN INFERENCE WITH CDAGS 101

Now, because node v [bold,1] satisfies φ, it set as terminal node for the query, and we have Ret(i ) = { v [bold,1] }. Then edges labeled as i 0 are relabeled with i . We assume also that the terminal-index Ret(i 0 ) is set to empty. However, since this is not mandatory for the correctness of the analysis we do not add it in the pseudocode. The result of the first iteration is the following.

text bold emph i i Ret(i ) = { v [bold,1] }
In the second iteration, the procedure takes as input the triplet ({v

[bold,1] , v [emph,1] }, φ, i ).
The procedure iterates over the two input nodes. Let us consider first node v [emph,1] . Below, i 1 is used as a shorthand for i v [emph,1] . Then, node v [emph,1] is extended with its children types, in the following way.

i i i 1 i 1 Ret(i ) = { v [bold,1] } Ret(i 1 ) = { v [bold,2] , v [emph,2] } By following line 9, node v [bold,2] is set as terminal node since it satisfies test φ. Let us consider now node v [bold,1] . Below we assume i 2 = i v [bold,1]
. The child navigation creates an edge between v [bold,1] and v [bold,2] . As we already discussed this is not problematic because the chain text.bold.bold indeed matches q. Notice also that there is a group of chains ending at v [emph,2] which does not match the query. They will be removed in the next iteration.

i i i i i 2 i 2 Ret(i ) = { v [bold,1] , v [bold,2] } Ret(i 2 ) = { v [bold,2] , v [emph,2] }
The third recursive call of the procedure is the one that terminates the inference. In this iteration step, the input of the procedure is the triplet ({v [bold,2] , v [emph,2] }, φ, i ). It turns out that both input nodes have some descendant types that satisfy φ, but they cannot be further extended, without exceeding the chain space. The maximal length of chains to consider is 1 + nk = 3, because the number of types in the schema is 2 (plus the root) and k = 1.

Both nodes v [bold,2] and v [emph,2] are thus added to the backtracking list. Because node v [bold,2] is a terminal node for a query return chain it will not be removed. Because 102CHAPTER

IMPLEMENTING THE CHAIN-BASED INDEPENDENCE ANALYSIS

text bold emph bold i i i i Ret(i ) = { v [bold,1] , v [bold,2] } node v [emph,2]
is not a terminal node, and it is not shared by any other expression, it is removed, and also all of its incoming edges. The resulting CDAG is the following.

Procedure parent computes chains for backward steps of the form x parent ∶∶ φ. In analogy with the child and descendant axes, this procedure is also used to compute the ancestor axis. The algorithm backtracks on each parent v ′ of an input node v, when the two nodes are connected by an edge i ′ belonging to the set I of ids that can be backtracked (which is part of the input). If the procedure is called to infer chains for a step e = x parent ∶∶ φ then I is I = vr + (e). If the procedure is iterated to infer chains for an ancestor then I is defined wrt the ancestor step, as discussed next.

To illustrate, consider chain inference over DTD d 3 and the following query for x 0 in x book for x 1 in x 0 author, x 0 publisher for x 2 in x 1 name for x 3 in x 2 parent ∶∶ * for x 4 in x 3 parent ∶∶ book return x 4 where x is bound to bib.

Below we assume the following coding id( book) = i 0 and id(x 0 author) = i 1 1 and id(x 0 publisher) = i 2 1 and for the remaining steps id(x i step i ) = i (i+1) . Chain inference for the first three lines of the query gives the following CDAG. bib book author publisher name

i 0 i 1 1 i 2 i 2 1 i 2 Ret(i 0 ) = { v [book,1] } Ret(i 1 1 ) = { v [author,2] } Ret(i 2 1 ) = { v [publisher,2] } Ret(i 2 ) = { v [name,3] } Processing of step x 2 parent ∶∶ * is now illustrated. Recall that id(x 2 parent ∶∶ * )=i 3 .
Algorithm 4: Procedure Parent Input : Node-set M ⊆ V rv , φ, id i , id set I Output: Infer chains for parent axis, side-effect on Ret(), Clean()

1 foreach v ∈ M do 2 some_parent ← false 3 foreach (v ′ , v, i ′ ) ∈ E do 4 if v ′ .type satisfies φ then 5 if i ′ ∈ I then 6 Ret(i ) ← Ret(i ) ∪ {v ′ } 7 some_parent ← true 8 if !some_parent then 9 Clean(i ) ← Clean(i ) ∪ {v}
The procedure iterates over chains bound to x 2 , thus over node v [name,3] . Because i 2 ∈ vr + (i 3 ), the procedure backtracks to the edges labeled as i 2 , namely

(v [author,2] , v [name,3] , i 2 ) and (v [publisher,2] , v [name,3] , i 2 ). Let us consider first the edge (v [author,2] , v [name,3] , i 2 ). Because v [author,2] satisfies φ, it is set as terminal node for the parent navigation, so Ret(i 3 ) = { v [author,2] }. The second iteration step on edge (v [publisher,2] , v [name,3] , i 2 ) is similar. Processing of step x 3 parent∶∶book is now illustrated. Recall that id(x 3 parent∶∶book)=i 4 .
The procedures iterates over chains bound to x 2 , thus v [author,2] and v [publisher,2] . It backtracks on both edges labeled as i 1 1 and i 2 1 , because i 1 1 , i 2 1 ∈ vr + (i 3 ). Let us consider first edge (v [book,1] , v [author,2] , i 1 1 ). Because v [book,1] satisfies φ = book, it is set as terminal node for the step, so Ret(i 4 ) = { v [book,1] }. The second iteration step on edge

(v [book,1] , v [publisher,2] , i 2 1
) is similar, and the resulting CDAG is the following. bib book author publisher name

i 0 i 1 1 i 2 i 2 1 i 2 Ret(i 0 ) = { v [book,1] } Ret(i 1 1 ) = { v [author,2] } Ret(i 2 1 ) = { v [publisher,2] } Ret(i 2 ) = { v [name,3] } Ret(i 3 ) = { v [author,2] , v [publisher,2] } Ret(i 4 ) = { v [book,1] }
Note that the procedure does not add new edges to the CDAG but it just affects Ret().

Algorithm 4 is simple, sound and ensure a quite precise analysis at once. It is worth outlining that, in some rare cases, the algorithms can infer unneeded chains, that is a 104CHAPTER

IMPLEMENTING THE CHAIN-BASED INDEPENDENCE ANALYSIS

chain that would not be inferred by the type system presented in Chapter 4. This may happen for expressions that navigate twice the same part of the schema, as illustrated by the following example over the DTD d 3 .

let x 0 ∶= x name let x 1 ∶= x 0 parent ∶∶ * let x 2 ∶= x 1 parent ∶∶ * let x 3 ∶= x 2 publisher let x 4 ∶= x 3 name return x 4 parent ∶∶ *
where we assume x is bound to bib.

Below we assume id(x name) = i 0 and id(x i step) = i i+1 . In this case, the last backward step of the query x 4 parent ∶∶ * produces an unneeded chain. To see this, consider the CDAG obtained by inference over all precedent steps. bib book author publisher name

i 0 i 0 i 0 i 0 , i 3 i 0 , i 4 Ret(i 0 ) = { v [name,3] } Ret(i 1 ) = { v [author,2] , v [publisher,2] } Ret(i 2 ) = { v [book,1] } Ret(i 3 ) = { v [publisher,2] } Ret(i 4 ) = { v [name,3] }
When processing step x 4 parent ∶∶ * , the procedures iterates over chains bound to x 4 , thus v [name,3] . It backtracks on both edges labeled as i 0 and i 4 , because i 0 , i 4 ∈ vr + (i 5 ) and i 5 is the id of x 4 parent ∶∶ * . At this point the procedures set as terminal nodes both v [author,2] and v [publisher,2] , while it should backtrack toly on v [publisher,2] .

In general, for a pair of codes i 1 , i 2 such that i 1 ∈ vr + (i 2 ), by running Procedure 4 it is possible to visit edges labeled as i 1 before those labeled as i 2 , and this can lead to infer chains as false negatives. However, it is indeed by avoiding to follow the transitive closure of relation vr () in the proper order, that we can compute backward navigations in polynomial time.

The way backward navigations are used in the above example resembles that of a conditional expression. They allow to verify that node elements labeled with book do have descendants labeled with name and, if this is the case, descendant nodes of book ones labeled with publisher are further navigated. Notice that this is not the usual way of expressing such a property in an XQuery program. The above expression could be for instance reformulated by using a conditional expression such as if (x name) then x publisher name parent ∶∶ * else ()

CHAIN INFERENCE WITH CDAGS 105

Algorithm 5: Procedure Ancestor-Rec Input : Node-set M ⊆ V rv , node-set S ⊆ V rv , φ, id i Output: Infer chains for ancestor axis, side-effect on Ret(), Clean()

1 M ′ ← ∅ 2 foreach v ∈ M do 3 if some ancestor-type of v.type satisfies φ then 4 Parent({ v }, * , i v , vr + (i )) 5 S ← S ∪ Ret(i v ) 6 Self(Ret(i v ), φ, i ) 7 M ′ ← M ′ ∪ Ret(i v ) 8 else 9 Clean(i ) ← Clean(i ) ∪ {v} 10 Ancestor-Rec((M ′ ∖S), S, φ, i )
For this expression, chain inference over the DTD d 3 is sound and complete wrt the inference system presented in Chapter 4, because edges inferred for the conditional query x name would not be mixed with edges inferred for the rest of the expression.

As illustrated, cases of incompleteness exist but are quite rare in practice and may have an equivalent formulation for which the analysis is complete. The precision of our algorithm have been tested over the wide XMark/XPathMark benchmarks as shown in Chapter 6, without incurring in a situation analogous to the one presented here, and by showing high improvements wrt the state-of-the-art method.

Algorithms implementing ancestor axes are presented in the following. We just describe the algorithm implementing axis ancestor since the case for ancestor-or-self is similar. Procedure Ancestor-Rec computes chains for steps of the form x ancestor ∶∶ φ.

The procedure performs a bottom-up visit of the CDAG, by simply iterating the procedure for the parent axis (Line 4). The set of codes that can be visited by procedure Parent is set as vr + (i ), as discussed before. The parents of a node v ∈ M , that are recorded in Ret(i v ), are then filtered by means of procedure Self to check if the satisfy the ancestor navigation. Furthermore, the procedure records a set of visited nodes S, so as to perform only once the parent navigation to each node of the G. This optimization makes the procedure running in linear time in the size of the CDAG. A node that has no parent satisfying φ represent a dangling chain that may be removed.

106CHAPTER 5. IMPLEMENTING THE CHAIN-BASED INDEPENDENCE ANALYSIS

We illustrate the procedure with an example. Consider the DTD d 11 defined as follows bib ← book * book ← title, author, publisher author, publisher ← name name ← first, last, String title, first, last ← String and the query sequence q = for x 1 in x author for y 1 in y author for x 2 in x 1 f irst , for y 2 in y 1 name return x 2 text() return y 2 ancestor ∶∶ * with both x and y bound to bib.

Below, we assume that id(x author) = i 11 , id(x 1 f irst) = i 12 , id(x 2 text()) = i 13 , id(y author) = i 21 , id(y 1 name) = i 22 and id(y 2 ancestor ∶∶ book) = i 23 . Provided that both x and y are bound to bib, chain inference for q, yields the following CDAG.

Ret(i 11 ) = { v [author,2] } Ret(i 12 ) = { v [first,4] } Ret(i 13 ) = { v [String,4] } Ret(i 21 ) = { v [publisher,2] } Ret(i 22 ) = { v [name,3] }
Now, inferring chains for y 2 ancestor ∶∶ * consist of visiting all ancestors of nodes of v [name,3] on G rv with a label in vr + (i 22 ), that means i 21 and i 22 . The set of terminal nodes for y 2 ancestor ∶∶ * is thus

Ret(i 22 ) = { v [publisher,2] , v [book,1] , v [bib,0] }.
Notice that thanks to the edge labeling we avoid to backtrack also to node v [author,2] .

Procedure Following-Sibling computes chains for the preceding-sibling navigational axis, by means of the Parent and Child procedures. Notice that the other procedure for sibling axis Preceding-Sibling just differ from this one by the test made in Line 5.

CHAIN INFERENCE WITH CDAGS 107

Algorithm 6: Procedure Following-Sibling Input : Node set M ⊆ V rv , φ, id i Output: Infer chains for preceding-sibling, following-sibling axes, side-effect on Ret(), Clean(), V and E

1 foreach v ∈ M do 2 new_sibling ← false 3 Parent({v}, * , i v , vr + (i )) 4 foreach v ′ ∈ Ret(i v ) do 5
foreach a following-sibling type of v.type that satisfies φ do 6

Child({v}, a, i )

7 new_sibling ← true 8 if !new_sibling then 9 Clean(i ) ← Clean(i ) ∪ {v}
To illustrate the procedure, consider chain inference for the following query q over DTD d 3 with x ↦ bib. q = for x 1 in x 0 title for x 2 in x 1 following-sibling ∶∶ author for x 3 in x 2 parent ∶∶ * return x 3 following-sibling ∶∶ book Below, we assume that id(x i step)=i i+1 . Chain inference for q gives the following CDAG. bib book title author

i 1 i 4 i 1 i 2 Ret(i 1 ) = { v [title,2] } Ret(i 2 ) = { v [author,2] } Ret(i 3 ) = { v [book,1] } Ret(i 4 ) = { v [book,1] }
Chain inference for step x 2 following-sibling ∶∶ author is performed by backtracking on edges labeled as i 1 ∈ vr + (i 3 ) created by the previous descendant navigation, and then by adding node v [author,2] in the CDAG. After this, the parent navigation further backtracks to node v [book,1] . Chain inference for step x 3 following-sibling ∶∶ book is performed again by backtracking on edges labeled with i 1 ∈ vr + (i 4 ).

Notice that the backward navigation in Line 3 makes this procedure inherently sound but not complete. Also, in the case where the schema enforces that a type a is both a following-sibling and a preceding-sibling of a type b (e.g., r ← a, b+, a?) we have that the result of chain inference for both the sibling axis is the same, if we start from some CDAG node labeled with b. Again this approximation is sound, but it may be not complete, because expressions like doc b following-sibling ∶∶ a and 108CHAPTER

IMPLEMENTING THE CHAIN-BASED INDEPENDENCE ANALYSIS

Algorithm 7: Procedure Infer-Query Input : Query q, G rv and G e Output: Infer chains for q, side effect on G rv , G e and Ret() 1 i ← id(q) 2 switch (q) do 3 case q = x axis ∶∶ φ 4 call procedure computing x axis ∶∶ φ 5 case q = q 1 , q 2 or q = if (q 0 ) then q 1 else q 2 6 foreach j ≤ 2 do 7 Infer-Query(q j )

8 i j ← id(q j ) 9 Ret(i ) ← Ret(i 1 ) ∪ Ret(i 2 ) 10 case q = for let x in ∶= q 1 return q 2 11 Infer-Query(q 1 ) 12 Infer-Query(q 2 ) 13 Ret(i ) ← Ret(i 2 ) 14 case q = "txt" 15 Build(String,_,i ) 16 case q = <a>q ′ < a> 17 Infer-Query(q ′ ) 18 i ′ ← id(q ′ ) 19 Build(a, Ret(i ′ ), i ) 20 Clean-Graph(i )
delete doc a preceding-sibling ∶∶ b are deemed dependent, while they are not. However, this does not depend on how chain inference is implemented, but on the fact that chains abstract away from structural constraints concerning the horizontal order of data.

Procedure Infer-Query infers chains for whole query expressions. The procedure does essentially two things. It recursively infer chains for each subexpression of the query, and it computes used, return, and element chains for the whole query.

The base case of procedure Infer-Query consist of calling the proper axis navigation for a step of the form x axis ∶∶ φ. Recall that for parent axis, the procedure also needs to pass vr + (x) as input. Return chains for q are set as return chains for the proper subexpression of q. Note that we do not need any particular extra structure for used chains of q, since they result to be marked as return chains of each q ′ subexpression of q.

We assume that in the first call of the procedure all CDAGs G rv and G e are initialized, and the root node is added in G rv . Finally, after chain inference for each subexpression Algorithm 8: Procedure Build Input : Type a ∈ Σ S , node-set M ⊆ V e , expression id i Output: Infer element chains for q, side effect on V e and E e 1 v a ← (a, 0)

2 V e ← V e ∪ { v [a,0] } 3 foreach v ∈ M do 4 v ′ ← Copy(v, 1, i ) 5 E e ← E e ∪ (v a , v ′ , i ) 6 if v ∈ V rv then 7 EltRet(i ) ← EltRet(i ) ∪ { v ′ } 8 Ret(i ) ← Ret(i ) ∪ { v a }
the CDAGs is done, dangling chains are removed by procedure Clean-Graph. This last operation correspond to the chain filtering made by the rule for iteration presented in the type system of Chapter 4.

Element chains are inferred by procedure Build. This procedure extends the CDAG of element chains G e . The procedure is called either for string query "txt", or for an expression of the form <a>q< a>. Because we assume that constructed elements are never navigated (see Chapter 2), element chains in the G e are simply stored as trees. This comports no relevant overhead.

The procedure first creates a fresh node representing the root of the constructed structure. Then, all nodes in M are copied (Line 4) and connected with v a (Line 5).

Function Copy(v), despite not being explicitly modeled here, does three things. First, it distinguishes if the input node belongs to G rv or to G e . In the first case, it simply copies the node. In the second case, it copies the node and all the structure below. Second, it sets as 1 the height of the copied nodes, and accordingly of all copied descendants. Third, it marks edges of the copied structure with i .

Finally, according to the rule for element construction presented in Chapter 4, to record the fact that that a node v ′ copy of v should be meant as a whole subtree, we record v ′ in EltRet(i ). This has to be done only if the original node v belongs to the CDAG G rv . 110CHAPTER

IMPLEMENTING THE CHAIN-BASED INDEPENDENCE ANALYSIS

Algorithm 9: Procedure Infer-Update Input : Update u, CDAG G U Output: Infer chains for u, side effect on G U 1 i ← id(u) 2 switch (u) do 3 case u = delete q 0 4 Infer-Query(q 0 )

5 i 0 ← id(q 0 ) 6 G U ← G rv 7 Upd(i ) ← Upd(i 0 ) 8 DescUpd(i ) ← Upd(i 0 ) 9 case u = rename q 0 as a Infer-Query(q 0 ) i 0 ← id(q 0 ) M ′ ← Ret(i 0 ) Sibling(Ret(i 0 ), a, i 0 ) Ret(i 0 ) ← Ret(i 0 ) ∪ M ′ G U ← G rv Upd(i ) ← Upd(i 0 ) DescUpd(i ) ← Upd(i 0 )
case u = insert q pos q 0 or u = replace q 0 with q Infer-Query(q) Infer-Query(q 0 ) i 0 ← id(q 0 ) i 1 ← id(q) G U ← G rv if pos ∈ into (as first as last)? then

Build-Update(Ret(i 1 ), Ret(i 0 ), i 0 , G e ) else M ′ ← Ret(i 0 ) Ret(i 0 ) ← ∅ I ← vr + (ret(q 0 )) Parent(M ′ , * , i 0 , I) Build-Update(Ret(i 0 ), Ret(e 1 ), i 0 , G e ) Upd(i ) ← Upd(i 0 ) if u is a replace then DescUpd(i ) ← Upd(i 0 )
Procedure Infer-Update infers chains from an update expression u. As updates are defined in terms of queries, this mainly consists of calling procedure Infer-Query for the update subexpressions.

For delete expressions, update chain inference is the same as query chain inference for the target expression q 0 . The update CDAG G U is set as the query CDAG G rv . Here, CDAG nodes in the prefix c ′ of an update chain of the form c ∶ c ′ are recorded by the inverted index Upd(). Furthermore it makes use of another index DescUpd() thats records the fact that the whole subtrees rooted at Ret(i 0 ) has to be considered as impacted by the update. This permits to avoid to infer all chains corresponding to descendants of nodes in Ret(i 0 ).

Chain inference is similar for rename expressions, with the difference that chains capturing renamed node are inferred by means of a further navigation on the siblings of the return nodes for q 0 . Procedure Sibling performs a following-sibling and a precedingsibling navigation on the terminal nodes of q 0 . Chain inference for insert and replace expressions are similar. They both combine chains inferred fro the source and for the target expression. The case where an insert update uses either position after or before is the same as for the replace command. In both cases it is necessary to perform a parent step, on the result locations of q 0 . In order to allow a backward navigation, the set of edges that can be visited has to be computed. This is done by first retrieving return subexpressions of q 0 by means of function ret() and vr + (), as already outlined.

Chains recording the structure of inserted subtrees are inferred by procedure Build-Update. The procedure puts an edge between terminal nodes of the target and the source query expressions. Nodes belonging to the source query are copied, setting also the level and the label of edges.

Algorithm 10: Procedure Build-Update Input : Target node-set T ⊆ V U , source node-set S ⊆ V e , expression id i , CDAG G e Output: Infer element chains for q, side effect on V U and

E U 1 foreach v ∈ T do 2 foreach v ′ ∈ S do 3 v ′′ ← Copy(v ′ , v.level + 1, i ) 4 V U ← V U ∪ { v ′′ } 5 E U ← E U ∪ (v ′ , v ′′ , i ) 112CHAPTER 5.

IMPLEMENTING THE CHAIN-BASED INDEPENDENCE ANALYSIS

Algorithm 11: Function CheckIndependence Input : CDAG for query G rv and CDAG for update G U , node sets M r , M v ⊆ V rv and M U , M ′ U ⊆ V U Output: Check for a common chain between two graphs v) and i ′ ∈ vr * (i ) and j ′ ∈ vr * (j)) or h = 0 then 4

1 foreach h = 0.. min(h Grv , h G U ) do 2 foreach (v, v ′ , i ) ∈ E rv and (v, v ′ , j) ∈ E U do 3 if ((i ′ , j ′ ) ∈ I (v ′′ ,
I (v,v ′ ) ← I (v,v ′ ) ∪ { (i, j) } 5 if v ∈ M r ∪ M v and v ∈ M U then 6 return false 7 if v ∈ M r then 8 if a descendant of v ∈ G U also belongs to M U then 9 return false 10 if v ∈ M U then 11 if a descendant of v ∈ G rv also belongs to M r ∪ M v (return-element) then 12 return false 13 return true
The last algorithm we present, is the one checking if query and update CDAGs have a conflicting chain. The procedure takes as input the set of terminal nodes denoting chains for used and return query chains, as well as for update nodes and for update and all descendant nodes. In particular, M r ⊆ V rv is set of nodes that are terminal of query return chains, M v ⊆ V rv is set of nodes that are terminal of query used chains, M U ⊆ V U is set of nodes that are in the suffix of an update chain and M ′ U ⊆ V U is set of nodes that are in the suffix of an update chain and whose whole subtree is impacted by the update.

The procedure iterates over all the levels of the CDAGs and inductively computes a product graph, where edges between nodes are sets of pairs of ids of query and update expressions that simulate the same chain.

At level h, a pair of codes (i, j) is added on the edge connecting a node v with a node v ′ (Line 4) only if it is the continuation of some chains computed at level h -1 (Line 3). Formally, this happens when for some node v ′′ parent of v there is a pair of codes (i ′ , j ′ ) such that i ′ ∈ vr * (i ) and j ′ ∈ vr * (j). Here vr * (i ) denotes the reflexive and transitive closure of vr (i ). This test is trivial for h = 0 since the root has no incoming edge. The set I (v,v ′ ) denotes all pair of edges between v and v ′ in the product graph.

In order to detect conflicts between query and update chains, and hence to implement Definition 4.4.1, we perform the following three tests. If we reached a node v such that v is both the terminal node of a used or return chain in G rv , and an update node of G U , then we raise a dependence. Otherwise, if v is only the terminal of a return chain, we visit G U to search for a descendant of v that also belongs to M U . If this node exists, we raise a dependence. Otherwise, if v is either an update node of M U or an update node with all descendants of M ′ U then we visit G rv and we search for a descendant of v that also belongs to M r ∪ M v . Of course, this is done by properly following edges corresponding to related subexpressions.

To illustrate, consider DTD d 11 and the following query and updates. q = for x ′ in x author , for y ′ in y publisher return x ′ f irst return y ′ last

u 1 = delete z name u 2 = for z ′ in z publisher return delete z ′ f irst
We run Algorithm 11 and show the result of the product graph for the pairs q-u 1 and q-u 2 , respectively. Below, we assume that x, y and z are all bound to bib. Furthermore, id(x author) = x 1 , id(x ′ f irst) = x 2 , id(y publisher) = y 1 , id(y ′ last) = y 2 , id(z name) = z 1 , id(z publisher) = z 2 and id(z ′ f irst) = z 3 .

The product graph for q-u 1 is the following.

} × {z 1 } {x 1 } × {z 1 } {x 2 } × {z 1 } {y 1 } × {z 1 } {y 2 } × {z 1 }
In this case there are two conflicting chains because the query and the update access and impacts nodes labeled with name. After node v [name,3] ∈ G U has been recognized as a node in the prefix of an update chain, the procedure start searching for a descendant of node v [name,3] ∈ G rv that is also the terminal of a used or return chain, by following ids x 2 , y 2 . The procedure then reaches both v [first,4] and v [last,4] and hence a conflict is correctly raised by the procedure. 114CHAPTER

IMPLEMENTING THE CHAIN-BASED INDEPENDENCE ANALYSIS

The product graph for q-u 2 is the following.

{x 1 , y 1 } × {z 2 } {y 1 } × {z 2 } {y 2 } × {z 3 } ∅ × ∅
In this case there is no conflicting chain between the two expressions. Notice first that chains for the left subexpression of sequence q does not simulate any chain inferred for u. This is reflected by the fact that in the product graph there is no edge with id x 1 after node v [book,1] . Similarly, also the right subexpression of sequence q does not simulated after node v [name,3] in the CDAG, because in the product graph there is no edge connecting v [name,3] with node v [first,4] .

Complexity of Chain Inference with CDAGs

In this section we present some results on the complexity of algorithms defined in the previous section. We mainly distinguish between recursive and non-recursive schemas, and outline how complexity can be lowered for some interesting classes of queries and updates.

Theorem 5.4.1. Let d be a non recursive DTD with n type definitions, and e a query or update expression of size m. By using Algorithms 1-10 of Section 5.3 chain inference can be done in O(mn 3 ) space and O(mn 5 ) time.

Proof. When d is not recursive, the k value stop being determinant for the analysis since no label repeats twice in any schema chain. We first consider the case where e is not an insert or replace update. By Lemma 5.2.1, we know that the worst-case size of the CDAG inferred for e is O(n 3 ). This, together with the fact that each edge can be labeled with a code, and that the number of codes is upper bounded by the size of the query entails that the CDAG needs at most O(mn 3 ) space. Moreover, by using Algorithms 1-11 of Section 5.3 Chain inference for any navigational step, can be computed in the worst case with a traversal of the CDAG, hence in O(n 3 ), for each input nodes. The number of input nodes is upper bounded by the number of nodes in the CDAG. By Lemma 5.2.1, there are at most O(n 2 ) nodes in the CDAG. For the whole expression it follows that inference time is in O(mn 5 ). If e is an insert or replace update, then by

COMPLEXITY OF CHAIN INFERENCE WITH CDAGS

115 making a cartesian product of chains for the target and source update expressions with Procedure build update, we have an overhead which is at most quadratic in the number or terminal nodes of each expression. However, since we assumed that updates preserve the schema, this cannot result in more than O(n 2 ) pairs of CDAG nodes corresponding to types satisfying the insert or replace expression. This overhead does not affect the asymptotical complexity.

Corollary 5.4.2. Let d be a non recursive DTD with n type definitions, and e a query or update expression of size m. By using Algorithms 1-10 of Section 5.3, the followings holds.

1. If e does not use step filter node() then chain inference can be done in O(mn 4 ) time;

2. If e does not use recursive downward an backward axis then chain inference can be done in O(mn 2 ) time;

3. If e does not use both step filter node() and recursive axis then chain inference can be done in O(mn);

4. If each navigational step of e returns a fixed number of chains, then chain inference can be done in O(mn 3 ).

Proof. Analogous to the proof of Theorem 5.4.1.

The above restriction are often met in practice, and in particular by expressions used in our testbed (when the recursive component of the XMark schema is not visited at all by the expression).

Theorem 5.4.3. Let d be a recursive DTD with n + 1 type definitions, and e a query or update expression of size m. By using Algorithms 1-10 of Section 5.3 chain inference can be done in in O(mkn 3 ) space and O(mk 2 n 5 ) time.

Proof. We first consider the case where e is not an insert or replace update. By Lemma 5.2.2 we know that the worst-case size of the CDAG inferred for k-chains of e is O(kn 3 ). Because each edge can be labeled with any code, the worst-case space occupancy for the CDAG is in O(mkn 3 ). By using Algorithms 1-10 of Section 5.3, chain inference for any navigational step can be computed in the worst case with a traversal of the CDAG, hence in O(kn 3 ), for each input nodes. The number of input nodes is upper bounded by the number of nodes in the CDAG. By Lemma 5.2.1, there are at most O(kn 2 ) nodes in the CDAG. For the whole expression then inference time is in O(mk 2 n 5 ). If e is an insert or replace update, Procedure build update introduce an overhead which is quadratic in the the size of the number or terminal nodes of each expression. At most O(kn 2 ) nodes are inferred for each expression. However, since we assumed that updates preserve the schema, this cannot result in more than O(mkn 3 ) pairs of CDAG nodes corresponding to types satisfying the insert or replace expression. Hence asymptotic complexity is not affected by this operation.

116CHAPTER 5. IMPLEMENTING THE CHAIN-BASED INDEPENDENCE ANALYSIS

Further restrictions on the the expression would lower again upper bounds.

Corollary 5.4.4. Let d be a recursive DTD with n + 1 type definitions, and e a query or update expression of size m. By using Algorithms 1-10 of Section 5.3, the followings holds.

1. If e does not use step filter node() then chain inference can be done in O(mk 2 n 4 ) time;

2. If e does not use recursive downward an backward axis then chain inference can be done in O(mkn 3 ) time;

3. If e does not use both step filter node() and recursive axis then chain inference can be done in O(mkn 2 ) time;

4. If each navigational step of e returns a fixed number of chains, then chain inference can be done in O(mkn 3 ) time.

Proof. Analogous to the proof of Theorem 5.4.1.

As suggested by the statement complexity of chain inference can be lowered in many cases of practical relevance. In particular, if we assume that during chain inference each XPath step can have a fixed number of CDAG nodes as input, time complexity goes down to O(mkn 3 ). The size of the input is likely to be close to 1 for most XPath steps used in practice. This holds in particular for XMark and XPathMark expressions. Another fact observable from such expressions is that they employ a small number of recursive navigations, thus further lowering the complexity.

Theorem 5.4.5. Checking independence between two CDAGs inferred for a query q and an update u over a DTD d, can be done by Function 11 in O(km 2 n 3 ) time, where k = k q + k u and m = min{ q , u }.

Proof. Function 11 iterates on the levels of the CDAGs. Each CDAG has at most nk levels, and there are at most n 2 edges between the two levels. Moreover, each edge is labeled with at most m codes. Each code for an edge in the query CDAG may be paired with each code for the same edge in the update CDAG, and this can be done in O(m 2 ) per edge. Putting everything together we have O(km 2 n 3 ).

Conclusions

In this section we provided algorithms for efficiently implementing our independence analysis based on schema chains. We showed that chain inference is challenging from the computational point of view, because schema constraints can lead to infer an exponential number of chains. To overcome this limitation, we proposed a conservative implementation of the chain analysis that runs in polynomial space and time. In the next chapter experiments will show that the proposed CDAG algorithm is highly precise.

Chapter 6

Experiments

In this chapter we report on experiments made for validating the efficiency of the chainbased independence analysis. We describe the benchmarks we used as well as results obtained witnessing precision and efficiency of our technique.

Benchmarks and Experimental Settings

Our technique has been fully implemented in Java 6. We performed extensive experiments by using our Java implementation, in order to measure i) efficiency, ii) precision and iii) scalability of our static analysis. We used two different benchmarks: a first one based on XMark /XPathMark, and a second one, dubbed R-benchmark, we specifically designed to measure scalability, that are now described.

Independence benchmark We used a superset of the independence benchmark adopted by Benedikt and Cheney in [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF]. Our benchmark is composed of a set of 36 queries v i and a set of 31 updates u i . A query belongs to either the XMark query set q 1 -q 20 [SWK + 02], or to the XPathMark query set A1-A8/B1-B8 [START_REF] Franceschet | XPathMark -An XPath benchmark for XMark generated data[END_REF]. Queries in the group Ai of XPathMark only use downward axes, whereas Bi queries use upward and horizontal axes as well. Concerning updates, a first set corresponds to those used in [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF]. These are derived from the XPathMark query set A1-A8/B1-B8 and are of the form UAi=delete Ai or UBi=delete Bi.

It is worth observing that not all of the delete-updates preserve the schema, but as already seen (Section 4) this is safe because if a chain does not belong to the schema then it is not inferred for these updates. Instead, remaining updates are defined so as to preserve the schema. We added a set of 15 updates formed by insert expressions U I1-U I5, rename expressions U N 1-U N 5, and replace expressions U P 1-U P 5. These updates have been defined so as to cover all different types of nodes in XMark documents, and in particular those parts defined by mutually recursive types. It is worth remarking that, even if not all of the delete-updates of the testbed preserve the schema (see UA4, UA5, UA6, UA7, UA8, UB1, UB5, UB6, UB7, UB8 ), the correctness of our technique is still 117 118 CHAPTER 6. EXPERIMENTS ensured, since no new chain is created by these expressions. As outlined before, our technique is just unaware of new chains built by breaking schema constraints. In light of this, insert, rename and replace update expressions have been chosen in order to preserve document validity.

Before performing the tests, XMark and XPathMark expressions have been opportunely rewritten into expressions belonging to the XQuery fragment we consider (Section 3), as done in [START_REF] Benedikt | Destabilizers and independence of XML updates[END_REF]. The rewriting essentially consists of: putting predicate conditions in disjunctive form, removing attribute use, and extracting paths from functions calls and arithmetic expressions. Clearly, the rewriting is such that a query and an update are independent if the rewritten query and update are. Updates extending XMark/XPathMark benchmark are reported in Table 6.2. This benchmark has been used in order to measure precision and efficiency of our technique.

R-benchmark

This benchmark is formed by schemas and expressions with a massive use of recursion. The benchmark is constituted of five saturated-recursive schemas with 1, 3, 5, 10 and 20 recursive types, denoted by d1, d3, d5, d10, and d20 respectively. In general, schema dn is defined as

a 0 ← (a 1 . . . a n ) * a 1 ← (a 1 . . . a n ) * ⋮ a n ← (a 1 . . . a n ) *
The benchmark also features a series of XPath expressions consisting on 1, 5 and 10 consecutive descendant-or-self ∶∶ node() steps, denoted by e1, e5 and e10 respectively. In general, expression en is defined as descendant-or-self ∶∶ node() 1 . . . descendant-or-self ∶∶ node() n This benchmark is designed for understanding the impact of recursion in the performances of our analysis, and draw conclusions on its scalability.

Configuration

We ran all tests on a desktop 4-core Intel Xeon 2.13 GHz machine with 8 GB RAM (the JVM was given 2 GB) running Linux. To avoid perturbations coming from system activity, we ran each experiment ten times, discarded the best and the worst performance, and computed the average of the remaining times.

EXPERIMENTAL RESULTS

Experimental Results

Precision on XMark

Independence (Definition 2.5.2) is undecidable in general [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF], so for the purpose of measuring precision, for each update u i we manually determined independent pairs (u i , q j ), and reported in Table 6.2 of the appendix. (note that for most pairs in the considered testbed independence is evident, so this process is much less time consuming than one may guess). We then express precision as the percentage of independent pairs that are deemed independent by our static analysis too. To estimate improvements wrt the alternative schema-based technique [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF] we computed the same percentages for that technique by using the public tool [START_REF] Cheney | XQuery Update analysis tools version 0.1[END_REF].

Results are reported in Figure 6.2.b. Our chain-based analysis turned out to be precise. Percentages goes from 72% to 100%, while the average precision is 96%. Also, Figure 6.2.b shows that the analysis proposed in [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF] (that has an average detection of 49%) is always outperformed in terms of precision by our static analysis, and in some cases improvements are huge. This happens in particular for updates UB1, UB5, UB6, UB8 (employing backward and horizontal axes). For these updates, the over-approximation made by type rules in [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF] entails a high number of false negatives. Our chain based inference instead is so precise to avoid most of these false-negatives. In general, improvements in terms of precision go from 8% (UN4) to 96% (UP1), and the average gain is 46%. In particular, precision of our analysis remains high in the presence of views using upward and horizontal axes (XPathMark queries in the group B). These queries are likely to be among the most expensive ones to re-evaluate after document updating. As expected, we found that in some cases independence is not captured by our static analysis. This happens for pairs that make use of particular node position, identity or value conditions whose semantics is not precisely captured by our static analysis. Also, our system is not able to understand that the renaming performed by UN4 does not change any document tag, thus excluding independence in many cases (the same holds for [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF]).

Inference time on XMark

We measured the time needed by the static analysis to detect independence of each update wrt the whole set of XMark queries. The XMark schema is particularly suitable for testing the performances of our technique since the type dependency graph of this schema contains 5 mutually recursive types that form two cliques of size 2 and 3 respectively. We recall that the execution cost depends on the three parameters d , e and k. In this testbed we have d = 76, and e ≤ 20, while multiplicity values k range from 2 to 6. As observed in Section 5.4, in many cases chain inference can be substantially lowered. Time values include the time for CDAGs inference and comparison, for each pair of expressions. Results are collected in Figure 6.2. It shows that the analysis is quite fast: in the worst case the analysis is performed in less than 40 ms for the whole set of queries, while the average cost is around 15 ms. According to complexity results of Section 5.4, inference time is influenced by i) the k values needed by a query-update pair and ii) the number of recursive types of the schema effectively unfolded. We see small changes in inference time values according to the k value (e.g., the pair UB1-UB2). Yet, two expressions having the same k value may have different time costs for chain inference, depending on the effective number of recursive types unfolded by the analysis (e.g., the pair UI3-UP3).

Running times obtained from the available OCaml implementation [START_REF] Cheney | XQuery Update analysis tools version 0.1[END_REF] of the analysis presented in [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF] are rather close to ours: the average time for analyzing an update vs all of the queries is around 10 ms. It is worth observing, that inference time for [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF] has no sensible oscillations, while in our case inference time depends on k, hence on the query and update expressions. The analysis presented in [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF] has worst case time complexity O(( d 2 + q ) 2 + u ), and thus is expected to be faster than our analysis in the presence of recursive schemas. Nevertheless, as shown shortly, our running times remain low enough to ensure high time savings in queries maintenance, even when queries are defined on relatively small documents.

Benefits of the Independence Analysis

Besides experimenting on our prototype, we verified that the precision and the efficiency of our method directly translate in time-savings when our static analysis is used to optimize view maintenance. Along the line of [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF], we simulated a view-maintenance scenario, where views are expressed as query, and on updates views are simply refreshed. We measured time savings obtained by avoiding the refreshing of views (queries) which our analysis deem as independent of an update.

We used three XQuery engines: Saxon 9.2EE, BaseX 7.0.1 and QizX 4.4 1 . This, in order to make a faithful comparison of the three systems. We considered a 1MB XMark document and we scaled to 10MB and 100MB, in order to measure time savings in larger XML corpora. Our test results only take into account query answering time, dried of import time and indexing time. This, in order to make a faithful comparison of the three systems. Saxon is a main-memory engine, that uses data summaries for rapidly access data. Differently, BaseX and QizX are persistent system that exploit indexing. We settled the common full-text indexes for the latter engines. Document were updated off-line, in order to ensure query answering independent from update executions. For this experiment only, the JVM was given 4GB of RAM, in order to minimize memory swapping.

Results are reported in Figure 6.2.c. Refreshing time has been measured without import and indexing time (a full-text index has been settled for both BaseX and QizX), that we assume asymptotically constants since done only once, and updating and indexmaintenance times, that is orthogonal to our goals. As in [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF], for each update u i we measured the time r i needed for refreshing all the 36 queries after the update, and the time r type i and r chain i needed to refresh only queries that are not deemed as independent by the static analysis of [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF] and by ours, respectively. In Figure 6.2.c, for each of the three used engines we report the averages of all refreshing times r i , r type . As a consequence of time efficiency and precision of our static analysis, even for a relatively small document of 1MB, our independence analysis ensures high time savings for all engines: 82% for Saxon, 75% for BaseX and 85% for QizX. While type based analysis [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF] ensures much lower time savings: 36% for Saxon, 31% for BaseX and 37% for QizX. These percentages are essentially the same as those obtained for 10MB and 100MB documents, both for our technique and for that of [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF]. This is because in the considered benchmark, queries that are not statically deemed as independent of an update, and hence refreshed, are the most expensive ones to refresh.

EXPERIMENTAL RESULTS

Scalability on R-benchmark

We ran experiments on the R-benchmark by ranging over each saturated recursive schema dn (n ranging over {1, 3, 5, 10, 20}), and each expression em (m ranging over {1, 5, 10}). Also, for each run we varied the multiplicity values, by considering k em , k em + 5 and k em + 10.

Results are now described. The schema d5 is quite complex, it contains 5 mutually recursive types. We can see from Figure 6.2 that even with such complex form of recursion, for e5, and for each k ∈ {5, 10, 15}, chain inference is still fast (inference time is around a decimal of a second). For schema d10, featuring an extremely complex form of recursion, inference time is around five seconds for e5, while for e10 the time exceeds ten seconds. The same happens for more complex cases. These test results show that even for forms of recursions that are unlikely to occur in practice (like the d5-e5 case), chain inference is still fast, while it takes more than one second for extremely complex cases.

We see that augmenting k does not substantially raise the inference time for an expression. This explained by the fact that a larger k value just enlarges the space of returned chains, without resulting in more context switches (where chains for step i are passed as input of chains for step i+1) that dominate the cost of inference. We see that for d10 and d20, computing chains for e5 is expensive, while for smaller queries the analysis can be afforded on such schemas. In such a case, even if unlikely to occur in practice, our analysis can still ensure substantial time savings in view maintenance and thus it may be worth running the analysis.

In this chapter we presented a set of experiments validating the precision and the efficiency of our independence analysis. On the XMark benchmark, our method resulted to have double precision as the related approach based on types and comparable inference time, thus validating the interest of using our analysis based on chains. Despite the fact that our method runs in polynomial space and time, the non-linear complexity required us to perform a worst-case analysis, so as to outline when a massive use of recursion may slow down inference time. This confirmed the analysis is fast for a large class of schemas we find in practice.

Extensions

In this chapter we illustrate how our chain-based type system can be extended in order to deal with features not considered in the previous formal development. We will first focus on additional features concerning queries and updates, and then on those concerning schema mechanisms.

Queries and Updates

The XQuery fragment we have considered, is the same as the one considered in the related approaches [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF][START_REF] Benedikt | Destabilizers and independence of XML updates[END_REF], and leaves out several query mechanisms. These can be handled by extending our framework by either by means of query rewriting or by defining new inference rules.

Query rewriting

Query rewriting can be adopted to rewrite a query-update pair q-u into a pair q ′ -u ′ belonging to the language we presented in Section 2.3, and such that static independence holds for q-u if it holds for q ′ -u ′ . Thus, here query rewriting is used wrt independence, not wrt to equivalence of XQuery expressions.

As already mentioned, rewriting has already been used in related approaches [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF][START_REF] Véronique Benzaken | Type-based XML projection[END_REF] as well as in our tests for dealing with XMark queries in performed tests. For instance, XMark query q 14 let $auction ∶= doc("auction.xml") return for $i in $auction site item where contains(string(exactly-one($i description)), "gold") return $i name text() 128 CHAPTER 7. EXTENSIONS is rewritten into let $auction ∶= doc("auction.xml") return for $i in $auction site item if ($i description descendant-or-self ∶∶ node()) then $i name text() else ()

The rewriting replaces the where clause with an ifthenelse clause; function calls are discarded and only the used paths are retained; note the adding of the step descendant-or-self ∶∶ node() in order to capture the fact that discarded function calls needs descendants of nodes selected by the path $i description. Recall that symbol $ is used to denote a variable in XQuery.

Query rewriting is an obvious solution to deal with conditional queries of the form if (q) then q 1 else q 2 If we do not consider negation, the condition q is rewritten into a query q ′ , by replacing in q each operator θ ∈ {and, or, =, <=} with the query concatenation operator ",". For instance, let x and y be two variables, predicate q = (x a and x b) or x c text()=y f text() is rewritten into q ′ = ( x a, x b, x c text(), y f text() ). It is easy to see that if an update does not impact q ′ then it does not impact q.

Negation requires to take into account that an update modifying a node which is neither used nor returned by q can impact not(q). For instance, assume variable x bound to a node having a and b children only, then an update deleting all a children impacts not(x b).

Negation is taken into account by rewriting not(q) into q ′ by simply replacing each node-test in q with the node-test node(). This rewriting ensures a sound analysis with a loss of precision in some cases. For the previous example, not(x b) is rewritten into x node(), enabling the chain analysis to exclude independence with the aforementioned deletion.

The above described rewriting is essentially the same used in [START_REF] Véronique Benzaken | Type-based XML projection[END_REF] in the context of type-based projection for query optimization. According to the above illustrated rewriting, a projection for q ′ is indeed a sound projection for q as well.

New Inference Rules

Query mechanisms left out can be handled by introducing new rules for inferring chains and by determining the k multiplicity value. For instance we can add new rules to handle where and orderby clauses and builtin functions. These new rules are quite similar to the existing ones, and presented in Table 7.1 whereas rules for inferring the multiplicity k value are presented in Table 7.2.

For the where clause the extension consists of adding two new rules for for and let expressions containing a where clause. For the orderby clause a similar reasoning applies. For conciseness, we restrict to descending ordering (the parameter does not affect the analysis), and assume where always co-occurs with orderby.

Concerning types switch expressions like typeswitch(q) case T 1 return q 1 ⋮ case T n-1 return q n-1 default return q n a sound and precise analysis can be ensured without involving types T i in the analysis. The chain inference for these expressions is similar to the chain inference for if expressions.

During chain inference for each query q i , the type T i could be taken into account to improve precision, by filtering out those chains inferred from q that can not be generated by any of the T i 's in the spirit of the precise type analysis provided in [START_REF] Benzaken | CDuce: an XML-centric generalpurpose language[END_REF] for pattern-matching in the CDuce language.

For functions call f(q 1 , . . . , q n ) new rules needs to take into account the nature of the function itself, and more specifically the way input parameters are used. Table 7.1 collects rules for several XQuery built-in functions used in the XMark query set that show how to deal with possible different cases.

For instance, the rule for count(q) is simple: it states that used chains of count(q) are those of q plus the return chains of q, and also that count(q) has no return chains. The return-to-used conversion is illustrated by the following example. Consider the query count(x employee), for the argument x employee we infer return chains pointing to employee elements selected by x employee.

Since counting these nodes does not depend on their descendants (e.g., employee has salary element as child), for a precise-analysis the return-to-used conversion is needed. Concerning element chains eventually inferred from the input q, these do not have to be considered as chains for count(q). Recall that element chains are inferred for return clauses of queries inside updates, so that precise chain inference for insert/replace updates can be done.

For the function string (that converts a value or a node to a string) the rule is simpler: used and return chains of string(q) are those of q. In this case the conversion is not needed due to the semantics of the string function: the descendants of return nodes of q are needed to compute the function output. Aggregation functions sum, min, max and avg, as well as conversion functions such as data and number are treated in the same way as string. Finally, contains function is defined similarly too, by collecting used and return chains of the queries passed as parameters.

For user-defined functions calls the rewriting method can be used as follows. Assuming that the definition of the function f is non recursive and given by (x 1 , . . . , x n ) = q the function call f(q 1 , . . . , q n ) is rewritten into

let x 1 ∶= q 1 ⋮ let x n ∶= q n return q
for chain inference and independence analysis (of course the rewriting is recursively done inside q eventually). Dealing with recursive functions raises problems wrt to determining the multiplicity value k, and is out of the scope of this work.

Concerning transform expressions of the form copy x ∶= q 1 modify u 1 return q 2

we have to notice that they do not change the input document, but rather a copy of some of its fragments.

In order for a transform query to be independent of an update u, we need that q 1 , q 2 and the 'query component' of u 1 (the part of u 1 that queries the schema instance) be independent of u. So chain inference for transform queries can be specified by relying on the existing chain inference for q 1 and q 2 , while for inferring chains from u 1 some modifications on update chain inference need to be done so that chains coming from the query component of u be taken into account. We leave this extension as future work. Note that the same kind of extension is needed for the related approach [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF].

Concerning the inference of the k multiplicity value for added constructs this is done along the lines of definitions for the core considered in Section 2.3. The extended definition is reported in Table 7.2.

Γ ⊢ C q 1 ∶ (r 1 , v 1 , e 1 ) Γ[x ↦ c] ⊢ C q w ∶ (r w c , v w c , e w c ) Γ[x ↦ c] ⊢ C q o ∶ (r o c , v o c , e o c ) Γ[x ↦ c] ⊢ C q 2 ∶ (r c , v c , e c ) for any c∈r 1 Γ ⊢ C
for x in q 1 where q w order-by q o return q 2 ∶ ( ⋃

c∈r 1 r c , v 1 ∪ ⋃ c∈r 1 λ∈{w, o} (r λ c ∪ v λ c ) ∪ ⋃ c∈r 1 rc∪ec ≠ ∅ (v c ∪{c}), ⋃ c∈r 1 e c ) (ForWhereOb) Γ ⊢ C q 1 ∶ (r 1 , v 1 , e 1 ) Γ[x ↦ r 1 ] ⊢ C q w ∶ (r w , v w , e w ) Γ[x ↦ r 1 ] ⊢ C q o ∶ (r o , v o , e o ) Γ[x ↦ r 1 ] ⊢ C q 2 ∶ (r, v, e) Γ ⊢ C let x ∶= q 1 where q w order-by q o return q 2 ∶ (r, r 1 ∪ ⋃ λ∈{w,o} (r λ ∪ v λ ) ∪ v 2 , e 2 ) (LetWhereOb) Γ ⊢ C q ∶ (r 0 , v 0 , e 0 ) Γ[x ↦ r] ⊢ C q i ∶ (r i , v i , e i )
for any i∈{1, . . . , n} Γ ⊢ C typeswitch q case T 1 return q 1 ∶ case T n-1 return q n-1 default return q n ∶ ( ⋃ Hence our chain inference system generates chains site.people.person.@id site.site.closed_auctions.closed_auction.buyer.@person If an update u changes either an id or person attributes, then are generated update chains like site.people.person ∶ @id site.site.closed_auctions.closed_auction.buyer ∶ @person These chains conflict with query chains, hence static independence is excluded.

Keyref constraints in XML Schema XML Schema provides powerful mechanisms to define keys and references formed by multiple attribute/element nodes. To this end, a fragment of XPath including downward axes and no predicates is used to specify the position and structure of keys and references. The example below is borrowed from the W3C specification [START_REF] Thompson | XML Schema Part 1: Structures Second Edition[END_REF].

< xs ∶ key name = "regKey" > <! --vehicles are keyed by a pair of state and plate --> < xs ∶ selector xpath = ". vehicle" > < xs ∶ field xpath = "@state" > < xs ∶ field xpath = "@plateNumber " > < xs ∶ key > < xs ∶ keyref name = "carRef" refer = "regKey" > <! -people"s cars are a reference --> < xs ∶ selector xpath = ". car " > < xs ∶ field xpath = "@regState" > < xs ∶ field xpath = "@regPlate" > < xs ∶ keyref > Both declarations are made inside the definition of a root element (whose definition can be found in [START_REF] Thompson | XML Schema Part 1: Structures Second Edition[END_REF]). So the two selectors . vehicle and . car navigates starting from a root element, and respectively select the parents of the key regKey and foreign key carRef . Both key and foreign keys consist of a pair of attributes selected by relative path expressions in the xs ∶ field elements. Field paths navigate starting from nodes selected by respective selectors. An important distinction wrt DTDs is that a field path may also select subelements of elements selected by the selector.

It is worth observing that the specification of key and keyref constraints and the specification of the type of the documents are different in nature. The purpose of key and keyref is to constraint the values of the elements of documents valid wrt a schema and have no impact on their structure. These constraints are defined using paths navigating valid documents. As a consequence, as for DTDs, key and keyref constraints can be totally 7.2. SCHEMAS 135 ignored by the static analysis in order to ensure a sound and precise static detection of independence.

One of the nice features of our static analysis is that it can be directly extended so as to capture Extended DTDs, and thus it is suitable also for XML Schema and a core of RelaxNG type languages.

Extended DTDs

As outlined in Chapter 1, EDTDs differ from DTDs mainly because they allow to write several type definitions for the same element. In order to perform our chain analysis, we have to reflect this aspect while doing chain inference.

Recall that in an EDTD [START_REF] Papakonstantinou | DTD inference for views of XML data[END_REF] we have a "type alphabet" Σ ′ = {a i a ∈ Σ} and a mapping to a "tag alphabet" µ such that µ(a i ) = a for all a i ∈ Σ ′ . This captures the fact that two types differently indexed produce the same label but possibly different content models.

That said, it is sufficient to change the definition of reachability Definition 4.1.2, and of some step chain inference rules. Both changes are straightforward. Reachability should be redefined so as chains contain indexed symbols a i instead of a, referring to different definitions of the same element tags.

Then, chain inference rule for step filtering has to be modified in order to deal with indexed symbols, as follows.

T C ( c.a i , b ) = { c.a i µ(a i ) = b}
Note that inference rules for axis chain inference remains unchanged.

Once chains have been inferred for a query and an update, to check query-update independence we use a slight variation of Definition 4.4.1, where we look for overlapping chains up to indexes i in chains symbols a i 's.

Notice that precision of the inference as well as complexity results remain unchanged for the EDTD case, since this can be simply seen as a schema with more definitions. Also < r definition can be easily adapter for dealing with interleaving operator of Relax NG.

For EDTDs, the CDAG compression needs to be a bit more careful. In Figure 7.2.3 we write an EDTD d 10 , featuring two definitions of element name, that are used in different contexts. Consider CDAG storing chains of d 10 made by considering only the tag-name of types, depicted in (a). This way of representing chains would include some artifacts (chains that do not belong to the schema), such as the following ones.

Conclusions

In this chapter we discussed some extension of our static analysis based on schema chains. We would like to stress that dealing with extensions is easy because our chain inference and independence analysis are based on the notions of used, return and element nodes (Chapter 4). These are universal and essential notions, in the sense that each processed node of whatever kind of query one wants to add to the framework falls in one of these three categories. Thus, generalizing our framework for a new query construct mainly consists of identifying how used, return and element nodes are determined. This simply requires the understanding of the semantics of query constructs. In the next chapter we draw the conclusions of our work and we outline possible future perspectives.

Chapter 8

Conclusions and Future Perspectives

In this thesis we have tackled the problem of statically detecting query-update independence in the context of typed XML databases. After having outlined the important issues raised by this problem in the context of XML data management, we provided an exhaustive overview of related existing techniques, by including both typed an untyped approaches. As discussed, existing techniques still suffer of several limitations.

To overcome these limitations, in this thesis we made the following contributions:

• We presented a type system able to statically detect XML query-update independence. One of the main features of the type system is the chain inference component, allowing to infer information at the basis of an highly precise analysis.

• We proposed a method to restrict the analysis to a finite set of chains in the presence of recursive schemas.

• We proposed techniques for a sound and efficient implementation of the above mentioned finite analysis.

• We conducted extensive experiments in order to validate precision and efficiency of our static analysis. As shown by test results, our technique succeeded from both aspects.

We also illustrated how the static analysis can be extended in order to deal with several features not considered in the core query and update languages, in order to show that the analysis is amenable to be adopted in most of the XQuery query and update languages, by preserving precision and efficiency.

CHAPTER 8. CONCLUSIONS AND FUTURE PERSPECTIVES

Future Perspectives

We discuss here some future directions that we believe are worth being investigated.

α-types

One of the main goals of this thesis is to show that schema information can be an extremely powerful tool for optimizing XML queries and updates. We presented a type system for inferring static projections of queries and updates (Theorems 4.3.4 and 4.3.6), used for the purpose of checking independence, that takes deeply into account informations concerning the hierarchical structure of data. We believe that a schema-based analysis, that is precise, cannot abstract away from such structural constraints. At the same time, when designing a method, there is a quest for tractability and efficiency of static analysis. Our method can run in polynomial time by introducing some approximations and has been proved fast by experiments. However particular applications may be interested in further lowering the computational time needed by the analysis. As shown in Chapters 3 and 6, one way to do this is to simplify the system and infer simple types [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF] rather than chains of types. To mitigate the lack of precision that this approach comports, it would be interesting to study inference for a parametric notion of type, called α-type. An α-type is a chain (not necessarily rooted) whose length is given by α (a positive natural value) and whose first α-1 type labels determine the context of the type indicated by the α th symbol, typing a set of nodes accessed by the query or update. The parameter α determines the amount of contextual information used to disambiguate types during the inference, and it can be opportunely tuned so as to vary the precision of the independence analysis wrt the computational resources that are available, because also the cost of the inference would result to be mainly determined by α. Note that with such an approach we would have that α = 1 would enable to capture the type system in [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF], while unbounded α would enable to capture the infinite analysis here proposed. One of the main interesting aspects of this research consists of finding methods for computing optimal α values, by taking into account queries, updates, schemas, and required constraints about execution time.

Probabilistic Independence Analysis

The decision procedure that we developed to check static independence gives a binary answer yes/no. However, because our method performs a conservative analysis, a query and an update may still be independent over a schema instance, even if this has been excluded by the static analysis. This may happen for instance, because a conflict is detected on an optional element tag that occurs quite rarely in practice. This said, it seems interesting to refine our method so as to take into account schemas with probabilities. Probabilistic schemas are useful in many contexts. As discussed in [AAD + 12], they can be used for instance to describe the distribution of the data, telling how many element nodes of a certain type are found in the database. By assigning to each chain an uncertainty value one could also estimate the probability that a conflict happened. This for 8.1. FUTURE PERSPECTIVES 139 instance can be used to design more sophisticated view-maintenance algorithms that do maintenance only when the estimated probability of conflict is higher than a treshold.

Schema-less Analysis

Designed for the Web, XML documents do not always come with a schema. Besides relying on schema inference techniques such as the one proposed by Bex et al. [START_REF] Geert | Inference of concise regular expressions and DTDs[END_REF], this case can be handled by performing chain inference starting from a data summary (e.g., DataGuide) in place of a schema. A DataGuide essentially is a superset of the chains belonging to the data, and can be efficiently inferred [START_REF] Goldman | Dataguides: Enabling query formulation and optimization in semistructured databases[END_REF]. Our system rules can be easily adapted because of the chain based nature of a DataGuide.

Independence Analysis for the Semantic Web

Query-update independence for Semantic Web databases is an open problem. Semantic web databases are graphs written in RDF. Despite designed for tree-shaped data, we believe that our method can be applied also for RDF graphs by making an analysis of accessed classes of data, provided that an ontology or a data summary is available. Also, our method could be applied for n-SPARQL, the navigational language for RDF [START_REF] Pérez | nSPARQL: A navigational language for RDF[END_REF].

Chapter 9

Proofs

In this chapter we prove the statements concerning the correctness of our chain analysis. The whole proof is organized in two main parts. In the first part we prove that the chain-based independence analysis is sound, in the case where a possibly infinite set of chains is inferred for an expression over a schema. In the second part we prove that the finite restriction to the subset of k-chains yields an analysis that is equivalent to the infinite one.

Proving that the possibly infinite chain analysis is sound mainly consists of showing that the sets of return, used, element and update chains inferred for an expression correctly abstract the data that is accessed/updated during the evaluation of the expression, over a valid schema instance. As a corollary of this we conclude the correctness of our notion of chain-based independence.

Proving that the finite restriction to the subset of k-chains yields an analysis that is equivalent to the infinite one. Consists of two main tasks. We first show that all chains can be reduced to k-chains. Then we show that any pair of conflicting chains can be reduced to a pair of conflicting k-chains. These proofs are developed by first introducing linear-path queries (see Section 9.2).

Soundness of Chain Inference in the Possibly Infinite Case

In this section we prove that our analysis makes a sound abstraction of accessed/updated data in the possibly infinite case. Because updates are defined in terms of queries, and queries in turn are defined by using navigational capabilities, the proof is structured as follows. We first prove correctness for XPath navigational steps. We then prove correctness for XQuery expressions. We finally prove correctness for XQuery Update expressions. Furthermore, we show that for XPath navigational steps chain inference is also complete. also complete for q ′ ) we conclude since by rule (Elt) a ∈ e q . If r q ′ ∪e q ′ ≠ ∅ (hence the system is correct but not complete for q ′ ) then rule (Elt) produces element chains as described in i) and ii). Since all these chains will start with label a, we can conclude that the resulting element of q is always typed.

[q = x step] No element is constructed by the query.

[q = for x in q 1 return q 2 ] The elements constructed and returned by q are those constructed and returned by q 2 . We conclude by inductive hypothesis on q 2 . [q = let x ∶= q 1 return q 2 ] Analogous to the for case.

[q = if (q 0 ) then q 1 else q 2 ] The elements constructed and returned by q are those constructed and returned either by q 1 or q 2 . We conclude by inductive hypothesis on q 1 and q 2 . Summing up, we proved that query chain inference is sound. This means two things. First, that locations in the input document accessed by the query are typed by some inferred chains. Second, that locations created and returned by the query are typed by some inferred chains. Completeness (whether inference yields to minimal sets of chains) is still open, and we leave it as a future work.

Soundness of the Chain Analysis for the Finite Case

In this section we prove that a finite subset of k-chains are sufficient to verify our static notion of indepednence. The main statement we prove is that a query and an update are conflicting if and only if they are conflicting on a finite set of k-chains. As a consequence of this, two expressions are independent if they do not conflict on a specific set of k-chains.

The proof is constituted of two main parts. We first prove that each chain inferred from an expression can be folded to a k-chain inferred for the same expression, yet preserving all informations concerning the behavior of the query. Then we show that this folding can be done also for a pair of conflicting expressions thus preserving all interactions between a query and update also in the finite analysis.

Folding Lemma for a Single Expression

In this section we prove Lemma 4.4.4 that states the existence of a folding relation between query chains and k-query-chains. We develop our proof with the aid of linear-path queries (in short, lp queries), a subclass of queries defined in Chapter 2 that allow both to capture all chains inferred from an expressions and simplify the formal development.

Linear-path queries are defined in order to represent all navigational paths of a query that are superposed at the syntactic level, and are defined as follows.

Definition 9.2.1 (Linear-path queries). A linear-path query, denoted by q, is an expression matching the following grammar q ∶∶= <a> q < a> q q ∶∶= for x in x axis ∶∶ φ return q x axis ∶∶ φ "txt"

Linear-path queries are the equivalent of navigational XPath expression without branching, plus both element and text node construction. These expressions are called linear because the grammar allows only for linear recursion. In fact, an iteration possibly nests only another iteration (on its right branch), and an element construction possibly nests either another element construction or an iteration. Also, element constructions are allowed only at the outermost level of the query.

A query q is reformulated in a set of lp queries τ q that induces a superset of the chains inferred from q. To illustrate the process, consider the query q defined as for x 1 ∶= x author, x editor return x 1 self ∶∶ author This is translated in the following set. It is easy to see that this reformulation provides an over-approximation of all navigational paths embodied in q, and hence all chains inferred for the original query are contained in the set of chains inferred for the reformulated ones. At the same time, we have that k q = 2 and for all q ∈ τ q it holds that k q ≤ k q , hence all chains inferred for a reformulated expression can be folded to k q -chains.

These two properties together makes sufficient to show a folding on the set of lpqueries, to scale on the whole language considered in this work. By showing a k q -folding for a superset of q chains, we immediately conclude the k q -folding for all q chains. This simplification is without loss of generality. Queries lp are a sort of normalized form for the problem of chain inference that simplify the formal development. In previous versions of this work, we developed proofs directly dealing with the general case. These resulted to be prolix, because they required involved properties, without clarifying the crux of the question. Folding for updates expressions will be given later, by means of linear-path queries.

Reformulating a query in a set of lp-queries

The set of linear-paths induced by a query is defined in Table 9.1. We describe the reformulation process. Given a query q, the set of lp queries induced by q is obtained by splitting paths in concatenations (",") and conditional expressions, by approximating let-bindings, by linearizing all iterations of the query and, finally, by rewriting element constructions.

Let-bindings are approximated by means of iteration. By doing this in principle we obtain a correct multiplicity values for the expression, however there is a gap to fill in terms of inferred chains. In fact, iterations discard chains bound to variables if they do not satisfy navigational specifications, while rule (Let) retains all chains bound to a variable x no regardless. For this reason, we put the iteration in union with all expression bound with a new let-variable. These are return chains instead of used ones, but the nature of the chains is irrelevant for the end of showing a folding relation.

To illustrate path splitting and let-binding approximation, consider the following example. Here the chains pointing to editor elements are discarded by the iteration. This is correct from the semantics point of view but it is not compliant with the (Let) rule that also produces chains pointing to editor as used chains.

LPQ

The functions R • for and R • e are introduced for the linearization of the iterations and for lifting element constructions.

We describe now the linearization of iterations. Given a for construct, we denote by R for the function that linearizes expressions of the form for x in q 1 return q 2 . R for is defined as the identity on any input query, except for the ones matching the following case.

R for ⎛ ⎜ ⎝

for x 1 in (for x 2 in q 2 return q 1 ) return q 0 ⎞ ⎟ ⎠ def = for x 2 in R for (q 2 ) for x 1 in R for (q 1 ) return R for (q 0 ) Notice that the rule applies locally on a query q and it has to be iterated until fixpoint for linearizing all subexpressions, until R for (q) = q. We denote this by R • for (q). Also, we denote by R • for (Q) the rewriting of a set of queries Q.

The fixpoint rewriting works as in the following example. LPQ(for x in q 1 return q 2 ) def = ⋃ q i ∈LPQ(q i ) R • for (for x in q 1 return q 2 ) LPQ(let x ∶= q 1 return q 2 ) def = LPQ(for x in q 1 return q 2 ) ∪ LPQ(q 1 ) LPQ(if (q 0 ) then q 1 else q 2 ) def = ⋃ i LPQ(q i ) LPQ(<a>q< a>) def = ⋃ q∈LPQ(q) <a>q< a> Table 9.1: Linear-path query extraction

For lp queries, element construction is allowed only at the outermost level of the query.1 Expressions that do not satisfy this property are rewritten in proper ones by lifting element construction. For example, the query for x in y b return <new>x< new> is rewritten in <new>for x in y b return x< new> First notice that the semantics of the two expressions is different: the former returns a forest of n trees, where n is the number of b elements in a tree, while the latter returns a single tree. Also, that there may be no type definition in the schema employing b as a label. In this case the chain inference process outputs the empty set for the former expression, while it outputs the element chain new for the latter. However, while the semantics of the expressions may differ, the rewriting is still sound for the purpose of chain inference. In this case, the set of used, return and element chains inferred for the original and the rewritten expression coincide. In general, it is easy to show that the set of element chains inferred for a lp query set a sound approximation of the element chains of the original query.

We denote by R e (q) the function that rewrites a query by lifting element constructions. R e (q) is defined as the identity for all input query, except for the ones matching 166 CHAPTER 9. PROOFS one of the following two cases. R e (for x in q 1 return <a>q 2 < a>) def = <a>for x in q 1 return R e (q 2 )< a> R e (<a>q< a>) def = <a>R e (q)< a>

The function is intentionally defined to work only on that specific form of iteration. It is meant to be applied over queries that are (almost) lp queries, up to element construction. Notice that the rules have to applied until fixpoint is reached, i.e. R e (q) = q. We denote this by R • e (q). We will use the same notation also when speaking about set of queries. The fixpoint is unique and always reached by the translation.

As an example consider the previous query for x in y b return <new>q< new> where q = for x 2 in y a return <sub >. We have that This translation is reminiscent of path extraction, however there are two difference. The first is that in the definition of the set of lp queries associated to an expression, we do not take into account variable binding. We avoid this process because it is not needed in order to have a sound k-folding. The second difference, and most important, is that this process is described formally, but actually never implemented. It is just used to show that the k-analysis is sound in principle.

Correctness wrt chains of the LPQ() transformation of queries is stated as follows.

SOUNDNESS OF THE CHAIN ANALYSIS FOR THE FINITE CASE 167

Proposition 9.2.2. Let d be a DTD, q a query, and Γ a static environment. Let us denote by τ q the set of used, return and element chains inferred for q wrt Γ and by τ LPQ(q) the union of used, return, and element chains inferred for each expression in LPQ(q). Then, τ q ⊆ τ LPQ(q) . Proof. By induction on the structure of q.

By over approximating the set of chains inferred for an expression, we have that also the result of a query is always over approximated by its associated set of linearpath queries. However, what is important for us is not only the resulting locations of a query, but also the whole set of locations accessed. This can be showed as a corollary of Proposition 9.2.2.

Computing the Multiplicity Value for lp-queries

In the general case (Section 2.3), the definition of the k value is (necessarily) structured, because several navigational paths are superposed at the syntactic level. Differently, linear-path allow us to directly compute the multiplicity value for a given query expression defined in Chapter 4, without inductive definition. This will be useful in the proof in order to show that the finite on k-chains is equivalent to the possibly infinite analysis.

Proposition 9.2.3. Let q be an lp query without element construction then

k q = max a∈Σ ⎧ ⎪ ⎪ ⎨ ⎪ ⎪ ⎩ step∈q F(a, step) + R(step) ⎫ ⎪ ⎪ ⎬ ⎪ ⎪ ⎭
Furthermore, in the case that q is nested inside an element construction, we have k <a>q< a> = 1 + k q if a is the most frequent label in q k q otherwise

Where a is the most frequent label in q if, for all b ∈ Σ S , if we have that step∈q F(b, step) ≤ step∈q F(a, step)

Proof. Straightforward by induction on q.

The following lemma shows that all lp-queries inferred for an expression have a multiplicity value bounded by that of the original query. Proposition 9.2.4. Let d be a DTD, q a query, and Γ a static environment. Let us denote by τ q and τ LPQ(q) the union of the set of used, return, and element chains inferred for q wrt Γ, and for each expression in LPQ(q), respectively. Then, for all query q ∈ LPQ(q) we have that k q ≤ k q .

Proof. By induction on the structure of q.

If a is not recursive, then no chain in C d has a cycle involving a. The type a is in a path between two distinct strongly-connected components of the dependency graph induced by the schema. Therefore c = c a .c 2 is of the form If a is recursive, then we distinguish two sub cases cases. If step 1 , . . . , step n do not employ any recursive axis, then no c ∈ Γ(x) need to be folded because each query step may extend the chain of at most one type. Therefore the proof is concluded straightforwardly by inductive hypothesis on the derivation of the expression that generated the chains for x.

Otherwise, if some steps in step 1 , . . . , step n employ a recursive axis then, analogously to the case of axis = parent, the label a may not be preserved by the folding relation. If a is preserved then the conclusion is immediate. We assume this is not the case. Now, to check that c ′′ i we obtained from the construction is a chain matching the semantics of step n it suffices to check that c ′′ i ∈ Γ(x). If this is not the case, then we chose another b i and we repeat the process. If no other b i exists than the step is unsatisfiable. If c ′′ i ∈ Γ(x) then we define c ′′ i = c ′′ a .c ′′ , where c ′′ a is the prefix of c ′′ i terminating with a. According to chain inference for the ancestor axis, we have that c ′′ a ∈ τ n+1 with c ′′ a is a (1+k n )-chain. Because R(ancestor) = 1, k n+1 = 1 + k n Notice that the lemma states something stronger than what is needed for queryupdate independence purpose. In fact, it does not only concern used and return chains, but it also takes into account element chains, even if they are not involved in the definition of independence.

As before, we generalize from lp queries to the whole language.

Lemma 4.4.5 (k-folding and conflict preservation) Let d be a DTD, q 1 , q 2 two queries with at most only one free variable x, and Γ = { x ↦ s d } a static environment. Provided that Γ ⊢ C d q i ∶ (r i , v i , e i ) and τ i = r i ∪ v i ∪ e i , for each pair of chains (c 1 , c 2 ) ∈ τ q 1 × τ q 2 such that c 1 ⪯ c 2 , there exists (c ′ 1 , c ′ 2 ) ∈ τ q 1 × τ q 2 such that c ′ 1 ⪯ c ′ 2 and c i ↪ * d c ′ i with c ′ i a (k q 1 +k q 2 )-chain (i=1, 2).

Proof. Let LPQ(q i ) be the set of linear-path queries associated to q i , and k ′ i = max{k q ′ i q ′ i ∈ LPQ(q i )}. By Lemma 9.2.2 we have that τ LPQ(q i ) ⊇ τ q i . Moreover, by Lemma 9.2.8 all pair of chains (c 1 , c 2 ) ∈ τ LPQ(q 1 ) × τ LPQ(q 2 ) can be folded to a pair of (k ′ 1 +k ′ 2 )-chains preserving the conflict, and by Proposition 9.2.4 k ′ i ≤ k q i . Thus all chains in τ q 1 × τ q 2 can be folded into k q 1 +k q 2 -chains.

Remark 9.2.9. As a direct corollary of Lemma 4.4.5 we can approximate the problem of queries disjunction in presence of a schema just looking on query k-chains. Indeed, if no pair of conflicting k-chain is found for the input query expressions, then no nodes are selected by both input query expressions on any valid document instance. Furthermore, for the subset of queries and schemas that make our chain inference system enjoying completeness, we can exactly solve the query intersection problem in presence of a schema.

We conclude this section by showing the equivalence of the chain analysis in the infinite and finite case.

Theorem 9.2.10. Let d be a DTD, q a query and u an update, with at most only one free variable x and Γ = { x ↦ s } a static environment. Then, q ⊥ C d u iff q ⊥ C k d u.

Proof. Direction ⇒) is straightforward since C k d ⊆ C d . We show now direction ⇐) by showing that q ⊥ C d u implies q ⊥ C k d u.

By structural induction on u. Base.

[u = ()] No chain is inferred for the empty update, hence it is independent wrt any query.

  CHAPTER 2. PRELIMINARIES <ELEMENT bib (book * )> <ELEMENT book (title, author+) <ELEMENT title (#PCDATA)> <ELEMENT author (name)> <ELEMENT name (#PCDATA)> bib ← book * book ← title, author+ title ← String author ← name name ← String

Figure 2

 2 Figure 2.2: DTD bibliography.dtd and the schema model d 1 Definition 2.2.2 (Validity). A tree t = (σ, l t ) is valid wrt a DTD (d, s, Σ), denoted by t ∈ d, if and only if there exists a mapping λ ∶ dom(t) ↦ Σ S such that • λ(l t ) = s d • λ(l) = String implies that σ(l) is a text node • λ(l) = a implies that σ(l) is an element-node a[L], and that the word λ(L) is generated by the regular expression d(a), i.e., λ(L) ∈ Lang(d(a))

Figure 2

 2 Figure 2.3: DTD d 2 and saturated type-dependency graph G d 2

  Figure 3.1: DTD d 3

lt 2 , 4 =

 24 because the root node has no parent. The type of l ′ 3 and l ′ 4 are the same, indeed type(l ′ 3 ) = type(l ′ 4 ) = name. However their chains differ since c σ l ′ 3 = bib.book.author.name c σ l ′ bib.book.publisher.name

  Definition 4.1.2 (Reachability and Chains). Given a DTD d, we denote by a ⇒ d b the reachability relation that holds for a pair a, b ∈ Σ S if b occurs in the regular expression d(a). A chain c over d is a non-empty sequence of labels a 1 .a 2 . . . .a n such that a i ⇒ d a (i+1) for i = 1 . . . n-1.

  As an example of schema chains, consider the DTD d 3 in Figure3.1. The set C d 3 includes the chains bib.book.title.String bib.book.author.name.String bib.book.publisher.name.String and all their non-empty subsequences. For instance, bib and author.name.String are C d 3 -chains, while bib.author and book.String are not.

  Lemma 4.1.3 (Soundness of ⇒ d ). Let d be a DTD and t = (σ, l t ) ∈ d a valid tree. If (l, l ′ ) ∈ Child t then type(l) ⇒ d type(l ′ ).

  Lemma 4.1.4 (Completeness of ⇒ d ). For all DTD d, if a ⇒ d b then there exists a valid tree t = (σ, l t ) ∈ d, and a pair of locations (l, l ′ ) ∈ Child t , such that type(l) = a and type(l ′ ) = b.

  Proposition 4.1.5. Given a valid tree t ∈ d and a location l ∈ dom(t) we have c t l ∈ C d . Proof. Immediate by Lemma 4.1.3.

A

  C d 3 (bib.book.title, following-sibling) = { bib.book.author bib.book.publisher } A C d 3 (bib.book.title, preceding-sibling) = ∅ As a more involved example of the sibling relation < r consider for instance

  Lemma 4.2.2 (Soundness of < r ). Let d be a DTD and t = (σ, l t ) ∈ d a valid tree. If (l, l ′ ) ∈ FollowingSibling t and c t l = c.a then type(l) < d(c) type(l ′ ).

  Lemma 4.2.3 (Completeness of < r ). For all DTD d, If a < d(c) b then there exists a valid tree t = (σ, l t ) ∈ d, and a pair of locations (l, l ′ ) ∈ FollowingSibling t , such that type(l) = a and type(l ′ ) = b, with c t l = c.a and c t l ′ = c.b.

  Figure 4.2: DTD d 4

  rename doc author as publisher By applying rule (Rename) we obtain the following derivation. Γ ⊢ C d 4 doc author ∶ ({bib.book.author}, ∅, ∅) Γ ⊢ C d 4 rename doc author as publisher ∶ {bib.book ∶ author, bib.book ∶ publisher}

  Lemma 4.3.2 (Completeness of Step Chain Inference). Let d be a DTD and c ∈ C d a chain. If

Figure 4

 4 Figure 4.4: DTD d 5

  .price ∶ String ≺ bib.book.priceHence it results that confl(r, U) = confl(U, r) = confl(U, v) = ∅.We conclude this section by formally stating the soundness of the independence analysis based on chains. When C is taken as the set C d of chains generated for the DTD d, C-independence implies ⊧ d independence, as stated by the following theorem. 70 CHAPTER 4. INDEPENDENCE ANALYSIS BASED ON SCHEMA-CHAINS Theorem 4.4.2 (Soundness of C d independence).

  The same holds for the navigational path with backward axisdoc self ∶∶ store component complist component parent ∶∶ complistHere, the chains inferred from the path are 2-chains store.component.complist.component store.component.complist.component.complist Similarly, for the path doc self ∶∶ store component complist * we infer k p = 2, since the wildcard * stands for any label.

  Sibling axes are managed as child and parent axes. Consider the following recursive DTD d 7 store ← component * component ← description, component? description ← String and the navigational path doc descendant ∶∶ description following-sibling ∶∶ component For this path, the used 1-chain store.component.description and the return 2-chain store.component.component are the needed chains. The presence of the recursive step descendant ∶∶ description entails k = 2.

  is possible to infer 2-chains witnessing the conflict such as store.component.complist ⪯ store.component.complist.component ∶ uselist 4.4. INDEPENDENCE ANALYSIS 79

  Given a DTD d, we define a folding relation↪ d ⊆ C d × C d as ↪ d def = { (c 1 , c 2 ) c 1 = c.a.c ′ .a.c ′′ ∧ c 2 = c.a.c ′′ }Notice that, above, the symbol a is a recursive type of the schema. We denote by ↪ * d the reflexive and transitive closure of ↪ d .

Figure 5 . 3 :

 53 Figure 5.3: CTREE and CDAG storing chains of d 2 Consider now the saturated recursive schema d 9 defined at the beginning of the section. a ← b, f b ← b * , f? f ← b? , f *

  .b.b.b a.f.f.f.b While this could suggest that the analysis imprecise (in fact, by inferring more chain than needed we may have false-negatives) it does not. The reason is that, because of the regularity of tree grammars, chains a.b.b.b.b and a.f.f.f.b, are indeed 4-chains matching b over d 9 . Therefore in this case chain inference for b with CDAGs is both sound and complete, in the sense that it infers all 2-chains matching b (soundness) and only chains matching b (completeness).

Figure 6

 6 Figure 6.1: Static Analysis Precision: Types vs Chains

Figure 6

 6 Figure 6.2: Static Analysis Time: Types vs Chains

i1CHAPTERFigure 6

 6 Figure 6.3: View Refreshing: Types vs Chains

Figure 6

 6 Figure 6.4: Chain Inference Time on R-benchmark

  A1 A2 A3 A4 A5 A6 A7 A8 B1 B2 B3 B4 B5 B6 B7 B8 Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 Q10 Q11 Q12 Q13 Q14 Q15 Q16 Q17 Q18 Q19 Q20Types[START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF] Chains TOT Types[BC09a] (%) Chains (

for x 1 in (for x 2 in for x 3 in x book return x 3 author return x 2 name) return x 1 f irst R • for →

 for for x 2 in (for x 3 in x bookreturn x 3 author) return for x 1 in x 2 name return x 1 f irst R • for → for x 3 in x book for x 2 in x 3 author for x 1 in x 2 name return x 1 f irst9.2. SOUNDNESS OF THE CHAIN ANALYSIS FOR THE FINITE CASE165 LPQ(()) def = ∅ LPQ("txt") def = { "txt" } LPQ(q 1 , q 2 ) def = LPQ(q 1 ) ∪ LPQ(q 2 )

  R • e (for x in y b return <new>q< new>) = R • e (<new>for x in y b return R e (q)< new>) = R • e (<new>for x in y b return <sub> for x 2 in y a return () < sub> < new>) = <new> <sub> for x in y b return for x 2 in y a return () < sub> < new>

c

  = c 1 . a. c 2 where c 1 and c 2 do not share any label. By inductive hypothesis, there exists ak n -chain c ′ ∈ Γ(x) such that c ↪ * d c ′ .Since c 1 and c 2 do not share any label, it is easy to see thatc ′ = c ′ 1 . a. c ′ 2 where c i ↪ * d c ′ i , and c ′ i is a k n -chain, (i = 1, 2). Then c ′ = c ′ 1 .a is a k n -chain folding of c a , and a k n+1 -chain as well.

  By inductive hypothesis, there exists a kn -chain c ′ ∈ Γ(x) such that c ↪ * d c ′ ,and c ′ is of the form c ′ = b 1 .b 2 . . . b m and b i ≠ a for all i ∈ {1, .., m}.We describe a procedure for constructing the desired k n+1 -chain.For all i = 1..m, if b i ⇒ * d aand a ⇒ * d b i+1 then construct a new chain from c ′ , by injecting a word u between b i , such as to obtain a chain of the form c ′′ i = b 1 ..b i .u .b i+1 ..b m such that u = a 1 . . . a k is a 1-chain with a ∈ u, and b i ⇒ d a 1 and a n ⇒ d b i+1 .

Table 2

 2

	.1: Query Language

Table 2

 2

.2: Update Language are supported by the grammar by mean of iteration, as follows.

Table 2

 2

.3: Query evaluation rules

Table 2

 2

.4: Rules for evaluating update expressions to pending update lists

Table 2 .

 2 5: Update pending list applicationSanity Check and Update Reordering In this phase, the sanity checks verify that UPL is consistent. As in[START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF], we do not model this phase here, and we defer the work to an abstract predicate sanitycheck(ω). The check enforces for instance that the same node is not a target of multiple rename or replace operators, that text nodes are not the targets of inserts, and that the elements being inserted are rooted at element nodes, as specified in [RCD + 11].

  .1, with the following examples. A C d 3 (bib.book, child) = { bib.book.title bib.book.author bib.book.publisher } A C d 3 (bib.book.author, descendant) = { bib.book.author.name bib.book.author.name.String }

A C d 3 (bib.book.author, parent) = { bib.book }

Table 4 .

 4 2: Chain Inference Rules for Updates60 CHAPTER 4. INDEPENDENCE ANALYSIS BASED ON SCHEMA-CHAINSdoc title, whose unique return chain is bib.book.title (forasmuch as title element is never a descendant of an author element): the update chain is not a prefix of the query chain and vice-versa.

  C d 4 doc author name ∶ ({bib.book.author.name}, ∅, ∅) Γ ⊢ C d 4 doc publisher name ∶ ({bib.book.publisher.name}, ∅, ∅) Γ ⊢ C d 4 replace doc author name with doc publisher name ∶ { bib.book.author ∶ name, bib.book.author ∶ name.String }

Γ ⊢

  independence can be decided in a finite amount of time when chain inference produces a finite set of chains i.e. when d has no vertical recursion. The next section provides a technique to capture C d -independence by means of a finite analysis.

	bib ← book *
	book ← title?, author * , publisher * , price?
	author, publisher ← name *
	title, name, price ← String?

  The static analysis infers from the update U = { bib.book ∶ title }. Indeed, there is no pair of conflicting query and update chains. query update bib.book.price ⪰ bib.book ∶ title bib.book.author ⪯ ⪰ bib.book ∶ title bib.book.publisher ⪯ ⪰ bib.book ∶ title Hence it results that confl

  of u 2 : the expression are conflicting because the update may change the result of the query. The static analysis infers from the update U = { bib.book ∶ publisher, bib.book ∶ author }. Indeed, query return-chains conflict with update chains. query update bib.book.publisher ⪯ bib.book ∶ publisher bib.book.publisher ⪰ bib.book ∶ publisher bib.book.author ⪯ bib.book ∶ author bib.book.author ⪰ bib.book ∶ author Hence it results that confl(r, U) = confl(U, r) ≠ ∅ q is not C d 5 -independent ofu 3 : the expressions may conflict because the data inserted by the update are accessed by the conditional query. The static analysis infers

from the update U = { bib.book ∶ price, bib.book ∶ price.String }. Indeed, a used chain conflicts with an update chain. update query bib.book ∶ price.String ≺ bib.book.price bib.book ∶ price ⪯ bib.book.price

Table 6 .

 6 3: Query-Update independent pairs detected. D=dynamic dependence; I=independence detected by chains but not by types; N=independence undetected by both approaches; White space = independence detected by both approaches

	Chapter 7

  book.author.name.String book.publisher.name.first.String book.publisher.name.last.String Example of CDAGs for EDTD However, this situation can be simply avoided by considering that type name 1 and name 2 come from different definitions. The result is depicted in (b). We stress that types name 1 and name 2 are considered as different when we store chains, but as the same type name when we do independence detection. Notice that the CDAG inferred from an EDTD is again polynomial in the size of the EDTD.

			book		book
	book ← author, publisher	author		publisher	author	publisher
	author ← name 1		name
	publisher ← name 2				name 1	name 2
	name 1 ← first, last	first	last	String
	name 2 ← String			first	last	String
	first, last ← String		String		String
			(a)		(b)
	Figure 7.1:

replace value of q0 with q becomes let x ∶= q0 return replace x text() with q

Recall that if more than one node labeled with publisher is selected by the update path then the update has to be encoded by means of iteration, otherwise a run-time error is raised.

A sound method for determining if an update preserves a schema and for maintaining the schema can be found in[START_REF] Benedikt | Semantics, types and effects for XML updates[END_REF]

• The purpose of an Update chain, denoted by c ∶ c ′ , is twofold: c types nodes l whose content may be changed by the update and c ′ , rooted at a child label of l, types descendants of l (either introduced or removed by the update) involved in the changes. For example, given c ∶ c ′ , independence is not guaranteed if a query returns an element whose root is typed by c.a, with a a prefix of c ′ .Rules for query chain inference are presented in Table4.1. These rules prove judgements of the form:Γ ⊢ C q ∶ (r, v, e)meaning that starting from a variable environment Γ and a set of chains C, the chain inference for query q produces the sets r, v and e, containing the return, used and element chains for q, respectively. Γ is a static variable environment that associates each query free-variable x with a set Γ(x) of chains, typing nodes that can be assigned to the variable during query evaluation. When x is bound to a single chain, we write x ↦ c as a shorthand of x ↦ { c }.All the rules mimic query semantics [DFF + 10, BC09b] introduced in Section 2.3. Rule (Empty) returns no chain, as the empty query performs no operation. Rule (Concat) returns the union of return, used and element chains for the two expressions.Navigational steps are captured by rule (StepF) and (StepUH) dealing with forward and upward/horizontal navigations respectively. Rule (StepF) produces only return chains, by using in turn step chain inference rules defined in the previous section. This is due to the fact that forward navigations only extend input chains, without loosing track of visited ancestor types. Differently, rule (StepUH) produces also used chains. These are input chains leading to a non-empty result for the axis inference. These chains are needed for developing a correct access analysis, since return chains produced by an horizontal/upward step may not contain as a prefix the input chain in Γ(x) from which they have been generated. Also, these input chains are kept as used chains because the descendants of the locations they are typing do not need to be accessed as well.

c ∈ r 1 rc∪ec ≠ ∅ (v c ∪{c}), ⋃ c∈r 1 e c )(For)Γ ⊢ C q 1 ∶ (r 1 , v 1 , e 1 ) Γ[x ↦ r 1 ] ⊢ C q 2 ∶ (r 2 , v 2 , e 2 ) Γ ⊢ C let x ∶= q 1 return q 2 ∶ (r 2 , r 1 ∪ v 1 ∪ v 2 , e 2 ) (Let) Γ ⊢ C q i ∶ (r i , v i , e i ) i=0..2 Γ ⊢ C if (q 0 ) then q 1 else q 2 ∶ (r 1 ∪ r 2 , ⋃ i=0..2 v i ∪ r 0 , e 1 ∪ e 2 ) (If) Γ ⊢ C "txt" ∶ (∅, ∅, {String}) (Text) Γ ⊢ C q ∶ (r, v, e) e 0 = { a.a.c ′ c.a ∈ r, c.a.c ′ ∈ r } ∪ { a.c c ∈ e } ∪ { a r ∪ e=∅ } Γ ⊢ C <a>q< a> ∶ (∅, r ∪ v, e 0 ) (Elt)Table 4.1: Chain Inference Rules for Queries

Γ ⊢ C q 0 ∶ (r 0 , v 0 , e 0 )U = { c ∶ a c.a ∈ r 0 } Γ ⊢ C delete q 0 ∶ U (Delete) Γ ⊢ C q 0 ∶ (r 0 , v 0 , e 0 ) U = { c ∶ a c.a ∈ r 0 } ∪ { c ∶ b c.a ∈ r 0 } Γ ⊢ C rename q 0 as b ∶ U (Rename) Γ ⊢ C q ∶ (r, v, e) Γ ⊢ C q 0 ∶ (r 0 , v 0 , e 0 ) pos ∈ {into, first, last} U = { c ∶ c ′ c ∈ r 0 , c ′ .c ′′ ∈ e, c ′ ≠ ǫ } ∪ { c ∶ a.c ′′ c.a ∈ r 0 , c ′ .a ∈ r, c ′ .a.c ′′ ∈ C } Γ ⊢ C insert q pos q 0 ∶ U (Insert-1) Γ ⊢ C q ∶ (r, v, e) Γ ⊢ C q 0 ∶ (r 0 , v 0 , e 0 ) pos ∈ {after, before} U = { c ∶ c ′ c.a ∈ r 0 , c ′ .c ′′ ∈ e, c ′ ≠ ǫ } ∪ { c ∶ b.c ′′ c.a ∈ r 0 , c ′ .b ∈ r, c. ′ b.c ′′ ∈ C } Γ ⊢ C insert q pos q 0 ∶ U (Insert-2) Γ ⊢ C q ∶ (r, v, e) Γ ⊢ C q 0 ∶ (r 0 , v 0 , e 0 ) U = { c ∶ a c.a ∈ r 0 } ∪ { c ∶ b.c ′′ c.a ∈ r 0 , c ′ .b ∈ r, c ′ .b.c ′′ ∈ C } ∪ { c ∶ c ′ c.a ∈ r 0 , c ′ .c ′′ ∈ e, c ′ ≠ ǫ } Γ ⊢ C replace q 0 with q ∶ U (Replace) Γ ⊢ C u = () ∶ ∅ (TU-Empty) Γ ⊢ C u 1 ∶ U 1 Γ ⊢ C u 2 ∶ U 2 Γ ⊢ C u 1 , u 2 ∶ U 1 ∪ U 2 (TU-Concat) Γ ⊢ C q ∶ (r, v, e) Γ[x ↦ c] ⊢ C u ∶ U c for any c ∈ r Γ ⊢ C for x in q return u ∶ ⋃ c U c (TU-For) Γ ⊢ C q ∶ (r, v, e) Γ[x ↦ r] ⊢ C u ∶ U

i∈{0...n} r i , ⋃ i∈{0...n} v i , ⋃ i∈{1...n} e i ) (TypeSwitch) Γ ⊢ C q ∶ (r, v, e) Γ ⊢ C count(q) ∶ (∅, r ∪ v, ∅) (Count) Γ ⊢ C q ∶ (r, v, e) Γ ⊢ C string(q) ∶ (r, v, ∅) (String) Γ ⊢ C q i ∶ (r i , v i , e i ) for i = 1, 2 Γ ⊢ C contains(q 1 , q 2 ) ∶ (r 1 ∪ r 2 , v 1 ∪ v 2 , ∅) (Contains)Table 7.1: Chain Inference Rules for Extensions

It is worth recalling that we assume also that query do not construct elements in the left branch of an iteration or let binding.

Consider for instance the schema { s ← b; b ← a?; a ← b? }

This happens for instance for schemas such as d1 = {s ← a; a ← a?} or d2 = {s ← (a, b); a ← b?; b ← a * } or d3 = {s ← a; a ← b1?; . . . bn-1 ← bn; bn ← a} and a query such as q = a parent ∶∶ a

Notice that q1 ○ q2 may not be linear anymore, thus with a little abuse of notation we denote by q1 ○ q2 also R • for (q1 ○ q2)

Rename some item elements as item. UN5 for x in //person[not(address) and phone] return k = rename x/phone with address Rename some phone element as address. UP1 replace //open_auctions/open_auction[@id="open_auction0"] k = with () Replace an open auction with empty. UP2 for x in //open_auction[@id="open_auction0"] return k = replace x/bidder/personref[@id="person1"] with <personref id={"person89"}/> Replace a bidder in an open auction. UP3 for x in //emph return k = let y:= x/text() return Replace all emph elements with bold ones, replace x with <bold>{y}</bold> yet preserving content. UP4 for x in //text[count(//keyword="fornitures")=0] return k = replace x with <text>{"element_removed"}</text>

Replace some text elements removing their content. UP5 replace () with //keyword//bold Replace nothing. k = Table 6.2: insert, rename and replace update expressions extending benchmark of [START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF] f = F(a, q 1 ) + max{ F(a, q 2 ), F(a, q w ), F(a, q o ) } F(a, for let x q 1 where q w order-by q o return q 2 ) = f (F-order-by) f = F(a, q) + max{F(a, q i )} F(a, typeswitch q case T i return q i default return q n ) = f (F-TypeSwitch) f = max{ F(a, q 1 ), F(a, q 2 ) } F(a, contains(q 1 ,q 2 )) = f (F-contains) f = F(a, q) F(a, string(q)) = f (F-string) f = F(a, q) F(a, count(q)) = f (F-count) r = R(q 1 ) + max{ R(q 2 ), R(q w ), R(q o ) } R(for let x q 1 where q w order-by q o return q 2 ) = r (R-order-by) r = R(q) + max{ R(q i ) } R(typeswitch q case T i return q i default return q n ) = r (R-TyeSwitch) r = max{ R(q 1 ), R(q 2 ) } R(contains(q 1 ,q 2 )) = r (R-contains) r = R(q) R(string(q)) = r (R-string) r = R(q) R(counts(q)) = r (R-count)

Attributes

As most of the studies on XQuery type systems [START_REF] Véronique Benzaken | Type-based XML projection[END_REF][START_REF] Benedikt | Schema-based independence analysis for XML updates[END_REF], we have excluded attribute types in our presentation, mainly because these does not introduce any particular issue. In any case, our implementation and our tests take attribute types into account.

To handle attribute types, the implementation considers chains possibly having a final label of the form @α. A chain c.@α is generated by a schema if an element pointed by c in a schema instance may have an attribute labeled as α (w.l.o.g, we assume the symbol @ not used in element tags defined by the schema). To infer such chains, the following new rule handling the attribute axis has been implemented:

Chain based independence is straightforwardly extended to handle the attribute extension. Furthermore, the inference of the k multiplicity value is not impacted by attribute types, as they cannot occur more than once in a chain.

Keys and foreign-keys integrity constraints

Concerning ID/IDREF constraints in DTDs, and key/keyref constraints in XSDs (studied in [START_REF] Arenas | On verifying consistency of XML specifications[END_REF]), we assume they are preserved by updates, as we assume that validity is preserved (Section 2.4). So, in order to ensure precise and sound independence analysis, chain inference does not need to consider these constraints. Our notion of static independence only concerns the type component of the schema, while these constraints pose restrictions on the values of attributes and elements in a document, and do not impact its structure.

To better illustrate, consider the following XMark q 8 [SWK + 02] query let $auction ∶= doc("auction.xml") for $p in $auction site people person let $a ∶= for $t in $auction site closed_auctions closed_auction where $t buyer @person = $p @id return $t return < item person = "$p name text()" > count($a) < item > Here ID/IDREF attributes are used, and selected by the following path expressions. p 1 = doc("auction.xml") site people person @id p 2 = doc("auction.xml") site site closed_auctions closed_auction buyer @person 142 CHAPTER 9. PROOFS

Soundness and Completeness of Schema Type Relations

Correctness (and also completeness) of chain inference for XPath navigational steps relies on the correctness of the auxiliary relations defined to capture with types the parent-child and sibling relations among documents nodes, namely ⇒ d and < r .

We show that ⇒ d and < r are both sound and complete. Soundness means that for any pair of parent-child (respectively sibling) locations belonging to a valid tree, there exists a correspondent pair of types in ⇒ d (respectively in < r ). Completeness means that these relations are also minimal, thus removing one pair from ⇒ d or < r we beak soundness.

Proof. Since t ∈ d, by definition of validity (Section 2.2) it follows that type(l 2 ) ∈ d(type(l 1 )) and thus type(l 1 ) ⇒ d type(l 2 ). Lemma 4.2.2 (Soundness of < r ) Let d be a DTD and t = (σ, l t ) ∈ d a valid tree. If (l, l ′ ) ∈ FollowingSibling t and c t l = c.a then type(l) < d(c) type(l ′ ).

Proof. If (l 1 , l 2 ) ∈ FollowingSibling t and (l, l 1 ) ∈ Child t and r = d(c t l ) then, by definition of validity, there exists a word w ∈ Lang(r) where type(l 1 ) occurs before type(l 2 ). We show that this in turn implies that type(l 1 ) < r type(l 2 ). By cases on r.

Base.

(Cases r = ǫ and r = a) Trivial since such w cannot exist.

Induction.

(Case r = r 1 ,r 2 ) Because Lang(r 1 , r 2 ) = Lang(r 1 ) ∪ Lang(r 2 ) ∪ Lang(r 1 ) × Lang(r 2 ) then either w ∈ Lang(r 1 )∪Lang(r 2 ) or w ∈ Lang(r 1 )×Lang(r 2 ). In the first case, we conclude by induction on r 1 , r 2 . In the second case, we conclude since (type(l 1 ), type(l 2 )) ∈ Sym(r 1 ) × Sym(r 2 ) ⊆ < r .

(Case r = r 1 r 2 ) In this case we have that Lang(r) = Lang(r 1 )∪Lang(r 2 ). Hence at least one of type(l 1 ) < r 1 type(l 2 ) and type(l 1 ) < r 2 type(l 2 ) hold, and we conclude by induction.

(Cases r = r + and r = r * and r = r ? ) Immediate since < r + 1 = < r 1 ,r 1 and r * =r + ǫ and r ? =r ǫ.

SOUNDNESS OF CHAIN INFERENCE IN THE POSSIBLY INFINITE CASE143

Let L = (l 1 , . . . , l n ) be a sequence of location, in the following, with a little abuse of notation, we write type(L) for denoting the word type(l 1 ), . . . , type(l n ). where a 1 = s d , a n-1 = a, and a n = b. In order to conclude the thesis, we want to show that there exists a valid tree t ∈ d and a pair of locations (l 1 , l 2 ) ∈ Child t such that c t l 2 = a 1 . . . a n Such t can be built with the following recursive procedure.

Start with i = 1.

(Generate an element of the desired chain)

Let l be a location such that type(l) = a i . Attach to l a finite sequence of locations L such that the following hold.

• type(L) ∈ Lang(d(a i ));

• type(l ′ ) = a (i+1) for some l ′ ∈ L;

(Recursively generate the desired chain)

For all l ′ ∈ L such that type(l ′ ) = a (i+1) do the following. If i < n then increment i by 1 and apply recursively step 1 on l ′ . Else, the desired chain of nodes is obtained. Go to the next step.

3. (Complete the tree so as to make it valid) For all l ′ ∈ dom(t), such that Child t (l ′ ) = ∅ and that ǫ ∉ Lang(type(l ′ )) do the following. Attach to l ′ a finite and valid sequence of locations L ′ such that let r ′ = d(type(l ′ ))

• r ′′ is the regular expression obtained by replacing each * -guarded or optional subterm of r ′ with ǫ (e.g. a? b+, a * becomes ǫ b+);

Repeat this step until obtaining a valid tree.

This procedure always terminates producing a finite tree since the all definitions in d terminates. Furthermore, this tree contains a pair of locations (l 1 , l 2 ) ∈ Child t such that c t l 2 = a 1 . . . Proof. By Lemma 4.1.4 we know that we can build a tree instance with a location l ′′ typed by a chain c ∈ C d . If a < d(c) b we claim that we can build a sequence of locations l 1 , . . . , l n such that the word type(l 1 ), . . . , type(l n ) belongs to the language of d(c), and for some locations l i and l j with 1 ≤ i < j ≤ n we have that type(l i ) = a and type(l j ) = b.

We show this by induction on the structure of r = d(c).

Base.

(Cases r=ǫ and d(c)=a) Trivial since they do not satisfy the hypothesis.

Induction.

(Case r = r 1 ,r 2 ) If it holds that a < r 1 b ∪ a < r 2 b then we conclude by induction. Otherwise, because a < d(c) b we have that a ∈ Sym(r 1 ) and b ∈ Sym(r 2 ). Therefore there exist two words w 1 ∈ Lang(r 1 ) and w 2 ∈ Lang(r 2 ) such that a ∈ w 1 and b ∈ w 2 . At this point take a sequence of locations L such that type(L) = w 1 w 2 .

(Case r = r 1 r 2 ) In this case it holds that a < r 1 b ∪ a < r 2 b and we conclude by induction.

(Cases r = r + and r = r * and r = r ? ) Immediate since < r + 1 = < r 1 ,r 1 and r * =(r + ǫ) and r ? =(r ǫ). To conclude the thesis it suffices to complete the tree so as to obtain a valid instance. This can be done by applying the procedure described at point 3 of Lemma 4.1.4.

Axis chain inference

In this section we prove that chain inference for XPath navigational is sound.

Lemma 9.1.1 (Soundness of Step Chain Inference). Let d be a DTD, t = (σ, l t ) ∈ d be a valid tree, and l ∈ dom(σ) be a location of the tree. If σ, (x ∶= l x ) ⊧ x axis ∶∶ φ ⇒ σ, L then for each location l ′ ∈ L we have that

Proof. By case analysis on axis. Since node() is used as test filtering, we consider the correspondent axis evaluation and we leave as implicit the set-to-sequence conversion of rule by mean of document order.

[axis = self] We conclude immediately since by definition

SOUNDNESS OF CHAIN INFERENCE IN THE POSSIBLY INFINITE CASE145

[axis = child] By definition [[child]] σ lx = Child σ (l x ) Since the document is valid wrt the DTD d, for all l ∈ Child σ (l x ), let a x = type(l x ) and a = type(l) we have that a x ⇒ d a, with a x ∈ Σ and a ∈ Σ S . Therefore the type chain of the location l is c l = c lx .a and by definition c lx .a ∈ C d . We conclude since

For all l ∈ Descendant σ (l x ) let L = (l 1 , l 2 , . . . , l n ) be the sequence of nodes such that (l i , l i+1 ) ∈ Child σ for i = 1..n-1, with l 1 = l x and l n = l. Since the document is valid wrt the DTD d, for all pair of locations l i , l i+1 ∈ L, let a i = type(l i ), we have that a i ⇒ d a i+1 .Therefore a lx ⇒ + d a l , and the type chain of the location l is c l = c lx .a 2 .a 3 . . . a ∈ C d . We conclude since

Since the document is valid wrt the DTD d, for l ∈ Parent σ (l x ), let a x = type(l x ) and a = type(l) we have a ⇒ d a x . Therefore c lx = c.a x , where the type chain of the location l is c l = c. We conclude since

[axis = ancestor] This case is similar to the case of descendant-or-self axis.

By definition we have that

Given l ∈ Ancestor σ (l x ), let L = (l 1 , l 2 , . . . , l n ) be the sequence of nodes such that (l i , l i+1 ) ∈ Child σ for i = 1..n-1 with l 1 = l and l n = l x . Since the document is valid wrt the DTD d, for all pair of locations l i , l i+1 ∈ L, let a i = type(l i ) we have that a i ⇒ d a i+1 and a i ∈ Σ S . Therefore a l ⇒ + d a lx and the type chain of location l is c lx = c l .a 2 . . . . a ∈ C d . We conclude since

Notice that case axis = ancestor-or-self is analogous.

Notice that case axis = preceding-sibling is analogous.

Test chain inference

Soundness of chain inference for test filtering is stated by the following theorem. For simplicity, we present it together with completeness.

Lemma 9.1.2 (Test Filtering Soundness and Completeness).

Proof. By case analysis on φ. Since self is used as navigational axis, we directly translate the judgment into the proper test filtering [[φ]] lx σ . Also note that the sequence L is equal to l x alone when the test is evaluated to true and L is empty otherwise.

then there exists a valid tree t = (σ, l t ) ∈ d and a location l x ∈ dom(t) such that c lx = c and, assuming that σ, (x ∶= l x ) ⊧ x axis ∶∶ node() ⇒ σ, L we have that c σ l ′ = c ′ , for some l ′ ∈ L.

Proof. As before, since node() is used as test filtering, we directly translate the judgment into the proper axis evaluation and we leave as implicit the set-to-sequence conversion by mean of document order. The we conclude by a case analysis on axis.

[axis = self] By Lemma 4.1.4, for all input chains c then there exists a valid tree t = (σ, l t ) ∈ d and a location l x ∈ dom(t) such that c lx = c. We conclude immediately since by definition we have that Case preceding-sibling is analogous.

Putting everything together, we can prove the theorems of soundness and completeness for chain inference of XPath Step expressions.

Lemma 4.3.1 (Step Chain Soundness). Let d be a DTD, t = (σ, l t ) ∈ d be a valid tree, and l ∈ dom(σ) be a location of the tree. If

Proof. By Lemma 9.1.1 and Lemma 9.1.2.

then there exists a valid tree t = (σ, l t ) ∈ d and a location l ∈ dom(t) such that c l = c and, assuming that σ,

Proof. By Lemma 9.1.3 and Lemma 9.1.2.

Soundness of Query Chain Inference

In this section we prove the correctness of chain inference for query expressions. We introduce first some auxiliary definitions and properties that we will use later in our formal development.

SOUNDNESS OF CHAIN INFERENCE IN THE POSSIBLY INFINITE CASE149

Auxiliary definitions

The notion of correctness we stated (Theorem 4.3.4) relies on tree projections (Section 4.3.1 ).

Let σ be a store and L 1 , L 2 be two sequences of locations belonging to dom(σ). The merge of L 1 , L 2 , denoted by L 1 ⊎ L 2 , is defined as the sequence L such that

Let σ be a store and σ 1 , σ 2 be two of its projections. The stores obtained by only common and uncommon locations between σ 1 and σ 2 are defined as follows.

Let σ be a store and σ 1 , σ 2 be two of its projections. The merge of σ 1 and σ 2 , denoted by σ 1 ⊎ σ 2 , is defined as

Let l ∈ dom(σ 1 )∩dom(σ 2 ) be a location, the merge of the trees t 1 = (σ 1 , l) and t 2 = (σ 2 , l),

We outline some simple properties of the merge operator.

Proposition 9.1.5. Given a tree t and two of its projections, t 1 , t 2 ⪯ t, the following properties hold.

Proof. 1) Follows from the definition of merge.

2) Follows from the definition of merge and from t i ⪯ t.

3) Follows since, by the point 1), we have that t

CHAPTER 9. PROOFS

We prove now an auxiliary lemma concerning return chains.

Proposition 9.1.6. Let d be a DTD, t = (σ, l t ) ∈ d a valid tree, q a query, γ a dynamic environment and Γ a static environment such that σ

Proof. By induction on the structure of q.

Base.

[q = ()] Immediate since r q = ∅.

[q = "txt"] Immediate since l ∉ dom(t).

Induction

[q = q 1 , q 2 ] By induction on q 1 , q 2 and by noticing that r q = r q 1 ∪ r q 2 .

[q = <a>q ′ < a>] Immediate since l ∉ dom(t).

[q = x step] By correctness of step chain inference (Theorem 4.3.1), and since resulting chains are in r q . [q = for x in q 1 return q 2 ] First we notice that L q = L q 2 . We conclude by inductive hypothesis on q 2 and because r q = r q 2 . [q = let x ∶= q 1 return q 2 ] Analogous to the for case.

[q = if (q 0 ) then q 1 else q 2 ] First we notice that either L q = L q 1 or L q = L q 2 . We conclude by inductive hypothesis on q 1 , q 2 and because r q = r q 1 ∪ r q 2 .

SOUNDNESS OF CHAIN INFERENCE IN THE POSSIBLY INFINITE CASE151

Theorem 4.3.4 ((Soundness of Query Chains)) Let d be a DTD, t = (σ, l t ) ∈ d a valid tree, q a query, γ a dynamic environment ad Γ a static environment such that σ ⊧ d γ ∶ Γ. Provided σ, γ ⊧ q ⇒ σ new , L and Γ ⊢ C d q ∶ (r, v, e) the following holds.

For the sake of conciseness we adopt the following abbreviations. The sequence L q denotes the result q evaluation, that is σ, γ ⊧ q ⇒ σ q , L q . The sets of chains r q , v q , e q denote the sets of return, used and element chains inferred for q, that is Γ ⊢ C d q ∶ (r q , v q , e q ). We prove the point 1.

Proof. By structural induction on q.

Base.

[q = (), q = "txt"] We conclude immediately since the q-projection of t is empty.

Induction.

[q = q 1 , q 2 ] A minimal q-projection t ′ is the merge of a minimal q 1 -projection t ′ 1 with a minimal q 2 -projection t ′ 2 . This follows from the semantics rule (SQ-Concat). By inductive hypothesis we have that

By Proposition 9.1.5

By chain inference rule (Concat) we have that r q = r q 1 ∪ r q 2 and v q = v q 1 ∪ v q 2 . Therefore we conclude

In this case, a tree projection is minimal for q if and only if it is minimal for q ′ . This follows from the fact that element construction always produces fresh locations that do not belong to the original store. This is specified by semantics rules (SQ-Elt) and (SQ-Copy). By inductive hypothesis, if t ′ is a minimal projection for q ′ then t ′ ⪯ t r q ′ ∪v q ′ . Following rule (Elt) we have that r q = ∅ and

We conclude since t ′ ⪯ t vq . CHAPTER 9. PROOFS [q = x step] Semantics of step navigation is defined by rule (SQ-Step). We assume that x is bound to a single location l x in γ. The general case where x is bound to a sequence of locations goes by induction and concludes this case.

We distinguish between two main cases depending on the axis steps being forward or not.

(axis is forward) Since axis is forward, for all location l ∈ L q we have that either l is a descendant of l x , or l = l x if axis = self. Let t ′ be a minimal q-projection of t. Projection t ′ allows to correctly evaluate q, hence it is given by all locations in L q together with their ancestors and their descendants. Formally, t ′ = (σ L , l t ) where

Notice that t ′ is both minimal and unique. Notice also that it may be the case that L q = () and thus t ′ is the empty forest. Because σ ⊧ d γ ∶ Γ we have that c lx ∈ Γ(x). By Theorem 4.3.1 step chain inference is correct. Therefore, following rule (StepF) we can conclude that if l ∈ L q then c l ∈ r q . Notice also that c l types any location l ′ that is an ancestors of l. The descendants of l are typed by the prolongation of c l , that belongs to r q . By rule (StepF) no used chain is inferred. Therefore we conclude

(axis is backward or horizontal) In this case, since the axis is either backward or horizontal, all resulting locations l ∈ L q are not descendants of l x . Notice however that it may be the case that l = l x if axis = ancestor-or-self. Let t ′ be a minimal q-projection of t. Because t ′ allows to correctly evaluate q, it must contain: i) all locations in the result sequence L q , together with their respective ancestors and descendants and ii) the input location l x together with its ancestors, but only in the case that L q ≠ (). We stress that we may not need to include the descendants of l x in the projection, for instance if we are evaluating an horizontal axis. Formally, t ′ = (σ L , l t ) where L is

Notice that for backward and horizontal axis we have

. By Theorem 4.3.1 step chain inference is correct. Therefore, for all l ∈ L q we have that c l ∈ r q . Furthermore, if L ≠ () then c lx ∈ v q . We conclude that t ′ ⪯ t rq∪vq

SOUNDNESS OF CHAIN INFERENCE IN THE POSSIBLY INFINITE CASE153

When γ(x) = L query evaluation is performed by means of iteration, as defined by rules (SQ-Iter) and (SQ-IterBase). Let t ′ be the minimal q-projection for γ = { l ∈ L }. By inductive hypothesis, chain inference is correct for each l ∈ L. Let t ′ l be the minimal query q-projection for γ = { l }. We conclude since by Lemma 9.1.5

[q = for x in q 1 return q 2 ] Semantics of iteration is defined by rule (SQ-For).

Query q 2 is evaluated once for each location l ∈ L q 1 binding x with l in γ. We denote by t l 2 a minimal q 2 -projection of t obtained by assuming that x ↦ l ∈ γ. We denote by L 1 the set of result locations of q 1 that are also productive for q 2 , that is

A minimal q-projection of t is defined as t ′ = t 1 ⊎ t 2 where t 1 is a minimal q 1projection of t that ensures only locations in L 1 in the result sequence of q 1 , and t 2 is a minimal q 2 -projection of t obtained by the merge of all q 2 -minimal projections of t where x is bound to a location l ∈ L 1 .

We want to show that

We show first t 2 ⪯ t rq∪vq . By inductive hypothesis, provided that

t l 2 ⪯ t r i ∪v i By Lemma 9.1.5 we have also that

In general, if the result of q 2 is non-empty then r i ∪ e i ≠ ∅.

By rule (For)

We show t 1 ⪯ t vq . By inductive hypothesis, t 1 ⪯ t rq 1 ∪vq 1 however since t ′ does not need the descendants of result locations of q 1 , we have also that t 1 ⪯ t rq 1 ∪vq 1 . Then, because we need only result locations in L 1 we have that

By rule (For) we have that r q 1 ∪ v q 1 ⊆ v q and therefore we conclude

Putting everything together, by Lemma 9.1.5

The semantics of the let binding is defined by rule (SQ-Let). Let t i be a minimal q i -projection for q i . Notice that in the evaluation of q 2 , x is bound to the resulting sequence of q 1 in γ (no iteration is performed by the rule).

By inductive hypothesis

Following rule (Let) we have that

Therefore t 1 ⪯ t vq Furthermore, by rule (Let) we have that

Now t ′ = t 1 ⊎ t 2 is a minimal q-projection of t. By Proposition 9.1.5 we conclude t 1 ⊎ t 2 ⪯ t rq∪vq [q = if (q 0 ) then q 1 else q 2 ] The semantics of the conditional expression is defined by rules (SQ-If). Let t ′ , t 0 , t 1 and t 2 minimal projection of t for q, q 0 , q 1 and q 2 , respectively. By inductive hypothesis

According to the semantics of the conditional expression

and then we conclude by rule (If) since ⊎ i=0..2 t i ⪯ t rq∪vq

SOUNDNESS OF CHAIN INFERENCE IN THE POSSIBLY INFINITE CASE155

We prove the point 2.

Proof. By structural induction on q.

Base.

[q = ()] The empty query does not construct any element.

[q = "txt"] The query constructs a fresh text-node and by rule (Text) we have that

String ∈ e.

Induction

[q = q 1 , q 2 ] The constructed elements returned by q are obtained by the concatenation of those returned by q 1 and q 2 , respectively. By inductive hypothesis the statemet holds for q 1 , q 2 and since e q = e q 1 ∪ e q 2 we conclude. [q =< a > q ′ < a >] Following the rule for query semantics (SQ-Constr), the query q adds to the input store σ a new location, say l a , such that (l a ← a[L copy q ′ ]), where L copy q ′ denotes the copy of L q ′ . The resulting store is denoted by σ q . We distinguish four cases depending on wether the subexpression q ′ returns i) only locations belonging to the input tree, ii) only constructed elements, iii) both constructed and input elements, or iv) the empty sequence.

i) We assume that l ∈ L q ′ implies l ∈ dom(t), where t = (σ, l t ) denotes the input tree. By Proposition 9.1.6 we know that for all l ∈ L q ′ we have c l ∈ r q ′ . By rule (Elt), if c l = c.b and c.b.c ′ ∈ r q ′ then a.b.c ′ ∈ e q . Therefore let t ′ = σ q @l a we conclude t ′ ⪯ t ′ eq ii) We assume that l ∈ L q ′ implies l ∉ dom(t), where t = (σ, l t ) denotes the input tree. By inductive hypothesis, for all tree t ′′ = σ q @l a , with l ∈ L q ′ , we have that

By rule (Elt), if c ∈ e q ′ then a.c ∈ e q . Let t ′ = σ q @l a , we conclude that all locations of t ′ are typed by a prefix of a chain in e q . Formally we have

iii) In the case where q ′ provides both input and fresh data, we conclude by reasoning as in i) and ii). iv) We assume L q ′ = (). In this case, the result of q is a tree composed by a single node labeled a. By inductive hypothesis we assume the system to be correct on q ′ , but it may not be complete, thus we do not know if r q ′ ∪e q ′ = ∅ or not. So we distinguish between the two cases. If r q ′ ∪e q ′ = ∅ (hence the system is

Soundness of Update chain Inference

In this section we prove that chain inference for update expressions is correct. As updates are defined in terms of queries, the proof relies on correctness of chain inference for query expressions (Theorem 4.3.4). Chain inference for updates is sound in the sense that all chains required to type locations involved by an update are inferred.

Theorem 4.3.6 (Soundness of Update Chain Inference) Let d be a DTD, t a valid tree t = (σ, l t ) ∈ d, and u an update with at most one free variable x, γ = { x ↦ l t } a dynamic environment, and

is a location in t, and the update u involves l then there exists c ∶ c ′ ∈ U such that c σ l = c ∶ c ′ , where c ′ ≠ ǫ.

• if l is a location in u(t), i.e. l ∈ dom(σ u @l t ), and the update u involves l then there exists c ∶ c ′ ∈ U such that c σu l = c ∶ c ′ , where c ′ ≠ ǫ.

Proof. By structural induction on u.

Base.

[u = ()] No location is involved by the empty update. As defined by rules (SU-Empty) and (SAU-Empty), u yields an empty update pending list, that performs no operation. Notice also that following rule (Empty) no chain is inferred.

[u = delete q 0 ] Update u involves all locations in L q 0 (that is the resulting sequence of q 0 ). As defined by rule (SU-Delete), there should be exactly one location in L q 0 . We assume L q 0 = (l 0 ), with l 0 ∈ dom(t). By rule (SAU-Delete) l 0 is detached from its parent. By rule (SanityCheck) this operation is correct since l 0 is mutable and thus can be updated. By Proposition 9.1.6 c σ l 0 ∈ r q 0 . The statement follows by definition since by following rule (Delete) we have that given c σ l 0 = c.a 0 then c∶a 0 ∈ U. [u = rename q 0 as b] Update u involves all locations in L q 0 . As defined by rule (SU-Rename) there is at most one location l 0 ∈ dom(t) in the resulting sequence of q 0 . We assume L q 0 =(l q 0 ). By rule (SAU-Rename) the label of l 0 is renamed in label b. This is correct since by rule (SanityCheck) l 0 is mutable, and thus can be updated, and the location is not the target of several rename expressions. By Proposition 9.1.6 c σ l 0 ∈ r q 0 . In this case, we have that the renamed location belongs both to the original and to the updated store. We conclude now that in both cases the location is typed. Let

CHAPTER 9. PROOFS

[u = insert q (into into as first into as last) q 0 ] The locations involved by u are copies of source locations in L q , together with their descendants. As defined by rules (SAU-InsertInto), (SAU-InsertFirst) and (SAU-InsertLast), these locations are in turn inserted as children of location L q 0 . By rule (SU-Insert1) there is at most one target location in the resulting sequence of q 0 , hence L q 0 = (l 0 ). Source locations in L q are typed by inferred chains, as stated by Theorem 4.3.4. We recall this fact, distinguishing between fresh and input source locations.

• If l ∈ L q belongs to the input document then by Proposition 9.1.6 we have that c σ l ∈ r q . Furthermore, for all l ′ descendant of l we have c σ l ′ ∈ r q . • If l ∈ L q is a fresh location, by Theorem 4.3.4, we have that l is typed by some chains in e q , formally c σw l .e ∈ e q . Furthermore, for all l ′ descendant of l we have c σw l ′ .e ′ ∈ e q . Recall that σ w is an intermediate store containing source locations that are arguments of elementary update commands, to be applied further.

Locations involved by u belongs to the updated store σ u only. We conclude showing that chains typing these locations are in U. By Proposition 9.1.6 c σ l 0 ∈ r q 0 . By rule (Insert1) we have that • if c.a ∈ r q and c.a.c ′ ∈ r q then c σ l 0 ∶ a.c ′ ∈ U • if e ∈ e q then c σ l 0 ∶e ∈ U [u = insert q (after before) q 0 ] This case is similar to the previous one, except for the fact that chains for after/before expressions have a different definition. The locations involved by u are copies of source locations in L q , together with their descendants. As defined by rules (SAU-InsertAfter), and (SAU-InsertBefore), these locations are in turn inserted as children of location L q 0 . By rule (SU-Insert2) there is at most one target location in the resulting sequence of q 0 , hence L q 0 = (l 0 ). Source locations in L q are typed as stated by Theorem 4.3.4. We recall this fact, distinguishing between fresh and input source locations.

• If l ∈ L q belongs to the input document then By Proposition 9.1.6 we have that c σ l ∈ r q . Furthermore, for all l ′ descendant of l we have c σ l ′ ∈ r q . • If l ∈ L q is a fresh location, by Theorem 4.3.4 we have that l is typed by some chains in e q , formally c σw l .e ∈ e q . Furthermore, for all l ′ descendant of l we have c σw l ′ .e ′ ∈ e q . Recall that σ w is an intermediate store containing source locations that are arguments of elementary update commands not yet applied.

Locations involved by u belongs to the updated store σ u . We conclude showing that chains for those locations are in U. By Proposition 9.1.6 c σ l 0 ∈ r q 0 . Now we can conclude since by rule (Insert1), if c σ l 0 = c.a we have that • if c.a ∈ r q and c.a.c ′ ∈ r q then c ∶ c ′ ∈ U

SOUNDNESS OF CHAIN INFERENCE IN THE POSSIBLY INFINITE CASE159

• if e ∈ e q then c ∶ e ∈ U [u = replace q 0 with q] In this case soundness follows as for delete and insert cases. The locations involved by u are copies of source locations in L q together with their descendants, and target locations returned by q 0 . By rule (SU-Replace) there is only one target location l 0 in the resulting sequence of q 0 , hence L q 0 =(l 0 ). We first treat the typing of source locations and the the typing of target locations. Source locations in L q are typed as stated by Theorem 4.3.4. We recall this fact, distinguishing between fresh and input source locations.

• If l ∈ L q belongs to the input document then By Proposition 9.1.6 we have that c σ l ∈ r q . Furthermore, for all l ′ descendant of l we have c σ l ′ ∈ r q . • If l ∈ L q is a fresh location, by Theorem 4.3.4 we have that l is typed by some chains in e q , formally c σw l .e ∈ e q . Furthermore, for all l ′ descendant of l we have c σw l ′ .e ′ ∈ e q . Recall that σ w is an intermediate store containing source locations that are arguments of elementary update commands not yet applied.

By Proposition 9.1.6 c σ l 0 ∈ r q 0 . Now we can conclude that source locations are typed since by rule (Replace) let c σ l 0 = c.a we have that • if c.a ∈ r q and c.a.c ′ ∈ r q then c ∶ a.c ′ ∈ U

• if e ∈ e q then c ∶ e ∈ U Concerning target locations, the statement follows since let c σ l 0 = c.a we have that c ∶ a ∈ U.

Induction.

[u = u 1 , u 2 ] The locations involved by the concatenation of two updates is the union of the locations involved by each expression. We conclude by inductive hypothesis on u 1 , u 2 .

[u = for x in q return u 1 ] The locations involved by the update are those involved by u 1 when x is bound to each node in the resulting sequence of q. By Proposition 9.1.6 the chain corresponding to all return location of q are inferred in r q . By inductive hypothesis the statement holds for the update u 1 when x is bound to a return chain inferred for q. This is described by rule (For), and therefore we conclude that the statement holds for u.

[u = let x ∶= q return u 1 ] The locations involved by the update are those involved by u 1 when applied with x bound to the resulting sequence of q. By Proposition 9.1.6 the chain corresponding to all return location of q are inferred in r q . By inductive hypothesis the statement holds for the update u 1 when x is bound to the resulting sequence of q.

CHAPTER 9. PROOFS This is described by rule (Let), and therefore we conclude that the statement holds for u 1 .

[u = if (q) then u 1 else u 2 ] The chains involved by u are those involved by u 1 or u 2 . By inductive hypothesis the statement holds for u 1 , u 2 and we conclude that it holds also for u.

In this section we proved the soundness of update chain inference. We showed that involved locations are always typed by some update chains, and that these update chains are correctly inferred. As for queries, completeness remains open and it is left as a future work. It is worth noticing however that completeness of chain inference for updates requires (as a necessary condition) chain inference for queries to be complete.

SOUNDNESS OF CHAIN INFERENCE IN THE POSSIBLY INFINITE CASE161

Soundness of Chain-based Independence

Proposition 9.1.7. If q ⊥ C d u, then we have:

We treat separately parts of the statement concerning t and u(t).

We show I t U ∩ L t r∪v = ∅, aiming at obtaining a contradiction. Assume there is an involved location l 0 belonging to a minimal q-projection, hence l ∈ I t U ∩ L t r∪v . We recall that the set of nodes of t typed by update chains in U is defined as

and the set of nodes in a tree t typed by chains in r ∪ v is defined as

Since confl(U, r) = ∅ there cannot exists c q ∈ r such that c.α.c ′ ⪯ c q . Hence we conclude that c.α.c ′ ∉ r. Finally, since confl(U, v) = ∅ there cannot exists c q ∈ v such that c ⪯ c q . Hence we conclude c.α.c ′ ∉ v. Therefore from q ⊥ C d u follows

The same reasoning holds for proving I

Theorem 4.4.2 (Soundness of C d independence) Let d be a DTD, t = (σ, l t ) ∈ d a valid tree, q a query, u an update, γ a dynamic environment and Γ a static environment such that σ

Proof. If q ⊥ C d u then by Proposition 9.1.7 we have that locations involved by the update are disjoint from location in a query projection. Since a query projection ensures preservation of query semantics under evaluation we can conclude q ⊧ d u.

CHAPTER 9. PROOFS

The existence of a folding relation between query chains and k query chains is stated by the following theorem. Lemma 9.2.5 (Folding of linear-path queries). Let d be a DTD, q a query with at most only one free variable x, and Γ = { x ↦ s d } a static environment. For all q ∈ LPQ(q), provided that Γ ⊢ C d q ∶ (r, v, e) and τ = r ∪ v ∪ e, for each chain c ∈ τ there exists a chain c ′ ∈ τ such that c ↪ * d c ′ and c ′ is a k q -chain. Thanks to the above lemma, we can finally conclude that the folding relation exists for chains inferred for all queries.

Lemma 4.4.4 (Folding) Let d be a DTD, q a query with at most only one free variable x, and

Proof. Let c ∈ τ q be a chain. By Lemma 9.2.2 we have that c ∈ τ LPQ(q) . We conclude since by Lemma 9.2.5 c can be folded to a k q -chains.

In the the remainder of this section we prove Lemma 9.2.5.

Folding Lemma for lp-queries

The height of an lp-query q, denoted by h(q), is defined as h( () ) = 0 h("txt") = 0 h(x axis ∶∶ φ) = 0 h(for x in q 1 return q 2 ) = 1 + max{h(q 1 ), h(q 2 )} h(<a>q< a>) = 1 + h(q)

The following lemma states that any chain can be folded to a 1-chain.

Lemma 9.2.6. Let d be a DTD. For all chain c ∈ C d there exists a 1-chain Now if c 1 .a.c 2 is a 1-chain then we are done, otherwise we repeat the folding process until we obtain a chain c ′ with no cycles, such that c ↪ * d c ′ . This process terminates because the number of symbols in c is finite.

SOUNDNESS OF THE CHAIN ANALYSIS FOR THE FINITE CASE 169

Lemma 9.2.5 (Folding of linear-path queries) Let d be a DTD, q a query with at most only one free variable x, and Γ = { x ↦ s d } a static environment. For all q ∈ LPQ(q), provided that Γ ⊢ C d q ∶ (r, v, e) and τ = r ∪ v ∪ e, for each chain c ∈ τ there exists a chain c ′ ∈ τ such that c ↪ * d c ′ and c ′ is a k q -chain.

Proof. By induction on h(q).

Base (h = 0) In this case q has one of the following three forms () "txt"

x axis ∶∶ φ

We conclude the proof by a case analysis.

[q = ()] Straightforward since τ q = ∅.

[q = "txt"] Recall that because the query "txt" is independent of any update, in Chapter 2 we assumed that "txt" is nested into a for expression. Furthermore, because we do not navigate on constructed sequences, we have that "txt" should be in the right branch of the for expression. Then, in order to do chain inference for "txt" we must have a navigational step in the left branch of q that makes k q > 0. In the case where k q = 0 it means that no operation is performed by the left branch of the query and thus chains for "txt" are not inferred by the type system rules. We conclude since τ q = {String} and String is a 1-chain.

[q = x axis ∶∶ φ] Because x ↦ s d we have that τ q ≠ ∅ only if axis is one of self, child, descendant, or descendant-or-self. We assume φ = a ∈ Σ and we proceed with a case analysis on axis. The proof for the case φ ∈ {node(), text()} is analogous, since node() can be simulated by ranging over all labels in Σ, and text() by considering only type String.

[axis = child] In this case k q = 1 and we conclude since either τ q = ∅ or τ q = { s d .a }, where s d ≠ a by hypothesis of non-recursive schema root (see Chapter 2).

[axis = self] In this case k q = 1 and we conclude since either τ q = ∅ or τ q = { s d }.

[axis = descendant] In this case k q = 1 since R(descendant ∶∶ a) = 1. We conclude since by Lemma 9.2.6 any chain can be folded to a 1-chain. [axis = descendant-or-self] Analogous to the self and descendant cases.

In this In this case q has one of two forms. <a> q ′ < a> for x in q 1 return q 2

[q = <a>q ′ < a>] We prove this case by making a case analysis wrt the set of used, return and element chains inferred for q.

CHAPTER 9. PROOFS used chains By rule (Elt), v q = r q ′ ∪ v q ′ . All chains inferred for the inner query q ′ are obtained by a derivation tree of height h(q ′ ) < h(q). Then by inductive hypothesis on q ′ we conclude the thesis for all chains in r q ′ ∪ v q ′ , since they are k q ′ -chains and provided that k q ′ ≤ k q they are k q -chains.

return chains By rule (Elt), r q = ∅ hence no return chain is inferred.

element chains We have two main cases to consider.

• If r q ′ ∪ v q ′ = ∅ then e q = {a}. We conclude since k q = 1.

• If r q ′ ∪ v q ′ ≠ ∅ then e q = e e q ∪ e r q where

The two sets are built from element and return chains of q ′ , respectively. Let us consider them separately.

-If a.c belongs to e e q then c ∈ e q ′ . By inductive hypothesis c is a (k q ′ )-chain.

a is the most frequent label in c with frequency upper bounded by k q ′ . Therefore a.c is a (1 + k q ′ )-chain and hence a k q -chain. In the case that k q = k q ′ then a is not the most frequent label in c. Thus the frequency of a in c is strictly upper bounded by k q ′ . Therefore a.c is still a k q ′ -chain and thus a k q -chain.

-If a.a.c ′ belongs to e r q then c.a ∈ r q ′ and c.a.c ′ ∈ r q ′ . By inductive hypothesis c.a.c ′ can be folded to a (1 + k q ′ )-chain c 1 .a.c ′ 1 . Thus a.a.c ′ can be folded to a.a.c ′ 1 . Provided that a.c ′ 1 is a (1 + k q ′ )-chain, we have that a.a.c ′ is again a (1 + k q ′ )-chain or the prefix a.c ′ can be folded to a (k q ′ )-chain, thus obtaining a (1 + k q ′ )-chain.

[q = for x in q 1 return q 2 ] Here q 2 possibly nests an arbitrary number n of iterations. In particular, we assume that the rightmost subexpression of q is a navigational step. It may also be that the rightmost subexpression is a text-element construction, but in that case the proof is a particular instance of the one given below where one does not make any use of the static variable environment. Any derivation tree of chain inference for q must end by applying the (For) rule, i.e., it looks like this (for simplicity we do not detail all rule operations)

where step i is of the form x i axis i ∶∶ φ i , with x i either a free-variable of q bound to the root-type in Γ, or a bound-variable of q previously defined in {x 1 , . . . , x i-1 }. Also, the resulting set of chains τ q ⊆ τ n ∪τ n+1 , as specified by rule (For).

We denote by h the height of the derivation tree for q. For each variable x i , chains in τ i are obtained by a derivation of height h i < h. By inductive hypothesis, the chains bound to x i can be folded to k i -chains, where k i is

Since τ q ⊆ τ n ∪τ n+1 , and all chains in τ n are k q -chains, what is left to show is that all chains inferred for step n+1 can be folded to k n+1 chains, provided that the static environment Γ binds variables with chains that can be folded to k n chains. This allows us to conclude the proof since k n+1 = k q .

We proceed with a case analysis on step i , assuming as before that φ i = a ∈ Σ. We focus on the cases where τ q ≠ ∅, i.e, the inference yields a non-empty result for some chains bound to x in Γ. When τ q = ∅ the thesis follows straightforwardly.

[step n+1 = x child ∶∶ a] In this case

By inductive hypothesis, for each c ∈ Γ(x) there exists a k n -chain c ′ ∈ Γ(x) such that c ↪ * d c ′ . Provided this, it follows c.a ↪ * d c ′ .a. We need to show that c ′ .a is a k n+1 -chain. We do this by distinguishing two cases, depending on wether

If k n = k n+1 , then c ′ .a is a k n -chain because a appears strictly less than k n times in c ′ . In other words, a is not the most frequent label in step 1 , . . . , step n . This can be shown as follows by considering that

and provided that

In the following we denote by c a the fact that a is the last symbol of the chain c, that is c = c ′ .a.

[step n+1 = descendant ∶∶ a] In this case

Given c.c a ∈ τ n+1 , by inductive hypothesis there exists a k n -chain c ′ ∈ Γ(x) such that c ↪ * d c ′ . By Lemma 9.2.6 the suffix c a can be folded to a 1-chain. 2 At this point we have that c.c a ↪ * d c ′ .c ′ a . Provided that c ′ is a k n -chain and c ′ a is a 1-chain, c ′ .c ′ a is (1+k n )-chain. We conclude since R(descendant) = 1 and thus k n+1 = k n +1. [step n+1 = descendant-or-self ∶∶ a] Analogous to the case descendant.

[step n+1 = parent ∶∶ a] In this case Now it remains to show that k n+1 = 1 + k n . We reason by contradiction. Assume k n+1 = k n . Then, as shown for the case axis = child, a is not the most frequent label in step 1 , . . . , step n . Since a belongs to w a , then also this symbols are not the most frequent in step 1 , . . . , step n . Thus there exists a chain c ′ a preserving the suffix b.a. A contradiction.

[step n+1 = ancestor ∶∶ a] In this case

We want to show a folding for c a .

We have two cases to consider, depending on wether a is recursive or not. and we conclude. It remains to show that some c ′′ i constructed as above belong to Γ(x). Assume that for all c ′′ i we have that c ′′ a ∉ Γ(x) then we conclude that step 1 , . . . , step n do not employ recursive navigations. A contradiction.

[step n+1 = following-sibling ∶∶ a] In this case

We want to show a folding for c p .a. By case axis = parent, we know that there exists a (1

Also, in this case the last label of c ′ p may be a as well. Now independently from whether a = a or not c ′ p .a is a 1 + k n -chain, as well as c ′ p .a. If k n+1 = 1 + k n , then we conclude. Otherwise, if k n+1 = k n then, analogously to the case axis = child, we can show that a is not the most frequent label in step 1 , . . . , step n , and thus that c ′ p .a is a k n -chain.

◻

Remark 9.2.7. As a direct corollary of the lemma we can approximate the problem of query unsatisfiability in presence of a schema just looking on query k-chains. Indeed, if no k-chain is inferred for the input query expression, then no data match query needs. Moreover, for the subset of queries and schemas that make our chain inference system enjoying completeness, we can exactly determine wether a query is satisfiable or not in presence of a schema.

Folding Lemma with conflict preservation

In this section we prove Lemma 4.4.5, by showing the existence of a folding relation that preserves also conflicts among chains. We show that such a folding exists for a pair of expressions if the multiplicity value we take is the sum of the multiplicity value of each expression.

Lemma 9.2.8. Let d be a DTD, q 1 , q 2 two queries with at most only one free variable x, and

Proof. We consider first the case when c 1 , c 2 are either used or return chains. Since c 1 ⪯ c 2 , we have that c 2 is the longest chain and we make a case analysis on q 2 . We distinguish three main cases depending on whether q 2 contains some recursive axis or not. If q 2 does not contains (forward or backward) recursive axis, τ q 2 is finite. Moreover, CHAPTER 9. PROOFS all chains in τ q 2 have height upper bounded by q 2 and label frequency upper bounded by

chain as well. Let k=k q 1 + k q 2 we conclude that all pairs of conflicting chains are k-chains, as desired. Notice that if q 2 also uses recursive backward navigation the statement still hold. As a matter of facts, a backward navigation would just backtrack on the input chain, without affecting the property that chains inferred for q 2 are k q 2 chains.

If q 2 uses at least one recursive forward axis, then an upper bound of the label frequency of chains witnessing the conflict is

The case requiring the largest k value occur when each prefix of q 2 navigates some descendant of nodes selected by q 1 , in the sense that c 2 ∈ τ q 2 , when q 2 has only one free variable x, and the chains are derived with the judgment

In this case let q 1 ○ q 2 be the composition of the two expressions, that is 5 q 1 ○ q 2 def = for x in q 1 return q 2 By definition we have that k q 1 ○q 2 = k q 1 + k q 2 . By Lemma 4.4.4 we can fold c ∈ τ q 1 ○q 2 to a k q 1 +q 2 -chain c ′ , such that c ′ is of the form c ′ 1 .c ′′ , with c ′ 1 a k q 1 -chain for q 1 and c ′ a (k q 1 +k q 2 )-chain for q 2 , thus exhibiting a pair of folded chains as desired.

In the remaining case where some q ′ 2 prefix of q 2 does not navigate descendants of nodes returned by q 1 , then either q ′ 2 is navigating some ancestors of types returned by q 1 , or q ′ 2 is navigating in parallel a node which is also navigated by q 1 (and of course in order to have a conflict, a sibling navigation should follow in the sequel). In both cases we need a multiplicity value upper bounded by the one given by the case shown above, when each q ′ 2 prefix of path q 2 navigates some descendant of c 1 .

Correctness when either c 1 or c 2 are element chains follows, since element chains are either completely specified, and then folding is not needed (seen that label frequency is precisely kept into account by F(, )), or they have an head completely specified and tail taken from a return chain, for which we assume the thesis holds by induction.

CHAPTER 9. PROOFS

[u = delete q 0 ] In this case q ⊥ C d u implies confl(r q , U u ) ∪ confl(U u , r q ) ∪ confl(U u , v q ) ≠ ∅ Since U u = r q 0 (up to ":" separator), let k = k q + k q 0 . By lemma 4.4.5 confl(r q , r q 0 ) ≠ ∅ implies confl(r k q , r k q 0 ) ≠ ∅ confl(r q 0 , r q ) ≠ ∅ implies confl(r k q 0 , r k q ) ≠ ∅ confl(r q 0 , v q ) ≠ ∅ implies confl(r k q 0 , v k q ) ≠ ∅ and therefore we conclude q ⊥ C k d u.

[u = rename q 0 as a] In this case q ⊥ C d u implies confl(r q , U u ) ∪ confl(U u , r q ) ∪ confl(U u , v q ) ≠ ∅ Recall that U u = U 1 ∪ U 2 where U 1 = { c∶b c.b ∈ r q 0 } and U 2 = { c∶a c.b ∈ r q 0 } For all conflicting update chain belonging to U 1 we conclude as for the delete case.

For all conflicting update chain belonging to U 2 we make a case analysis on the kind of conflict. confl(r q , U 2 ) For all (c q , c u ) ∈ r q ×U 2 such that c q ⪯ c u we have two cases to consider: c q ≺ c u and c q = c u . If c q ≺ c u then confl(r q , U 2 ) ≠ ∅ if and only if confl(r q , U 1 ) ≠ ∅ because the conflict arises on a label preceding the renamed one. Then reasoning as for U 1 we conclude q ⊥ C k d u. If c q = c u , we distinguish again if confl(r q , U 1 ) ≠ ∅ or not. If confl(r q , U 1 ) ≠ ∅ then we conclude q ⊥ C k d u as before. If confl(r q , U 1 ) = ∅ then in order for the update to be valid wrt the schema a is required to be a sibling of a type returned by q 0 . Since confl(r q , U 1 ) = ∅ then c.b ∈r 0 and this means that q 0 specifies a label b ≠ a in the step generating c.b. We modify q 0 substituting b with a and we conclude by Lemma 4.4.5 on q, q 0 noticing that adding a a tag in q 0 raises a label frequency of 1 at most. confl(U 2 , r q ) For all (c u , c q ) ∈ U 2 ×r q such that c u ⪯ c q we only consider: c u ≺ c q since c q = c u has been adressed in the case of confl(r q , U 2 ). With a case analysis on the emptiness of confl(U 1 , r q ) and by substituting a with b in q 0 , we conclude q ⊥ C k d u as before.

confl(U 2 , v q ) Identical to confl(U 2 , r q ).

SOUNDNESS OF THE CHAIN ANALYSIS FOR THE FINITE CASE

179

[u = insert q 1 pos q 0 ] In this case q ⊥ C d u implies confl(r q , U u ) ∪ confl(U u , r q ) ∪ confl(U u , v q ) ≠ ∅

We consider the case pos = into since other cases are similar. Recall that U = U 1 ∪ U 2 where U 1 = { c∶e c ∈ r q 0 e ∈ e q 1 } U 2 = { c∶α.c ′ c ∈ r q 0 c 1 .α ∈ r q 1 c 1 .α.c ′ ∈ C d }

We consider first conflicts generated by U 1 confl(r q , U 1 ) For all (c q , c u ) ∈ r q × U 1 such that c q ⪯ c u , let c u = c ∶ e we have two cases to consider depending on wether c q ⪯ c or c ≺ c q . If c q ⪯ c, by Lemma 4.4.5 on q, q 0 we can fold c q to c ′ q and c to c ′ with c ′ q , c ′ both (k q +k q 0 )-chains. Since e is created by element construction it is completely specified and it is easy to see that c ′ .e is a (k q +k u )-chain.

If c ≺ c q by Lemma 4.4.5 on q, q 0 we can fold c q to c ′ q and c to c ′ with c ′ q , c ′ both (k q +k q 0 )-chains. Let e ⪯ e such that c.e = c q , since e is completely specified by query syntax by in the element construction then we have c ′′ q = c ′′ .e as a folding of c q that preserves e as a suffix, with c ′′ a folding of c as prefix, and c ′′ q is a (k q +k q 0 )-chain. Also, of course c ′′ .e is a (k q +k u )-chain and we conclude q ⊥ C k d u.

confl(U 1 , r q ) Analogous to confl(r q , U 1 ). confl(U 1 , v q ) Analogous to confl(r q , U 1 ).

Concerning U 2 , we want to show that we can restrict the conflict analysis on a subset of U 2 namely U ′ 2 defined as U ′ 2 = { c∶α c ∈ r q 0 c 1 .α ∈ r q 1 } • If confl(r q , U 2 ) = ∅ then either confl(r q , U ′ 2 ) or confl(U ′ 2 , r q ). • If confl(U 2 , r q ) = ∅ then confl(U ′ 2 , r q ). • If confl(U 2 , v q ) = ∅ then confl(U ′ 2 , v q ). The proof for confl(r, U ′ 2 ) follows as for the rename case.

[u = replace q 0 with q] The statement follows as a combination of delete and insert cases.

Induction.

[u = u 1 , u 2 ] By inductive hypothesis on u 1 , u 2 .

CHAPTER 9. PROOFS

[u = for x in q return u 1 ] By inductive hypothesis on the length of the derivation for q and then for u. Analogous to the case of Lemma 9.2.5.

[u = let x ∶= q return u 1 ] Analogous to the for case.

[u = if (q) then u 1 else u 2 ] By inductive hypothesis on the length of the derivation for q, u 1 and u 2 .

Theorem 9.2.11 (Soudness of C k d Independence). Let d be a DTD, q a query and u an update, with at most only one free variable x, which is always bound, during static analysis, to the root type s d and, during query evaluation, to the root location l t of a valid tree t ∈ d. Let k = k q + k u as defined above, then q ⊥ C k d u implies q ⊧ d u

Proof. Straightforward since by Theorem 9.2.10 q ⊥ C d u iff q ⊥ C k d u, and by Theorem 4.4.2 q ⊥ C d u implies q ⊧ d u.