mozilla

Revision 165407 of User talk:sdwilsh

  • Revision slug: User_talk:sdwilsh
  • Revision title: User talk:sdwilsh
  • Revision id: 165407
  • Created:
  • Creator: sdwilsh
  • Is current revision? No
  • Comment /* Async Storage Statements */ Added discussion section

Revision Content

FUEL API for opening a window with parameters?

idl:

nsIDOMWindow open(in nsIDOMWindow aParent, in string aURL, in string aName, in string aFeatures, in unsigned long aParamCount, [array, size_is(aParamCount)] in aParams);

js to covert it for the window watcher

open: function FUEL_open(aParent, aURL, aName, aFeatures, aParamCount, aParams)
{
  var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].getService(Ci.nsIWindowWatcher);

  var args = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
  for (var i = 0; i < aParams.length; i++) {
    var obj = null;

    switch (typeof(aParams[i])) {
      case "string":
        obj = Cc[@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
        obj.data = aParams[i];
        break;
      case "number":
        obj = Cc["@mozilla.org/supports-double;1"].createInstance(Ci.nsISupportsDouble);
        obj.data = aParams[i];
        break;
      default:
        // XXX some kind of error
    } 

    if (obj)
      args.appendElement(obj, false);
  }

  ww.open(aParent, aURL, aName, aFeatures, args);
}

Async Storage Statements

This is loosely based off of the HTML 5 SQL spec

Sample Code

This is an attempt at some sample code on using async statements.

JavaScript
// conn is a mozIStorageConnection
let stmt = conn.newAsyncTransaction();

// you should be able to bind numbered parameters (as well as unnumbered ones)
stmt.execute("SELECT * FROM moz_downloads WHERE state = ?1",
             [Ci.nsIDownloadManager.DOWNLOAD_FINISHED],
             {
               handleResult(aTransaction, aResult)
               {
                 for (let row in aResult) {
                   // process data
                   // should be able to access data in a row by name or argument number
                 }
               },
               handleError(aTransaction, aError)
               {
                 // update UI accordingly
               }
             });


// You should be able to bind parameters by name as well
stmt = conn.newAsyncTransaction();
stmt.execute("SELECT * FROM moz_downloads WHERE state = :state",
             {state: Ci.nsIDownloadManager.DOWNLOAD_FAILED},
             {
               handleResult(aTransaction, aResult)
               {
                 for (let row in aResult) {
                   // process data
                   // should be able to access data in a row by name or argument number
                 }
               },
               handleError(aTransaction, aError)
               {
                 // update UI accordingly
               }
             });
C++
class Listener : public AsyncTransactionLisener {
  NS_IMETHODIMP HandleResult(AsyncTransaction *aTransaction, ?? aResult)
  {
    nsCOMPtr<mozIStorageValueArray> row;
    while (NS_SUCCEEDED(aResult->GetRow(row)) && row) {
      // do something with result
    }
  }

  NS_IMETHODIMP HandleError(AsyncTransaction *aTransaction, ?? aError)
  {
  }
};

// conn is a mozIStorageConnection
nsCOMPtr<AsyncTransaction> stmt;
(void)conn->newAsyncTransaction(getter_AddRefs(stmt));

// Special object for C++ to bind params - implements some predefined interface
nsRefPtr<Parameters> params(new Parameters());
params->Bind(0, nsIDownloadManager::DOWNLOAD_FINISHED);

(void)stmt->Execute(
  NS_LITERAL_CSTRING("SELECT * FROM moz_downloads WHERE state = ?1"),
  params,
  new Listener()
);

// Also allows binding of named parameters
params = new Parameters();
parms->Bind(NS_LITERAL_CSTRING("state"), nsIDownloadManager::DOWNLOAD_FINISHED);
(void)stmt->Execute(
  NS_LITERAL_CSTRING("SELECT * FROM moz_downloads WHERE state = ?1"),
  params,
  new Listener()
);

Proposed Interface

This is a work in progress. Comments welcome.

mozIStorageConnection

These are necessary changes to the mozIStorageConnection interface.

AsyncTransaction newAsyncTransaction();

Creates a new object to execute the async transaction.

AsyncTransaction

This is a new interface that handles asynchronous calls to the db.

void execute(in AUTF8String aSQL, [optional] in Parameters aParameters, [optional] in Callback aCallback);

Executes a sql statement and calls the callback when a result is returned.

Parameters

Interface to handle the adding of properties. My expectation is that this just offers a series of getters for storage to call, and we'll have special objects implemented in each language. This still needs lots of defining, so feedback welcome.

Callback

Interface handles some sort of callback on the calling thread.

void handleResult(in AsyncTransaction aTransaction, in ResultSet aResultSet);

Handles a successful execution of the statement.

void handleError(in AsyncTransaction aTransaction, in ?? aError);

Handles an error of the statement.

ResultSet

Interface used to get the data back. In JS, this should be able to be used as an iterator.

mozIStorageValueArray getNextResult();

Obtains the next tuple of results. Null if no results available.

Discussion

Revision Source

<h3 name="FUEL_API_for_opening_a_window_with_parameters.3F"> FUEL API for opening a window with parameters? </h3>
<p>idl:
</p>
<pre>nsIDOMWindow open(in nsIDOMWindow aParent, in string aURL, in string aName, in string aFeatures, in unsigned long aParamCount, [array, size_is(aParamCount)] in aParams);</pre>
<p>js to covert it for the window watcher
</p>
<pre>open: function FUEL_open(aParent, aURL, aName, aFeatures, aParamCount, aParams)
{
  var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].getService(Ci.nsIWindowWatcher);

  var args = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
  for (var i = 0; i &lt; aParams.length; i++) {
    var obj = null;

    switch (typeof(aParams[i])) {
      case "string":
        obj = Cc[@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
        obj.data = aParams[i];
        break;
      case "number":
        obj = Cc["@mozilla.org/supports-double;1"].createInstance(Ci.nsISupportsDouble);
        obj.data = aParams[i];
        break;
      default:
        // XXX some kind of error
    } 

    if (obj)
      args.appendElement(obj, false);
  }

  ww.open(aParent, aURL, aName, aFeatures, args);
}</pre>
<h3 name="Async_Storage_Statements"> Async Storage Statements </h3>
<p>This is loosely based off of the <a class="external" href="http://www.whatwg.org/specs/web-apps/current-work/#executing">HTML 5 SQL spec</a>
</p>
<h4 name="Sample_Code"> Sample Code </h4>
<p>This is an attempt at some sample code on using async statements.
</p>
<h5 name="JavaScript"> JavaScript </h5>
<pre>// conn is a mozIStorageConnection
let stmt = conn.newAsyncTransaction();

// you should be able to bind numbered parameters (as well as unnumbered ones)
stmt.execute("SELECT * FROM moz_downloads WHERE state = ?1",
             [Ci.nsIDownloadManager.DOWNLOAD_FINISHED],
             {
               handleResult(aTransaction, aResult)
               {
                 for (let row in aResult) {
                   // process data
                   // should be able to access data in a row by name or argument number
                 }
               },
               handleError(aTransaction, aError)
               {
                 // update UI accordingly
               }
             });


// You should be able to bind parameters by name as well
stmt = conn.newAsyncTransaction();
stmt.execute("SELECT * FROM moz_downloads WHERE state = :state",
             {state: Ci.nsIDownloadManager.DOWNLOAD_FAILED},
             {
               handleResult(aTransaction, aResult)
               {
                 for (let row in aResult) {
                   // process data
                   // should be able to access data in a row by name or argument number
                 }
               },
               handleError(aTransaction, aError)
               {
                 // update UI accordingly
               }
             });
</pre>
<h5 name="C.2B.2B"> C++ </h5>
<pre>class Listener : public AsyncTransactionLisener {
  NS_IMETHODIMP HandleResult(AsyncTransaction *aTransaction, ?? aResult)
  {
    nsCOMPtr&lt;mozIStorageValueArray&gt; row;
    while (NS_SUCCEEDED(aResult-&gt;GetRow(row)) &amp;&amp; row) {
      // do something with result
    }
  }

  NS_IMETHODIMP HandleError(AsyncTransaction *aTransaction, ?? aError)
  {
  }
};

// conn is a mozIStorageConnection
nsCOMPtr&lt;AsyncTransaction&gt; stmt;
(void)conn-&gt;newAsyncTransaction(getter_AddRefs(stmt));

// Special object for C++ to bind params - implements some predefined interface
nsRefPtr&lt;Parameters&gt; params(new Parameters());
params-&gt;Bind(0, nsIDownloadManager::DOWNLOAD_FINISHED);

(void)stmt-&gt;Execute(
  NS_LITERAL_CSTRING("SELECT * FROM moz_downloads WHERE state = ?1"),
  params,
  new Listener()
);

// Also allows binding of named parameters
params = new Parameters();
parms-&gt;Bind(NS_LITERAL_CSTRING("state"), nsIDownloadManager::DOWNLOAD_FINISHED);
(void)stmt-&gt;Execute(
  NS_LITERAL_CSTRING("SELECT * FROM moz_downloads WHERE state = ?1"),
  params,
  new Listener()
);
</pre>
<h4 name="Proposed_Interface"> Proposed Interface </h4>
<p>This is a work in progress.  Comments welcome.
</p>
<h5 name="mozIStorageConnection"> mozIStorageConnection </h5>
<p>These are necessary changes to the mozIStorageConnection interface.
</p><p><code><a href="#AsyncTransaction">AsyncTransaction</a> newAsyncTransaction();</code>
</p><p>Creates a new object to execute the async transaction.
</p>
<h5 name="AsyncTransaction"> AsyncTransaction </h5>
<p>This is a new interface that handles asynchronous calls to the db.
</p><p><code>void execute(in <a href="en/AUTF8String">AUTF8String</a> aSQL, <span class="plain">[optional]</span> in <a href="#Parameters">Parameters</a> aParameters, <span class="plain">[optional]</span> in <a href="#Callback">Callback</a> aCallback);</code>
</p><p>Executes a sql statement and calls the callback when a result is returned.
</p>
<h5 name="Parameters"> Parameters </h5>
<p>Interface to handle the adding of properties.  My expectation is that this just offers a series of getters for storage to call, and we'll have special objects implemented in each language.  This still needs lots of defining, so feedback welcome.
</p>
<h5 name="Callback"> Callback </h5>
<p>Interface handles some sort of callback on the calling thread.
</p><p><code>void handleResult(in <a href="#AsyncTransaction">AsyncTransaction</a> aTransaction, in <a href="#ResultSet">ResultSet</a> aResultSet);</code>
</p><p>Handles a successful execution of the statement.
</p><p><code>void handleError(in <a href="#AsyncTransaction">AsyncTransaction</a> aTransaction, in ?? aError);</code>
</p><p>Handles an error of the statement.
</p>
<h5 name="ResultSet"> ResultSet </h5>
<p>Interface used to get the data back.  In JS, this should be able to be used as an iterator.
</p><p><code><a href="en/MozIStorageValueArray">mozIStorageValueArray</a> getNextResult();</code>
</p><p>Obtains the next tuple of results.  Null if no results available.
</p>
<h4 name="Discussion"> Discussion </h4>
Revert to this revision