1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
3 : * ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is Oracle Corporation code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Oracle Corporation
20 : * Portions created by the Initial Developer are Copyright (C) 2004
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * Vladimir Vukicevic <vladimir.vukicevic@oracle.com>
25 : * Shawn Wilsher <me@shawnwilsher.com>
26 : *
27 : * Alternatively, the contents of this file may be used under the terms of
28 : * either the GNU General Public License Version 2 or later (the "GPL"), or
29 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 : * in which case the provisions of the GPL or the LGPL are applicable instead
31 : * of those above. If you wish to allow use of your version of this file only
32 : * under the terms of either the GPL or the LGPL, and not to allow others to
33 : * use your version of this file under the terms of the MPL, indicate your
34 : * decision by deleting the provisions above and replace them with the notice
35 : * and other provisions required by the GPL or the LGPL. If you do not delete
36 : * the provisions above, a recipient may use your version of this file under
37 : * the terms of any one of the MPL, the GPL or the LGPL.
38 : *
39 : * ***** END LICENSE BLOCK ***** */
40 :
41 : #include "nsMemory.h"
42 : #include "nsString.h"
43 :
44 : #include "mozStoragePrivateHelpers.h"
45 : #include "mozStorageStatementParams.h"
46 : #include "mozIStorageStatement.h"
47 :
48 : namespace mozilla {
49 : namespace storage {
50 :
51 : ////////////////////////////////////////////////////////////////////////////////
52 : //// StatementParams
53 :
54 10735 : StatementParams::StatementParams(mozIStorageStatement *aStatement) :
55 10735 : mStatement(aStatement)
56 : {
57 10735 : NS_ASSERTION(mStatement != nsnull, "mStatement is null");
58 10735 : (void)mStatement->GetParameterCount(&mParamCount);
59 10735 : }
60 :
61 332873 : NS_IMPL_ISUPPORTS2(
62 : StatementParams,
63 : mozIStorageStatementParams,
64 : nsIXPCScriptable
65 : )
66 :
67 : ////////////////////////////////////////////////////////////////////////////////
68 : //// nsIXPCScriptable
69 :
70 : #define XPC_MAP_CLASSNAME StatementParams
71 : #define XPC_MAP_QUOTED_CLASSNAME "StatementParams"
72 : #define XPC_MAP_WANT_SETPROPERTY
73 : #define XPC_MAP_WANT_NEWENUMERATE
74 : #define XPC_MAP_WANT_NEWRESOLVE
75 : #define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
76 : #include "xpc_map_end.h"
77 :
78 : NS_IMETHODIMP
79 99869 : StatementParams::SetProperty(nsIXPConnectWrappedNative *aWrapper,
80 : JSContext *aCtx,
81 : JSObject *aScopeObj,
82 : jsid aId,
83 : jsval *_vp,
84 : bool *_retval)
85 : {
86 99869 : NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED);
87 :
88 99869 : if (JSID_IS_INT(aId)) {
89 4 : int idx = JSID_TO_INT(aId);
90 :
91 8 : nsCOMPtr<nsIVariant> variant(convertJSValToVariant(aCtx, *_vp));
92 4 : NS_ENSURE_TRUE(variant, NS_ERROR_UNEXPECTED);
93 4 : nsresult rv = mStatement->BindByIndex(idx, variant);
94 4 : NS_ENSURE_SUCCESS(rv, rv);
95 : }
96 99865 : else if (JSID_IS_STRING(aId)) {
97 99865 : JSString *str = JSID_TO_STRING(aId);
98 : size_t length;
99 99865 : const jschar *chars = JS_GetStringCharsAndLength(aCtx, str, &length);
100 99865 : NS_ENSURE_TRUE(chars, NS_ERROR_UNEXPECTED);
101 199730 : NS_ConvertUTF16toUTF8 name(chars, length);
102 :
103 : // check to see if there's a parameter with this name
104 199730 : nsCOMPtr<nsIVariant> variant(convertJSValToVariant(aCtx, *_vp));
105 99865 : NS_ENSURE_TRUE(variant, NS_ERROR_UNEXPECTED);
106 99864 : nsresult rv = mStatement->BindByName(name, variant);
107 99864 : NS_ENSURE_SUCCESS(rv, rv);
108 : }
109 : else {
110 0 : return NS_ERROR_INVALID_ARG;
111 : }
112 :
113 99868 : *_retval = true;
114 99868 : return NS_OK;
115 : }
116 :
117 : NS_IMETHODIMP
118 41 : StatementParams::NewEnumerate(nsIXPConnectWrappedNative *aWrapper,
119 : JSContext *aCtx,
120 : JSObject *aScopeObj,
121 : PRUint32 aEnumOp,
122 : jsval *_statep,
123 : jsid *_idp,
124 : bool *_retval)
125 : {
126 41 : NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED);
127 :
128 41 : switch (aEnumOp) {
129 : case JSENUMERATE_INIT:
130 : case JSENUMERATE_INIT_ALL:
131 : {
132 : // Start our internal index at zero.
133 13 : *_statep = JSVAL_ZERO;
134 :
135 : // And set our length, if needed.
136 13 : if (_idp)
137 0 : *_idp = INT_TO_JSID(mParamCount);
138 :
139 13 : break;
140 : }
141 : case JSENUMERATE_NEXT:
142 : {
143 28 : NS_ASSERTION(*_statep != JSVAL_NULL, "Internal state is null!");
144 :
145 : // Make sure we are in range first.
146 28 : PRUint32 index = static_cast<PRUint32>(JSVAL_TO_INT(*_statep));
147 28 : if (index >= mParamCount) {
148 13 : *_statep = JSVAL_NULL;
149 13 : return NS_OK;
150 : }
151 :
152 : // Get the name of our parameter.
153 30 : nsCAutoString name;
154 15 : nsresult rv = mStatement->GetParameterName(index, name);
155 15 : NS_ENSURE_SUCCESS(rv, rv);
156 :
157 : // But drop the first character, which is going to be a ':'.
158 15 : JSString *jsname = ::JS_NewStringCopyN(aCtx, &(name.get()[1]),
159 30 : name.Length() - 1);
160 15 : NS_ENSURE_TRUE(jsname, NS_ERROR_OUT_OF_MEMORY);
161 :
162 : // Set our name.
163 15 : if (!::JS_ValueToId(aCtx, STRING_TO_JSVAL(jsname), _idp)) {
164 0 : *_retval = false;
165 0 : return NS_OK;
166 : }
167 :
168 : // And increment our index.
169 15 : *_statep = INT_TO_JSVAL(++index);
170 :
171 15 : break;
172 : }
173 : case JSENUMERATE_DESTROY:
174 : {
175 : // Clear our state.
176 0 : *_statep = JSVAL_NULL;
177 :
178 0 : break;
179 : }
180 : }
181 :
182 28 : return NS_OK;
183 : }
184 :
185 : NS_IMETHODIMP
186 34001 : StatementParams::NewResolve(nsIXPConnectWrappedNative *aWrapper,
187 : JSContext *aCtx,
188 : JSObject *aScopeObj,
189 : jsid aId,
190 : PRUint32 aFlags,
191 : JSObject **_objp,
192 : bool *_retval)
193 : {
194 34001 : NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED);
195 : // We do not throw at any point after this unless our index is out of range
196 : // because we want to allow the prototype chain to be checked for the
197 : // property.
198 :
199 34001 : bool resolved = false;
200 34001 : bool ok = true;
201 34001 : if (JSID_IS_INT(aId)) {
202 4 : PRUint32 idx = JSID_TO_INT(aId);
203 :
204 : // Ensure that our index is within range. We do not care about the
205 : // prototype chain being checked here.
206 4 : if (idx >= mParamCount)
207 0 : return NS_ERROR_INVALID_ARG;
208 :
209 : ok = ::JS_DefineElement(aCtx, aScopeObj, idx, JSVAL_VOID, nsnull,
210 4 : nsnull, JSPROP_ENUMERATE);
211 4 : resolved = true;
212 : }
213 33997 : else if (JSID_IS_STRING(aId)) {
214 33997 : JSString *str = JSID_TO_STRING(aId);
215 : size_t nameLength;
216 33997 : const jschar *nameChars = JS_GetStringCharsAndLength(aCtx, str, &nameLength);
217 33997 : NS_ENSURE_TRUE(nameChars, NS_ERROR_UNEXPECTED);
218 :
219 : // Check to see if there's a parameter with this name, and if not, let
220 : // the rest of the prototype chain be checked.
221 67994 : NS_ConvertUTF16toUTF8 name(nameChars, nameLength);
222 : PRUint32 idx;
223 33997 : nsresult rv = mStatement->GetParameterIndex(name, &idx);
224 33997 : if (NS_SUCCEEDED(rv)) {
225 : ok = ::JS_DefinePropertyById(aCtx, aScopeObj, aId, JSVAL_VOID, nsnull,
226 33970 : nsnull, JSPROP_ENUMERATE);
227 33970 : resolved = true;
228 : }
229 : }
230 :
231 34001 : *_retval = ok;
232 34001 : *_objp = resolved && ok ? aScopeObj : nsnull;
233 34001 : return NS_OK;
234 : }
235 :
236 : } // namespace storage
237 : } // namespace mozilla
|