Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(430)

Side by Side Diff: lib/src/datastore_impl.dart

Issue 2285803002: Upgrade to use stable `package:googleapis/v1.dart` of datastore (Closed) Base URL: git@github.com:dart-lang/gcloud.git@master
Patch Set: Add notice about the [project] parameter Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library gcloud.datastore_impl; 5 library gcloud.datastore_impl;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 8
9 import 'package:http/http.dart' as http; 9 import 'package:http/http.dart' as http;
10 10
11 import '../datastore.dart' as datastore; 11 import '../datastore.dart' as datastore;
12 import '../common.dart' show Page; 12 import '../common.dart' show Page;
13 import 'package:googleapis_beta/datastore/v1beta2.dart' as api; 13 import 'package:googleapis/datastore/v1.dart' as api;
14 14
15 class TransactionImpl implements datastore.Transaction { 15 class TransactionImpl implements datastore.Transaction {
16 final String data; 16 final String data;
17 TransactionImpl(this.data); 17 TransactionImpl(this.data);
18 } 18 }
19 19
20 class DatastoreImpl implements datastore.Datastore { 20 class DatastoreImpl implements datastore.Datastore {
21 static const List<String> SCOPES = const <String>[ 21 static const List<String> SCOPES = const <String>[
22 api.DatastoreApi.DatastoreScope, 22 api.DatastoreApi.DatastoreScope,
23 api.DatastoreApi.UserinfoEmailScope, 23 api.DatastoreApi.CloudPlatformScope,
24 ]; 24 ];
25 25
26 final api.DatastoreApi _api; 26 final api.DatastoreApi _api;
27 final String _project; 27 final String _project;
28 28
29 DatastoreImpl(http.Client client, this._project) 29 /// The [project] parameter is the name of the cloud project (it should not
30 : _api = new api.DatastoreApi(client); 30 /// start with a `s~`).
31 DatastoreImpl(http.Client client, String project)
32 : _api = new api.DatastoreApi(client), _project = project;
31 33
32 api.Key _convertDatastore2ApiKey(datastore.Key key, {bool enforceId: true}) { 34 api.Key _convertDatastore2ApiKey(datastore.Key key, {bool enforceId: true}) {
33 var apiKey = new api.Key(); 35 var apiKey = new api.Key();
34 36
35 apiKey.partitionId = new api.PartitionId() 37 apiKey.partitionId = new api.PartitionId()
36 ..datasetId = _project 38 ..projectId = _project
37 ..namespace = key.partition.namespace; 39 ..namespaceId = key.partition.namespace;
38 40
39 apiKey.path = key.elements.map((datastore.KeyElement element) { 41 apiKey.path = key.elements.map((datastore.KeyElement element) {
40 var part = new api.KeyPathElement(); 42 var part = new api.PathElement();
41 part.kind = element.kind; 43 part.kind = element.kind;
42 if (element.id is int) { 44 if (element.id is int) {
43 part.id = '${element.id}'; 45 part.id = '${element.id}';
44 } else if (element.id is String) { 46 } else if (element.id is String) {
45 part.name = element.id; 47 part.name = element.id;
46 } else if (enforceId) { 48 } else if (enforceId) {
47 throw new datastore.ApplicationError( 49 throw new datastore.ApplicationError(
48 'Error while encoding entity key: Using `null` as the id is not ' 50 'Error while encoding entity key: Using `null` as the id is not '
49 'allowed.'); 51 'allowed.');
50 } 52 }
51 return part; 53 return part;
52 }).toList(); 54 }).toList();
53 55
54 return apiKey; 56 return apiKey;
55 } 57 }
56 58
57 static datastore.Key _convertApi2DatastoreKey(api.Key key) { 59 static datastore.Key _convertApi2DatastoreKey(api.Key key) {
58 var elements = key.path.map((api.KeyPathElement element) { 60 var elements = key.path.map((api.PathElement element) {
59 if (element.id != null) { 61 if (element.id != null) {
60 return new datastore.KeyElement(element.kind, int.parse(element.id)); 62 return new datastore.KeyElement(element.kind, int.parse(element.id));
61 } else if (element.name != null) { 63 } else if (element.name != null) {
62 return new datastore.KeyElement(element.kind, element.name); 64 return new datastore.KeyElement(element.kind, element.name);
63 } else { 65 } else {
64 throw new datastore.DatastoreError( 66 throw new datastore.DatastoreError(
65 'Invalid server response: Expected allocated name/id.'); 67 'Invalid server response: Expected allocated name/id.');
66 } 68 }
67 }).toList(); 69 }).toList();
68 70
69 var partition; 71 var partition;
70 if (key.partitionId != null) { 72 if (key.partitionId != null) {
71 partition = new datastore.Partition(key.partitionId.namespace); 73 partition = new datastore.Partition(key.partitionId.namespaceId);
72 // TODO: assert projectId. 74 // TODO: assert projectId.
73 } 75 }
74 return new datastore.Key(elements, partition: partition); 76 return new datastore.Key(elements, partition: partition);
75 } 77 }
76 78
77 bool _compareApiKey(api.Key a, api.Key b) { 79 bool _compareApiKey(api.Key a, api.Key b) {
78 if (a.path.length != b.path.length) return false; 80 if (a.path.length != b.path.length) return false;
79 81
80 // FIXME(Issue #2): Is this comparison working correctly? 82 // FIXME(Issue #2): Is this comparison working correctly?
81 if (a.partitionId != null) { 83 if (a.partitionId != null) {
82 if (b.partitionId == null) return false; 84 if (b.partitionId == null) return false;
83 if (a.partitionId.datasetId != b.partitionId.datasetId) return false; 85 if (a.partitionId.projectId != b.partitionId.projectId) return false;
84 if (a.partitionId.namespace != b.partitionId.namespace) return false; 86 if (a.partitionId.namespaceId != b.partitionId.namespaceId) return false;
85 } else { 87 } else {
86 if (b.partitionId != null) return false; 88 if (b.partitionId != null) return false;
87 } 89 }
88 90
89 for (int i = 0; i < a.path.length; i++) { 91 for (int i = 0; i < a.path.length; i++) {
90 if (a.path[i].id != b.path[i].id || 92 if (a.path[i].id != b.path[i].id ||
91 a.path[i].name != b.path[i].name || 93 a.path[i].name != b.path[i].name ||
92 a.path[i].kind != b.path[i].kind) return false; 94 a.path[i].kind != b.path[i].kind) return false;
93 } 95 }
94 return true; 96 return true;
95 } 97 }
96 98
97 static _convertApi2DatastorePropertyValue(api.Value value) {
98 if (value.booleanValue != null)
99 return value.booleanValue;
100 else if (value.integerValue != null)
101 return int.parse(value.integerValue);
102 else if (value.doubleValue != null)
103 return value.doubleValue;
104 else if (value.stringValue != null)
105 return value.stringValue;
106 else if (value.dateTimeValue != null)
107 return value.dateTimeValue;
108 else if (value.blobValue != null)
109 return new datastore.BlobValue(value.blobValueAsBytes);
110 else if (value.keyValue != null)
111 return _convertApi2DatastoreKey(value.keyValue);
112 else if (value.listValue != null)
113 // FIXME(Issue #3): Consistently handle exceptions.
114 throw new Exception('Cannot have lists inside lists.');
115 else if (value.blobKeyValue != null)
116 throw new UnsupportedError('Blob keys are not supported.');
117 else if (value.entityValue != null)
118 throw new UnsupportedError('Entity values are not supported.');
119 return null;
120 }
121
122 api.Value _convertDatastore2ApiPropertyValue( 99 api.Value _convertDatastore2ApiPropertyValue(
123 value, bool indexed, {bool lists: true}) { 100 value, bool indexed, {bool lists: true}) {
124 var apiValue = new api.Value() 101 var apiValue = new api.Value()
125 ..indexed = indexed; 102 ..excludeFromIndexes = !indexed;
126 if (value == null) { 103 if (value == null) {
127 return apiValue; 104 return apiValue
105 ..nullValue = "NULL_VALUE";
Søren Gjesse 2016/08/29 10:29:09 How does this nullValue thing work? Is this requir
kustermann 2016/08/29 16:24:04 It is an enum and the enum values are ["NULL_VALUE
128 } else if (value is bool) { 106 } else if (value is bool) {
129 return apiValue 107 return apiValue
130 ..booleanValue = value; 108 ..booleanValue = value;
131 } else if (value is int) { 109 } else if (value is int) {
132 return apiValue 110 return apiValue
133 ..integerValue = '$value'; 111 ..integerValue = '$value';
134 } else if (value is double) { 112 } else if (value is double) {
135 return apiValue 113 return apiValue
136 ..doubleValue = value; 114 ..doubleValue = value;
137 } else if (value is String) { 115 } else if (value is String) {
138 return apiValue 116 return apiValue
139 ..stringValue = value; 117 ..stringValue = value;
140 } else if (value is DateTime) { 118 } else if (value is DateTime) {
141 return apiValue 119 return apiValue
142 ..dateTimeValue = value; 120 ..timestampValue = value.toIso8601String();
143 } else if (value is datastore.BlobValue) { 121 } else if (value is datastore.BlobValue) {
144 return apiValue 122 return apiValue
145 ..blobValueAsBytes = value.bytes; 123 ..blobValueAsBytes = value.bytes;
146 } else if (value is datastore.Key) { 124 } else if (value is datastore.Key) {
147 return apiValue 125 return apiValue
148 ..keyValue = _convertDatastore2ApiKey(value, enforceId: false); 126 ..keyValue = _convertDatastore2ApiKey(value, enforceId: false);
149 } else if (value is List) { 127 } else if (value is List) {
150 if (!lists) { 128 if (!lists) {
151 // FIXME(Issue #3): Consistently handle exceptions. 129 // FIXME(Issue #3): Consistently handle exceptions.
152 throw new Exception('List values are not allowed.'); 130 throw new Exception('List values are not allowed.');
153 } 131 }
154 132
155 convertItem(i) 133 convertItem(i)
156 => _convertDatastore2ApiPropertyValue(i, indexed, lists: false); 134 => _convertDatastore2ApiPropertyValue(i, indexed, lists: false);
157 135
158 return new api.Value() 136 return new api.Value()..arrayValue = (
159 ..listValue = value.map(convertItem).toList(); 137 new api.ArrayValue()..values = value.map(convertItem).toList());
160 } else { 138 } else {
161 throw new UnsupportedError( 139 throw new UnsupportedError(
162 'Types ${value.runtimeType} cannot be used for serializing.'); 140 'Types ${value.runtimeType} cannot be used for serializing.');
163 } 141 }
164 } 142 }
165 143
166 static _convertApi2DatastoreProperty(api.Property property) { 144 static _convertApi2DatastoreProperty(api.Value value) {
Søren Gjesse 2016/08/29 10:29:09 Add explicit dynamic here?
kustermann 2016/08/29 16:24:04 done
167 if (property.booleanValue != null) 145 if (value.booleanValue != null)
168 return property.booleanValue; 146 return value.booleanValue;
169 else if (property.integerValue != null) 147 else if (value.integerValue != null)
170 return int.parse(property.integerValue); 148 return int.parse(value.integerValue);
171 else if (property.doubleValue != null) 149 else if (value.doubleValue != null)
172 return property.doubleValue; 150 return value.doubleValue;
173 else if (property.stringValue != null) 151 else if (value.stringValue != null)
174 return property.stringValue; 152 return value.stringValue;
175 else if (property.dateTimeValue != null) 153 else if (value.timestampValue != null)
176 return property.dateTimeValue; 154 return DateTime.parse(value.timestampValue);
177 else if (property.blobValue != null) 155 else if (value.blobValue != null)
178 return new datastore.BlobValue(property.blobValueAsBytes); 156 return new datastore.BlobValue(value.blobValueAsBytes);
179 else if (property.keyValue != null) 157 else if (value.keyValue != null)
180 return _convertApi2DatastoreKey(property.keyValue); 158 return _convertApi2DatastoreKey(value.keyValue);
181 else if (property.listValue != null) 159 else if (value.arrayValue != null && value.arrayValue.values != null)
182 return 160 return value
183 property.listValue.map(_convertApi2DatastorePropertyValue).toList(); 161 .arrayValue.values.map(_convertApi2DatastoreProperty).toList();
184 else if (property.blobKeyValue != null) 162 else if (value.entityValue != null)
Søren Gjesse 2016/08/29 10:29:09 Why is value.nullValue not handled here?
kustermann 2016/08/29 16:24:04 It was handled via the default case below, but I'v
185 throw new UnsupportedError('Blob keys are not supported.');
186 else if (property.entityValue != null)
187 throw new UnsupportedError('Entity values are not supported.'); 163 throw new UnsupportedError('Entity values are not supported.');
188 return null; 164 return null;
189 } 165 }
190 166
191 api.Property _convertDatastore2ApiProperty(
192 value, bool indexed, {bool lists: true}) {
193 var apiProperty = new api.Property()
194 ..indexed = indexed;
195 if (value == null) {
196 return null;
197 } else if (value is bool) {
198 return apiProperty
199 ..booleanValue = value;
200 } else if (value is int) {
201 return apiProperty
202 ..integerValue = '$value';
203 } else if (value is double) {
204 return apiProperty
205 ..doubleValue = value;
206 } else if (value is String) {
207 return apiProperty
208 ..stringValue = value;
209 } else if (value is DateTime) {
210 return apiProperty
211 ..dateTimeValue = value;
212 } else if (value is datastore.BlobValue) {
213 return apiProperty
214 ..blobValueAsBytes = value.bytes;
215 } else if (value is datastore.Key) {
216 return apiProperty
217 ..keyValue = _convertDatastore2ApiKey(value, enforceId: false);
218 } else if (value is List) {
219 if (!lists) {
220 // FIXME(Issue #3): Consistently handle exceptions.
221 throw new Exception('List values are not allowed.');
222 }
223 convertItem(i)
224 => _convertDatastore2ApiPropertyValue(i, indexed, lists: false);
225 return new api.Property()..listValue = value.map(convertItem).toList();
226 } else {
227 throw new UnsupportedError(
228 'Types ${value.runtimeType} cannot be used for serializing.');
229 }
230 }
231
232 static datastore.Entity _convertApi2DatastoreEntity(api.Entity entity) { 167 static datastore.Entity _convertApi2DatastoreEntity(api.Entity entity) {
233 var unindexedProperties = new Set(); 168 var unindexedProperties = new Set();
234 var properties = {}; 169 var properties = {};
235 170
236 if (entity.properties != null) { 171 if (entity.properties != null) {
237 entity.properties.forEach((String name, api.Property property) { 172 entity.properties.forEach((String name, api.Value value) {
238 properties[name] = _convertApi2DatastoreProperty(property); 173 properties[name] = _convertApi2DatastoreProperty(value);
239 if (property.indexed == false) { 174 if (value.excludeFromIndexes != null &&
240 // TODO(Issue #$4): Should we support mixed indexed/non-indexed list 175 value.excludeFromIndexes) {
241 // values? 176 unindexedProperties.add(name);
242 if (property.listValue != null) {
243 if (property.listValue.length > 0) {
244 var firstIndexed = property.listValue.first.indexed;
245 for (int i = 1; i < property.listValue.length; i++) {
246 if (property.listValue[i].indexed != firstIndexed) {
247 throw new Exception('Some list entries are indexed and some '
248 'are not. This is currently not supported.');
249 }
250 }
251 if (firstIndexed == false) {
252 unindexedProperties.add(name);
253 }
254 }
255 } else {
256 unindexedProperties.add(name);
257 }
258 } 177 }
259 }); 178 });
260 } 179 }
261 return new datastore.Entity(_convertApi2DatastoreKey(entity.key), 180 return new datastore.Entity(_convertApi2DatastoreKey(entity.key),
262 properties, 181 properties,
263 unIndexedProperties: unindexedProperties); 182 unIndexedProperties: unindexedProperties);
264 } 183 }
265 184
266 api.Entity _convertDatastore2ApiEntity(datastore.Entity entity, 185 api.Entity _convertDatastore2ApiEntity(datastore.Entity entity,
267 {bool enforceId: false}) { 186 {bool enforceId: false}) {
(...skipping 28 matching lines...) Expand all
296 var pf = new api.PropertyFilter(); 215 var pf = new api.PropertyFilter();
297 var operator = relationMapping[filter.relation]; 216 var operator = relationMapping[filter.relation];
298 // FIXME(Issue #5): Is this OK? 217 // FIXME(Issue #5): Is this OK?
299 if (filter.relation == datastore.FilterRelation.In) { 218 if (filter.relation == datastore.FilterRelation.In) {
300 operator = 'EQUAL'; 219 operator = 'EQUAL';
301 } 220 }
302 221
303 if (operator == null) { 222 if (operator == null) {
304 throw new ArgumentError('Unknown filter relation: ${filter.relation}.'); 223 throw new ArgumentError('Unknown filter relation: ${filter.relation}.');
305 } 224 }
306 pf.operator = operator; 225 pf.op = operator;
307 pf.property = new api.PropertyReference()..name = filter.name; 226 pf.property = new api.PropertyReference()..name = filter.name;
308 227
309 // FIXME(Issue #5): Is this OK? 228 // FIXME(Issue #5): Is this OK?
310 var value = filter.value; 229 var value = filter.value;
311 if (filter.relation == datastore.FilterRelation.In) { 230 if (filter.relation == datastore.FilterRelation.In) {
312 if (value is List && value.length == 1) { 231 if (value is List && value.length == 1) {
313 value = value.first; 232 value = value.first;
314 } else { 233 } else {
315 throw new ArgumentError('List values not supported (was: $value).'); 234 throw new ArgumentError('List values not supported (was: $value).');
316 } 235 }
317 } 236 }
318 237
319 pf.value = _convertDatastore2ApiPropertyValue(value, true, lists: false); 238 pf.value = _convertDatastore2ApiPropertyValue(value, true, lists: false);
320 return new api.Filter()..propertyFilter = pf; 239 return new api.Filter()..propertyFilter = pf;
321 } 240 }
322 241
323 api.Filter _convertDatastoreAncestorKey2ApiFilter(datastore.Key key) { 242 api.Filter _convertDatastoreAncestorKey2ApiFilter(datastore.Key key) {
324 var pf = new api.PropertyFilter(); 243 var pf = new api.PropertyFilter();
325 pf.operator = 'HAS_ANCESTOR'; 244 pf.op = 'HAS_ANCESTOR';
326 pf.property = new api.PropertyReference()..name = '__key__'; 245 pf.property = new api.PropertyReference()..name = '__key__';
327 pf.value = new api.Value() 246 pf.value = new api.Value()
328 ..keyValue = _convertDatastore2ApiKey(key, enforceId: true); 247 ..keyValue = _convertDatastore2ApiKey(key, enforceId: true);
329 return new api.Filter()..propertyFilter = pf; 248 return new api.Filter()..propertyFilter = pf;
330 } 249 }
331 250
332 api.Filter _convertDatastore2ApiFilters(List<datastore.Filter> filters, 251 api.Filter _convertDatastore2ApiFilters(List<datastore.Filter> filters,
333 datastore.Key ancestorKey) { 252 datastore.Key ancestorKey) {
334 if ((filters == null || filters.length == 0) && ancestorKey == null) { 253 if ((filters == null || filters.length == 0) && ancestorKey == null) {
335 return null; 254 return null;
336 } 255 }
337 256
338 var compFilter = new api.CompositeFilter(); 257 var compFilter = new api.CompositeFilter();
339 if (filters != null) { 258 if (filters != null) {
340 compFilter.filters = filters.map(_convertDatastore2ApiFilter).toList(); 259 compFilter.filters = filters.map(_convertDatastore2ApiFilter).toList();
341 } 260 }
342 if (ancestorKey != null) { 261 if (ancestorKey != null) {
343 var filter = _convertDatastoreAncestorKey2ApiFilter(ancestorKey); 262 var filter = _convertDatastoreAncestorKey2ApiFilter(ancestorKey);
344 if (compFilter.filters == null) { 263 if (compFilter.filters == null) {
345 compFilter.filters = [filter]; 264 compFilter.filters = [filter];
346 } else { 265 } else {
347 compFilter.filters.add(filter); 266 compFilter.filters.add(filter);
348 } 267 }
349 } 268 }
350 compFilter.operator = 'AND'; 269 compFilter.op = 'AND';
351 return new api.Filter()..compositeFilter = compFilter; 270 return new api.Filter()..compositeFilter = compFilter;
352 } 271 }
353 272
354 api.PropertyOrder _convertDatastore2ApiOrder(datastore.Order order) { 273 api.PropertyOrder _convertDatastore2ApiOrder(datastore.Order order) {
355 var property = new api.PropertyReference()..name = order.propertyName; 274 var property = new api.PropertyReference()..name = order.propertyName;
356 var direction = order.direction == datastore.OrderDirection.Ascending 275 var direction = order.direction == datastore.OrderDirection.Ascending
357 ? 'ASCENDING' : 'DESCENDING'; 276 ? 'ASCENDING' : 'DESCENDING';
358 return new api.PropertyOrder() 277 return new api.PropertyOrder()
359 ..direction = direction 278 ..direction = direction
360 ..property = property; 279 ..property = property;
(...skipping 21 matching lines...) Expand all
382 } 301 }
383 } 302 }
384 return new Future.error(error, stack); 303 return new Future.error(error, stack);
385 } 304 }
386 305
387 Future<List<datastore.Key>> allocateIds(List<datastore.Key> keys) { 306 Future<List<datastore.Key>> allocateIds(List<datastore.Key> keys) {
388 var request = new api.AllocateIdsRequest(); 307 var request = new api.AllocateIdsRequest();
389 request..keys = keys.map((key) { 308 request..keys = keys.map((key) {
390 return _convertDatastore2ApiKey(key, enforceId: false); 309 return _convertDatastore2ApiKey(key, enforceId: false);
391 }).toList(); 310 }).toList();
392 return _api.datasets.allocateIds(request, _project).then((response) { 311 return _api.projects.allocateIds(request, _project).then((response) {
393 return response.keys.map(_convertApi2DatastoreKey).toList(); 312 return response.keys.map(_convertApi2DatastoreKey).toList();
394 }, onError: _handleError); 313 }, onError: _handleError);
395 } 314 }
396 315
397 Future<datastore.Transaction> beginTransaction( 316 Future<datastore.Transaction> beginTransaction(
398 {bool crossEntityGroup: false}) { 317 {bool crossEntityGroup: false}) {
399 var request = new api.BeginTransactionRequest(); 318 var request = new api.BeginTransactionRequest();
400 // TODO: Should this be made configurable? 319 return _api.projects.beginTransaction(request, _project).then((result) {
401 request.isolationLevel = 'SERIALIZABLE';
402 return _api.datasets.beginTransaction(request, _project).then((result) {
403 return new TransactionImpl(result.transaction); 320 return new TransactionImpl(result.transaction);
404 }, onError: _handleError); 321 }, onError: _handleError);
405 } 322 }
406 323
407 Future<datastore.CommitResult> commit({List<datastore.Entity> inserts, 324 Future<datastore.CommitResult> commit({List<datastore.Entity> inserts,
408 List<datastore.Entity> autoIdInserts, 325 List<datastore.Entity> autoIdInserts,
409 List<datastore.Key> deletes, 326 List<datastore.Key> deletes,
410 datastore.Transaction transaction}) { 327 datastore.Transaction transaction}) {
411 var request = new api.CommitRequest(); 328 var request = new api.CommitRequest();
412 329
413 if (transaction != null) { 330 if (transaction != null) {
414 request.mode = 'TRANSACTIONAL'; 331 request.mode = 'TRANSACTIONAL';
415 request.transaction = (transaction as TransactionImpl).data; 332 request.transaction = (transaction as TransactionImpl).data;
416 } else { 333 } else {
417 request.mode = 'NON_TRANSACTIONAL'; 334 request.mode = 'NON_TRANSACTIONAL';
418 } 335 }
419 336
420 request.mutation = new api.Mutation(); 337 var mutations = request.mutations = [];
421 if (inserts != null) { 338 if (inserts != null) {
422 request.mutation.upsert = new List(inserts.length);
423 for (int i = 0; i < inserts.length; i++) { 339 for (int i = 0; i < inserts.length; i++) {
424 request.mutation.upsert[i] = _convertDatastore2ApiEntity(inserts[i]); 340 mutations.add(
341 new api.Mutation()..upsert =
342 _convertDatastore2ApiEntity(inserts[i], enforceId: true));
425 } 343 }
426 } 344 }
345 int autoIdStartIndex = -1;
427 if (autoIdInserts != null) { 346 if (autoIdInserts != null) {
428 request.mutation.insertAutoId = new List(autoIdInserts.length); 347 autoIdStartIndex = mutations.length;
429 for (int i = 0; i < autoIdInserts.length; i++) { 348 for (int i = 0; i < autoIdInserts.length; i++) {
430 request.mutation.insertAutoId[i] = 349 mutations.add(
431 _convertDatastore2ApiEntity(autoIdInserts[i], enforceId: false); 350 new api.Mutation()..insert =
351 _convertDatastore2ApiEntity(autoIdInserts[i], enforceId: false));
432 } 352 }
433 } 353 }
434 if (deletes != null) { 354 if (deletes != null) {
435 request.mutation.delete = new List(deletes.length);
436 for (int i = 0; i < deletes.length; i++) { 355 for (int i = 0; i < deletes.length; i++) {
437 request.mutation.delete[i] = 356 mutations.add(
438 _convertDatastore2ApiKey(deletes[i], enforceId: true); 357 new api.Mutation()..delete =
358 _convertDatastore2ApiKey(deletes[i], enforceId: true));
439 } 359 }
440 } 360 }
441 return _api.datasets.commit(request, _project).then((result) { 361 return _api.projects.commit(request, _project).then((result) {
442 var keys; 362 var keys;
443 if (autoIdInserts != null && autoIdInserts.length > 0) { 363 if (autoIdInserts != null && autoIdInserts.length > 0) {
444 keys = result 364 List<api.MutationResult> mutationResults = result.mutationResults;
445 .mutationResult 365 assert(autoIdStartIndex != -1);
446 .insertAutoIdKeys 366 assert(mutationResults.length >=
447 .map(_convertApi2DatastoreKey).toList(); 367 (autoIdStartIndex + autoIdInserts.length));
368 keys = mutationResults
369 .skip(autoIdStartIndex)
370 .take(autoIdInserts.length)
371 .map((api.MutationResult r) => _convertApi2DatastoreKey(r.key))
372 .toList();
448 } 373 }
449 return new datastore.CommitResult(keys); 374 return new datastore.CommitResult(keys);
450 }, onError: _handleError); 375 }, onError: _handleError);
451 } 376 }
452 377
453 Future<List<datastore.Entity>> lookup(List<datastore.Key> keys, 378 Future<List<datastore.Entity>> lookup(List<datastore.Key> keys,
454 {datastore.Transaction transaction}) { 379 {datastore.Transaction transaction}) {
455 var apiKeys = keys.map((key) { 380 var apiKeys = keys.map((key) {
456 return _convertDatastore2ApiKey(key, enforceId: true); 381 return _convertDatastore2ApiKey(key, enforceId: true);
457 }).toList(); 382 }).toList();
458 var request = new api.LookupRequest(); 383 var request = new api.LookupRequest();
459 request.keys = apiKeys; 384 request.keys = apiKeys;
460 if (transaction != null) { 385 if (transaction != null) {
461 // TODO: Make readOptions more configurable. 386 // TODO: Make readOptions more configurable.
462 request.readOptions = new api.ReadOptions(); 387 request.readOptions = new api.ReadOptions();
463 request.readOptions.transaction = (transaction as TransactionImpl).data; 388 request.readOptions.transaction = (transaction as TransactionImpl).data;
464 } 389 }
465 return _api.datasets.lookup(request, _project).then((response) { 390 return _api.projects.lookup(request, _project).then((response) {
466 if (response.deferred != null && response.deferred.length > 0) { 391 if (response.deferred != null && response.deferred.length > 0) {
467 throw new datastore.DatastoreError( 392 throw new datastore.DatastoreError(
468 'Could not successfully look up all keys due to resource ' 393 'Could not successfully look up all keys due to resource '
469 'constraints.'); 394 'constraints.');
470 } 395 }
471 396
472 // NOTE: This is worst-case O(n^2)! 397 // NOTE: This is worst-case O(n^2)!
473 // Maybe we can optimize this somehow. But the API says: 398 // Maybe we can optimize this somehow. But the API says:
474 // message LookupResponse { 399 // message LookupResponse {
475 // // The order of results in these fields is undefined and has no rela tion to 400 // // The order of results in these fields is undefined and has no rela tion to
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
527 datastore.Transaction transaction}) { 452 datastore.Transaction transaction}) {
528 // NOTE: We explicitly do not set 'limit' here, since this is handled by 453 // NOTE: We explicitly do not set 'limit' here, since this is handled by
529 // QueryPageImpl.runQuery. 454 // QueryPageImpl.runQuery.
530 var apiQuery = new api.Query() 455 var apiQuery = new api.Query()
531 ..filter = _convertDatastore2ApiFilters(query.filters, 456 ..filter = _convertDatastore2ApiFilters(query.filters,
532 query.ancestorKey) 457 query.ancestorKey)
533 ..order = _convertDatastore2ApiOrders(query.orders) 458 ..order = _convertDatastore2ApiOrders(query.orders)
534 ..offset = query.offset; 459 ..offset = query.offset;
535 460
536 if (query.kind != null) { 461 if (query.kind != null) {
537 apiQuery.kinds = [new api.KindExpression()..name = query.kind]; 462 apiQuery.kind = [new api.KindExpression()..name = query.kind];
538 } 463 }
539 464
540 var request = new api.RunQueryRequest(); 465 var request = new api.RunQueryRequest();
541 request.query = apiQuery; 466 request.query = apiQuery;
542 if (transaction != null) { 467 if (transaction != null) {
543 // TODO: Make readOptions more configurable. 468 // TODO: Make readOptions more configurable.
544 request.readOptions = new api.ReadOptions(); 469 request.readOptions = new api.ReadOptions();
545 request.readOptions.transaction = (transaction as TransactionImpl).data; 470 request.readOptions.transaction = (transaction as TransactionImpl).data;
546 } 471 }
547 if (partition != null) { 472 if (partition != null) {
548 request.partitionId = new api.PartitionId() 473 request.partitionId = new api.PartitionId()
549 ..namespace = partition.namespace; 474 ..namespaceId = partition.namespace;
550 } 475 }
551 476
552 return QueryPageImpl.runQuery(_api, _project, request, query.limit) 477 return QueryPageImpl.runQuery(_api, _project, request, query.limit)
553 .catchError(_handleError); 478 .catchError(_handleError);
554 } 479 }
555 480
556 Future rollback(datastore.Transaction transaction) { 481 Future rollback(datastore.Transaction transaction) {
557 // TODO: Handle [transaction] 482 // TODO: Handle [transaction]
558 var request = new api.RollbackRequest() 483 var request = new api.RollbackRequest()
559 ..transaction = (transaction as TransactionImpl).data; 484 ..transaction = (transaction as TransactionImpl).data;
560 return _api.datasets.rollback(request, _project).catchError(_handleError); 485 return _api.projects.rollback(request, _project).catchError(_handleError);
561 } 486 }
562 } 487 }
563 488
564 class QueryPageImpl implements Page<datastore.Entity> { 489 class QueryPageImpl implements Page<datastore.Entity> {
565 static const int MAX_ENTITIES_PER_RESPONSE = 2000; 490 static const int MAX_ENTITIES_PER_RESPONSE = 2000;
566 491
567 final api.DatastoreApi _api; 492 final api.DatastoreApi _api;
568 final String _project; 493 final String _project;
569 final api.RunQueryRequest _nextRequest; 494 final api.RunQueryRequest _nextRequest;
570 final List<datastore.Entity> _entities; 495 final List<datastore.Entity> _entities;
(...skipping 14 matching lines...) Expand all
585 int batchLimit = batchSize; 510 int batchLimit = batchSize;
586 if (batchLimit == null) { 511 if (batchLimit == null) {
587 batchLimit = MAX_ENTITIES_PER_RESPONSE; 512 batchLimit = MAX_ENTITIES_PER_RESPONSE;
588 } 513 }
589 if (limit != null && limit < batchLimit) { 514 if (limit != null && limit < batchLimit) {
590 batchLimit = limit; 515 batchLimit = limit;
591 } 516 }
592 517
593 request.query.limit = batchLimit; 518 request.query.limit = batchLimit;
594 519
595 return api.datasets.runQuery(request, project).then((response) { 520 return api.projects.runQuery(request, project).then((response) {
596 var returnedEntities = const []; 521 var returnedEntities = const [];
597 522
598 var batch = response.batch; 523 var batch = response.batch;
599 if (batch.entityResults != null) { 524 if (batch.entityResults != null) {
600 returnedEntities = batch.entityResults 525 returnedEntities = batch.entityResults
601 .map((result) => result.entity) 526 .map((result) => result.entity)
602 .map(DatastoreImpl._convertApi2DatastoreEntity) 527 .map(DatastoreImpl._convertApi2DatastoreEntity)
603 .toList(); 528 .toList();
604 } 529 }
605 530
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
701 return new Future.sync(() { 626 return new Future.sync(() {
702 throw new ArgumentError('Cannot call next() on last page.'); 627 throw new ArgumentError('Cannot call next() on last page.');
703 }); 628 });
704 } 629 }
705 630
706 return QueryPageImpl.runQuery( 631 return QueryPageImpl.runQuery(
707 _api, _project, _nextRequest, _remainingNumberOfEntities) 632 _api, _project, _nextRequest, _remainingNumberOfEntities)
708 .catchError(DatastoreImpl._handleError); 633 .catchError(DatastoreImpl._handleError);
709 } 634 }
710 } 635 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698