Bug 1154325 P1 Add convenience routines to bind and get Blobs as strings. r=asuth
authorBen Kelly <ben@wanderview.com>
Wed, 29 Apr 2015 09:03:15 -0700
changeset 272976 0ee4a1086547d150ec6bfd1c0ecd7be8e6ff6a2f
parent 272975 8ffa93f4c8c5eb7b4d9f15bc8c11020e4d3a7a1d
child 272977 4583badf15cfa57d8d8c48f290fbd6748df260c2
push id863
push userraliiev@mozilla.com
push dateMon, 03 Aug 2015 13:22:43 +0000
treeherdermozilla-release@f6321b14228d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersasuth
bugs1154325
milestone40.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1154325 P1 Add convenience routines to bind and get Blobs as strings. r=asuth
storage/public/mozIStorageBaseStatement.idl
storage/public/mozIStorageBindingParams.idl
storage/public/mozIStorageStatement.idl
storage/public/mozIStorageValueArray.idl
storage/src/StorageBaseStatementInternal.h
storage/src/mozStorageArgValueArray.cpp
storage/src/mozStorageBindingParams.cpp
storage/src/mozStoragePrivateHelpers.h
storage/src/mozStorageRow.cpp
storage/src/mozStorageStatement.cpp
--- a/storage/public/mozIStorageBaseStatement.idl
+++ b/storage/public/mozIStorageBaseStatement.idl
@@ -14,17 +14,17 @@ interface mozIStorageBindingParams;
 interface mozIStorageBindingParamsArray;
 
 /**
  * The base interface for both pure asynchronous storage statements 
  * (mozIStorageAsyncStatement) and 'classic' storage statements
  * (mozIStorageStatement) that can be used for both synchronous and asynchronous
  * purposes.
  */
-[scriptable, uuid(5d34f333-ed3f-4aa2-ba51-f2a8b0cfa33a)]
+[scriptable, uuid(16ca67aa-1325-43e2-aac7-859afd1590b2)]
 interface mozIStorageBaseStatement : mozIStorageBindingParams {
   /**
    * Finalizes a statement so you can successfully close a database connection.
    * Once a statement has been finalized it can no longer be used for any
    * purpose.
    * 
    * Statements are implicitly finalized when their reference counts hits zero.
    * If you are a native (C++) caller this is accomplished by setting all of
@@ -62,16 +62,22 @@ interface mozIStorageBaseStatement : moz
                                        in long aValue);
   [deprecated] void bindInt64Parameter(in unsigned long aParamIndex,
                                        in long long aValue);
   [deprecated] void bindNullParameter(in unsigned long aParamIndex);
   [deprecated] void bindBlobParameter(
     in unsigned long aParamIndex,
     [array,const,size_is(aValueSize)] in octet aValue,
     in unsigned long aValueSize);
+  [deprecated] void bindStringAsBlobParameter(
+    in unsigned long aParamIndex,
+    in AString aValue);
+  [deprecated] void bindUTF8StringAsBlobParameter(
+    in unsigned long aParamIndex,
+    in AUTF8String aValue);
   [deprecated] void bindAdoptedBlobParameter(
     in unsigned long aParamIndex,
     [array,size_is(aValueSize)] in octet aValue,
     in unsigned long aValueSize);
   /**@}*/
 
   /**
    * Binds the array of parameters to the statement.  When executeAsync is
--- a/storage/public/mozIStorageBindingParams.idl
+++ b/storage/public/mozIStorageBindingParams.idl
@@ -3,17 +3,17 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 interface nsIVariant;
 
-[scriptable, uuid(7d8763ad-79d9-4674-ada1-37fd702af68c)]
+[scriptable, uuid(2d09f42f-966e-4663-b4b3-b0c8676bf2bf)]
 interface mozIStorageBindingParams : nsISupports {
   /**
    * Binds aValue to the parameter with the name aName.
    *
    * @param aName
    *        The name of the parameter to bind aValue to.
    * @param aValue
    *        The value to bind.
@@ -29,16 +29,21 @@ interface mozIStorageBindingParams : nsI
    [noscript] void bindInt32ByName(in AUTF8String aName,
                                    in long aValue);
    [noscript] void bindInt64ByName(in AUTF8String aName,
                                    in long long aValue);
    [noscript] void bindNullByName(in AUTF8String aName);
    void bindBlobByName(in AUTF8String aName,
                        [array, const, size_is(aValueSize)] in octet aValue,
                        in unsigned long aValueSize);
+
+   // Convenience routines for storing strings as blobs.
+   void bindStringAsBlobByName(in AUTF8String aName, in AString aValue);
+   void bindUTF8StringAsBlobByName(in AUTF8String aName, in AUTF8String aValue);
+
    // The function adopts the storage for the provided blob.  After calling
    // this function, mozStorage will ensure that NS_Free is called on the
    // underlying pointer.
    [noscript]
    void bindAdoptedBlobByName(in AUTF8String aName,
                               [array, size_is(aValueSize)] in octet aValue,
                               in unsigned long aValueSize);
 
@@ -61,16 +66,21 @@ interface mozIStorageBindingParams : nsI
    [noscript] void bindInt32ByIndex(in unsigned long aIndex,
                                     in long aValue);
    [noscript] void bindInt64ByIndex(in unsigned long aIndex,
                                     in long long aValue);
    [noscript] void bindNullByIndex(in unsigned long aIndex);
    void bindBlobByIndex(in unsigned long aIndex,
                         [array, const, size_is(aValueSize)] in octet aValue,
                         in unsigned long aValueSize);
+
+   // Convenience routines for storing strings as blobs.
+   void bindStringAsBlobByIndex(in unsigned long aIndex, in AString aValue);
+   void bindUTF8StringAsBlobByIndex(in unsigned long aIndex, in AUTF8String aValue);
+
    // The function adopts the storage for the provided blob.  After calling
    // this function, mozStorage will ensure that NS_Free is called on the
    // underlying pointer.
    [noscript]
    void bindAdoptedBlobByIndex(in unsigned long aIndex,
                                [array, size_is(aValueSize)] in octet aValue,
                                in unsigned long aValueSize);
 };
--- a/storage/public/mozIStorageStatement.idl
+++ b/storage/public/mozIStorageStatement.idl
@@ -10,17 +10,17 @@
 %}
 
 [ptr] native octetPtr(uint8_t);
 
 /**
  * A SQL statement that can be used for both synchronous and asynchronous
  * purposes.
  */
-[scriptable, uuid(b3c4476e-c490-4e3b-9db1-e2d3a6f0287c)]
+[scriptable, uuid(5f567c35-6c32-4140-828c-683ea49cfd3a)]
 interface mozIStorageStatement : mozIStorageBaseStatement {
   /**
    * Create a clone of this statement, by initializing a new statement
    * with the same connection and same SQL statement as this one.  It
    * does not preserve statement state; that is, if a statement is
    * being executed when it is cloned, the new statement will not be
    * executing.
    */
@@ -202,16 +202,39 @@ interface mozIStorageStatement : mozISto
    * @param aIndex
    *        0-based colummn index.
    * @param[out] aDataSize
    *             The number of bytes in the blob.
    * @param[out] aData
    *             The contents of the BLOB.  This will be NULL if aDataSize == 0.
    */
   void getBlob(in unsigned long aIndex, out unsigned long aDataSize, [array,size_is(aDataSize)] out octet aData);
+
+  /**
+   * Retrieve the contents of a Blob column from the current result row as a
+   * string.
+   *
+   * @param aIndex
+   *        0-based colummn index.
+   * @return The value for the result Blob column interpreted as a String.
+   *         No encoding conversion is performed.
+   */
+  AString getBlobAsString(in unsigned long aIndex);
+
+  /**
+   * Retrieve the contents of a Blob column from the current result row as a
+   * UTF8 string.
+   *
+   * @param aIndex
+   *        0-based colummn index.
+   * @return The value for the result Blob column interpreted as a UTF8 String.
+   *         No encoding conversion is performed.
+   */
+  AUTF8String getBlobAsUTF8String(in unsigned long aIndex);
+
   /**
    * Check whether the given column in the current result row is NULL.
    *
    * @param aIndex
    *        0-based colummn index.
    * @return true if the value for the result column is null.
    */
   boolean getIsNull(in unsigned long aIndex);
--- a/storage/public/mozIStorageValueArray.idl
+++ b/storage/public/mozIStorageValueArray.idl
@@ -9,17 +9,17 @@
 %}
 
 [ptr] native octetPtr(uint8_t);
 
 /**
  * mozIStorageValueArray wraps an array of SQL values, such as a single database
  * row.
  */
-[scriptable, uuid(07b5b93e-113c-4150-863c-d247b003a55d)]
+[scriptable, uuid(6e6306f4-ffa7-40f5-96ca-36159ce8f431)]
 interface mozIStorageValueArray : nsISupports {
   /**
    * These type values are returned by getTypeOfIndex
    * to indicate what type of value is present at
    * a given column.
    */
   const long VALUE_TYPE_NULL = 0;
   const long VALUE_TYPE_INTEGER = 1;
@@ -57,16 +57,18 @@ interface mozIStorageValueArray : nsISup
   long getInt32(in unsigned long aIndex);
   long long getInt64(in unsigned long aIndex);
   double getDouble(in unsigned long aIndex);
   AUTF8String getUTF8String(in unsigned long aIndex);
   AString getString(in unsigned long aIndex);
 
   // data will be NULL if dataSize = 0
   void getBlob(in unsigned long aIndex, out unsigned long aDataSize, [array,size_is(aDataSize)] out octet aData);
+  AString getBlobAsString(in unsigned long aIndex);
+  AUTF8String getBlobAsUTF8String(in unsigned long aIndex);
   boolean getIsNull(in unsigned long aIndex);
 
   /**
    * Returns a shared string pointer
    */
   [noscript] void getSharedUTF8String(in unsigned long aIndex, out unsigned long aLength, [shared,retval] out string aResult);
   [noscript] void getSharedString(in unsigned long aIndex, out unsigned long aLength, [shared,retval] out wstring aResult);
   [noscript] void getSharedBlob(in unsigned long aIndex, out unsigned long aLength, [shared,retval] out octetPtr aResult);
--- a/storage/src/StorageBaseStatementInternal.h
+++ b/storage/src/StorageBaseStatementInternal.h
@@ -317,16 +317,30 @@ NS_DEFINE_STATIC_IID_ACCESSOR(StorageBas
                 (const nsACString &aWhere,               \
                  const uint8_t *aValue,                  \
                  uint32_t aValueSize),                   \
                 (uint32_t aWhere,                        \
                  const uint8_t *aValue,                  \
                  uint32_t aValueSize),                   \
                 (aWhere, aValue, aValueSize))            \
   BIND_GEN_IMPL(_class, _optionalGuard,                  \
+                StringAsBlob,                            \
+                (const nsACString &aWhere,               \
+                 const nsAString& aValue),               \
+                (uint32_t aWhere,                        \
+                 const nsAString& aValue),               \
+                (aWhere, aValue))                        \
+  BIND_GEN_IMPL(_class, _optionalGuard,                  \
+                UTF8StringAsBlob,                        \
+                (const nsACString &aWhere,               \
+                 const nsACString& aValue),              \
+                (uint32_t aWhere,                        \
+                 const nsACString& aValue),              \
+                (aWhere, aValue))                        \
+  BIND_GEN_IMPL(_class, _optionalGuard,                  \
                 AdoptedBlob,                             \
                 (const nsACString &aWhere,               \
                  uint8_t *aValue,                        \
                  uint32_t aValueSize),                   \
                 (uint32_t aWhere,                        \
                  uint8_t *aValue,                        \
                  uint32_t aValueSize),                   \
                 (aWhere, aValue, aValueSize))
--- a/storage/src/mozStorageArgValueArray.cpp
+++ b/storage/src/mozStorageArgValueArray.cpp
@@ -148,16 +148,28 @@ ArgValueArray::GetBlob(uint32_t aIndex,
   NS_ENSURE_TRUE(blob, NS_ERROR_OUT_OF_MEMORY);
 
   *_blob = static_cast<uint8_t *>(blob);
   *_size = size;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+ArgValueArray::GetBlobAsString(uint32_t aIndex, nsAString& aValue)
+{
+  return DoGetBlobAsString(this, aIndex, aValue);
+}
+
+NS_IMETHODIMP
+ArgValueArray::GetBlobAsUTF8String(uint32_t aIndex, nsACString& aValue)
+{
+  return DoGetBlobAsString(this, aIndex, aValue);
+}
+
+NS_IMETHODIMP
 ArgValueArray::GetIsNull(uint32_t aIndex,
                          bool *_isNull)
 {
   // GetTypeOfIndex will check aIndex for us, so we don't have to.
   int32_t type;
   nsresult rv = GetTypeOfIndex(aIndex, &type);
   NS_ENSURE_SUCCESS(rv, rv);
 
--- a/storage/src/mozStorageBindingParams.cpp
+++ b/storage/src/mozStorageBindingParams.cpp
@@ -353,16 +353,30 @@ BindingParams::BindBlobByName(const nsAC
     int(aValueSize)
   );
   nsCOMPtr<nsIVariant> value(new BlobVariant(data));
   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
 
   return BindByName(aName, value);
 }
 
+NS_IMETHODIMP
+BindingParams::BindStringAsBlobByName(const nsACString& aName,
+                                      const nsAString& aValue)
+{
+  return DoBindStringAsBlobByName(this, aName, aValue);
+}
+
+NS_IMETHODIMP
+BindingParams::BindUTF8StringAsBlobByName(const nsACString& aName,
+                                          const nsACString& aValue)
+{
+  return DoBindStringAsBlobByName(this, aName, aValue);
+}
+
 
 NS_IMETHODIMP
 BindingParams::BindAdoptedBlobByName(const nsACString &aName,
                                      uint8_t *aValue,
                                      uint32_t aValueSize)
 {
   NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
   std::pair<uint8_t *, int> data(
@@ -489,16 +503,29 @@ BindingParams::BindBlobByIndex(uint32_t 
   );
   nsCOMPtr<nsIVariant> value(new BlobVariant(data));
   NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
 
   return BindByIndex(aIndex, value);
 }
 
 NS_IMETHODIMP
+BindingParams::BindStringAsBlobByIndex(uint32_t aIndex, const nsAString& aValue)
+{
+  return DoBindStringAsBlobByIndex(this, aIndex, aValue);
+}
+
+NS_IMETHODIMP
+BindingParams::BindUTF8StringAsBlobByIndex(uint32_t aIndex,
+                                           const nsACString& aValue)
+{
+  return DoBindStringAsBlobByIndex(this, aIndex, aValue);
+}
+
+NS_IMETHODIMP
 BindingParams::BindAdoptedBlobByIndex(uint32_t aIndex,
                                       uint8_t *aValue,
                                       uint32_t aValueSize)
 {
   NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
   std::pair<uint8_t *, int> data(
     static_cast<uint8_t *>(aValue),
     int(aValueSize)
--- a/storage/src/mozStoragePrivateHelpers.h
+++ b/storage/src/mozStoragePrivateHelpers.h
@@ -83,12 +83,60 @@ Variant_base *convertVariantToStorageVar
  * @param aCallback
  *        The callback to be notified.
  * @return an nsIRunnable that can be dispatched to the calling thread.
  */
 already_AddRefed<nsIRunnable> newCompletionEvent(
   mozIStorageCompletionCallback *aCallback
 );
 
+/**
+ * Utility method to get a Blob as a string value.  The string expects
+ * the interface exposed by nsAString/nsACString/etc.
+ */
+template<class T, class V>
+nsresult
+DoGetBlobAsString(T* aThis, uint32_t aIndex, V& aValue)
+{
+  typedef typename V::char_type char_type;
+
+  uint32_t size;
+  char_type* blob;
+  nsresult rv =
+    aThis->GetBlob(aIndex, &size, reinterpret_cast<uint8_t**>(&blob));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  aValue.Adopt(blob, size / sizeof(char_type));
+  return NS_OK;
+}
+
+/**
+ * Utility method to bind a string value as a Blob.  The string expects
+ * the interface exposed by nsAString/nsACString/etc.
+ */
+template<class T, class V>
+nsresult
+DoBindStringAsBlobByName(T* aThis, const nsACString& aName, const V& aValue)
+{
+  typedef typename V::char_type char_type;
+  return aThis->BindBlobByName(aName,
+                        reinterpret_cast<const uint8_t*>(aValue.BeginReading()),
+                        aValue.Length() * sizeof(char_type));
+}
+
+/**
+ * Utility method to bind a string value as a Blob.  The string expects
+ * the interface exposed by nsAString/nsACString/etc.
+ */
+template<class T, class V>
+nsresult
+DoBindStringAsBlobByIndex(T* aThis, uint32_t aIndex, const V& aValue)
+{
+  typedef typename V::char_type char_type;
+  return aThis->BindBlobByIndex(aIndex,
+                        reinterpret_cast<const uint8_t*>(aValue.BeginReading()),
+                        aValue.Length() * sizeof(char_type));
+}
+
 } // namespace storage
 } // namespace mozilla
 
 #endif // mozStoragePrivateHelpers_h
--- a/storage/src/mozStorageRow.cpp
+++ b/storage/src/mozStorageRow.cpp
@@ -190,16 +190,28 @@ Row::GetBlob(uint32_t aIndex,
 
   uint16_t type;
   nsIID interfaceIID;
   return mData.ObjectAt(aIndex)->GetAsArray(&type, &interfaceIID, _size,
                                             reinterpret_cast<void **>(_blob));
 }
 
 NS_IMETHODIMP
+Row::GetBlobAsString(uint32_t aIndex, nsAString& aValue)
+{
+  return DoGetBlobAsString(this, aIndex, aValue);
+}
+
+NS_IMETHODIMP
+Row::GetBlobAsUTF8String(uint32_t aIndex, nsACString& aValue)
+{
+  return DoGetBlobAsString(this, aIndex, aValue);
+}
+
+NS_IMETHODIMP
 Row::GetIsNull(uint32_t aIndex,
                bool *_isNull)
 {
   ENSURE_INDEX_VALUE(aIndex, mNumCols);
   NS_ENSURE_ARG_POINTER(_isNull);
 
   uint16_t type;
   (void)mData.ObjectAt(aIndex)->GetDataType(&type);
--- a/storage/src/mozStorageStatement.cpp
+++ b/storage/src/mozStorageStatement.cpp
@@ -828,16 +828,28 @@ Statement::GetBlob(uint32_t aIndex,
   }
 
   *_blob = static_cast<uint8_t *>(blob);
   *_size = size;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+Statement::GetBlobAsString(uint32_t aIndex, nsAString& aValue)
+{
+  return DoGetBlobAsString(this, aIndex, aValue);
+}
+
+NS_IMETHODIMP
+Statement::GetBlobAsUTF8String(uint32_t aIndex, nsACString& aValue)
+{
+  return DoGetBlobAsString(this, aIndex, aValue);
+}
+
+NS_IMETHODIMP
 Statement::GetSharedUTF8String(uint32_t aIndex,
                                uint32_t *_length,
                                const char **_value)
 {
   if (_length)
     *_length = ::sqlite3_column_bytes(mDBStatement, aIndex);
 
   *_value = reinterpret_cast<const char *>(::sqlite3_column_text(mDBStatement,