SlideShare a Scribd company logo
28   msec
            Not Your Grandma’s XQuery
            Key Features & Perspectives
            William Candillon {candillon@28msec.com}
            XML Amsterdam 2011
“What I saw in your five-minutes talk hardly
looks at all like the XQuery I saw back then.”


                     - Daniel Weinred, Google
Not Your Grandma’s XQuery
Download the CoreSDK
Deploy in one-click
Automatic Scaling
Not your Grandma's XQuery
• ........
Not your Grandma's XQuery
Not your Grandma's XQuery
Not your Grandma's XQuery
Not your Grandma's XQuery
Not your Grandma's XQuery
Not your Grandma's XQuery
Not your Grandma's XQuery
Not your Grandma's XQuery
Not your Grandma's XQuery
Not your Grandma's XQuery
Not your Grandma's XQuery
Not your Grandma's XQuery
Not your Grandma's XQuery
Application Stack



    Client      JavaScript


  Middleware         Java

   Content
                    Lucene
  Management

   Database         MySQL
Application Stack



    Client      JavaScript


  Middleware         Java

   Content
                             XQuery
                    Lucene
  Management

   Database         MySQL
Application Stack



    Client              in the Browser


  Middleware               Scripting

   Content
               XQuery
                           Full-Text
  Management

                        Data Definition
   Database
                            Facility
XQuery Data Definition Facility


    • Open Specification (http://goo.gl/XzK8p)
    • Implemented by Zorba (http://goo.gl/4huso)
    • Extending XQuery with
      - Collections
      - Indexes
      - Integrity Contraints
declare collection f:forecasts as element(forecast);
declare %automatic %value-equality %non-unique index
f:forecasts-index
  on nodes cdml:collection(xs:QName("f:forecasts"))
  by @site-id as xs:string;
Index Properties
declare %automatic %value-equality %non-unique index
f:forecasts-index
  on nodes cdml:collection(xs:QName("f:forecasts"))
  by @site-id as xs:string;
Index Name
declare %automatic %value-equality %non-unique index
f:forecasts-index
  on nodes cdml:collection(xs:QName("f:forecasts"))
  by @site-id as xs:string;
declare %automatic %value-equality %non-unique index
f:forecasts-index
  on nodes cdml:collection(xs:QName("f:forecasts"))
  by @site-id as xs:string;
                            Domain Expression
declare %automatic %value-equality %non-unique index
f:forecasts-index
  on nodes cdml:collection(xs:QName("f:forecasts"))
  by @site-id as xs:string;

          Index Key
declare %automatic %value-equality %non-unique index
f:forecasts-index
  on nodes cdml:collection(xs:QName("f:forecasts"))
  by @site-id as xs:string, @city as xs:string;
declare %automatic %value-range index
f:forecasts-index
  on nodes cdml:collection(xs:QName("f:forecasts"))
  by @temperature as xs:decimal;
Not your Grandma's XQuery
$ sausalito backup data
Backup data for project at:   /Users/test/forecast
Project URI:                  http://www.example.com/

Starting backup for collection data ... OK
Backup successful

$ sausalito restore data -f forecast.tar.gz
Restored data
Full-Text

• XQuery and XPath Full Text 1.0
• Thesaurus
• Stemming
• Complete access to the full text internals
 ft:tokenize($node, $lang)
 ft:tokenizer-properties()

 ft:thesaurus-lookup($uri, $phrase)

 ft:stem($work)

 ...
$data//element()[. contains text {$search-term}]
let $x := <msg>breakfast of champions</msg>
return $x contains text "meal"
  using thesaurus at "http://wordnet.princeton.edu"
  relationship "narrower term"
ft:stem( "flavoring", xs:language("en") )
let $doc := doc(“doc.xml”)
for $token in ft:tokenize($doc)
return
  concat($token/@value, “ at ”,
         $token/@paragraph,
         $token/@sentence
  )
Scripting


• Open Specification
• Implemented by Zorba
• Friendly syntax for imperative programming
• Semantic for side-effects
• Specification at http://goo.gl/kTYuf
• Tutorial at http://goo.gl/F23je
let $handler :=
  function($request){
    let $world := $request/http:body/text()
    return
      <h1>Hello {$world}!</h1>
  }
return mongoose:start($handler, 8080);
mongoose:cin();
while(true()) {
   variable $request := server:listen("localhost", 8080);
   variable $response := api:process($request);
   api:serialize($response)
};
if(count($result) lt count($collection)) then {
   http:set-header("x-truncated", "true");
   http:set-header("x-next", "/api?start=7b5c28c0");
} else {
 http:set-header("x-truncated", "false");
};
$result
in the Browser




• Open Source Project from ETH
• http://xqib.org
• XQuery in the browser without a plug-in
• Processor compiled to JavaScript
• DOM as the processor store
<script type=”application/xquery��>
b:addEventListener(b:dom()//*:button, "onclick",
   function($ev, $obj){
     b:alert(“Clicked”)
   }
);
</script>
<script type="text/javascript">
foo = function (arg){
        return 'the text was '+ arg;
};
</script>

<script type="application/xquery">
! let $x := b:js-call('window.foo', “Foo”)
! return
     b:alert($x)
</script>
<script type="application/xquery">
b:js-eval('window.alert("eval!")')
</script>
declare variable $ui:easing := (0, 0.02, 0.08,
0.19, 0.33, 0.5, 0.67, 0.81, 0.92, 0.98, 1);

declare sequential function ui:fade() {
  declare $con     := b:dom()//*[@id = "entries"];
  declare $opacity := b:getStyle($con, "opacity");

     if($opacity lt 1) then (
       b:setStyle($con, "opacity",
                  $ui:easing[. gt $opacity][1]),
       b:timer(100, ui:fade#0)
     ) else b:setStyle($con, "opacity", 1)
};
Client                                          Server

<script type="application/xquery">
declare sequential function                        declare sequential function guestbook:add(
local:submit($loc, $evtObj)                           $author as xs:string, $entry as xs:string
{                                                  ){
                                                      let $date   := fn:current-dateTime()
     let $name    := s:id("author")/data(@value)      let $entry := <entry author="{$author}"
     let $text    := s:id("text")/text()                        datetime="{$date}">{$text}</entry>
     return                                           return
       guestbook:add($name, $text);                      xqddf:insert-nodes-last($entries, $entry);
};                                                 };

b:addEventListener(s:id("submit"),                 declare sequential function guestbook:list() {
                  "onclick",                          <entries>{
                   local:submit#2);                     xqddf:collection($entries)
                                                      }</entries>;
guestbook:list();                                  };
</script>
Client                                          Server

<script type="application/xquery">
declare sequential function                        declare sequential function guestbook:add(
local:submit($loc, $evtObj)                           $author as xs:string, $entry as xs:string
{                                                  ){
                                                      let $date   := fn:current-dateTime()
     let $name    := s:id("author")/data(@value)      let $entry := <entry author="{$author}"
     let $text    := s:id("text")/text()                        datetime="{$date}">{$text}</entry>
     return                                           return
       guestbook:add($name, $text);                      xqddf:insert-nodes-last($entries, $entry);
};                                                 };

b:addEventListener(s:id("submit"),                 declare sequential function guestbook:list(){
                  "onclick",                          <entries>{
                   local:submit#2);                     xqddf:collection($entries)
                                                      }</entries>;
guestbook:list();                                  };
</script>



         Seamless Invocations
Pubzone (2009)

                                  Model              View
                                  Controler

                           4100
    Lines of code



                    3100



                                                     1830

                                                             1210
                                    900
                                              450


                           Java                     XQuery
AWS Libraries

                                       Java               XQuery

                    8589
    Lines of code




                                          2905
                                                             2309
                                1469
                                                    572                   455


                           S3                 SimpleDB              SNS
AWS Libraries

                Java            XQuery

                 13803



                                         Lines of Codes
Lines of code




                                             - 80%
                               2496




                         AWS
AWS Libraries

                PHP            XQuery

                 6531



                                        Lines of Codes
Lines of code




                              2496
                                            - 62%

                        AWS
<html>
  <head>
    <script type='text/javascript'>
    function buy(e) {
       newElement = document.createElement("p");
       elementText = document.createTextNode
                  (e.target.getAttribute(id));
       newElement.appendChild(elementText);
       var res = document.evaluate(
         "//div[@id='shoppingcart']",
         document, null,
         XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,            HTML
         null);
       res.snapshotItem(0).appendChild("newElement");}
    </script>                                               JavaScript
  </head>
  <body>
    <div>Shopping cart</div>
    <div id="shoppingcart"></div>
    <%
                                                             XPath
       // Code establishing connection
       ResultSet results =
       statement.executeQuery ("SELECT * FROM PRODUCTS");
       while (results.next()) {
         out.println("<div>");
                                                               Java
         String prodName = results.getString(1);
         out.println(prodName);
         out.println("<input type='button' value='Buy'");
         out.println("id='"+prodName+"'");                    SQL
         out.println("onclick='buy(event)'/>").
         out.println("</div>");
       }
       results.close();
       // Code closing connection
    %>
  </body>
</html>
<html xmlns="http://www.w3.org/1999/xhtml">
   <head>
    <script type='application/xquery'>
declare updating function local:buy($evt, $obj) {
   insert node <p>{$obj/@id}</p> as first
     into //div[@id="shoppingcart"]
};
b:addEventListener(b:dom()//input,
                     "onclick",
                     xs:Qname("local:buy"));
</script>
   </head>
   <body>
     <div>Shopping cart</div>
     <div id="shoppingcart">{
                                                    XQuery Everywhere
       for $p in doc("products.xml")//*:product
       return
          <div>
            {$p/*:name}
            <input type='button'
                   value='Buy'
                   id='{$p/*:name}'/>
          </div>
     }</div>
   </body>
</html>
Wadler's theorem of language adoption



“A programming language will be adopted
 if and only if
 it permits its users to
 do something that cannot be done in any
 other way.”
GO



                   Mapping              Mapping
JavaScript                       Java             SQL
                      Glue               Glue




         GO
                    Seamless
                   Invocations
XQuery                                  XQuery
GO



                                           Mapping
JavaScript           Local          Java
                     Store                           SQL
                                            Glue
              Sync           Sync
GO



                                                        Mapping
JavaScript                    Local              Java
                              Store                               SQL
                                                         Glue
                   Sync                   Sync




         GO




XQuery                      Local                       XQuery
                            Store

                     Seamless Synchronisation
Demo Offline XQuery App
XQuery in Mobile Apps
• 2 XQuery Stores
  - DOM
  - HTML5 Local Storage
• When Offline
 - Each update is applied to local store
 - Pending Update Lists are stored in the local store

• When Online
 - PULs are aggregated and sent to the Cloud
 - PULs are applied to the Cloud
insert node attribute done { “true” }
  into xqddf:collection($todos)[@id = $id]
insert node attribute done { “true” }
    into xqddf:collection($todos)[@id = $id]


1. Apply PUL
   Store PUL


            Local Store

TODOs   <todo done=”true”/>

        <insert src=”...”
PULs            target=”...” />
insert node attribute done { “true” }
    into xqddf:collection($todos)[@id = $id]




           Local Store        2. Send PUL
TODOs   <todo done=”true”/>

PULs
insert node attribute done { “true” }
    into xqddf:collection($todos)[@id = $id]




           Local Store
                                     3. Apply PUL
TODOS   <todo done=”true”/>

PULs
Operators on Updates



• Aggregation
• Integration (+ detecting conflicts)
• Reconciliation of conflicts
• Reduction
• Inversion
Spacial Axis
Time Axis
avg(
           $tempA/future-or-current::*
              intersect
           $tempB/past-or-current::*
         )              Text


                                               Time
 68°       70°       65°      69°        72°

$tempA                               $tempB
Not your Grandma's XQuery
28   msec
            Thank you!

More Related Content

Not your Grandma's XQuery

  • 1. 28 msec Not Your Grandma’s XQuery Key Features & Perspectives William Candillon {candillon@28msec.com} XML Amsterdam 2011
  • 2. “What I saw in your five-minutes talk hardly looks at all like the XQuery I saw back then.” - Daniel Weinred, Google
  • 22. Application Stack Client JavaScript Middleware Java Content Lucene Management Database MySQL
  • 23. Application Stack Client JavaScript Middleware Java Content XQuery Lucene Management Database MySQL
  • 24. Application Stack Client in the Browser Middleware Scripting Content XQuery Full-Text Management Data Definition Database Facility
  • 25. XQuery Data Definition Facility • Open Specification (http://goo.gl/XzK8p) • Implemented by Zorba (http://goo.gl/4huso) • Extending XQuery with - Collections - Indexes - Integrity Contraints
  • 26. declare collection f:forecasts as element(forecast);
  • 27. declare %automatic %value-equality %non-unique index f:forecasts-index on nodes cdml:collection(xs:QName("f:forecasts")) by @site-id as xs:string;
  • 28. Index Properties declare %automatic %value-equality %non-unique index f:forecasts-index on nodes cdml:collection(xs:QName("f:forecasts")) by @site-id as xs:string;
  • 29. Index Name declare %automatic %value-equality %non-unique index f:forecasts-index on nodes cdml:collection(xs:QName("f:forecasts")) by @site-id as xs:string;
  • 30. declare %automatic %value-equality %non-unique index f:forecasts-index on nodes cdml:collection(xs:QName("f:forecasts")) by @site-id as xs:string; Domain Expression
  • 31. declare %automatic %value-equality %non-unique index f:forecasts-index on nodes cdml:collection(xs:QName("f:forecasts")) by @site-id as xs:string; Index Key
  • 32. declare %automatic %value-equality %non-unique index f:forecasts-index on nodes cdml:collection(xs:QName("f:forecasts")) by @site-id as xs:string, @city as xs:string;
  • 33. declare %automatic %value-range index f:forecasts-index on nodes cdml:collection(xs:QName("f:forecasts")) by @temperature as xs:decimal;
  • 35. $ sausalito backup data Backup data for project at: /Users/test/forecast Project URI: http://www.example.com/ Starting backup for collection data ... OK Backup successful $ sausalito restore data -f forecast.tar.gz Restored data
  • 36. Full-Text • XQuery and XPath Full Text 1.0 • Thesaurus • Stemming • Complete access to the full text internals ft:tokenize($node, $lang) ft:tokenizer-properties() ft:thesaurus-lookup($uri, $phrase) ft:stem($work) ...
  • 38. let $x := <msg>breakfast of champions</msg> return $x contains text "meal" using thesaurus at "http://wordnet.princeton.edu" relationship "narrower term"
  • 40. let $doc := doc(“doc.xml”) for $token in ft:tokenize($doc) return concat($token/@value, “ at ”, $token/@paragraph, $token/@sentence )
  • 41. Scripting • Open Specification • Implemented by Zorba • Friendly syntax for imperative programming • Semantic for side-effects • Specification at http://goo.gl/kTYuf • Tutorial at http://goo.gl/F23je
  • 42. let $handler := function($request){ let $world := $request/http:body/text() return <h1>Hello {$world}!</h1> } return mongoose:start($handler, 8080); mongoose:cin();
  • 43. while(true()) { variable $request := server:listen("localhost", 8080); variable $response := api:process($request); api:serialize($response) };
  • 44. if(count($result) lt count($collection)) then { http:set-header("x-truncated", "true"); http:set-header("x-next", "/api?start=7b5c28c0"); } else { http:set-header("x-truncated", "false"); }; $result
  • 45. in the Browser • Open Source Project from ETH • http://xqib.org • XQuery in the browser without a plug-in • Processor compiled to JavaScript • DOM as the processor store
  • 46. <script type=”application/xquery”> b:addEventListener(b:dom()//*:button, "onclick", function($ev, $obj){ b:alert(“Clicked”) } ); </script>
  • 47. <script type="text/javascript"> foo = function (arg){ return 'the text was '+ arg; }; </script> <script type="application/xquery"> ! let $x := b:js-call('window.foo', “Foo”) ! return b:alert($x) </script>
  • 49. declare variable $ui:easing := (0, 0.02, 0.08, 0.19, 0.33, 0.5, 0.67, 0.81, 0.92, 0.98, 1); declare sequential function ui:fade() { declare $con := b:dom()//*[@id = "entries"]; declare $opacity := b:getStyle($con, "opacity"); if($opacity lt 1) then ( b:setStyle($con, "opacity", $ui:easing[. gt $opacity][1]), b:timer(100, ui:fade#0) ) else b:setStyle($con, "opacity", 1) };
  • 50. Client Server <script type="application/xquery"> declare sequential function declare sequential function guestbook:add( local:submit($loc, $evtObj) $author as xs:string, $entry as xs:string { ){ let $date := fn:current-dateTime() let $name := s:id("author")/data(@value) let $entry := <entry author="{$author}" let $text := s:id("text")/text() datetime="{$date}">{$text}</entry> return return guestbook:add($name, $text); xqddf:insert-nodes-last($entries, $entry); }; }; b:addEventListener(s:id("submit"), declare sequential function guestbook:list() { "onclick", <entries>{ local:submit#2); xqddf:collection($entries) }</entries>; guestbook:list(); }; </script>
  • 51. Client Server <script type="application/xquery"> declare sequential function declare sequential function guestbook:add( local:submit($loc, $evtObj) $author as xs:string, $entry as xs:string { ){ let $date := fn:current-dateTime() let $name := s:id("author")/data(@value) let $entry := <entry author="{$author}" let $text := s:id("text")/text() datetime="{$date}">{$text}</entry> return return guestbook:add($name, $text); xqddf:insert-nodes-last($entries, $entry); }; }; b:addEventListener(s:id("submit"), declare sequential function guestbook:list(){ "onclick", <entries>{ local:submit#2); xqddf:collection($entries) }</entries>; guestbook:list(); }; </script> Seamless Invocations
  • 52. Pubzone (2009) Model View Controler 4100 Lines of code 3100 1830 1210 900 450 Java XQuery
  • 53. AWS Libraries Java XQuery 8589 Lines of code 2905 2309 1469 572 455 S3 SimpleDB SNS
  • 54. AWS Libraries Java XQuery 13803 Lines of Codes Lines of code - 80% 2496 AWS
  • 55. AWS Libraries PHP XQuery 6531 Lines of Codes Lines of code 2496 - 62% AWS
  • 56. <html> <head> <script type='text/javascript'> function buy(e) { newElement = document.createElement("p"); elementText = document.createTextNode (e.target.getAttribute(id)); newElement.appendChild(elementText); var res = document.evaluate( "//div[@id='shoppingcart']", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, HTML null); res.snapshotItem(0).appendChild("newElement");} </script> JavaScript </head> <body> <div>Shopping cart</div> <div id="shoppingcart"></div> <% XPath // Code establishing connection ResultSet results = statement.executeQuery ("SELECT * FROM PRODUCTS"); while (results.next()) { out.println("<div>"); Java String prodName = results.getString(1); out.println(prodName); out.println("<input type='button' value='Buy'"); out.println("id='"+prodName+"'"); SQL out.println("onclick='buy(event)'/>"). out.println("</div>"); } results.close(); // Code closing connection %> </body> </html>
  • 57. <html xmlns="http://www.w3.org/1999/xhtml"> <head> <script type='application/xquery'> declare updating function local:buy($evt, $obj) { insert node <p>{$obj/@id}</p> as first into //div[@id="shoppingcart"] }; b:addEventListener(b:dom()//input, "onclick", xs:Qname("local:buy")); </script> </head> <body> <div>Shopping cart</div> <div id="shoppingcart">{ XQuery Everywhere for $p in doc("products.xml")//*:product return <div> {$p/*:name} <input type='button' value='Buy' id='{$p/*:name}'/> </div> }</div> </body> </html>
  • 58. Wadler's theorem of language adoption “A programming language will be adopted if and only if it permits its users to do something that cannot be done in any other way.”
  • 59. GO Mapping Mapping JavaScript Java SQL Glue Glue GO Seamless Invocations XQuery XQuery
  • 60. GO Mapping JavaScript Local Java Store SQL Glue Sync Sync
  • 61. GO Mapping JavaScript Local Java Store SQL Glue Sync Sync GO XQuery Local XQuery Store Seamless Synchronisation
  • 63. XQuery in Mobile Apps • 2 XQuery Stores - DOM - HTML5 Local Storage • When Offline - Each update is applied to local store - Pending Update Lists are stored in the local store • When Online - PULs are aggregated and sent to the Cloud - PULs are applied to the Cloud
  • 64. insert node attribute done { “true” } into xqddf:collection($todos)[@id = $id]
  • 65. insert node attribute done { “true” } into xqddf:collection($todos)[@id = $id] 1. Apply PUL Store PUL Local Store TODOs <todo done=”true”/> <insert src=”...” PULs target=”...” />
  • 66. insert node attribute done { “true” } into xqddf:collection($todos)[@id = $id] Local Store 2. Send PUL TODOs <todo done=”true”/> PULs
  • 67. insert node attribute done { “true” } into xqddf:collection($todos)[@id = $id] Local Store 3. Apply PUL TODOS <todo done=”true”/> PULs
  • 68. Operators on Updates • Aggregation • Integration (+ detecting conflicts) • Reconciliation of conflicts • Reduction • Inversion
  • 71. avg( $tempA/future-or-current::* intersect $tempB/past-or-current::* ) Text Time 68° 70° 65° 69° 72° $tempA $tempB
  • 73. 28 msec Thank you!