Contexte des expressions et évaluation des requêtes (XQuery)

Le contexte d'une expression rassemble les informations utilisées pour l'analyser et l'évaluer. Voici les deux phases au cours desquelles XQuery est évalué :

  • Contexte statique : il s'agit de la phase de compilation de la requête. En fonction des informations disponibles, des erreurs sont quelquefois générées au cours de l'analyse statique de la requête.

  • Contexte dynamique : il s'agit de la phase d'exécution de la requête. Même si elle ne présente pas d'erreurs statiques (erreurs survenues lors de la compilation de la requête), la requête peut renvoyer des erreurs au cours de son exécution.

Contexte statique

L'initialisation du contexte statique consiste à rassembler toutes les informations requises par l'analyse statique de l'expression. L'initialisation du contexte statique comprend les étapes suivantes :

  • La stratégie espace limite est définie sur strip. Par conséquent, l'espace limite n'est pas préservé par les constructeurs any element et attribute dans la requête. Par exemple :

    declare @x xml
    set @x=''
    select @x.query('<a>  {"Hello"}  </a>,
    
        <b> {"Hello2"}  </b>')
    

    Cette requête renvoie le résultat suivant puisque l'espace limite est ignoré lors de l'analyse de l'expression XQuery :

    <a>Hello</a><b>Hello2</b>
    
  • Le préfixe et l'espace de noms de liaison sont initialisés pour les éléments suivants :

    • Un ensemble d'espaces de noms prédéfinis.

    • Tous les espaces de noms définis à l'aide de WITH XMLNAMESPACES. Pour plus d'informations, consultez Ajout d'espaces de noms à l'aide de WITH XMLNAMESPACES).

    • Tous les espaces de noms définis dans le prologue de la requête. Remarquez que les déclarations d'espace de noms du prologue peuvent remplacer la déclaration d'espace de noms de WITH XMLNAMESPACES. Dans la requête suivante, par exemple, WITH XMLNAMESPACES déclare un préfixe (pd) qui établit une liaison avec l'espace de noms (http://someURI). En revanche, dans la clause WHERE, le prologue de la requête remplace la liaison.

      WITH XMLNAMESPACES ('http://someURI' AS pd)
      SELECT ProductModelID, CatalogDescription.query('
          <Product 
              ProductModelID= "{ sql:column("ProductModelID") }" 
              />
      ') AS Result
      FROM Production.ProductModel
      WHERE CatalogDescription.exist('
          declare namespace  pd="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
           /pd:ProductDescription[(pd:Specifications)]'
          ) = 1
      

    Toutes les liaisons d'espace de noms sont résolues au cours de l'initialisation du contexte statique.

  • En cas d'interrogation d'une colonne ou d'une variable de type xml, les composants de la collection de schémas XML associée à la colonne ou à la variable sont importés dans le contexte statique. Pour plus d'informations, consultez Comparaison du XML typé et du XML non typé.

  • Pour chaque type atomique des schémas importés, une fonction de conversion est également mise à disposition dans le contexte statique. L'exemple suivant illustre ce concept. Dans cet exemple, une requête porte sur une variable de type xml. La collection de schémas XML associée à cette variable définit un type atomique, myType. Avec ce type, une fonction de conversion, myType(), est disponible au cours de l'analyse statique. L'expression de la requête (ns:myType(0)) renvoie une valeur de type myType.

    -- DROP XML SCHEMA COLLECTION SC
    -- go
    CREATE XML SCHEMA COLLECTION SC AS '<schema xmlns="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="myNS" xmlns:ns="myNS"
    xmlns:s="https://schemas.microsoft.com/sqlserver/2004/sqltypes">
          <import namespace="https://schemas.microsoft.com/sqlserver/2004/sqltypes"/>
          <simpleType name="myType">
                <restriction base="int">
                 <enumeration value="0" />
                  <enumeration value="1"/>
                </restriction>
          </simpleType>
          <element name="root" type="ns:myType"/>
    </schema>'
    go
    
    DECLARE @var XML(SC)
    SET @var = '<root xmlns="myNS">0</root>'
    -- specify myType() casting function in the query
    SELECT @var.query('declare namespace ns="myNS"; ns:myType(0)')
    

    Dans l'exemple suivant, la fonction de conversion du type XML intégré int est spécifiée dans l'expression.

    declare @x xml
    set @x = ''
    select @x.query('xs:int(5)')
    go
    

Après l'initialisation du contexte statique, l'expression de requête est analysée (compilée). L'analyse statique implique les étapes suivantes :

  1. Analyse de la requête.

  2. Résolution des noms de fonction et de type spécifiés dans l'expression.

  3. Typage statique de la requête. De cette façon, le type de la requête est sûr. Par exemple, la requête suivante renvoie une erreur statique car l'opérateur + requiert des arguments de type Primitive.

    declare @x xml
    set @x=''
    SELECT @x.query('"x" + 4')
    

    Dans l'exemple suivant, l'opérateur value() requiert un singleton. Comme indiqué dans le schéma XML, il peut exister plusieurs éléments <Elem>. L'analyse statique de l'expression détermine que le type n'est pas sûr et une erreur statique est générée. Pour corriger cette erreur, vous devez réécrire l'expression de façon à spécifier explicitement un singleton (data(/x:Elem)[1]).

    DROP XML SCHEMA COLLECTION SC
    go
    CREATE XML SCHEMA COLLECTION SC AS '<schema xmlns="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="myNS" xmlns:ns="myNS"
    xmlns:s="https://schemas.microsoft.com/sqlserver/2004/sqltypes">
          <import namespace="https://schemas.microsoft.com/sqlserver/2004/sqltypes"/>
          <element name="Elem" type="string"/>
    </schema>'
    go
    
    declare @x xml (SC)
    set @x='<Elem xmlns="myNS">test</Elem><Elem xmlns="myNS">test2</Elem>'
    SELECT @x.value('declare namespace x="myNS"; data(/x:Elem)[1]','varchar(20)')
    

    Pour plus d'informations, consultez XQuery et le typage statique.

Limites de la mise en œuvre

Voici les limites liées à un contexte statique :

  • Le mode de compatibilité XPath n'est pas pris en charge.

  • En cas de construction XML, seul le mode de construction strip est pris en charge. Il s'agit du paramètre par défaut. Par conséquent, le nœud d'élément construit est de type xdt:untyped et les attributs de type xdt:untypedAtomic.

  • Seul le mode de classement ordered est pris en charge.

  • Seule la stratégie d'espaces XML strip est prise en charge.

  • La fonctionnalité URI de base n'est pas prise en charge.

  • La fonction fn:doc() n'est pas prise en charge.

  • La fonction fn:collection() n'est pas prise en charge.

  • XQuery Static Flagger n'est pas fourni.

  • Le classement associé au type de données xml est utilisé. Ce classement est toujours paramétré sur le classement des points de code Unicode.

Contexte dynamique

Le contexte dynamique fait référence aux informations dont vous devez disposer au moment de l'exécution de l'expression. Outre le contexte statique, les informations suivantes sont initialisées comme partie du contexte dynamique :

  • Le focus de l'expression tel que l'élément contextuel, la position contextuelle et la taille du contexte, est initialisé comme le montre l'exemple suivant. Remarquez que toutes ces valeurs peuvent être remplacées par la méthode nodes().

    • Le type de données xml prend pour élément contextuel (soit le nœud à traiter), le nœud de document.

    • La position contextuelle, c'est-à-dire la position de l'élément contextuel par rapport aux nœuds à traiter, est tout d'abord définie à 1.

    • La taille du contexte, c'est-à-dire le nombre d'éléments de la séquence à traiter, est tout d'abord définie à 1 puisqu'il y a toujours un seul nœud de document.

Limites de la mise en œuvre

Voici les limites liées à un contexte dynamique :

  • Les fonctions de contexte Date et heure actuelles, fn:current-date, fn:current-time et fn:current-dateTime, ne sont pas prises en charge.

  • Le fuseau horaire implicite est fixé à UTC+0 et ne peut pas être modifié.

  • La fonction fn:doc() n'est pas prise en charge. Toutes les requêtes s'exécutent sur des colonnes ou des variables de type xml.

  • La fonction fn:collection() n'est pas prise en charge.