michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ : michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsString.h" michael@0: michael@0: #include "sqlite3.h" michael@0: #include "mozStoragePrivateHelpers.h" michael@0: #include "Variant.h" michael@0: #include "mozStorageRow.h" michael@0: michael@0: namespace mozilla { michael@0: namespace storage { michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: //// Row michael@0: michael@0: nsresult michael@0: Row::initialize(sqlite3_stmt *aStatement) michael@0: { michael@0: // Get the number of results michael@0: mNumCols = ::sqlite3_column_count(aStatement); michael@0: michael@0: // Start copying over values michael@0: for (uint32_t i = 0; i < mNumCols; i++) { michael@0: // Store the value michael@0: nsIVariant *variant = nullptr; michael@0: int type = ::sqlite3_column_type(aStatement, i); michael@0: switch (type) { michael@0: case SQLITE_INTEGER: michael@0: variant = new IntegerVariant(::sqlite3_column_int64(aStatement, i)); michael@0: break; michael@0: case SQLITE_FLOAT: michael@0: variant = new FloatVariant(::sqlite3_column_double(aStatement, i)); michael@0: break; michael@0: case SQLITE_TEXT: michael@0: { michael@0: nsDependentString str( michael@0: static_cast(::sqlite3_column_text16(aStatement, i)) michael@0: ); michael@0: variant = new TextVariant(str); michael@0: break; michael@0: } michael@0: case SQLITE_NULL: michael@0: variant = new NullVariant(); michael@0: break; michael@0: case SQLITE_BLOB: michael@0: { michael@0: int size = ::sqlite3_column_bytes(aStatement, i); michael@0: const void *data = ::sqlite3_column_blob(aStatement, i); michael@0: variant = new BlobVariant(std::pair(data, size)); michael@0: break; michael@0: } michael@0: default: michael@0: return NS_ERROR_UNEXPECTED; michael@0: } michael@0: NS_ENSURE_TRUE(variant, NS_ERROR_OUT_OF_MEMORY); michael@0: michael@0: // Insert into our storage array michael@0: NS_ENSURE_TRUE(mData.InsertObjectAt(variant, i), NS_ERROR_OUT_OF_MEMORY); michael@0: michael@0: // Associate the name (if any) with the index michael@0: const char *name = ::sqlite3_column_name(aStatement, i); michael@0: if (!name) break; michael@0: nsAutoCString colName(name); michael@0: mNameHashtable.Put(colName, i); michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: /** michael@0: * Note: This object is only ever accessed on one thread at a time. It it not michael@0: * threadsafe, but it does need threadsafe AddRef and Release. michael@0: */ michael@0: NS_IMPL_ISUPPORTS( michael@0: Row, michael@0: mozIStorageRow, michael@0: mozIStorageValueArray michael@0: ) michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: //// mozIStorageRow michael@0: michael@0: NS_IMETHODIMP michael@0: Row::GetResultByIndex(uint32_t aIndex, michael@0: nsIVariant **_result) michael@0: { michael@0: ENSURE_INDEX_VALUE(aIndex, mNumCols); michael@0: NS_ADDREF(*_result = mData.ObjectAt(aIndex)); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: Row::GetResultByName(const nsACString &aName, michael@0: nsIVariant **_result) michael@0: { michael@0: uint32_t index; michael@0: NS_ENSURE_TRUE(mNameHashtable.Get(aName, &index), NS_ERROR_NOT_AVAILABLE); michael@0: return GetResultByIndex(index, _result); michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: //// mozIStorageValueArray michael@0: michael@0: NS_IMETHODIMP michael@0: Row::GetNumEntries(uint32_t *_entries) michael@0: { michael@0: *_entries = mNumCols; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: Row::GetTypeOfIndex(uint32_t aIndex, michael@0: int32_t *_type) michael@0: { michael@0: ENSURE_INDEX_VALUE(aIndex, mNumCols); michael@0: michael@0: uint16_t type; michael@0: (void)mData.ObjectAt(aIndex)->GetDataType(&type); michael@0: switch (type) { michael@0: case nsIDataType::VTYPE_INT32: michael@0: case nsIDataType::VTYPE_INT64: michael@0: *_type = mozIStorageValueArray::VALUE_TYPE_INTEGER; michael@0: break; michael@0: case nsIDataType::VTYPE_DOUBLE: michael@0: *_type = mozIStorageValueArray::VALUE_TYPE_FLOAT; michael@0: break; michael@0: case nsIDataType::VTYPE_ASTRING: michael@0: *_type = mozIStorageValueArray::VALUE_TYPE_TEXT; michael@0: break; michael@0: case nsIDataType::VTYPE_ARRAY: michael@0: *_type = mozIStorageValueArray::VALUE_TYPE_BLOB; michael@0: break; michael@0: default: michael@0: *_type = mozIStorageValueArray::VALUE_TYPE_NULL; michael@0: break; michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: Row::GetInt32(uint32_t aIndex, michael@0: int32_t *_value) michael@0: { michael@0: ENSURE_INDEX_VALUE(aIndex, mNumCols); michael@0: return mData.ObjectAt(aIndex)->GetAsInt32(_value); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: Row::GetInt64(uint32_t aIndex, michael@0: int64_t *_value) michael@0: { michael@0: ENSURE_INDEX_VALUE(aIndex, mNumCols); michael@0: return mData.ObjectAt(aIndex)->GetAsInt64(_value); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: Row::GetDouble(uint32_t aIndex, michael@0: double *_value) michael@0: { michael@0: ENSURE_INDEX_VALUE(aIndex, mNumCols); michael@0: return mData.ObjectAt(aIndex)->GetAsDouble(_value); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: Row::GetUTF8String(uint32_t aIndex, michael@0: nsACString &_value) michael@0: { michael@0: ENSURE_INDEX_VALUE(aIndex, mNumCols); michael@0: return mData.ObjectAt(aIndex)->GetAsAUTF8String(_value); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: Row::GetString(uint32_t aIndex, michael@0: nsAString &_value) michael@0: { michael@0: ENSURE_INDEX_VALUE(aIndex, mNumCols); michael@0: return mData.ObjectAt(aIndex)->GetAsAString(_value); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: Row::GetBlob(uint32_t aIndex, michael@0: uint32_t *_size, michael@0: uint8_t **_blob) michael@0: { michael@0: ENSURE_INDEX_VALUE(aIndex, mNumCols); michael@0: michael@0: uint16_t type; michael@0: nsIID interfaceIID; michael@0: return mData.ObjectAt(aIndex)->GetAsArray(&type, &interfaceIID, _size, michael@0: reinterpret_cast(_blob)); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: Row::GetIsNull(uint32_t aIndex, michael@0: bool *_isNull) michael@0: { michael@0: ENSURE_INDEX_VALUE(aIndex, mNumCols); michael@0: NS_ENSURE_ARG_POINTER(_isNull); michael@0: michael@0: uint16_t type; michael@0: (void)mData.ObjectAt(aIndex)->GetDataType(&type); michael@0: *_isNull = type == nsIDataType::VTYPE_EMPTY; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: Row::GetSharedUTF8String(uint32_t, michael@0: uint32_t *, michael@0: char const **) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: Row::GetSharedString(uint32_t, michael@0: uint32_t *, michael@0: const char16_t **) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: Row::GetSharedBlob(uint32_t, michael@0: uint32_t *, michael@0: const uint8_t **) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: } // namespace storage michael@0: } // namespace mozilla