Return to Overview.html CVS log | Up to [Public] / html5 / webdatabase |
1.79 ihickson 1: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"><html lang="en-US-x-Hixie"><title>Web SQL Database</title><style type="text/css"> 1.1 ihickson 2: pre { margin-left: 2em; white-space: pre-wrap; } 3: h2 { margin: 3em 0 1em 0; } 4: h3 { margin: 2.5em 0 1em 0; } 5: h4 { margin: 2.5em 0 0.75em 0; } 6: h5, h6 { margin: 2.5em 0 1em; } 7: h1 + h2, h1 + h2 + h2 { margin: 0.75em 0 0.75em; } 8: h2 + h3, h3 + h4, h4 + h5, h5 + h6 { margin-top: 0.5em; } 9: p { margin: 1em 0; } 10: hr:not(.top) { display: block; background: none; border: none; padding: 0; margin: 2em 0; height: auto; } 11: dl, dd { margin-top: 0; margin-bottom: 0; } 12: dt { margin-top: 0.75em; margin-bottom: 0.25em; clear: left; } 13: dt + dt { margin-top: 0; } 14: dd dt { margin-top: 0.25em; margin-bottom: 0; } 15: dd p { margin-top: 0; } 16: dd dl + p { margin-top: 1em; } 17: dd table + p { margin-top: 1em; } 18: p + * > li, dd li { margin: 1em 0; } 19: dt, dfn { font-weight: bold; font-style: normal; } 20: dt dfn { font-style: italic; } 21: pre, code { font-size: inherit; font-family: monospace; font-variant: normal; } 22: pre strong { color: black; font: inherit; font-weight: bold; background: yellow; } 23: pre em { font-weight: bolder; font-style: normal; } 24: @media screen { code { color: orangered; } code :link, code :visited { color: inherit; } } 25: var sub { vertical-align: bottom; font-size: smaller; position: relative; top: 0.1em; } 26: table { border-collapse: collapse; border-style: hidden hidden none hidden; } 1.83 ihickson 27: table thead, table tbody { border-bottom: solid; } 1.1 ihickson 28: table tbody th:first-child { border-left: solid; } 1.37 ihickson 29: table tbody th { text-align: left; } 1.1 ihickson 30: table td, table th { border-left: solid; border-right: solid; border-bottom: solid thin; vertical-align: top; padding: 0.2em; } 31: blockquote { margin: 0 0 0 2em; border: 0; padding: 0; font-style: italic; } 32: 33: .bad, .bad *:not(.XXX) { color: gray; border-color: gray; background: transparent; } 34: .matrix, .matrix td { border: none; text-align: right; } 35: .matrix { margin-left: 2em; } 36: .dice-example { border-collapse: collapse; border-style: hidden solid solid hidden; border-width: thin; margin-left: 3em; } 37: .dice-example caption { width: 30em; font-size: smaller; font-style: italic; padding: 0.75em 0; text-align: left; } 38: .dice-example td, .dice-example th { border: solid thin; width: 1.35em; height: 1.05em; text-align: center; padding: 0; } 39: 40: .toc dfn, h1 dfn, h2 dfn, h3 dfn, h4 dfn, h5 dfn, h6 dfn { font: inherit; } 41: img.extra { float: right; } 42: pre.idl { border: solid thin; background: #EEEEEE; color: black; padding: 0.5em 1em; } 43: pre.idl :link, pre.idl :visited { color: inherit; background: transparent; } 44: pre.css { border: solid thin; background: #FFFFEE; color: black; padding: 0.5em 1em; } 45: pre.css:first-line { color: #AAAA50; } 1.72 ihickson 46: dl.domintro { color: green; margin: 2em 0 2em 2em; padding: 0.5em 1em; border: none; background: #DDFFDD; } 1.1 ihickson 47: hr + dl.domintro, div.impl + dl.domintro { margin-top: 2.5em; margin-bottom: 1.5em; } 48: dl.domintro dt, dl.domintro dt * { color: black; text-decoration: none; } 49: dl.domintro dd { margin: 0.5em 0 1em 2em; padding: 0; } 50: dl.domintro dd p { margin: 0.5em 0; } 51: dl.switch { padding-left: 2em; } 52: dl.switch > dt { text-indent: -1.5em; } 53: dl.switch > dt:before { content: '\21AA'; padding: 0 0.5em 0 0; display: inline-block; width: 1em; text-align: right; line-height: 0.5em; } 54: dl.triple { padding: 0 0 0 1em; } 55: dl.triple dt, dl.triple dd { margin: 0; display: inline } 56: dl.triple dt:after { content: ':'; } 57: dl.triple dd:after { content: '\A'; white-space: pre; } 58: .diff-old { text-decoration: line-through; color: silver; background: transparent; } 59: .diff-chg, .diff-new { text-decoration: underline; color: green; background: transparent; } 60: a .diff-new { border-bottom: 1px blue solid; } 61: 62: h2 { page-break-before: always; } 63: h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } 64: h1 + h2, hr + h2.no-toc { page-break-before: auto; } 65: 66: p > span:not([title=""]):not([class="XXX"]):not([class="impl"]), li > span:not([title=""]):not([class="XXX"]):not([class="impl"]) { border-bottom: solid #9999CC; } 67: 68: div.head { margin: 0 0 1em; padding: 1em 0 0 0; } 69: div.head p { margin: 0; } 70: div.head h1 { margin: 0; } 71: div.head .logo { float: right; margin: 0 1em; } 72: div.head .logo img { border: none } /* remove border from top image */ 73: div.head dl { margin: 1em 0; } 1.55 ihickson 74: div.head p.copyright, div.head p.alt { font-size: x-small; font-style: oblique; margin: 0; } 1.1 ihickson 75: 76: body > .toc > li { margin-top: 1em; margin-bottom: 1em; } 77: body > .toc.brief > li { margin-top: 0.35em; margin-bottom: 0.35em; } 78: body > .toc > li > * { margin-bottom: 0.5em; } 79: body > .toc > li > * > li > * { margin-bottom: 0.25em; } 80: .toc, .toc li { list-style: none; } 81: 82: .brief { margin-top: 1em; margin-bottom: 1em; line-height: 1.1; } 83: .brief li { margin: 0; padding: 0; } 84: .brief li p { margin: 0; padding: 0; } 85: 86: .category-list { margin-top: -0.75em; margin-bottom: 1em; line-height: 1.5; } 87: .category-list::before { content: '\21D2\A0'; font-size: 1.2em; font-weight: 900; } 88: .category-list li { display: inline; } 89: .category-list li:not(:last-child)::after { content: ', '; } 90: .category-list li > span, .category-list li > a { text-transform: lowercase; } 91: .category-list li * { text-transform: none; } /* don't affect <code> nested in <a> */ 92: 93: .XXX { color: #E50000; background: white; border: solid red; padding: 0.5em; margin: 1em 0; } 94: .XXX > :first-child { margin-top: 0; } 95: p .XXX { line-height: 3em; } 1.21 ihickson 96: .annotation { border: solid thin black; background: #0C479D; color: white; position: relative; margin: 8px 0 20px 0; } 97: .annotation:before { position: absolute; left: 0; top: 0; width: 100%; height: 100%; margin: 6px -6px -6px 6px; background: #333333; z-index: -1; content: ''; } 98: .annotation :link, .annotation :visited { color: inherit; } 99: .annotation :link:hover, .annotation :visited:hover { background: transparent; } 100: .annotation span { border: none ! important; } 1.1 ihickson 101: .note { color: green; background: transparent; font-family: sans-serif; } 102: .warning { color: red; background: transparent; } 103: .note, .warning { font-weight: bolder; font-style: italic; } 104: p.note, div.note { padding: 0.5em 2em; } 105: span.note { padding: 0 2em; } 106: .note p:first-child, .warning p:first-child { margin-top: 0; } 107: .note p:last-child, .warning p:last-child { margin-bottom: 0; } 108: .warning:before { font-style: normal; } 109: p.note:before { content: 'Note: '; } 110: p.warning:before { content: '\26A0 Warning! '; } 111: 112: .bookkeeping:before { display: block; content: 'Bookkeeping details'; font-weight: bolder; font-style: italic; } 113: .bookkeeping { font-size: 0.8em; margin: 2em 0; } 114: .bookkeeping p { margin: 0.5em 2em; display: list-item; list-style: square; } 115: 116: h4 { position: relative; z-index: 3; } 117: h4 + .element, h4 + div + .element { margin-top: -2.5em; padding-top: 2em; } 118: .element { 119: background: #EEEEFF; 120: color: black; 121: margin: 0 0 1em 0.15em; 122: padding: 0 1em 0.25em 0.75em; 123: border-left: solid #9999FF 0.25em; 124: position: relative; 125: z-index: 1; 126: } 127: .element:before { 128: position: absolute; 129: z-index: 2; 130: top: 0; 131: left: -1.15em; 132: height: 2em; 133: width: 0.9em; 134: background: #EEEEFF; 135: content: ' '; 136: border-style: none none solid solid; 137: border-color: #9999FF; 138: border-width: 0.25em; 139: } 140: 1.12 ihickson 141: .example { display: block; color: #222222; background: #FCFCFC; border-left: double; margin-left: 2em; padding-left: 1em; } 142: td > .example:only-child { margin: 0 0 0 0.1em; } 1.1 ihickson 143: 144: ul.domTree, ul.domTree ul { padding: 0 0 0 1em; margin: 0; } 145: ul.domTree li { padding: 0; margin: 0; list-style: none; position: relative; } 146: ul.domTree li li { list-style: none; } 147: ul.domTree li:first-child::before { position: absolute; top: 0; height: 0.6em; left: -0.75em; width: 0.5em; border-style: none none solid solid; content: ''; border-width: 0.1em; } 148: ul.domTree li:not(:last-child)::after { position: absolute; top: 0; bottom: -0.6em; left: -0.75em; width: 0.5em; border-style: none none solid solid; content: ''; border-width: 0.1em; } 149: ul.domTree span { font-style: italic; font-family: serif; } 150: ul.domTree .t1 code { color: purple; font-weight: bold; } 151: ul.domTree .t2 { font-style: normal; font-family: monospace; } 152: ul.domTree .t2 .name { color: black; font-weight: bold; } 153: ul.domTree .t2 .value { color: blue; font-weight: normal; } 154: ul.domTree .t3 code, .domTree .t4 code, .domTree .t5 code { color: gray; } 155: ul.domTree .t7 code, .domTree .t8 code { color: green; } 156: ul.domTree .t10 code { color: teal; } 157: 1.67 ihickson 158: body.dfnEnabled dfn { cursor: pointer; } 159: .dfnPanel { 160: display: inline; 161: position: absolute; 162: z-index: 10; 163: height: auto; 164: width: auto; 165: padding: 0.5em 0.75em; 166: font: small sans-serif, Droid Sans Fallback; 167: background: #DDDDDD; 168: color: black; 169: border: outset 0.2em; 170: } 171: .dfnPanel * { margin: 0; padding: 0; font: inherit; text-indent: 0; } 172: .dfnPanel :link, .dfnPanel :visited { color: black; } 173: .dfnPanel p { font-weight: bolder; } 174: .dfnPanel * + p { margin-top: 0.25em; } 175: .dfnPanel li { list-style-position: inside; } 176: 1.53 ihickson 177: #configUI { position: absolute; z-index: 20; top: 10em; right: 1em; width: 11em; font-size: small; } 178: #configUI p { margin: 0.5em 0; padding: 0.3em; background: #EEEEEE; color: black; border: inset thin; } 179: #configUI p label { display: block; } 180: #configUI #updateUI, #configUI .loginUI { text-align: center; } 181: #configUI input[type=button] { display: block; margin: auto; } 1.58 ihickson 182: </style><link href="http://www.w3.org/StyleSheets/TR/W3C-ED" rel="stylesheet" type="text/css"><div class="head"> 1.1 ihickson 183: <p><a href="http://www.w3.org/"><img alt="W3C" height="48" src="http://www.w3.org/Icons/w3c_home" width="72"></a></p> 1.50 ihickson 184: <h1>Web SQL Database</h1> 1.29 ihickson 185: 1.85 ! ihickson 186: <h2 class="no-num no-toc" id="editor-s-draft-11-may-2010">Editor's Draft 11 May 2010</h2> 1.58 ihickson 187: <dl><dt>Latest Published Version:</dt> 1.1 ihickson 188: <dd><a href="http://www.w3.org/TR/webdatabase/">http://www.w3.org/TR/webdatabase/</a></dd> 1.29 ihickson 189: <dt>Latest Editor's Draft:</dt> 1.1 ihickson 190: <dd><a href="http://dev.w3.org/html5/webdatabase/">http://dev.w3.org/html5/webdatabase/</a></dd> 1.43 ihickson 191: <!-- ZZZ: add the new version after it has shipped--> 1.1 ihickson 192: <dt>Previous Versions:</dt> 1.43 ihickson 193: <dd><a href="http://www.w3.org/TR/2009/WD-webstorage-20090423/">http://www.w3.org/TR/2009/WD-webstorage-20090423/</a> <!-- yes, storage, not db --> 1.46 ihickson 194: <dd><a href="http://www.w3.org/TR/2009/WD-webdatabase-20091029/">http://www.w3.org/TR/2009/WD-webdatabase-20091029/</a></dd> 1.43 ihickson 195: <!-- :ZZZ --> 1.1 ihickson 196: <dt>Editors:</dt> 197: <dd><a href="mailto:ian@hixie.ch">Ian Hickson</a>, Google, Inc.</dd> 1.10 ihickson 198: </dl><p class="copyright"><a href="http://www.w3.org/Consortium/Legal/ipr-notice#Copyright">Copyright</a> 1.73 ihickson 199: © 2010 <a href="http://www.w3.org/"><abbr title="World Wide 1.10 ihickson 200: Web Consortium">W3C</abbr></a><sup>®</sup> (<a href="http://www.csail.mit.edu/"><abbr title="Massachusetts 1.1 ihickson 201: Institute of Technology">MIT</abbr></a>, <a href="http://www.ercim.org/"><abbr title="European Research 202: Consortium for Informatics and Mathematics">ERCIM</abbr></a>, <a href="http://www.keio.ac.jp/">Keio</a>), All Rights Reserved. W3C 203: <a href="http://www.w3.org/Consortium/Legal/ipr-notice#Legal_Disclaimer">liability</a>, 204: <a href="http://www.w3.org/Consortium/Legal/ipr-notice#W3C_Trademarks">trademark</a> 205: and <a href="http://www.w3.org/Consortium/Legal/copyright-documents">document 206: use</a> rules apply.</p> 1.10 ihickson 207: </div><hr class="top"><h2 class="no-num no-toc" id="abstract">Abstract</h2><p>This specification defines an API for storing data in databases 1.55 ihickson 208: that can be queried using a variant of SQL.<h2 class="no-num no-toc" id="status-of-this-document">Status of This document</h2><!-- intro boilerplate (required) --><p><em>This section describes the status of this document at the 1.1 ihickson 209: time of its publication. Other documents may supersede this 210: document. A list of current W3C publications and the most recently 211: formally published revision of this technical report can be found in 212: the <a href="http://www.w3.org/TR/">W3C technical reports index</a> 1.10 ihickson 213: at http://www.w3.org/TR/.</em></p><!-- where to send feedback (required) --><p>If you wish to make comments regarding this document, please send 1.1 ihickson 214: them to <a href="mailto:public-webapps@w3.org">public-webapps@w3.org</a> 215: (<a href="mailto:public-webapps-request@w3.org?subject=subscribe">subscribe</a>, 216: <a href="http://lists.w3.org/Archives/Public/public-webapps/">archives</a>) 217: 218: <!-- UNDER NO CIRCUMSTANCES IS THE FOLLOWING SENTENCE TO BE REMOVED OR EDITED WITHOUT TALKING TO IAN FIRST --> 219: or <a href="mailto:whatwg@whatwg.org">whatwg@whatwg.org</a> (<a href="http://lists.whatwg.org/listinfo.cgi/whatwg-whatwg.org">subscribe</a>, 220: <a href="http://lists.whatwg.org/pipermail/whatwg-whatwg.org/">archives</a>), 221: <!-- UNDER NO CIRCUMSTANCES IS THE PRECEDING SENTENCE TO BE REMOVED OR EDITED WITHOUT TALKING TO IAN FIRST --> 222: 1.84 ihickson 223: or submit them using <a href="http://www.w3.org/Bugs/Public/enter_bug.cgi?assigned_to=ian%40hixie.ch&blocked=&bug_file_loc=http%3A%2F%2F&bug_severity=normal&bug_status=NEW&comment=&component=Web%20Database%20%28editor%3A%20Ian%20Hickson%29&contenttypeentry=&contenttypemethod=autodetect&contenttypeselection=text%2Fplain&data=&dependson=&description=&form_name=enter_bug&keywords=&maketemplate=Remember%20values%20as%20bookmarkable%20template&op_sys=All&priority=P5&product=WebAppsWG&qa_contact=member-webapi-cvs%40w3.org&rep_platform=All&short_desc=&target_milestone=---&version=unspecified">our 1.1 ihickson 224: public bug database</a>. 225: 1.10 ihickson 226: All feedback is welcome.</p><!-- stability (required) --><p>Implementors should be aware that this specification is not 1.1 ihickson 227: stable. <strong>Implementors who are not taking part in the 228: discussions are likely to find the specification changing out from 229: under them in incompatible ways.</strong> Vendors interested in 230: implementing this specification before it eventually reaches the 231: Candidate Recommendation stage should join the aforementioned 1.56 ihickson 232: mailing lists and take part in the discussions.<p class="XXX">This specification has reached an impasse: all 233: interested implementors have used the same SQL backend (Sqlite), but 234: we need multiple independent implementations to proceed along a 235: standardisation path. Until another implementor is interested in 236: implementing this spec, the description of the SQL dialect has been 237: left as simply a reference to Sqlite, which isn't acceptable for a 238: standard. Should you be an implementor interested in implementing an 239: independent SQL backend, please contact the editor so that he can 240: write a specification for the dialect, thus allowing this 241: specification to move forward.</p><!-- version history or list of changes (required) --><p>The latest stable version of the editor's draft of this 1.1 ihickson 242: specification is always available on <a href="http://dev.w3.org/html5/webdatabase/Overview.html">the W3C CVS 243: server</a>. Change tracking for this document is available at the 1.10 ihickson 244: following location:<ul><li>CVS log: <a href="http://dev.w3.org/cvsweb/html5/webdatabase/Overview.html">http://dev.w3.org/cvsweb/html5/webdatabase/Overview.html</a></li> 245: </ul><!-- UNDER NO CIRCUMSTANCES IS THE FOLLOWING PARAGRAPH TO BE REMOVED OR EDITED WITHOUT TALKING TO IAN FIRST --><!-- relationship to other work (required) --><p>This specification is automatically generated from the 1.1 ihickson 246: corresponding section in the HTML5 specification's source document, 247: as hosted in the <a href="http://svn.whatwg.org/webapps/">WHATWG 248: Subversion repository</a>. Detailed change history for all of HTML5, 249: including the parts that form this specification, can be found at 1.10 ihickson 250: the following locations:</p><!-- UNDER NO CIRCUMSTANCES IS THE PRECEDING PARAGRAPH TO BE REMOVED OR EDITED WITHOUT TALKING TO IAN FIRST --><!-- UNDER NO CIRCUMSTANCES IS THE FOLLOWING LIST TO BE REMOVED OR EDITED WITHOUT TALKING TO IAN FIRST --><ul><li>Twitter messages (non-editorial changes only): <a href="http://twitter.com/WHATWG">http://twitter.com/WHATWG</a></li> 1.1 ihickson 251: <li>Interactive Web interface: <a href="http://html5.org/tools/web-apps-tracker">http://html5.org/tools/web-apps-tracker</a></li> 252: <li>Commit-Watchers mailing list: <a href="http://lists.whatwg.org/listinfo.cgi/commit-watchers-whatwg.org">http://lists.whatwg.org/listinfo.cgi/commit-watchers-whatwg.org</a></li> 253: <li>Subversion interface: <a href="http://svn.whatwg.org/webapps/">http://svn.whatwg.org/webapps/</a></li> 1.10 ihickson 254: </ul><!-- UNDER NO CIRCUMSTANCES IS THE PRECEDING LIST TO BE REMOVED OR EDITED WITHOUT TALKING TO IAN FIRST --><!-- status of document, group responsible (required) --><p>The W3C <a href="http://www.w3.org/2008/webapps/">Web Apps 1.1 ihickson 255: Working Group</a> is the W3C working group responsible for this 256: specification's progress along the W3C Recommendation track. 1.29 ihickson 257: 1.85 ! ihickson 258: This specification is the 11 May 2010 Editor's Draft. 1.10 ihickson 259: </p><!-- required patent boilerplate --><p>This document was produced by a group operating under the <a href="http://www.w3.org/Consortium/Patent-Policy-20040205/">5 1.1 ihickson 260: February 2004 W3C Patent Policy</a>. W3C maintains a <a href="http://www.w3.org/2004/01/pp-impl/42538/status" rel="disclosure">public list of 261: any patent disclosures</a> made in connection with the deliverables 262: of the group; that page also includes instructions for disclosing a 263: patent. An individual who has actual knowledge of a patent which the 264: individual believes contains <a href="http://www.w3.org/Consortium/Patent-Policy-20040205/#def-essential">Essential 265: Claim(s)</a> must disclose the information in accordance with <a href="http://www.w3.org/Consortium/Patent-Policy-20040205/#sec-Disclosure">section 1.55 ihickson 266: 6 of the W3C Patent Policy</a>.<h2 class="no-num no-toc" id="contents">Table of Contents</h2> 1.1 ihickson 267: <!--begin-toc--> 268: <ol class="toc"> 269: <li><a href="#introduction"><span class="secno">1 </span>Introduction</a></li> 270: <li><a href="#conformance-requirements"><span class="secno">2 </span>Conformance requirements</a> 271: <ol> 272: <li><a href="#dependencies"><span class="secno">2.1 </span>Dependencies</a></ol></li> 273: <li><a href="#terminology"><span class="secno">3 </span>Terminology</a></li> 274: <li><a href="#sql"><span class="secno">4 </span>The API</a> 275: <ol> 276: <li><a href="#databases"><span class="secno">4.1 </span>Databases</a></li> 277: <li><a href="#parsing-and-processing-sql-statements"><span class="secno">4.2 </span>Parsing and processing SQL statements</a></li> 278: <li><a href="#asynchronous-database-api"><span class="secno">4.3 </span>Asynchronous database API</a> 279: <ol> 280: <li><a href="#executing-sql-statements"><span class="secno">4.3.1 </span>Executing SQL statements</a></li> 281: <li><a href="#processing-model"><span class="secno">4.3.2 </span>Processing model</a></ol></li> 282: <li><a href="#synchronous-database-api"><span class="secno">4.4 </span>Synchronous database API</a> 283: <ol> 284: <li><a href="#executing-sql-statements-0"><span class="secno">4.4.1 </span>Executing SQL statements</a></ol></li> 285: <li><a href="#database-query-results"><span class="secno">4.5 </span>Database query results</a></li> 286: <li><a href="#errors-and-exceptions"><span class="secno">4.6 </span>Errors and exceptions</a></ol></li> 1.19 ihickson 287: <li><a href="#web-sql"><span class="secno">5 </span>Web SQL</a></li> 288: <li><a href="#disk-space"><span class="secno">6 </span>Disk space</a></li> 289: <li><a href="#privacy"><span class="secno">7 </span>Privacy</a> 1.1 ihickson 290: <ol> 1.19 ihickson 291: <li><a href="#user-tracking"><span class="secno">7.1 </span>User tracking</a></li> 1.31 ihickson 292: <li><a href="#sensitivity-of-data"><span class="secno">7.2 </span>Sensitivity of data</a></ol></li> 1.76 ihickson 293: <li><a href="#security-storage"><span class="secno">8 </span>Security</a> 1.1 ihickson 294: <ol> 1.19 ihickson 295: <li><a href="#dns-spoofing-attacks"><span class="secno">8.1 </span>DNS spoofing attacks</a></li> 296: <li><a href="#cross-directory-attacks"><span class="secno">8.2 </span>Cross-directory attacks</a></li> 297: <li><a href="#implementation-risks"><span class="secno">8.3 </span>Implementation risks</a></li> 298: <li><a href="#sql-and-user-agents"><span class="secno">8.4 </span>SQL and user agents</a></li> 299: <li><a href="#sql-injection"><span class="secno">8.5 </span>SQL injection</a></ol></li> 1.1 ihickson 300: <li><a class="no-num" href="#references">References</a></ol> 1.10 ihickson 301: <!--end-toc--><hr><!-- Feature requests for future versions (v2): 1.1 ihickson 302: * deleting databases 303: * determining how much storage room is left 304: * handling the database getting corrupted 1.14 ihickson 305: --><h2 id="introduction"><span class="secno">1 </span>Introduction</h2><p><i>This section is non-normative.</i><p>This specification introduces a set of APIs to manipulate 306: client-side databases using SQL.<p>The API is asynchronous, so authors are likely to find anonymous 307: functions (lambdas) very useful in using this API.<p>Here is an example of a script using this API. First, a function 308: <code title="">prepareDatabase()</code> is defined. This function 309: tries to create the database if necessary, giving it one table 310: called "docids" with two columns ("id" and "name"). If it is 311: successful, or if the table doesn't need creating, it calls a 312: section function, <code title="">getDatabase()</code>, which obtains 313: a handle to the database, and then calls the function to do the 314: actual work, in this case <code title="">showDocCount()</code>.<pre>function prepareDatabase(ready, error) { 1.17 ihickson 315: return openDatabase('documents', '1.0', 'Offline document storage', 5*1024*1024, function (db) { 1.14 ihickson 316: db.changeVersion('', '1.0', function (t) { 317: t.executeSql('CREATE TABLE docids (id, name)'); 1.17 ihickson 318: }, error); 319: }); 1.14 ihickson 320: } 321: 322: function showDocCount(db, span) { 323: db.readTransaction(function (t) { 1.18 ihickson 324: t.executeSql('SELECT COUNT(*) AS c FROM docids', [], function (t, r) { 325: span.textContent = r.rows[0].c; 1.14 ihickson 326: }, function (t, e) { 327: // couldn't read database 328: span.textContent = '(unknown: ' + e.message + ')'; 329: }); 330: }); 331: } 332: 333: prepareDatabase(function(db) { 334: // got database 335: var span = document.getElementById('doc-count'); 336: showDocCount(db, span); 337: }, function (e) { 338: // error getting database 339: alert(e.message); 1.18 ihickson 340: });</pre><hr><p>The <code title="dom-sqltransaction-executeSql"><a href="#dom-sqltransaction-executesql">executeSql()</a></code> method has 341: an argument intended to allow variables to be substituted into 342: statements without risking SQL injection vulnerabilities:<pre>db.readTransaction(function (t) { 343: t.executeSql('SELECT title, author FROM docs WHERE id=?', [id], function (t, data) { 344: report(data.rows[0].title, data.rows[0].author); 345: }); 1.19 ihickson 346: });</pre><hr><p>Sometimes, there might be an arbitrary number of variables to 1.18 ihickson 347: substitute in. Even in these case, the right solution is to 348: construct the query using only "?" characters, and then to pass the 1.19 ihickson 349: variables in as the second argument:<pre>function findDocs(db, resultCallback) { 1.18 ihickson 350: var q = ""; 351: for each (var i in labels) 352: q += (q == "" ? "" : ", ") + "?"; 353: db.readTransaction(function (t) { 354: t.executeSql('SELECT id FROM docs WHERE label IN (' + q + ')', labels, function (t, data) { 355: resultCallback(data); 356: }); 357: }); 1.19 ihickson 358: }</pre><h2 id="conformance-requirements"><span class="secno">2 </span>Conformance requirements</h2><p>All diagrams, examples, and notes in this specification are 1.1 ihickson 359: non-normative, as are all sections explicitly marked non-normative. 1.19 ihickson 360: Everything else in this specification is normative.<p>The key words "MUST", "MUST NOT", "REQUIRED", <!--"SHALL", "SHALL 1.1 ihickson 361: NOT",--> "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and 362: "OPTIONAL" in the normative parts of this document are to be 363: interpreted as described in RFC2119. For readability, these words do 1.19 ihickson 364: not appear in all uppercase letters in this specification. <a href="#refsRFC2119">[RFC2119]</a><p>Requirements phrased in the imperative as part of algorithms 1.1 ihickson 365: (such as "strip any leading space characters" or "return false and 366: abort these steps") are to be interpreted with the meaning of the 367: key word ("must", "should", "may", etc) used in introducing the 1.19 ihickson 368: algorithm.<p>Some conformance requirements are phrased as requirements on 1.1 ihickson 369: attributes, methods or objects. Such requirements are to be 1.19 ihickson 370: interpreted as requirements on user agents.<p>Conformance requirements phrased as algorithms or specific steps 1.1 ihickson 371: may be implemented in any manner, so long as the end result is 372: equivalent. (In particular, the algorithms defined in this 373: specification are intended to be easy to follow, and not intended to 1.19 ihickson 374: be performant.)<p>The only conformance class defined by this specification is user 375: agents.<p>User agents may impose implementation-specific limits on 1.1 ihickson 376: otherwise unconstrained inputs, e.g. to prevent denial of service 377: attacks, to guard against running out of memory, or to work around 1.70 ihickson 378: platform-specific limitations.<p>When support for a feature is disabled (e.g. as an emergency 379: measure to mitigate a security problem, or to aid in development, or 380: for performance reasons), user agents must act as if they had no 381: support for the feature whatsoever, and as if the feature was not 382: mentioned in this specification. For example, if a particular 383: feature is accessed via an attribute in a Web IDL interface, the 384: attribute itself would be omitted from the objects that implement 385: that interface — leaving the attribute on the object but 386: making it return null or throw an exception is insufficient.<h3 id="dependencies"><span class="secno">2.1 </span>Dependencies</h3><p>This specification relies on several other underlying 1.68 ihickson 387: specifications.<dl><dt>HTML</dt> 1.1 ihickson 388: 389: <dd> 390: 1.68 ihickson 391: <p>Many fundamental concepts from HTML are used by this 392: specification. <a href="#refsHTML">[HTML]</a></p> 1.1 ihickson 393: 394: </dd> 395: 396: <dt>WebIDL</dt> 397: 398: <dd> 399: 400: <p>The IDL blocks in this specification use the semantics of the 1.7 ihickson 401: WebIDL specification. <a href="#refsWEBIDL">[WEBIDL]</a></p> 1.1 ihickson 402: 403: </dd> 404: 1.10 ihickson 405: </dl><h2 id="terminology"><span class="secno">3 </span>Terminology</h2><p>The construction "a <code title="">Foo</code> object", where 1.1 ihickson 406: <code title="">Foo</code> is actually an interface, is sometimes 407: used instead of the more accurate "an object implementing the 1.10 ihickson 408: interface <code title="">Foo</code>".<p>The term DOM is used to refer to the API set made available to 1.1 ihickson 409: scripts in Web applications, and does not necessarily imply the 410: existence of an actual <code>Document</code> object or of any other 411: <code>Node</code> objects as defined in the DOM Core 1.33 ihickson 412: specifications. <a href="#refsDOMCORE">[DOMCORE]</a><p>An IDL attribute is said to be <em>getting</em> when its value is 1.1 ihickson 413: being retrieved (e.g. by author script), and is said to be 1.10 ihickson 414: <em>setting</em> when a new value is assigned to it.<p>The term "JavaScript" is used to refer to ECMA262, rather than 1.1 ihickson 415: the official term ECMAScript, since the term JavaScript is more 1.10 ihickson 416: widely known. <a href="#refsECMA262">[ECMA262]</a><h2 id="sql"><span class="secno">4 </span>The API</h2><h3 id="databases"><span class="secno">4.1 </span>Databases</h3><p>Each <i>origin</i> has an associated set of databases. Each 1.1 ihickson 417: database has a name and a current version. There is no way to 418: enumerate or delete the databases available for an origin from this 1.10 ihickson 419: API.<p class="note">Each database has one version at a time; a database 1.1 ihickson 420: can't exist in multiple versions at once. Versions are intended to 421: allow authors to manage schema changes incrementally and 422: non-destructively, and without running the risk of old code (e.g. in 423: another browser window) trying to write to a database with incorrect 1.10 ihickson 424: assumptions.<pre class="idl">[Supplemental, NoInterfaceObject] 1.5 ihickson 425: interface <span>WindowDatabase</span> { 1.16 ihickson 426: <a href="#database">Database</a> <a href="#dom-opendatabase" title="dom-opendatabase">openDatabase</a>(in DOMString name, in DOMString version, in DOMString displayName, in unsigned long estimatedSize, in optional <a href="#databasecallback">DatabaseCallback</a> creationCallback); 1.1 ihickson 427: }; 1.5 ihickson 428: <span>Window</span> implements <span>WindowDatabase</span>; 1.1 ihickson 429: 1.5 ihickson 430: [Supplemental, NoInterfaceObject] 431: interface <span>WorkerUtilsDatabase</span> { 1.16 ihickson 432: <a href="#database">Database</a> <a href="#dom-opendatabase" title="dom-opendatabase">openDatabase</a>(in DOMString name, in DOMString version, in DOMString displayName, in unsigned long estimatedSize, in optional <a href="#databasecallback">DatabaseCallback</a> creationCallback); 433: <a href="#databasesync">DatabaseSync</a> <a href="#dom-opendatabase-sync" title="dom-opendatabase-sync">openDatabaseSync</a>(in DOMString name, in DOMString version, in DOMString displayName, in unsigned long estimatedSize, in optional <a href="#databasecallback">DatabaseCallback</a> creationCallback); 1.5 ihickson 434: }; 1.16 ihickson 435: <span>WorkerUtils</span> implements <span>WorkerUtilsDatabase</span>; 436: 437: [Callback=FunctionOnly, NoInterfaceObject] 438: interface <dfn id="databasecallback">DatabaseCallback</dfn> { 439: void <span title="dom-databasecallback-handleEvent">handleEvent</span>(in <a href="#database">Database</a> database); 440: };</pre><p>The <dfn id="dom-opendatabase" title="dom-opendatabase"><code>openDatabase()</code></dfn> method on 441: the <code>Window</code> and <code>WorkerUtils</code> interfaces and 442: the <dfn id="dom-opendatabase-sync" title="dom-opendatabase-sync"><code>openDatabaseSync()</code></dfn> 443: method on the <code>WorkerUtils</code> interface take the following 444: arguments: a database name, a database version, a display name, an 445: estimated size — in bytes — of the data that will be 446: stored in the database, and optionally a callback to be invoked if 1.17 ihickson 447: the database has not yet been created. The callback, if provided, is 448: intended to be used to call <code title="dom-database-changeVersion"><a href="#dom-database-changeversion">changeVersion()</a></code>; the 449: callback is invoked with the database having the empty string as its 450: version regardless of the given database version. If the callback is 451: not provided, the database is created with the given database 452: version as its version.<p>When invoked, these methods must run the following steps, with all 453: but the last two steps being run atomically:<ol><li> 1.16 ihickson 454: 455: <p>The user agent may raise a <code>SECURITY_ERR</code> exception 456: instead of returning a <code><a href="#database">Database</a></code> object if the request 457: violates a policy decision (e.g. if the user agent is configured 458: to not allow the page to open databases).</p> 459: 460: </li> 461: 462: <li> 463: 464: <p>For the method on the <code>Window</code> object: let <var title="">origin</var> be the <span>origin</span> of the 465: <span>active document</span> of the <span>browsing context</span> 466: of the <code>Window</code> object on which the method was 467: invoked.</p> 468: 469: <p>For the methods on the <code>WorkerUtils</code> object: let 470: <var title="">origin</var> be the <span>origin</span> of the 471: scripts in the worker.</p> 472: 473: </li> 474: 1.65 ihickson 475: <li><p>If <var title="">origin</var> is not a scheme/host/port 476: tuple, then throw a <code>SECURITY_ERR</code> exception and abort 477: these steps.</li> 478: 1.16 ihickson 479: <li><p>If the database version provided is not the empty string, 480: and there is already a database with the given name from the origin 481: <var title="">origin</var>, but the database has a different 482: version than the version provided, then throw an 483: <code>INVALID_STATE_ERR</code> exception and abort these 484: steps.</li> 485: 486: <li> 487: 1.17 ihickson 488: <p>If no database with the given name from the origin <var title="">origin</var> exists, then create the database and let 1.30 ihickson 489: <var title="">created</var> be true. If a callback was passed to 490: the method, then set the new database's version to the empty 491: string. Otherwise, set the new database's version to the given 492: database version.</p> 1.17 ihickson 493: 1.30 ihickson 494: <p>Otherwise, if a database with the given name already exists, 495: let <var title="">created</var> be false.</p> 1.16 ihickson 496: 497: </li> 498: 499: <li> 500: 501: <p>For the <code title="dom-opendatabase"><a href="#dom-opendatabase">openDatabase()</a></code> 502: methods: let <var title="">result</var> be a newly constructed 503: <code><a href="#database">Database</a></code> object representing the database with the 504: given database name from the origin <var title="">origin</var>.</p> 505: 506: <p>For the <code title="dom-opendatabase-sync"><a href="#dom-opendatabase-sync">openDatabaseSync()</a></code> method: 507: let <var title="">result</var> be a newly constructed 508: <code><a href="#databasesync">DatabaseSync</a></code> object representing the database with 509: the given database name from the origin <var title="">origin</var>.</p> 510: 511: </li> 512: 513: <li> 514: 515: <p>If <var title="">created</var> is false or if no callback was 516: passed to the method, skip this step. Otherwise:</p> 517: 518: <p>For the <code title="dom-opendatabase"><a href="#dom-opendatabase">openDatabase()</a></code> 519: methods: <span>queue a task</span> to to invoke the callback with 520: <var title="">result</var> as its only argument.</p> 521: 522: <p>For the <code title="dom-opendatabase-sync"><a href="#dom-opendatabase-sync">openDatabaseSync()</a></code> method: 523: invoke the callback with <var title="">result</var> as its only 524: argument. If the callback throws an exception, rethrow that 525: exception and abort these steps.</p> 526: 527: </li> 528: 529: <li> 530: 531: <p>Return <var title="">result</var>.</p> 532: 533: </li> 534: 535: </ol><p>All strings including the empty string are valid database 1.1 ihickson 536: names. Database names must be compared in a 1.10 ihickson 537: <span>case-sensitive</span> manner.<p class="note">Implementations can support this even in 1.1 ihickson 538: environments that only support a subset of all strings as database 539: names by mapping database names (e.g. using a hashing algorithm) to 1.16 ihickson 540: the supported set of names.<p>The version that the database was opened with is the <dfn id="concept-database-expected-version" title="concept-database-expected-version">expected version</dfn> of 1.1 ihickson 541: this <code><a href="#database">Database</a></code> or <code><a href="#databasesync">DatabaseSync</a></code> object. It 542: can be the empty string, in which case there is no expected version 1.16 ihickson 543: — any version is fine.<p>User agents are expected to use the display name and the 1.1 ihickson 544: estimated database size to optimize the user experience. For 545: example, a user agent could use the estimated size to suggest an 546: initial quota to the user. This allows a site that is aware that it 547: will try to use hundreds of megabytes to declare this upfront, 548: instead of the user agent prompting the user for permission to 1.10 ihickson 549: increase the quota every five megabytes.<h3 id="parsing-and-processing-sql-statements"><span class="secno">4.2 </span>Parsing and processing SQL statements</h3><p>When the user agent is to <dfn id="preprocess-the-sql-statement" title="preprocess the SQL 550: statement">preprocess a SQL statement</dfn> <var title="">sqlStatement</var> with an array of arguments <var title="">arguments</var>, it must run the following steps:<ol><li><p>Parse <var title="">sqlStatement</var> as a SQL statement, 1.41 ihickson 551: with the exception that U+003F QUESTION MARK characters (?) can be 1.6 ihickson 552: used in place of SQL literals in the statement. <a href="#refsSQL">[SQL]</a></li> 1.1 ihickson 553: 554: <li> 555: 1.49 ihickson 556: <p>Bind each <code title="">?</code> placeholder with the value of 557: the argument in the <var title="">arguments</var> array with the 558: same position. (So the first <code title="">?</code> placeholder 559: gets bound to the first value in the <var title="">arguments</var> 560: array, and generally the <var title="">n</var>th <code title="">?</code> placeholder gets bound to the <var title="">n</var>th value in the <var title="">arguments</var> 561: array.)</p> 562: 563: <p class="note">Binding the <code title="">?</code> placeholders 564: is done at the literal level, not as string concatenations, so 565: this provides a way to dynamically insert parameters into a 566: statement without risk of a SQL injection attack.</p> 1.1 ihickson 567: 568: <p>The result is <var title="">the statement</var>.</p> 569: 570: </li> 571: 572: <li><p>If the <code><a href="#database">Database</a></code> object that the 573: <code><a href="#sqltransaction">SQLTransaction</a></code> or <code><a href="#sqltransactionsync">SQLTransactionSync</a></code> 574: object was created from has an <a href="#concept-database-expected-version" title="concept-database-expected-version">expected version</a> 575: that is neither the empty string nor the actual version of the 576: database, then mark <var title="">the statement</var> as 577: bogus. (<a href="#dom-sqlerror-code-2" title="dom-sqlerror-code-2">Error code 578: 2</a>.)</li> 579: 580: <li> 581: 582: <p>Otherwise, if the syntax of <var title="">sqlStatement</var> is 583: not valid (except for the use of <code title="">?</code> 584: characters in the place of literals), or the statement uses 585: features that are not supported (e.g. due to security reasons), or 586: the number of items in the <var title="">arguments</var> array is 587: not equal to the number of <code title="">?</code> placeholders in 588: the statement, or the statement cannot be parsed for some other 589: reason, then mark <var title="">the statement</var> as 590: bogus. (<a href="#dom-sqlerror-code-5" title="dom-sqlerror-code-5">Error code 591: 5</a>.)</p> 592: 593: <p>User agents must consider statements that use the <code title="">BEGIN</code>, <code title="">COMMIT</code>, and <code title="">ROLLBACK</code> SQL features as being unsupported (and thus 594: will mark them as bogus), so as to not let these statements 595: interfere with the explicit transactions managed by the database API 596: itself.</p> 597: 598: </li> 599: 600: <li id="modifications-fail-if-read-only"> 601: 602: <p>Otherwise, if the <i>mode</i> that was used to create the 603: <code><a href="#sqltransaction">SQLTransaction</a></code> or <code><a href="#sqltransactionsync">SQLTransactionSync</a></code> 604: object is read-only but the statement's main verb can modify the 605: database, mark the statement as bogus. (<a href="#dom-sqlerror-code-5" title="dom-sqlerror-code-5">Error code 5</a>.)</p> 606: 607: <p class="note">Only the statement's main verb (e.g. <code title="">UPDATE</code>, <code title="">SELECT</code>, <code title="">DROP</code>) is considered here. Thus, a statement like 608: "<code title="">UPDATE test SET id=0 WHERE 0=1</code>" would be 609: treated as potentially modifying the database for the purposes 610: of this step, even though it could never in fact have any 611: side-effects.</p> 612: 613: </li> 614: 615: <li><p>Return <var title="">the statement</var>.</li> 616: 1.10 ihickson 617: </ol><p>The user agent must act as if the database was hosted in an 1.1 ihickson 618: otherwise completely empty environment with no resources. For 619: example, attempts to read from or write to the file system will 1.10 ihickson 620: fail.<p class="note">A future version of this specification will probably 621: define the exact SQL subset required in more detail.<h3 id="asynchronous-database-api"><span class="secno">4.3 </span>Asynchronous database API</h3><pre class="idl">interface <dfn id="database">Database</dfn> { 1.34 ihickson 622: void <a href="#dom-database-transaction" title="dom-database-transaction">transaction</a>(in <a href="#sqltransactioncallback">SQLTransactionCallback</a> callback, in optional <a href="#sqltransactionerrorcallback">SQLTransactionErrorCallback</a> errorCallback, in optional <a href="#sqlvoidcallback">SQLVoidCallback</a> successCallback); 623: void <a href="#dom-database-readtransaction" title="dom-database-readTransaction">readTransaction</a>(in <a href="#sqltransactioncallback">SQLTransactionCallback</a> callback, in optional <a href="#sqltransactionerrorcallback">SQLTransactionErrorCallback</a> errorCallback, in optional <a href="#sqlvoidcallback">SQLVoidCallback</a> successCallback); 1.1 ihickson 624: 625: readonly attribute DOMString <a href="#dom-database-version" title="dom-database-version">version</a>; 1.25 ihickson 626: void <a href="#dom-database-changeversion" title="dom-database-changeVersion">changeVersion</a>(in DOMString oldVersion, in DOMString newVersion, in optional <a href="#sqltransactioncallback">SQLTransactionCallback</a> callback, in optional <a href="#sqltransactionerrorcallback">SQLTransactionErrorCallback</a> errorCallback, in optional <a href="#sqlvoidcallback">SQLVoidCallback</a> successCallback); 1.1 ihickson 627: }; 628: 629: [Callback=FunctionOnly, NoInterfaceObject] 630: interface <dfn id="sqlvoidcallback">SQLVoidCallback</dfn> { 631: void <span title="dom-sqlvoidcallback-handleEvent">handleEvent</span>(); 632: }; 633: 634: [Callback=FunctionOnly, NoInterfaceObject] 635: interface <dfn id="sqltransactioncallback">SQLTransactionCallback</dfn> { 636: void <span title="dom-sqltransactioncallback-handleEvent">handleEvent</span>(in <a href="#sqltransaction">SQLTransaction</a> transaction); 637: }; 638: 639: [Callback=FunctionOnly, NoInterfaceObject] 640: interface <dfn id="sqltransactionerrorcallback">SQLTransactionErrorCallback</dfn> { 641: void <span title="dom-sqltransactionerrorcallback-handleEvent">handleEvent</span>(in <a href="#sqlerror">SQLError</a> error); 1.10 ihickson 642: };</pre><p>The <dfn id="dom-database-transaction" title="dom-database-transaction"><code>transaction()</code></dfn> 1.1 ihickson 643: and <dfn id="dom-database-readtransaction" title="dom-database-readTransaction"><code>readTransaction()</code></dfn> 644: methods takes one to three arguments. When called, these methods must 645: immediately return and then asynchronously run the <a href="#transaction-steps">transaction 646: steps</a> with the <i>transaction callback</i> being the first 647: argument, the <i>error callback</i> being the second argument, if 648: any, the <i>success callback</i> being the third argument, if any, 649: and with no <i>preflight operation</i> or <i>postflight 1.10 ihickson 650: operation</i>.<p>For the <code title="dom-database-transaction"><a href="#dom-database-transaction">transaction()</a></code> method, the 1.1 ihickson 651: <i>mode</i> must be read/write. For the <code title="dom-database-readTransaction"><a href="#dom-database-readtransaction">readTransaction()</a></code> 1.10 ihickson 652: method, the <i>mode</i> must be read-only.<p>On getting, the <dfn id="dom-database-version" title="dom-database-version"><code>version</code></dfn> attribute 1.1 ihickson 653: must return the current version of the database (as opposed to the 654: <a href="#concept-database-expected-version" title="concept-database-expected-version">expected 1.10 ihickson 655: version</a> of the <code><a href="#database">Database</a></code> object).<p>The <dfn id="dom-database-changeversion" title="dom-database-changeVersion"><code>changeVersion()</code></dfn> 1.1 ihickson 656: method allows scripts to atomically verify the version number and 657: change it at the same time as doing a schema update. When the method 658: is invoked, it must immediately return, and then asynchronously run 659: the <a href="#transaction-steps">transaction steps</a> with the <i>transaction 660: callback</i> being the third argument, the <i>error callback</i> 661: being the fourth argument, the <i>success callback</i> being the 662: fifth argument, the <i>preflight operation</i> being the 1.10 ihickson 663: following:<ol><li><p>Check that the value of the first argument to the <code title="dom-database-changeVersion"><a href="#dom-database-changeversion">changeVersion()</a></code> method 1.1 ihickson 664: exactly matches the database's actual version. If it does not, then 665: the <i>preflight operation</i> fails.</li> 666: 1.10 ihickson 667: </ol><p>...the <i>postflight operation</i> being the following:<ol><li>Change the database's actual version to the value of the second 1.1 ihickson 668: argument to the <code title="dom-database-changeVersion"><a href="#dom-database-changeversion">changeVersion()</a></code> 669: method.</li> 670: 671: <li>Change the <code><a href="#database">Database</a></code> object's expected version to 672: the value of the second argument to the <code title="dom-database-changeVersion"><a href="#dom-database-changeversion">changeVersion()</a></code> 673: method.</li> 674: 1.25 ihickson 675: </ol><p>...and the <i>mode</i> being read/write.<p>If any of the optional arguments are omitted, then they must be 676: treated as if they were null.<h4 id="executing-sql-statements"><span class="secno">4.3.1 </span>Executing SQL statements</h4><p>The <code title="dom-database-transaction"><a href="#dom-database-transaction">transaction()</a></code>, 1.1 ihickson 677: <code title="dom-database-readTransaction"><a href="#dom-database-readtransaction">readTransaction()</a></code>, 678: and <code title="dom-database-changeVersion"><a href="#dom-database-changeversion">changeVersion()</a></code> 679: methods invoke callbacks with <code><a href="#sqltransaction">SQLTransaction</a></code> 1.10 ihickson 680: objects.<pre class="idl">typedef sequence<any> <dfn id="objectarray">ObjectArray</dfn>; 1.1 ihickson 681: 682: interface <dfn id="sqltransaction">SQLTransaction</dfn> { 1.34 ihickson 683: void <a href="#dom-sqltransaction-executesql" title="dom-sqltransaction-executeSql">executeSql</a>(in DOMString sqlStatement, in optional <a href="#objectarray">ObjectArray</a> arguments, in optional <a href="#sqlstatementcallback">SQLStatementCallback</a> callback, in optional <a href="#sqlstatementerrorcallback">SQLStatementErrorCallback</a> errorCallback); 1.1 ihickson 684: }; 685: 686: [Callback=FunctionOnly, NoInterfaceObject] 687: interface <dfn id="sqlstatementcallback">SQLStatementCallback</dfn> { 688: void <span title="dom-sqlstatementcallback-handleEvent">handleEvent</span>(in <a href="#sqltransaction">SQLTransaction</a> transaction, in <a href="#sqlresultset">SQLResultSet</a> resultSet); 689: }; 690: 691: [Callback=FunctionOnly, NoInterfaceObject] 692: interface <dfn id="sqlstatementerrorcallback">SQLStatementErrorCallback</dfn> { 693: boolean <span title="dom-sqlstatementerrorcallback-handleEvent">handleEvent</span>(in <a href="#sqltransaction">SQLTransaction</a> transaction, in <a href="#sqlerror">SQLError</a> error); 1.10 ihickson 694: };</pre><p>When the <dfn id="dom-sqltransaction-executesql" title="dom-sqltransaction-executeSql"><code>executeSql(<var title="">sqlStatement</var>, <var title="">arguments</var>, <var title="">callback</var>, <var title="">errorCallback</var>)</code></dfn> method is invoked, the 1.1 ihickson 695: user agent must run the following algorithm. (This algorithm is 696: relatively simple in that it doesn't actually execute any SQL 1.10 ihickson 697: — the bulk of the work is actually done as part of the 698: <a href="#transaction-steps">transaction steps</a>.)<ol><li><p>If the method was not invoked during the execution of a 1.1 ihickson 699: <code><a href="#sqltransactioncallback">SQLTransactionCallback</a></code>, 700: <code><a href="#sqlstatementcallback">SQLStatementCallback</a></code>, or 701: <code><a href="#sqlstatementerrorcallback">SQLStatementErrorCallback</a></code> then raise an 702: <code>INVALID_STATE_ERR</code> exception. (Calls from inside a 703: <code><a href="#sqltransactionerrorcallback">SQLTransactionErrorCallback</a></code> thus raise an 704: exception. The <code><a href="#sqltransactionerrorcallback">SQLTransactionErrorCallback</a></code> handler is 705: only called once a transaction has failed, and no SQL statements 706: can be added to a failed transaction.)</li> 707: 708: <li> 709: 710: <p><a href="#preprocess-the-sql-statement">Preprocess the SQL statement</a> given as the first 711: argument to the method (<var title="">sqlStatement</var>), using 712: the second argument to the method as the <var title="">arguments</var> array, to obtain <var title="">the 713: statement</var>.</p> 714: 715: <p>If the second argument is omitted or null, then treat the <var title="">arguments</var> array as empty.</p> 716: 717: </li> 718: 719: <li><p>Queue up <var title="">the statement</var> in the 720: transaction, along with the third argument (if any) as the 721: statement's result set callback and the fourth argument (if any) as 722: the error callback.</li> 723: 1.10 ihickson 724: </ol><h4 id="processing-model"><span class="secno">4.3.2 </span>Processing model</h4><p>The <dfn id="transaction-steps">transaction steps</dfn> are as follows. These steps must 1.1 ihickson 725: be run asynchronously. These steps are invoked with a <i>transaction 726: callback</i>, optionally an <i>error callback</i>, optionally a 727: <i>success callback</i>, optionally a <i>preflight operation</i>, 728: optionally a <i>postflight operation</i>, and with a <i>mode</i> 1.10 ihickson 729: that is either read/write or read-only.<ol><li><p>Open a new SQL transaction to the database, and create a 1.1 ihickson 730: <code><a href="#sqltransaction">SQLTransaction</a></code> object that represents that 731: transaction. If the <i>mode</i> is read/write, the transaction must 732: have an exclusive write lock over the entire database. If the 733: <i>mode</i> is read-only, the transaction must have a shared read 734: lock over the entire database. The user agent should wait for an 735: appropriate lock to be available.</li> 736: 737: <li><p>If an error occurred in the opening of the transaction 738: (e.g. if the user agent failed to obtain an appropriate lock after 739: an appropriate delay), jump to the last step.</li> 740: 741: <li><p>If a <i>preflight operation</i> was defined for this 742: instance of the transaction steps, run that. If it fails, then jump 743: to the last step. (This is basically a hook for the <code title="dom-database-changeVersion"><a href="#dom-database-changeversion">changeVersion()</a></code> 744: method.)</li> 745: 1.25 ihickson 746: <li><p>If the <i>transaction callback</i> is not null, <span>queue 747: a task</span> to invoke the <i>transaction callback</i> with the 748: aforementioned <code><a href="#sqltransaction">SQLTransaction</a></code> object as its only 749: argument, and wait for that task to be run.</li> 1.1 ihickson 750: 1.25 ihickson 751: <li><p>If the callback raised an exception, jump to the last 1.1 ihickson 752: step.</li> 1.25 ihickson 753: 1.1 ihickson 754: <li><p>While there are any statements queued up in the transaction, 755: perform the following steps for each queued up statement in the 756: transaction, oldest first. Each statement has a statement, 757: optionally a result set callback, and optionally an error 758: callback.</p> 759: 1.10 ihickson 760: <ol><li><p>If the statement is marked as bogus, jump to the "in case 1.1 ihickson 761: of error" steps below.</li> 762: 763: <li><p>Execute the statement in the context of the transaction. 1.6 ihickson 764: <a href="#refsSQL">[SQL]</a></p> 1.1 ihickson 765: 766: <li><p>If the statement failed, jump to the "in case of error" 767: steps below.</li> 768: 769: <li><p>Create a <code><a href="#sqlresultset">SQLResultSet</a></code> object that represents 770: the result of the statement.</li> 771: 1.25 ihickson 772: <li><p>If the statement has a result set callback that is not 773: null, <span>queue a task</span> to invoke it with the 774: <code><a href="#sqltransaction">SQLTransaction</a></code> object as its first argument and the 775: new <code><a href="#sqlresultset">SQLResultSet</a></code> object as its second argument, and 776: wait for that task to be run.</li> 1.1 ihickson 777: 778: <li><p>If the callback was invoked and raised an exception, jump 779: to the last step in the overall steps.</li> 780: 781: <li><p>Move on to the next statement, if any, or onto the next 782: overall step otherwise.</li> 783: 1.10 ihickson 784: </ol><p>In case of error (or more specifically, if the above substeps 1.1 ihickson 785: say to jump to the "in case of error" steps), run the following 786: substeps:</p> 787: 1.25 ihickson 788: <ol><li><p>If the statement had an associated error callback that is 789: not null, then <span>queue a task</span> to invoke that error 790: callback with the <code><a href="#sqltransaction">SQLTransaction</a></code> object and a newly 791: constructed <code><a href="#sqlerror">SQLError</a></code> object that represents the 792: error that caused these substeps to be run as the two arguments, 1.1 ihickson 793: respectively, and wait for the task to be run.</li> 794: 795: <li><p>If the error callback returns false, then move on to the 796: next statement, if any, or onto the next overall step 797: otherwise.</li> 798: 799: <li><p>Otherwise, the error callback did not return false, or 800: there was no error callback. Jump to the last step in the overall 801: steps.</li> 802: 1.10 ihickson 803: </ol></li> 1.1 ihickson 804: 1.15 ihickson 805: <li> 1.1 ihickson 806: 1.15 ihickson 807: <p>If a <i>postflight operation</i> was defined for this instance 808: of the transaction steps, then: as one atomic operation, commit 1.66 ihickson 809: the transaction and, if that succeeds, run the <i>postflight 810: operation</i>. If the commit fails, then instead jump to the last 811: step. (This is basically a hook for the <code title="dom-database-changeVersion"><a href="#dom-database-changeversion">changeVersion()</a></code> 1.15 ihickson 812: method.)</p> 813: 1.66 ihickson 814: <p>Otherwise: commit the transaction. If an error occurred in the 815: committing of the transaction, jump to the last step.</p> 1.1 ihickson 816: 1.15 ihickson 817: </li> 1.1 ihickson 818: 819: <li><p><span>Queue a task</span> to invoke the <i>success 1.25 ihickson 820: callback</i>, if it is not null.</li> 1.1 ihickson 821: 822: <li><p>End these steps. The next step is only used when something 823: goes wrong.</li> 824: 1.48 ihickson 825: <li><p><span>Queue a task</span> to invoke the transaction's 826: <i>error callback</i>, if it is not null, with a newly constructed 1.25 ihickson 827: <code><a href="#sqlerror">SQLError</a></code> object that represents the last error to have 828: occurred in this transaction. Rollback the transaction. Any 829: still-pending statements in the transaction are discarded.</li> 1.1 ihickson 830: 1.35 ihickson 831: </ol><p>The <span>task source</span> for these <span title="concept-task">tasks</span> is the <dfn id="database-access-task-source">database access task 1.28 ihickson 832: source</dfn>.<h3 id="synchronous-database-api"><span class="secno">4.4 </span>Synchronous database API</h3><pre class="idl">interface <dfn id="databasesync">DatabaseSync</dfn> { 1.11 ihickson 833: void <a href="#dom-database-sync-transaction" title="dom-database-sync-transaction">transaction</a>(in <a href="#sqltransactionsynccallback">SQLTransactionSyncCallback</a> callback); 834: void <a href="#dom-database-sync-readtransaction" title="dom-database-sync-readTransaction">readTransaction</a>(in <a href="#sqltransactionsynccallback">SQLTransactionSyncCallback</a> callback); 1.1 ihickson 835: 836: readonly attribute DOMString <a href="#dom-database-sync-version" title="dom-database-sync-version">version</a>; 1.34 ihickson 837: void <a href="#dom-database-sync-changeversion" title="dom-database-sync-changeVersion">changeVersion</a>(in DOMString oldVersion, in DOMString newVersion, in optional <a href="#sqltransactionsynccallback">SQLTransactionSyncCallback</a> callback); 1.11 ihickson 838: }; 839: 840: [Callback=FunctionOnly, NoInterfaceObject] 841: interface <dfn id="sqltransactionsynccallback">SQLTransactionSyncCallback</dfn> { 842: void <span title="dom-sqltransactionsynccallback-handleEvent">handleEvent</span>(in <a href="#sqltransactionsync">SQLTransactionSync</a> transaction); 1.10 ihickson 843: };</pre><p>The <dfn id="dom-database-sync-transaction" title="dom-database-sync-transaction"><code>transaction()</code></dfn> 1.11 ihickson 844: and <dfn id="dom-database-sync-readtransaction" title="dom-database-sync-readTransaction"><code>readTransaction()</code></dfn> 845: methods must run the following steps:<ol><li><p>If the method was the <code title="dom-database-sync-transaction"><a href="#dom-database-sync-transaction">transaction()</a></code> method, 846: <a href="#create-a-sqltransactionsync-object">create a <code>SQLTransactionSync</code> object</a> for a 847: read/write transaction. Otherwise, <a href="#create-a-sqltransactionsync-object">create a 848: <code>SQLTransactionSync</code> object</a> for a read-only 849: transaction. In either case, if this throws an exception, then 850: rethrow it and abort these steps. Otherwise, let <var title="">transaction</var> be the newly created 851: <code><a href="#sqltransactionsync">SQLTransactionSync</a></code> object.</li> 852: 853: <li><p>If the first argument is null, rollback the transaction, 854: throw a <code><a href="#sqlexception">SQLException</a></code> exception, and abort these 855: steps. (<a href="#dom-sqlerror-code-0" title="dom-sqlerror-code-0">Error code 856: 0</a>.)</li> 857: 858: <li><p>Invoke the callback given by the first argument, passing it 859: the <var title="">transaction</var> object as its only 860: argument.</li> 861: 862: <li><p>Mark the <code><a href="#sqltransactionsync">SQLTransactionSync</a></code> object as <i title="">stale</i>.</p> 863: 864: <li><p>If the callback was terminated by an exception, then 865: rollback the transaction, rethrow that exception, and abort these 866: steps.</li> 867: 868: <li><p>Commit the transaction.</li> 869: 870: <li><p>If an error occurred in the committing of the transaction, 871: rollback the transaction, throw a <code><a href="#sqlexception">SQLException</a></code> 872: exception, and abort these steps.</li> 873: 874: </ol><p>On getting, the <dfn id="dom-database-sync-version" title="dom-database-sync-version"><code>version</code></dfn> 1.1 ihickson 875: attribute must return the current version of the database (as 876: opposed to the <a href="#concept-database-expected-version" title="concept-database-expected-version">expected version</a> of 1.10 ihickson 877: the <code><a href="#databasesync">DatabaseSync</a></code> object).<p>The <dfn id="dom-database-sync-changeversion" title="dom-database-sync-changeVersion"><code>changeVersion()</code></dfn> 1.1 ihickson 878: method allows scripts to atomically verify the version number and 879: change it at the same time as doing a schema update. When the method 1.10 ihickson 880: is invoked, it must run the following steps:<ol><li><p><a href="#create-a-sqltransactionsync-object">Create a <code>SQLTransactionSync</code> object</a> 1.1 ihickson 881: for a read/write transaction. If this throws an exception, then 1.11 ihickson 882: rethrow it and abort these steps. Otherwise, let <var title="">transaction</var> be the newly created 883: <code><a href="#sqltransactionsync">SQLTransactionSync</a></code> object.</li> 1.1 ihickson 884: 885: <li><p>Check that the value of the first argument to the <code title="dom-database-sync-changeVersion"><a href="#dom-database-sync-changeversion">changeVersion()</a></code> 886: method exactly matches the database's actual version. If it does 1.11 ihickson 887: not, then throw a <code><a href="#sqlexception">SQLException</a></code> exception and abort 1.1 ihickson 888: these steps. (<a href="#dom-sqlerror-code-2" title="dom-sqlerror-code-2">Error code 889: 2</a>.)</li> 890: 1.25 ihickson 891: <li><p>If the third argument is not null, invoke the callback given 892: by the third argument, passing it the <var title="">transaction</var> object as its only argument.</li> 1.11 ihickson 893: 894: <li><p>Mark the <code><a href="#sqltransactionsync">SQLTransactionSync</a></code> object as <i title="">stale</i>.</p> 895: 896: <li><p>If the callback was terminated by an exception, then 897: rollback the transaction, rethrow the exception, and abort these 898: steps.</li> 1.1 ihickson 899: 1.11 ihickson 900: <li><p>Commit the transaction.</li> 901: 902: <li><p>If an error occurred in the committing of the transaction, 903: rollback the transaction, throw a <code><a href="#sqlexception">SQLException</a></code> 904: exception, and abort these steps.</li> 905: 906: <li>Change the database's actual version to the value of the second 1.1 ihickson 907: argument to the <code title="dom-database-sync-changeVersion"><a href="#dom-database-sync-changeversion">changeVersion()</a></code> 908: method.</li> 909: 910: <li>Change the <code><a href="#database">Database</a></code> object's expected version to 911: the value of the second argument to the <code title="dom-database-sync-changeVersion"><a href="#dom-database-sync-changeversion">changeVersion()</a></code> 912: method.</li> 913: 1.10 ihickson 914: </ol><hr><p>When the user agent is to <dfn id="create-a-sqltransactionsync-object">create a 1.1 ihickson 915: <code>SQLTransactionSync</code> object</dfn> for a transaction that 916: is either read/write or read-only, it must run the following 1.10 ihickson 917: steps:<ol><li><p>Open a new SQL transaction to the database, and create a 1.1 ihickson 918: <code><a href="#sqltransactionsync">SQLTransactionSync</a></code> object that represents that 919: transaction. If the <i>mode</i> is read/write, the transaction must 920: have an exclusive write lock over the entire database. If the 921: <i>mode</i> is read-only, the transaction must have a shared read 922: lock over the entire database. The user agent should wait for an 923: appropriate lock to be available.</li> 924: 925: <li><p>If an error occurred in the opening of the transaction 926: (e.g. if the user agent failed to obtain an appropriate lock after 927: an appropriate delay), throw a <code><a href="#sqlexception">SQLException</a></code> exception 928: and abort these steps.</li> 929: 930: <li><p>Return the newly created <code><a href="#sqltransactionsync">SQLTransactionSync</a></code> 931: object.</li> 932: 1.10 ihickson 933: </ol><h4 id="executing-sql-statements-0"><span class="secno">4.4.1 </span>Executing SQL statements</h4><p>The <code title="dom-database-sync-transaction"><a href="#dom-database-sync-transaction">transaction()</a></code>, <code title="dom-database-sync-readTransaction"><a href="#dom-database-sync-readtransaction">readTransaction()</a></code>, 1.1 ihickson 934: and <code title="dom-database-sync-changeVersion"><a href="#dom-database-sync-changeversion">changeVersion()</a></code> 1.25 ihickson 935: methods invoke callbacks that are passed 936: <code><a href="#sqltransactionsync">SQLTransactionSync</a></code> objects.<pre class="idl">// typedef sequence<any> <a href="#objectarray">ObjectArray</a>; 1.1 ihickson 937: 938: interface <dfn id="sqltransactionsync">SQLTransactionSync</dfn> { 1.34 ihickson 939: <a href="#sqlresultset">SQLResultSet</a> <a href="#dom-sqltransaction-sync-executesql" title="dom-sqltransaction-sync-executeSql">executeSql</a>(in DOMString sqlStatement, in optional <a href="#objectarray">ObjectArray</a> arguments); 1.10 ihickson 940: };</pre><p>A <code><a href="#sqltransactionsync">SQLTransactionSync</a></code> object is initially <i title="">fresh</i>, but it will be marked as <i title="">stale</i> 941: once it has been committed or rolled back.<p>When the <dfn id="dom-sqltransaction-sync-executesql" title="dom-sqltransaction-sync-executeSql"><code>executeSql(<var title="">sqlStatement</var>, <var title="">arguments</var>)</code></dfn> method is invoked, the user 942: agent must run the following algorithm:<ol><li><p>If the <code><a href="#sqltransactionsync">SQLTransactionSync</a></code> object is <i title="">stale</i>, then throw an <code>INVALID_STATE_ERR</code> 1.1 ihickson 943: exception.</li> 944: 945: <li> 946: 947: <p><a href="#preprocess-the-sql-statement">Preprocess the SQL statement</a> given as the first 948: argument to the method (<var title="">sqlStatement</var>), using 949: the second argument to the method as the <var title="">arguments</var> array, to obtain <var title="">the 950: statement</var>.</p> 951: 952: <p>If the second argument is omitted or null, then treat the <var title="">arguments</var> array as empty.</p> 953: 954: </li> 955: 956: <li><p>If the statement is marked as bogus, throw a 957: <code><a href="#sqlexception">SQLException</a></code> exception.</li> 958: 959: <li><p>Execute the statement in the context of the transaction. 1.6 ihickson 960: <a href="#refsSQL">[SQL]</a></p> 1.1 ihickson 961: 962: <li><p>If the statement failed, throw a <code><a href="#sqlexception">SQLException</a></code> 963: exception.</li> 964: 965: <li><p>Create a <code><a href="#sqlresultset">SQLResultSet</a></code> object that represents 966: the result of the statement.</li> 967: 968: <li><p>Return the newly created <code><a href="#sqlresultset">SQLResultSet</a></code> 969: object.</li> 970: 1.11 ihickson 971: </ol><h3 id="database-query-results"><span class="secno">4.5 </span>Database query results</h3><p>The <code title="dom-sqltransaction-executeSql"><a href="#dom-sqltransaction-executesql">executeSql()</a></code> 1.1 ihickson 972: method invokes its callback with a <code><a href="#sqlresultset">SQLResultSet</a></code> object 1.10 ihickson 973: as an argument.<pre class="idl">interface <dfn id="sqlresultset">SQLResultSet</dfn> { 1.1 ihickson 974: readonly attribute long <a href="#dom-sqlresultset-insertid" title="dom-SQLResultSet-insertId">insertId</a>; 975: readonly attribute long <a href="#dom-sqlresultset-rowsaffected" title="dom-SQLResultSet-rowsAffected">rowsAffected</a>; 976: readonly attribute <a href="#sqlresultsetrowlist">SQLResultSetRowList</a> <a href="#dom-sqlresultset-rows" title="dom-SQLResultSet-rows">rows</a>; 1.10 ihickson 977: };</pre><p>The <dfn id="dom-sqlresultset-insertid" title="dom-SQLResultSet-insertId"><code>insertId</code></dfn> 1.1 ihickson 978: attribute must return the row ID of the row that the 979: <code><a href="#sqlresultset">SQLResultSet</a></code> object's SQL statement inserted into the 980: database, if the statement inserted a row. If the statement inserted 981: multiple rows, the ID of the last row must be the one returned. If 982: the statement did not insert a row, then the attribute must instead 1.10 ihickson 983: raise an <code>INVALID_ACCESS_ERR</code> exception.<p>The <dfn id="dom-sqlresultset-rowsaffected" title="dom-SQLResultSet-rowsAffected"><code>rowsAffected</code></dfn> 1.1 ihickson 984: attribute must return the number of rows that were changed by the 985: SQL statement. If the statement did not affected any rows, then the 986: attribute must return zero. For "SELECT" statements, this returns 1.10 ihickson 987: zero (querying the database doesn't affect any rows).<p>The <dfn id="dom-sqlresultset-rows" title="dom-SQLResultSet-rows"><code>rows</code></dfn> 1.1 ihickson 988: attribute must return a <code><a href="#sqlresultsetrowlist">SQLResultSetRowList</a></code> 989: representing the rows returned, in the order returned by the 1.71 ihickson 990: database. The same object must be returned each time. If no rows 991: were returned, then the object will be empty (its <code title="dom-SQLResultSetRowList-length"><a href="#dom-sqlresultsetrowlist-length">length</a></code> will be 992: zero).<pre class="idl">interface <dfn id="sqlresultsetrowlist">SQLResultSetRowList</dfn> { 1.1 ihickson 993: readonly attribute unsigned long <a href="#dom-sqlresultsetrowlist-length" title="dom-SQLResultSetRowList-length">length</a>; 1.5 ihickson 994: getter <span>any</span> <a href="#dom-sqlresultsetrowlist-item" title="dom-SQLResultSetRowList-item">item</a>(in unsigned long index); 1.47 ihickson 995: };</pre><p class="note">For the asynchronous API, implementors are 996: encouraged to prefetch all the data for 997: <code><a href="#sqlresultsetrowlist">SQLResultSetRowList</a></code> objects when the object is 998: constructed (before the result set callback is invoked), rather than 999: on-demand, for better responsiveness. For the synchronous API, an 1000: on-demand lazy evaluation implementation strategy is encouraged 1001: instead, for better performance.<p><code><a href="#sqlresultsetrowlist">SQLResultSetRowList</a></code> objects have a <dfn id="dom-sqlresultsetrowlist-length" title="dom-SQLResultSetRowList-length"><code>length</code></dfn> 1.1 ihickson 1002: attribute that must return the number of rows it represents (the 1.10 ihickson 1003: number of rows returned by the database). This is the <var title="dom-SQLResultSetRowList-length"><a href="#dom-sqlresultsetrowlist-length">length</a></var>.<p class="note">Fetching the <code title="dom-SQLResultSetRowList-length"><a href="#dom-sqlresultsetrowlist-length">length</a></code> might be 1.1 ihickson 1004: expensive, and authors are thus encouraged to avoid using it (or 1005: enumerating over the object, which implicitly uses it) where 1.10 ihickson 1006: possible.<p>The object's <span>indices of the supported indexed 1.1 ihickson 1007: properties</span> are the numbers in the range zero to <span title=""><var title="dom-SQLResultSetRowList-length"><a href="#dom-sqlresultsetrowlist-length">length</a></var>-1</span>, unless 1008: the <var title="dom-SQLResultSetRowList-length"><a href="#dom-sqlresultsetrowlist-length">length</a></var> is 1009: zero, in which case there are no <span>supported indexed 1.10 ihickson 1010: properties</span>.<p>The <dfn id="dom-sqlresultsetrowlist-item" title="dom-SQLResultSetRowList-item"><code>item(<var title="">index</var>)</code></dfn> attribute must return the row 1.1 ihickson 1011: with the given index <var title="">index</var>. If there is no such 1.10 ihickson 1012: row, then the method must return null.<p>Each row must be represented by a native ordered dictionary data 1.1 ihickson 1013: type. In the JavaScript binding, this must be <code>Object</code>. 1014: Each row object must have one property (or dictionary entry) per 1015: column, with those properties enumerating in the order that these 1016: columns were returned by the database. Each property must have the 1017: name of the column and the value of the cell, as they were returned 1.10 ihickson 1018: by the database.<h3 id="errors-and-exceptions"><span class="secno">4.6 </span>Errors and exceptions</h3><p>Errors in the asynchronous database API are reported using 1.1 ihickson 1019: callbacks that have a <code><a href="#sqlerror">SQLError</a></code> object as one of their 1.10 ihickson 1020: arguments.<pre class="idl">interface <dfn id="sqlerror">SQLError</dfn> { 1.9 ihickson 1021: const unsigned short <a href="#dom-sqlexception-code-unknown" title="dom-SQLException-code-UNKNOWN">UNKNOWN_ERR</a> = 0; 1022: const unsigned short <a href="#dom-sqlexception-code-database" title="dom-SQLException-code-DATABASE">DATABASE_ERR</a> = 1; 1023: const unsigned short <a href="#dom-sqlexception-code-version" title="dom-SQLException-code-VERSION">VERSION_ERR</a> = 2; 1024: const unsigned short <a href="#dom-sqlexception-code-too_large" title="dom-SQLException-code-TOO_LARGE">TOO_LARGE_ERR</a> = 3; 1025: const unsigned short <a href="#dom-sqlexception-code-quota" title="dom-SQLException-code-QUOTA">QUOTA_ERR</a> = 4; 1026: const unsigned short <a href="#dom-sqlexception-code-syntax" title="dom-SQLException-code-SYNTAX">SYNTAX_ERR</a> = 5; 1027: const unsigned short <a href="#dom-sqlexception-code-constraint" title="dom-SQLException-code-CONSTRAINT">CONSTRAINT_ERR</a> = 6; 1028: const unsigned short <a href="#dom-sqlexception-code-timeout" title="dom-SQLException-code-TIMEOUT">TIMEOUT_ERR</a> = 7; 1029: readonly attribute unsigned short <a href="#dom-sqlerror-code" title="dom-SQLError-code">code</a>; 1.1 ihickson 1030: readonly attribute DOMString <a href="#dom-sqlerror-message" title="dom-SQLError-message">message</a>; 1.24 ihickson 1031: };</pre><p>The <dfn id="dom-sqlerror-code" title="dom-SQLError-code"><code>code</code></dfn> IDL 1.1 ihickson 1032: attribute must return the most appropriate code from the table 1.10 ihickson 1033: below.<p>The <dfn id="dom-sqlerror-message" title="dom-SQLError-message"><code>message</code></dfn> 1.24 ihickson 1034: IDL attribute must return an error message describing the error 1.1 ihickson 1035: encountered. The message should be localized to the user's 1.10 ihickson 1036: language.<hr><p>Errors in the synchronous database API are reported using 1037: <code><a href="#sqlexception">SQLException</a></code> exceptions:<pre class="idl">exception <dfn id="sqlexception">SQLException</dfn> { 1.9 ihickson 1038: const unsigned short <a href="#dom-sqlexception-code-unknown" title="dom-SQLException-code-UNKNOWN">UNKNOWN_ERR</a> = 0; 1039: const unsigned short <a href="#dom-sqlexception-code-database" title="dom-SQLException-code-DATABASE">DATABASE_ERR</a> = 1; 1040: const unsigned short <a href="#dom-sqlexception-code-version" title="dom-SQLException-code-VERSION">VERSION_ERR</a> = 2; 1041: const unsigned short <a href="#dom-sqlexception-code-too_large" title="dom-SQLException-code-TOO_LARGE">TOO_LARGE_ERR</a> = 3; 1042: const unsigned short <a href="#dom-sqlexception-code-quota" title="dom-SQLException-code-QUOTA">QUOTA_ERR</a> = 4; 1043: const unsigned short <a href="#dom-sqlexception-code-syntax" title="dom-SQLException-code-SYNTAX">SYNTAX_ERR</a> = 5; 1044: const unsigned short <a href="#dom-sqlexception-code-constraint" title="dom-SQLException-code-CONSTRAINT">CONSTRAINT_ERR</a> = 6; 1045: const unsigned short <a href="#dom-sqlexception-code-timeout" title="dom-SQLException-code-TIMEOUT">TIMEOUT_ERR</a> = 7; 1046: unsigned short <a href="#dom-sqlexception-code" title="dom-SQLException-code">code</a>; 1.1 ihickson 1047: DOMString <a href="#dom-sqlexception-message" title="dom-SQLException-message">message</a>; 1.10 ihickson 1048: };</pre><p>The <dfn id="dom-sqlexception-code" title="dom-SQLException-code"><code>code</code></dfn> 1.24 ihickson 1049: IDL attribute must return the most appropriate code from the table 1050: below.<p>The <dfn id="dom-sqlexception-message" title="dom-SQLException-message"><code>message</code></dfn> IDL 1.1 ihickson 1051: attribute must return an error message describing the error 1052: encountered. The message should be localized to the user's 1.10 ihickson 1053: language.<hr><p>The error codes are as follows:<table><thead><tr><th>Constant 1.6 ihickson 1054: <th>Code 1.1 ihickson 1055: <th>Situation 1.10 ihickson 1056: <tbody><tr><td><dfn id="dom-sqlexception-code-unknown" title="dom-SQLException-code-UNKNOWN"><code>UNKNOWN_ERR</code></dfn> 1.6 ihickson 1057: <td><dfn id="dom-sqlerror-code-0" title="dom-sqlerror-code-0">0</dfn> 1.1 ihickson 1058: <td>The transaction failed for reasons unrelated to the database 1059: itself and not covered by any other error code. 1060: 1.10 ihickson 1061: <tr><td><dfn id="dom-sqlexception-code-database" title="dom-SQLException-code-DATABASE"><code>DATABASE_ERR</code></dfn> 1.6 ihickson 1062: <td><dfn id="dom-sqlerror-code-1" title="dom-sqlerror-code-1">1</dfn> 1.1 ihickson 1063: <td>The statement failed for database reasons not covered by any 1064: other error code. 1065: 1.10 ihickson 1066: <tr><td><dfn id="dom-sqlexception-code-version" title="dom-SQLException-code-VERSION"><code>VERSION_ERR</code></dfn> 1.6 ihickson 1067: <td><dfn id="dom-sqlerror-code-2" title="dom-sqlerror-code-2">2</dfn> 1.1 ihickson 1068: <td>The operation failed because the actual database version was 1069: not what it should be. For example, a statement found that the 1070: actual database version no longer matched the <a href="#concept-database-expected-version" title="concept-database-expected-version">expected version</a> 1071: of the <code><a href="#database">Database</a></code> or <code><a href="#databasesync">DatabaseSync</a></code> object, 1072: or the <code title="dom-database-changeversion"><a href="#dom-database-changeversion">Database.changeVersion()</a></code> 1073: or <code title="dom-database-sync-changeversion"><a href="#dom-database-sync-changeversion">DatabaseSync.changeVersion()</a></code> 1074: methods were passed a version that doesn't match the actual 1075: database version. 1076: 1.10 ihickson 1077: <tr><td><dfn id="dom-sqlexception-code-too_large" title="dom-SQLException-code-TOO_LARGE"><code>TOO_LARGE_ERR</code></dfn> 1.6 ihickson 1078: <td><dfn id="dom-sqlerror-code-3" title="dom-sqlerror-code-3">3</dfn> 1.1 ihickson 1079: <td>The statement failed because the data returned from the 1080: database was too large. The SQL "LIMIT" modifier might be useful 1081: to reduce the size of the result set. 1082: 1.10 ihickson 1083: <tr><td><dfn id="dom-sqlexception-code-quota" title="dom-SQLException-code-QUOTA"><code>QUOTA_ERR</code></dfn> 1.6 ihickson 1084: <td><dfn id="dom-sqlerror-code-4" title="dom-sqlerror-code-4">4</dfn> 1.1 ihickson 1085: <td>The statement failed because there was not enough remaining 1086: storage space, or the storage quota was reached and the user 1087: declined to give more space to the database. 1088: 1.10 ihickson 1089: <tr><td><dfn id="dom-sqlexception-code-syntax" title="dom-SQLException-code-SYNTAX"><code>SYNTAX_ERR</code></dfn> 1.6 ihickson 1090: <td><dfn id="dom-sqlerror-code-5" title="dom-sqlerror-code-5">5</dfn> 1.1 ihickson 1091: <td>The statement failed because of a syntax error, or the number 1092: of arguments did not match the number of <code title="">?</code> 1093: placeholders in the statement, or the statement tried to use a 1094: statement that is not allowed, such as <code title="">BEGIN</code>, <code title="">COMMIT</code>, or <code title="">ROLLBACK</code>, or the statement tried to use a verb 1095: that could modify the database but the transaction was read-only. 1096: 1.10 ihickson 1097: <tr><td><dfn id="dom-sqlexception-code-constraint" title="dom-SQLException-code-CONSTRAINT"><code>CONSTRAINT_ERR</code></dfn> 1.6 ihickson 1098: <td><dfn id="dom-sqlerror-code-6" title="dom-sqlerror-code-6">6</dfn> 1.1 ihickson 1099: <td>An <code title="">INSERT</code>, <code title="">UPDATE</code>, or <code title="">REPLACE</code> 1100: statement failed due to a constraint failure. For example, 1101: because a row was being inserted and the value given for the 1102: primary key column duplicated the value of an existing row. 1103: 1.10 ihickson 1104: <tr><td><dfn id="dom-sqlexception-code-timeout" title="dom-SQLException-code-TIMEOUT"><code>TIMEOUT_ERR</code></dfn> 1.6 ihickson 1105: <td><dfn id="dom-sqlerror-code-7" title="dom-sqlerror-code-7">7</dfn> 1.1 ihickson 1106: <td>A lock for the transaction could not be obtained in a 1107: reasonable time. 1108: 1.51 ihickson 1109: </table><h2 id="web-sql"><span class="secno">5 </span>Web SQL</h2><p>User agents must implement the SQL dialect supported by Sqlite 3.6.19.<p>When converting bound arguments to SQL data types, the JavaScript 1.64 ihickson 1110: ToPrimitive abstract operation must be applied to obtain the raw 1111: value to be processed. <a href="#refsECMA262">[ECMA262]</a>.<h2 id="disk-space"><span class="secno">6 </span>Disk space</h2><p>User agents should limit the total amount of space allowed for 1.1 ihickson 1112: databases. 1113: 1114: <p>User agents should guard against sites storing data under the 1115: origins other affiliated sites, e.g. storing up to the limit in 1116: a1.example.com, a2.example.com, a3.example.com, etc, circumventing 1.10 ihickson 1117: the main example.com storage limit.<p>User agents may prompt the user when quotas are reached, allowing 1.1 ihickson 1118: the user to grant a site more space. This enables sites to store 1119: many user-created documents on the user's computer, for 1.10 ihickson 1120: instance.<p>User agents should allow users to see how much space each domain 1121: is using.<p>A mostly arbitrary limit of five megabytes per 1.1 ihickson 1122: <span>origin</span> is recommended. Implementation feedback is 1123: welcome and will be used to update this suggestion in the 1.19 ihickson 1124: future.<h2 id="privacy"><span class="secno">7 </span>Privacy</h2><h3 id="user-tracking"><span class="secno">7.1 </span>User tracking</h3><p>A third-party advertiser (or any entity capable of getting 1.1 ihickson 1125: content distributed to multiple sites) could use a unique identifier 1126: stored in its 1.39 ihickson 1127: client-side databases 1.1 ihickson 1128: 1.45 ihickson 1129: 1.1 ihickson 1130: to track a user across multiple sessions, building a profile of the 1131: user's interests to allow for highly targeted advertising. In 1132: conjunction with a site that is aware of the user's real identity 1133: (for example an e-commerce site that requires authenticated 1134: credentials), this could allow oppressive groups to target 1135: individuals with greater accuracy than in a world with purely 1.10 ihickson 1136: anonymous Web usage.<p>There are a number of techniques that can be used to mitigate the 1137: risk of user tracking:<dl><dt>Blocking third-party storage</dt> 1.1 ihickson 1138: <dd> 1139: 1140: <p>User agents may restrict access to 1141: the database objects 1142: 1.45 ihickson 1143: 1.1 ihickson 1144: to scripts originating at the domain of the top-level document of 1145: the <span>browsing context</span>, for instance denying access to 1146: the API for pages from other domains running in 1147: <code>iframe</code>s.</p> 1148: 1149: </dd> 1150: 1151: <dt>Expiring stored data</dt> 1152: <dd> 1153: 1.40 ihickson 1154: <p>User agents may, if so configured by the user, automatically 1155: delete stored data after a period of time.</p> 1.1 ihickson 1156: 1157: 1158: <p>This can restrict the ability of a site to track a user, as the 1159: site would then only be able to track the user across multiple 1160: sessions when he authenticates with the site itself (e.g. by 1161: making a purchase or logging in to a service).</p> 1162: 1.40 ihickson 1163: <p>However, this also reduces the usefulness of the API as a 1164: long-term storage mechanism. It can also put the user's data at 1165: risk, if the user does not fully understand the implications of 1166: data expiration.</p> 1.1 ihickson 1167: 1168: 1169: </dd> 1170: 1171: <dt>Treating persistent storage as cookies</dt> 1172: <dd> 1173: 1.31 ihickson 1174: <p>If users attempt to protect their privacy by clearing cookies 1175: without also clearing data stored in the 1.39 ihickson 1176: relevant databases, 1177: 1178: sites can defeat those attempts by using the two features as 1179: redundant backup for each other. User agents should present the 1.31 ihickson 1180: interfaces for clearing these in a way that helps users to 1181: understand this possibility and enables them to delete data in all 1182: persistent storage features simultaneously. <a href="#refsCOOKIES">[COOKIES]</a></p> 1.1 ihickson 1183: 1184: </dd> 1185: 1186: <dt>Site-specific white-listing of access to 1187: databases 1188: 1.45 ihickson 1189: 1.1 ihickson 1190: </dt> 1191: <dd> 1192: 1193: <p>User agents may require the user to authorize access to 1194: databases before a site can use the feature.</p> 1195: 1.45 ihickson 1196: 1.1 ihickson 1197: 1198: </dd> 1199: 1200: <dt>Origin-tracking of stored data</dt> 1201: <dd> 1202: 1203: <p>User agents may record the <span title="origin">origins</span> 1204: of sites that contained content from third-party origins that 1205: caused data to be stored.</p> 1206: 1207: <p>If this information is then used to present the view of data 1208: currently in persistent storage, it would allow the user to make 1209: informed decisions about which parts of the persistent storage to 1210: prune. Combined with a blacklist ("delete this data and prevent 1211: this domain from ever storing data again"), the user can restrict 1212: the use of persistent storage to sites that he trusts.</p> 1213: 1214: </dd> 1215: 1216: <dt>Shared blacklists</dt> 1217: <dd> 1218: 1219: <p>User agents may allow users to share their persistent storage 1220: domain blacklists.</p> 1221: 1222: <p>This would allow communities to act together to protect their 1223: privacy.</p> 1224: 1225: </dd> 1226: 1.10 ihickson 1227: </dl><p>While these suggestions prevent trivial use of this API for user 1.1 ihickson 1228: tracking, they do not block it altogether. Within a single domain, a 1229: site can continue to track the user during a session, and can then 1230: pass all this information to the third party along with any 1231: identifying information (names, credit card numbers, addresses) 1232: obtained by the site. If a third party cooperates with multiple 1233: sites to obtain such information, a profile can still be 1.10 ihickson 1234: created.<p>However, user tracking is to some extent possible even with no 1.1 ihickson 1235: cooperation from the user agent whatsoever, for instance by using 1236: session identifiers in URLs, a technique already commonly used for 1237: innocuous purposes but easily repurposed for user tracking (even 1238: retroactively). This information can then be shared with other 1239: sites, using using visitors' IP addresses and other user-specific 1240: data (e.g. user-agent headers and configuration settings) to combine 1.31 ihickson 1241: separate sessions into coherent user profiles.<h3 id="sensitivity-of-data"><span class="secno">7.2 </span>Sensitivity of data</h3><p>User agents should treat persistently stored data as potentially 1.13 ihickson 1242: sensitive; it's quite possible for e-mails, calendar appointments, 1243: health records, or other confidential documents to be stored in this 1244: mechanism.<p>To this end, user agents should ensure that when deleting data, 1.76 ihickson 1245: it is promptly deleted from the underlying storage.<h2 id="security-storage"><span class="secno">8 </span>Security</h2><h3 id="dns-spoofing-attacks"><span class="secno">8.1 </span>DNS spoofing attacks</h3><p>Because of the potential for DNS spoofing attacks, one cannot 1.1 ihickson 1246: guarantee that a host claiming to be in a certain domain really is 1247: from that domain. To mitigate this, pages can use SSL. Pages using 1248: SSL can be sure that only pages using SSL that have certificates 1249: identifying them as being from the same domain can access their 1250: databases. 1251: 1.19 ihickson 1252: <h3 id="cross-directory-attacks"><span class="secno">8.2 </span>Cross-directory attacks</h3><p>Different authors sharing one host name, for example users 1.1 ihickson 1253: hosting content on <code>geocities.com</code>, all share one 1254: set of databases. 1255: 1256: There is no feature to restrict the access by pathname. Authors on 1257: shared hosts are therefore recommended to avoid using these 1258: features, as it would be trivial for other authors to read the data 1.10 ihickson 1259: and overwrite it.<p class="note">Even if a path-restriction feature was made 1.1 ihickson 1260: available, the usual DOM scripting security model would make it 1261: trivial to bypass this protection and access the data from any 1.19 ihickson 1262: path.<h3 id="implementation-risks"><span class="secno">8.3 </span>Implementation risks</h3><p>The two primary risks when implementing these persistent storage 1.1 ihickson 1263: features are letting hostile sites read information from other 1264: domains, and letting hostile sites write information that is then 1.10 ihickson 1265: read from other domains.<p>Letting third-party sites read data that is not supposed to be 1.1 ihickson 1266: read from their domain causes <em>information leakage</em>, For 1267: example, a user's shopping wishlist on one domain could be used by 1268: another domain for targeted advertising; or a user's 1269: work-in-progress confidential documents stored by a word-processing 1.10 ihickson 1270: site could be examined by the site of a competing company.<p>Letting third-party sites write data to the persistent storage of 1.1 ihickson 1271: other domains can result in <em>information spoofing</em>, which is 1272: equally dangerous. For example, a hostile site could add items to a 1273: user's wishlist; or a hostile site could set a user's session 1274: identifier to a known ID that the hostile site can then use to track 1.10 ihickson 1275: the user's actions on the victim site.<p>Thus, strictly following the <span>origin</span> model described 1.19 ihickson 1276: in this specification is important for user security.<h3 id="sql-and-user-agents"><span class="secno">8.4 </span>SQL and user agents</h3><p>User agent implementors are strongly encouraged to audit all 1.1 ihickson 1277: their supported SQL statements for security implications. For 1278: example, <code title="">LOAD DATA INFILE</code> is likely to pose 1.10 ihickson 1279: security risks and there is little reason to support it.<p>In general, it is recommended that user agents not support 1.1 ihickson 1280: features that control how databases are stored on disk. For example, 1281: there is little reason to allow Web authors to control the character 1282: encoding used in the disk representation of the data, as all data in 1.19 ihickson 1283: JavaScript is implicitly UTF-16.<h3 id="sql-injection"><span class="secno">8.5 </span>SQL injection</h3><p>Authors are strongly recommended to make use of the <code title="">?</code> placeholder feature of the <code title="dom-sqltransaction-executeSql"><a href="#dom-sqltransaction-executesql">executeSql()</a></code> method, 1.68 ihickson 1284: and to never construct SQL statements on the fly.<h2 class="no-num" id="references">References</h2><!--REFS--><p>All references are normative unless marked "Non-normative".</p><!-- Dates are only included for standards older than the Web, 1285: because the newer ones keep changing. --><dl><dt id="refsCOOKIES">[COOKIES]</dt> 1.7 ihickson 1286: <!-- 1.38 ihickson 1287: <dd><cite><a href="http://www.ietf.org/rfc/rfc2109.txt">HTTP State 1.68 ihickson 1288: Management Mechanism</a></cite>, D. Kristol, L. Montulli. IETF.</dd> 1.7 ihickson 1289: <dd><cite><a href="http://www.ietf.org/rfc/rfc2965.txt">HTTP State Management 1.68 ihickson 1290: Mechanism</a></cite>, D. Kristol, L. Montulli. IETF.</dd> 1.7 ihickson 1291: --> 1.78 ihickson 1292: <dd><cite><a href="http://tools.ietf.org/html/draft-ietf-httpstate-cookie">HTTP State 1.68 ihickson 1293: Management Mechanism</a></cite>, A. Barth. IETF.</dd> 1.7 ihickson 1294: 1295: <dt id="refsDOMCORE">[DOMCORE]</dt> 1296: <dd><cite><a href="http://www.w3.org/TR/DOM-Level-3-Core/">Document 1297: Object Model (DOM) Level 3 Core Specification</a></cite>, A. Le 1298: Hors, P. Le Hegaret, L. Wood, G. Nicol, J. Robie, M. Champion, 1.68 ihickson 1299: S. Byrnes. W3C.</dd> 1.7 ihickson 1300: <!-- 1301: <dd><cite><a href="http://simon.html5.org/specs/web-dom-core">Web 1.68 ihickson 1302: DOM Core</a></cite>, S. Pieters. W3C.</dd> 1.7 ihickson 1303: --> 1304: 1.6 ihickson 1305: <dt id="refsECMA262">[ECMA262]</dt> 1306: <dd><cite><a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm">ECMAScript 1.68 ihickson 1307: Language Specification</a></cite>. ECMA.</dd> 1.6 ihickson 1308: 1.68 ihickson 1309: <dt id="refsHTML">[HTML]</dt> 1310: <dd><cite><a href="http://www.whatwg.org/specs/web-apps/current-work/">HTML</a></cite>, 1311: I. Hickson. WHATWG.</dd> 1.8 ihickson 1312: 1313: <dt id="refsRFC2119">[RFC2119]</dt> 1314: <dd><cite><a href="http://www.ietf.org/rfc/rfc2119.txt">Key words for use in 1.68 ihickson 1315: RFCs to Indicate Requirement Levels</a></cite>, S. Bradner. IETF.</dd> 1.8 ihickson 1316: 1.6 ihickson 1317: <dt id="refsSQL">[SQL]</dt> 1318: <dd>The precise dialect has not yet been specified.</dd> 1319: 1.8 ihickson 1320: <dt id="refsWEBIDL">[WEBIDL]</dt> 1321: <!-- 1322: <dd><cite><a href="http://www.w3.org/TR/WebIDL/">Web 1.68 ihickson 1323: IDL</a></cite>, C. McCormack. W3C.</dd> 1.8 ihickson 1324: --> 1325: <dd><cite><a href="http://dev.w3.org/2006/webapi/WebIDL/">Web 1.68 ihickson 1326: IDL</a></cite>, C. McCormack. W3C.</dd> 1.8 ihickson 1327: 1.61 ihickson 1328: </dl>