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
- 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;
- 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;
- 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
- 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
- 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