Merge lp:~nwilliams/akiban-server/remove-modelbuilder-jonquil into lp:~akiban-technologies/akiban-server/trunk

Proposed by Nathan Williams
Status: Merged
Approved by: Mike McMahon
Approved revision: 2721
Merged at revision: 2724
Proposed branch: lp:~nwilliams/akiban-server/remove-modelbuilder-jonquil
Merge into: lp:~akiban-technologies/akiban-server/trunk
Diff against target: 1568 lines (+3/-1320)
28 files modified
pom.xml (+0/-5)
src/main/java/com/akiban/rest/RestResponseBuilder.java (+1/-1)
src/main/java/com/akiban/rest/RestServiceImpl.java (+0/-1)
src/main/java/com/akiban/rest/resources/BuilderResource.java (+0/-218)
src/main/java/com/akiban/rest/resources/EntityResource.java (+0/-39)
src/main/java/com/akiban/server/error/ErrorCode.java (+1/-1)
src/main/java/com/akiban/server/error/ModelBuilderException.java (+0/-30)
src/main/java/com/akiban/server/service/restdml/ModelBuilder.java (+0/-441)
src/main/java/com/akiban/server/service/restdml/RestDMLService.java (+0/-2)
src/main/java/com/akiban/server/service/restdml/RestDMLServiceImpl.java (+0/-90)
src/main/resources/com/akiban/server/error/error_code.properties (+0/-1)
src/test/java/com/akiban/server/entity/changes/EntityParserIT.java (+1/-1)
src/test/java/com/akiban/server/service/restdml/ModelBuilderIT.java (+0/-333)
src/test/resources/com/akiban/rest/caoi/builder-implode.check (+0/-1)
src/test/resources/com/akiban/rest/caoi/builder-implode.check_expected (+0/-68)
src/test/resources/com/akiban/rest/caoi/builder-implode.expected (+0/-4)
src/test/resources/com/akiban/rest/caoi/builder-implode.post (+0/-1)
src/test/resources/com/akiban/rest/caoi/builder-insert.body (+0/-4)
src/test/resources/com/akiban/rest/caoi/builder-insert.check (+0/-1)
src/test/resources/com/akiban/rest/caoi/builder-insert.check_expected (+0/-7)
src/test/resources/com/akiban/rest/caoi/builder-insert.expected (+0/-3)
src/test/resources/com/akiban/rest/caoi/builder-insert.post (+0/-1)
src/test/resources/com/akiban/rest/caoi/c1-jonquil-query.body (+0/-9)
src/test/resources/com/akiban/rest/caoi/c1-jonquil-query.expected (+0/-46)
src/test/resources/com/akiban/rest/caoi/c1-jonquil-query.post (+0/-1)
src/test/resources/com/akiban/rest/caoi/c1-jonquil-tosql.body (+0/-9)
src/test/resources/com/akiban/rest/caoi/c1-jonquil-tosql.expected (+0/-1)
src/test/resources/com/akiban/rest/caoi/c1-jonquil-tosql.post (+0/-1)
To merge this branch: bzr merge lp:~nwilliams/akiban-server/remove-modelbuilder-jonquil
Reviewer Review Type Date Requested Status
Mike McMahon Approve
Review via email: mp+177417@code.launchpad.net

Description of the change

Remove ModelBuilder and Jonquil REST endpoints.

Entirely minus aside from import tweaks due to Jonquil dependency no longer bringing in two versions of Jackson.

To post a comment you must log in.
Revision history for this message
Mike McMahon (mmcm) wrote :

As agreed.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'pom.xml'
2--- pom.xml 2013-06-14 11:23:11 +0000
3+++ pom.xml 2013-07-29 15:32:48 +0000
4@@ -52,11 +52,6 @@
5
6 <dependencies>
7 <dependency>
8- <groupId>com.akiban</groupId>
9- <artifactId>jonquil</artifactId>
10- <version>1.0</version>
11- </dependency>
12- <dependency>
13 <groupId>org.apache.commons</groupId>
14 <artifactId>commons-math</artifactId>
15 <version>2.2</version>
16
17=== modified file 'src/main/java/com/akiban/rest/RestResponseBuilder.java'
18--- src/main/java/com/akiban/rest/RestResponseBuilder.java 2013-04-26 15:25:38 +0000
19+++ src/main/java/com/akiban/rest/RestResponseBuilder.java 2013-07-29 15:32:48 +0000
20@@ -26,7 +26,7 @@
21 import com.akiban.server.error.NoSuchRoutineException;
22 import com.akiban.server.error.NoSuchTableException;
23 import com.akiban.util.AkibanAppender;
24-import org.codehaus.jackson.JsonParseException;
25+import com.fasterxml.jackson.core.JsonParseException;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29
30=== modified file 'src/main/java/com/akiban/rest/RestServiceImpl.java'
31--- src/main/java/com/akiban/rest/RestServiceImpl.java 2013-06-11 16:32:59 +0000
32+++ src/main/java/com/akiban/rest/RestServiceImpl.java 2013-07-29 15:32:48 +0000
33@@ -109,7 +109,6 @@
34 new VersionResource(reqs),
35 new DirectResource(reqs),
36 new ViewResource(reqs),
37- new BuilderResource(reqs),
38 // This must be last to capture anything not handled above
39 new DefaultResource()
40 ));
41
42=== removed file 'src/main/java/com/akiban/rest/resources/BuilderResource.java'
43--- src/main/java/com/akiban/rest/resources/BuilderResource.java 2013-06-11 16:30:17 +0000
44+++ src/main/java/com/akiban/rest/resources/BuilderResource.java 1970-01-01 00:00:00 +0000
45@@ -1,218 +0,0 @@
46-/**
47- * Copyright (C) 2009-2013 Akiban Technologies, Inc.
48- *
49- * This program is free software: you can redistribute it and/or modify
50- * it under the terms of the GNU Affero General Public License as published by
51- * the Free Software Foundation, either version 3 of the License, or
52- * (at your option) any later version.
53- *
54- * This program is distributed in the hope that it will be useful,
55- * but WITHOUT ANY WARRANTY; without even the implied warranty of
56- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57- * GNU Affero General Public License for more details.
58- *
59- * You should have received a copy of the GNU Affero General Public License
60- * along with this program. If not, see <http://www.gnu.org/licenses/>.
61- */
62-
63-package com.akiban.rest.resources;
64-
65-import com.akiban.ais.model.TableName;
66-import com.akiban.rest.ResourceRequirements;
67-import com.akiban.rest.RestResponseBuilder;
68-import com.akiban.server.service.restdml.ModelBuilder;
69-import com.akiban.server.service.restdml.RestDMLService;
70-import com.akiban.server.service.security.SecurityService;
71-import com.akiban.util.JsonUtils;
72-import com.fasterxml.jackson.databind.node.ObjectNode;
73-
74-import javax.servlet.http.HttpServletRequest;
75-import javax.ws.rs.DELETE;
76-import javax.ws.rs.GET;
77-import javax.ws.rs.POST;
78-import javax.ws.rs.PUT;
79-import javax.ws.rs.Path;
80-import javax.ws.rs.PathParam;
81-import javax.ws.rs.Produces;
82-import javax.ws.rs.core.Context;
83-import javax.ws.rs.core.Response;
84-import javax.ws.rs.core.UriInfo;
85-import java.io.PrintWriter;
86-
87-import static com.akiban.rest.resources.ResourceHelper.IDENTIFIERS_MULTI;
88-import static com.akiban.rest.resources.ResourceHelper.MEDIATYPE_JSON_JAVASCRIPT;
89-import static com.akiban.rest.resources.ResourceHelper.checkTableAccessible;
90-import static com.akiban.rest.resources.ResourceHelper.getPKString;
91-import static com.akiban.rest.resources.ResourceHelper.parseTableName;
92-
93-@Path("/builder")
94-public class BuilderResource {
95- private final SecurityService securityService;
96- private final RestDMLService restDMLService;
97- private final ModelBuilder modelBuilder;
98-
99- public BuilderResource(ResourceRequirements reqs) {
100- this.securityService = reqs.securityService;
101- this.restDMLService = reqs.restDMLService;
102- this.modelBuilder = new ModelBuilder(
103- reqs.sessionService,
104- reqs.transactionService,
105- reqs.dxlService,
106- reqs.store,
107- restDMLService
108- );
109- }
110-
111- @GET
112- @Path("/entity/{entity}")
113- @Produces(MEDIATYPE_JSON_JAVASCRIPT)
114- public Response getAll(@Context HttpServletRequest request,
115- @PathParam("entity") String entityName) {
116- final TableName tableName = parseTableName(request, entityName);
117- checkTableAccessible(securityService, request, tableName);
118- return RestResponseBuilder
119- .forRequest(request)
120- .body(new RestResponseBuilder.BodyGenerator() {
121- @Override
122- public void write(PrintWriter writer) throws Exception {
123- modelBuilder.getAll(writer, tableName);
124- }
125- })
126- .build();
127- }
128-
129- @GET
130- @Path("/entity/{entity}/" + IDENTIFIERS_MULTI)
131- @Produces(MEDIATYPE_JSON_JAVASCRIPT)
132- public Response getSingle(@Context HttpServletRequest request,
133- @PathParam("entity") String entityName,
134- @Context final UriInfo uri) {
135- final TableName tableName = parseTableName(request, entityName);
136- checkTableAccessible(securityService, request, tableName);
137- return RestResponseBuilder
138- .forRequest(request)
139- .body(new RestResponseBuilder.BodyGenerator() {
140- @Override
141- public void write(PrintWriter writer) throws Exception {
142- modelBuilder.getKeys(writer, tableName, getPKString(uri));
143- }
144- })
145- .build();
146- }
147-
148- @POST
149- @Path("/entity/{entity}")
150- @Produces(MEDIATYPE_JSON_JAVASCRIPT)
151- public Response post(@Context HttpServletRequest request,
152- @PathParam("entity") String entityName,
153- final String entityData) {
154- final TableName tableName = parseTableName(request, entityName);
155- checkTableAccessible(securityService, request, tableName);
156- return RestResponseBuilder
157- .forRequest(request)
158- .body(new RestResponseBuilder.BodyGenerator() {
159- @Override
160- public void write(PrintWriter writer) throws Exception {
161- modelBuilder.insert(writer, tableName, entityData);
162- }
163- })
164- .build();
165- }
166-
167- @PUT
168- @Path("/entity/{entity}/" + IDENTIFIERS_MULTI)
169- @Produces(MEDIATYPE_JSON_JAVASCRIPT)
170- public Response put(@Context HttpServletRequest request,
171- @PathParam("entity") String entityName,
172- @Context final UriInfo uri,
173- final String entityData) {
174- final TableName tableName = parseTableName(request, entityName);
175- checkTableAccessible(securityService, request, tableName);
176- return RestResponseBuilder
177- .forRequest(request)
178- .body(new RestResponseBuilder.BodyGenerator() {
179- @Override
180- public void write(PrintWriter writer) throws Exception {
181- modelBuilder.update(writer, tableName, getPKString(uri), entityData);
182- }
183- })
184- .build();
185- }
186-
187- @DELETE
188- @Path("/entity/{entity}/" + IDENTIFIERS_MULTI)
189- public Response delete(@Context HttpServletRequest request,
190- @PathParam("entity") String entityName,
191- @Context final UriInfo uri) {
192- final TableName tableName = parseTableName(request, entityName);
193- checkTableAccessible(securityService, request, tableName);
194- try {
195- modelBuilder.create(tableName);
196- restDMLService.delete(tableName, getPKString(uri));
197- return RestResponseBuilder
198- .forRequest(request)
199- .status(Response.Status.NO_CONTENT)
200- .build();
201- } catch (Exception e) {
202- throw RestResponseBuilder.forRequest(request).wrapException(e);
203- }
204- }
205-
206- @GET
207- @Path("/is_builder/{entity}")
208- @Produces(MEDIATYPE_JSON_JAVASCRIPT)
209- public Response isBuilder(@Context HttpServletRequest request,
210- @PathParam("entity") final String entityName) {
211- final TableName tableName = parseTableName(request, entityName);
212- checkTableAccessible(securityService, request, tableName);
213- return RestResponseBuilder
214- .forRequest(request)
215- .body(new RestResponseBuilder.BodyGenerator() {
216- @Override
217- public void write(PrintWriter writer) throws Exception {
218- boolean isBuilder = modelBuilder.isBuilderTable(tableName);
219- ObjectNode node = JsonUtils.mapper.createObjectNode();
220- node.put("entity", entityName);
221- node.put("is_builder", isBuilder);
222- writer.append(node.toString());
223- }
224- })
225- .build();
226- }
227-
228- @POST
229- @Path("/explode/{entity}")
230- @Produces(MEDIATYPE_JSON_JAVASCRIPT)
231- public Response explode(@Context HttpServletRequest request,
232- @PathParam("entity") String entityName) {
233- final TableName tableName = parseTableName(request, entityName);
234- checkTableAccessible(securityService, request, tableName);
235- return RestResponseBuilder
236- .forRequest(request)
237- .body(new RestResponseBuilder.BodyGenerator() {
238- @Override
239- public void write(PrintWriter writer) throws Exception {
240- modelBuilder.explode(writer, tableName);
241- }
242- })
243- .build();
244- }
245-
246- @POST
247- @Path("/implode/{entity}")
248- @Produces(MEDIATYPE_JSON_JAVASCRIPT)
249- public Response implode(@Context HttpServletRequest request,
250- @PathParam("entity") String entityName) {
251- final TableName tableName = parseTableName(request, entityName);
252- checkTableAccessible(securityService, request, tableName);
253- return RestResponseBuilder
254- .forRequest(request)
255- .body(new RestResponseBuilder.BodyGenerator() {
256- @Override
257- public void write(PrintWriter writer) throws Exception {
258- modelBuilder.implode(writer, tableName);
259- }
260- })
261- .build();
262- }
263-}
264
265=== modified file 'src/main/java/com/akiban/rest/resources/EntityResource.java'
266--- src/main/java/com/akiban/rest/resources/EntityResource.java 2013-04-23 14:20:47 +0000
267+++ src/main/java/com/akiban/rest/resources/EntityResource.java 2013-07-29 15:32:48 +0000
268@@ -95,45 +95,6 @@
269 }
270
271 @POST
272- @Path("/jonquil/to-sql")
273- @Consumes(MEDIATYPE_JSON_JAVASCRIPT)
274- public Response jonquilToSQL(@Context final HttpServletRequest request,
275- @PathParam("entity") String entity,
276- final String query) {
277- final TableName tableName = parseTableName(request, entity);
278- checkTableAccessible(reqs.securityService, request, tableName);
279- return RestResponseBuilder
280- .forRequest(request)
281- .body(new RestResponseBuilder.BodyGenerator() {
282- @Override
283- public void write(PrintWriter writer) throws Exception {
284- writer.write(reqs.restDMLService.jonquilToSQL(tableName, query));
285- }
286- })
287- .build();
288- }
289-
290- @POST
291- @Path("/jonquil/query")
292- @Produces(MEDIATYPE_JSON_JAVASCRIPT)
293- public Response jonquilQuery(@Context final HttpServletRequest request,
294- @PathParam("entity") String entity,
295- final String query) {
296- final TableName tableName = parseTableName(request, entity);
297- checkTableAccessible(reqs.securityService, request, tableName);
298- return RestResponseBuilder
299- .forRequest(request)
300- .body(new RestResponseBuilder.BodyGenerator() {
301- @Override
302- public void write(PrintWriter writer) throws Exception {
303- String sql = reqs.restDMLService.jonquilToSQL(tableName, query);
304- reqs.restDMLService.runSQL(writer, request, sql, tableName.getSchemaName());
305- }
306- })
307- .build();
308- }
309-
310- @POST
311 @Consumes(MediaType.APPLICATION_JSON)
312 @Produces(MEDIATYPE_JSON_JAVASCRIPT)
313 public Response createEntity(@Context HttpServletRequest request,
314
315=== modified file 'src/main/java/com/akiban/server/error/ErrorCode.java'
316--- src/main/java/com/akiban/server/error/ErrorCode.java 2013-07-19 19:40:21 +0000
317+++ src/main/java/com/akiban/server/error/ErrorCode.java 2013-07-29 15:32:48 +0000
318@@ -374,7 +374,7 @@
319 ALTER_MADE_NO_CHANGE ("50", "023", Importance.DEBUG, AlterMadeNoChangeException.class),
320 INVALID_ROUTINE ("50", "024", Importance.DEBUG, InvalidRoutineException.class),
321 INVALID_INDEX_ID ("50", "025", Importance.DEBUG, InvalidIndexIDException.class),
322- MODEL_BUILDER_ERROR ("50", "026", Importance.DEBUG, ModelBuilderException.class),
323+ // 50026 available
324 COLUMN_NOT_GENERATED ("50", "027", Importance.DEBUG, ColumnNotGeneratedException.class),
325 COLUMN_ALREADY_GENERATED ("50", "028", Importance.DEBUG, ColumnAlreadyGeneratedException.class),
326 DROP_SEQUENCE_NOT_ALLOWED ("50", "029", Importance.DEBUG, DropSequenceNotAllowedException.class),
327
328=== removed file 'src/main/java/com/akiban/server/error/ModelBuilderException.java'
329--- src/main/java/com/akiban/server/error/ModelBuilderException.java 2013-03-25 22:53:24 +0000
330+++ src/main/java/com/akiban/server/error/ModelBuilderException.java 1970-01-01 00:00:00 +0000
331@@ -1,30 +0,0 @@
332-/**
333- * Copyright (C) 2009-2013 Akiban Technologies, Inc.
334- *
335- * This program is free software: you can redistribute it and/or modify
336- * it under the terms of the GNU Affero General Public License as published by
337- * the Free Software Foundation, either version 3 of the License, or
338- * (at your option) any later version.
339- *
340- * This program is distributed in the hope that it will be useful,
341- * but WITHOUT ANY WARRANTY; without even the implied warranty of
342- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
343- * GNU Affero General Public License for more details.
344- *
345- * You should have received a copy of the GNU Affero General Public License
346- * along with this program. If not, see <http://www.gnu.org/licenses/>.
347- */
348-
349-package com.akiban.server.error;
350-
351-import com.akiban.ais.model.TableName;
352-
353-public class ModelBuilderException extends InvalidOperationException {
354- public ModelBuilderException(TableName tableName, String message) {
355- super(ErrorCode.MODEL_BUILDER_ERROR,
356- tableName.getSchemaName(),
357- tableName.getTableName(),
358- message
359- );
360- }
361-}
362
363=== removed file 'src/main/java/com/akiban/server/service/restdml/ModelBuilder.java'
364--- src/main/java/com/akiban/server/service/restdml/ModelBuilder.java 2013-07-23 21:24:34 +0000
365+++ src/main/java/com/akiban/server/service/restdml/ModelBuilder.java 1970-01-01 00:00:00 +0000
366@@ -1,441 +0,0 @@
367-/**
368- * Copyright (C) 2009-2013 Akiban Technologies, Inc.
369- *
370- * This program is free software: you can redistribute it and/or modify
371- * it under the terms of the GNU Affero General Public License as published by
372- * the Free Software Foundation, either version 3 of the License, or
373- * (at your option) any later version.
374- *
375- * This program is distributed in the hope that it will be useful,
376- * but WITHOUT ANY WARRANTY; without even the implied warranty of
377- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
378- * GNU Affero General Public License for more details.
379- *
380- * You should have received a copy of the GNU Affero General Public License
381- * along with this program. If not, see <http://www.gnu.org/licenses/>.
382- */
383-
384-package com.akiban.server.service.restdml;
385-
386-import com.akiban.ais.model.AkibanInformationSchema;
387-import com.akiban.ais.model.Join;
388-import com.akiban.ais.model.TableName;
389-import com.akiban.ais.model.UserTable;
390-import com.akiban.ais.model.aisb2.AISBBasedBuilder;
391-import com.akiban.ais.model.aisb2.NewAISBuilder;
392-import com.akiban.qp.expression.IndexKeyRange;
393-import com.akiban.qp.operator.API;
394-import com.akiban.qp.operator.Cursor;
395-import com.akiban.qp.operator.Operator;
396-import com.akiban.qp.operator.QueryBindings;
397-import com.akiban.qp.operator.QueryContext;
398-import com.akiban.qp.operator.SimpleQueryContext;
399-import com.akiban.qp.operator.StoreAdapter;
400-import com.akiban.qp.row.Row;
401-import com.akiban.qp.rowtype.IndexRowType;
402-import com.akiban.qp.rowtype.Schema;
403-import com.akiban.qp.util.SchemaCache;
404-import com.akiban.server.api.DDLFunctions;
405-import com.akiban.server.entity.changes.EntityParser;
406-import com.akiban.server.error.ModelBuilderException;
407-import com.akiban.server.service.dxl.DXLService;
408-import com.akiban.server.service.externaldata.JsonRowWriter;
409-import com.akiban.server.service.externaldata.TableRowTracker;
410-import com.akiban.server.service.session.Session;
411-import com.akiban.server.service.session.SessionService;
412-import com.akiban.server.service.transaction.TransactionService;
413-import com.akiban.server.store.Store;
414-import com.akiban.server.types3.mcompat.mtypes.MString;
415-import com.akiban.server.types3.pvalue.PValue;
416-import com.akiban.sql.optimizer.rule.PlanGenerator;
417-import com.akiban.util.AkibanAppender;
418-import com.akiban.util.JsonUtils;
419-import com.akiban.util.tap.InOutTap;
420-import com.akiban.util.tap.Tap;
421-import com.fasterxml.jackson.databind.JsonNode;
422-import com.fasterxml.jackson.databind.node.ObjectNode;
423-
424-import java.io.IOException;
425-import java.io.PrintWriter;
426-import java.util.Collections;
427-import java.util.Iterator;
428-import java.util.List;
429-import java.util.Map;
430-
431-import static com.akiban.server.service.transaction.TransactionService.CloseableTransaction;
432-
433-public class ModelBuilder {
434- public static final String DATA_COL_NAME = "_data";
435- private static final InOutTap BUILDER_GET = Tap.createTimer("rest: builder GET");
436- private static final InOutTap BUILDER_GET_ALL = Tap.createTimer("rest: builder getall");
437- private static final InOutTap BUILDER_POST = Tap.createTimer("rest: builder POST");
438- private static final InOutTap BUILDER_PUT = Tap.createTimer("rest: builder PUT");
439- private static final InOutTap BUILDER_EXPLODE = Tap.createTimer("rest: builder explode");
440- private static final InOutTap BUILDER_IMPLODE = Tap.createTimer("rest: builder implode");
441-
442-
443- private final SessionService sessionService;
444- private final TransactionService txnService;
445- private final DDLFunctions ddlFunctions;
446- private final Store store;
447- private final RestDMLService restDMLService;
448-
449- public ModelBuilder(SessionService sessionService,
450- TransactionService txnService,
451- DXLService dxlService,
452- Store store,
453- RestDMLService restDMLService) {
454- this.sessionService = sessionService;
455- this.txnService = txnService;
456- this.ddlFunctions = dxlService.ddlFunctions();
457- this.store = store;
458- this.restDMLService = restDMLService;
459- }
460-
461- public void create(TableName tableName) {
462- try (Session session = sessionService.createSession();
463- CloseableTransaction txn = txnService.beginCloseableTransaction(session)) {
464- createInternal(session, tableName);
465- txn.commit();
466- }
467- }
468-
469- public boolean isBuilderTable(TableName tableName) {
470- try (Session session = sessionService.createSession()) {
471- UserTable curTable = ddlFunctions.getUserTable(session, tableName);
472- return isBuilderTable(curTable);
473- }
474- }
475-
476- public void getAll(PrintWriter writer, TableName tableName) throws IOException {
477- BUILDER_GET_ALL.in();
478- try (Session session = sessionService.createSession();
479- CloseableTransaction txn = txnService.beginCloseableTransaction(session)) {
480- createInternal(session, tableName);
481- Cursor cursor = groupScanCursor(session, tableName);
482- writer.append('[');
483- scanCursor(writer, cursor, true);
484- writer.append(']');
485- } finally {
486- BUILDER_GET_ALL.out();
487- }
488- }
489-
490- public void getKeys(PrintWriter writer, TableName tableName, String identifiers) throws IOException {
491- BUILDER_GET.in();
492- try (Session session = sessionService.createSession();
493- CloseableTransaction txn = txnService.beginCloseableTransaction(session)) {
494- createInternal(session, tableName);
495- AkibanInformationSchema ais = ddlFunctions.getAIS(session);
496- UserTable table = ais.getUserTable(tableName);
497- List<List<String>> keys = PrimaryKeyParser.parsePrimaryKeys(identifiers, table.getPrimaryKey().getIndex());
498- Operator plan = PlanGenerator.generateBranchPlan(ais, table);
499- QueryContext context = queryContext(session, ais);
500- QueryBindings bindings = context.createBindings();
501- Cursor cursor = API.cursor(plan, context, bindings);
502- boolean first = true;
503- writer.append('[');
504- for(List<String> pk : keys) {
505- for(int i = 0; i < pk.size(); i++) {
506- PValue pvalue = new PValue(MString.varchar());
507- pvalue.putString(pk.get(i), null);
508- bindings.setPValue(i, pvalue);
509- }
510- first = scanCursor(writer, cursor, first);
511- }
512- writer.append(']');
513- txn.commit();
514- } finally {
515- BUILDER_GET.out();
516- }
517- }
518-
519- public void insert(PrintWriter writer, TableName tableName, String data) {
520- BUILDER_POST.in();
521- try (Session session = sessionService.createSession();
522- CloseableTransaction txn = txnService.beginCloseableTransaction(session)) {
523- createInternal(session, tableName);
524- ObjectNode node = JsonUtils.mapper.createObjectNode();
525- // Sequence will fill in ID
526- node.put(ModelBuilder.DATA_COL_NAME, data);
527- restDMLService.insertNoTxn(session, writer, tableName, node);
528- txn.commit();
529- } finally {
530- BUILDER_POST.out();
531- }
532- }
533-
534- public void update(PrintWriter writer, TableName tableName, String id, String data) {
535- BUILDER_PUT.in();
536- try (Session session = sessionService.createSession();
537- CloseableTransaction txn = txnService.beginCloseableTransaction(session)) {
538- createInternal(session, tableName);
539- ObjectNode node = JsonUtils.mapper.createObjectNode();
540- node.put(EntityParser.PK_COL_NAME, id);
541- node.put(ModelBuilder.DATA_COL_NAME, data);
542- restDMLService.updateNoTxn(session, writer, tableName, id, node);
543- txn.commit();
544- } finally {
545- BUILDER_PUT.out();
546- }
547- }
548-
549- public void explode(PrintWriter writer, TableName tableName) throws IOException {
550- BUILDER_EXPLODE.in();
551- try (Session session = sessionService.createSession()) {
552- // Find the last row
553- Row row = getLastRow(session, tableName);
554- if(row == null) {
555- throw new ModelBuilderException(tableName, "Entity has no rows");
556- }
557-
558- // Parse that row
559- ObjectNode node = (ObjectNode)JsonUtils.readTree(row.pvalue(1).getString());
560- node.remove(EntityParser.PK_COL_NAME);
561-
562- // Move builder out of the way and create exploded table(s)
563- EntityParser parser = new EntityParser(true);
564- UserTable explodedTable = parser.parse(tableName, node);
565- TableName tempName = new TableName(tableName.getSchemaName(), "__" + tableName.getTableName());
566- ddlFunctions.renameTable(session, tableName, tempName);
567- parser.create(ddlFunctions, session, explodedTable);
568-
569- // Convert builder rows
570- int convertedRows = 0;
571- try(CloseableTransaction txn = txnService.beginCloseableTransaction(session)) {
572- Cursor cursor = groupScanCursor(session, tempName);
573- cursor.openTopLevel();
574- try {
575- while((row = cursor.next()) != null) {
576- node = (ObjectNode)JsonUtils.readTree(row.pvalue(1).getString());
577- node.put(EntityParser.PK_COL_NAME, row.pvalue(0).getInt64());
578- removeUnknownFields(explodedTable, node);
579- restDMLService.insertNoTxn(session, null, tableName, node);
580- ++convertedRows;
581- }
582- cursor.closeTopLevel();
583- } finally {
584- cursor.destroy();
585- }
586- txn.commit();
587- }
588-
589- // Remove builder table
590- ddlFunctions.dropTable(session, tempName);
591-
592- ObjectNode summaryNode = JsonUtils.mapper.createObjectNode();
593- summaryNode.put("exploded", tableName.getTableName());
594- summaryNode.put("rows", convertedRows);
595- writer.append(summaryNode.toString());
596- } finally {
597- BUILDER_EXPLODE.out();
598- }
599- }
600-
601- public void implode(PrintWriter writer, TableName tableName) {
602- BUILDER_IMPLODE.in();
603- try (Session session = sessionService.createSession()) {
604- UserTable curTable = ddlFunctions.getUserTable(session, tableName);
605- if(!curTable.isRoot()) {
606- throw new ModelBuilderException(tableName, "Cannot implode non-root table");
607- }
608- if(isBuilderTable(curTable)) {
609- throw new ModelBuilderException(tableName, "Table is already imploded");
610- }
611-
612- // Rename current
613- TableName tempName = new TableName(tableName.getSchemaName(), "__" + tableName.getTableName());
614- ddlFunctions.renameTable(session, tableName, tempName);
615-
616- // Create new
617- createInternal(session, tableName);
618-
619- // Scan old into new
620- UserTable oldTable = ddlFunctions.getUserTable(session, tempName);
621- UserTable newTable = ddlFunctions.getUserTable(session, tableName);
622- ImplodeTracker tracker = new ImplodeTracker(newTable, oldTable, -1);
623- Cursor cursor = groupScanCursor(session, tempName);
624- try {
625- JsonRowWriter rowWriter = new JsonRowWriter(tracker);
626- rowWriter.writeRows(cursor, AkibanAppender.of(tracker.getStringBuilder()), "", new JsonRowWriter.WriteTableRow());
627- } finally {
628- cursor.destroy();
629- }
630-
631- // drop old
632- ddlFunctions.dropGroup(session, tempName);
633-
634- ObjectNode summaryNode = JsonUtils.mapper.createObjectNode();
635- summaryNode.put("imploded", tableName.getTableName());
636- summaryNode.put("rows", tracker.getRowCount());
637- writer.append(summaryNode.toString());
638- } finally {
639- BUILDER_IMPLODE.out();
640- }
641- }
642-
643-
644- private void createInternal(Session session, TableName tableName) {
645- AkibanInformationSchema curAIS = ddlFunctions.getAIS(session);
646- UserTable curTable = curAIS.getUserTable(tableName);
647- if(curTable == null) {
648- NewAISBuilder builder = AISBBasedBuilder.create();
649- builder.userTable(tableName)
650- .autoIncLong(EntityParser.PK_COL_NAME, 1)
651- .colString(DATA_COL_NAME, 65535, true)
652- .pk(EntityParser.PK_COL_NAME);
653- ddlFunctions.createTable(session, builder.ais().getUserTable(tableName));
654- } else {
655- if(!isBuilderTable(curTable)) {
656- throw new ModelBuilderException(tableName, "Entity already exists as non-builder table");
657- }
658- }
659- }
660-
661- private Row getLastRow(Session session, TableName tableName) {
662- UserTable table = ddlFunctions.getUserTable(session, tableName);
663- Schema schema = SchemaCache.globalSchema(table.getAIS());
664- IndexRowType indexRowType = schema.indexRowType(table.getPrimaryKey().getIndex());
665- Operator plan = API.groupLookup_Default(
666- API.indexScan_Default(
667- indexRowType,
668- true,
669- IndexKeyRange.unbounded(indexRowType)
670- ),
671- table.getGroup(),
672- indexRowType,
673- Collections.singleton(schema.userTableRowType(table)),
674- API.InputPreservationOption.DISCARD_INPUT,
675- 1
676- );
677- StoreAdapter adapter = store.createAdapter(session, schema);
678- QueryContext queryContext = new SimpleQueryContext(adapter);
679- QueryBindings queryBindings = queryContext.createBindings();
680- Cursor cursor = API.cursor(plan, queryContext, queryBindings);
681- cursor.openTopLevel();
682- try {
683- return cursor.next();
684- } finally {
685- cursor.destroy();
686- }
687- }
688-
689- private QueryContext queryContext(Session session, AkibanInformationSchema ais) {
690- StoreAdapter adapter = store.createAdapter(session, SchemaCache.globalSchema(ais));
691- return new SimpleQueryContext(adapter);
692- }
693-
694- private Cursor groupScanCursor(Session session, TableName tableName) {
695- UserTable table = ddlFunctions.getUserTable(session, tableName);
696- Operator plan = PlanGenerator.generateScanPlan(table.getAIS(), table);
697- QueryContext queryContext = queryContext(session, table.getAIS());
698- QueryBindings queryBindings = queryContext.createBindings();
699- return API.cursor(plan, queryContext, queryBindings);
700- }
701-
702- private boolean scanCursor(PrintWriter writer, Cursor cursor, boolean first) throws IOException {
703- Row row;
704- cursor.openTopLevel();
705- try {
706- while((row = cursor.next()) != null) {
707- if(!first) {
708- writer.append(",\n");
709- }
710- first = false;
711- long id = row.pvalue(0).getInt64();
712- String json = row.pvalue(1).getString();
713- ObjectNode node = (ObjectNode)JsonUtils.readTree(json);
714- node.put(EntityParser.PK_COL_NAME, id);
715- writer.write(node.toString());
716- }
717- } finally {
718- cursor.closeTopLevel();
719- }
720- return first;
721- }
722-
723-
724- private static UserTable findChildTable(UserTable parent, String childName) {
725- for(Join j : parent.getChildJoins()) {
726- UserTable child = j.getChild();
727- if(child.getName().getTableName().equals(childName)) {
728- return child;
729- }
730- }
731- return null;
732- }
733-
734- private static void removeUnknownFields(UserTable table, JsonNode node) {
735- if(node.isArray()) {
736- Iterator<JsonNode> it = node.elements();
737- while(it.hasNext()) {
738- removeUnknownFields(table, it.next());
739- }
740- }
741- else {
742- Iterator<Map.Entry<String,JsonNode>> fieldIt = node.fields();
743- while(fieldIt.hasNext()) {
744- Map.Entry<String,JsonNode> pair = fieldIt.next();
745- String itName = pair.getKey();
746- JsonNode itNode = pair.getValue();
747- if(itNode.isContainerNode()) {
748- UserTable child = findChildTable(table, itName);
749- if(child != null) {
750- removeUnknownFields(child, itNode);
751- } else {
752- fieldIt.remove();
753- }
754- } else {
755- if(table.getColumn(itName) == null) {
756- fieldIt.remove();
757- }
758- }
759- }
760- }
761- }
762-
763- private static boolean isBuilderTable(UserTable table) {
764- return (table.getColumns().size() == 2) &&
765- EntityParser.PK_COL_NAME.equals(table.getColumn(0).getName()) &&
766- DATA_COL_NAME.equals(table.getColumn(1).getName());
767- }
768-
769- private class ImplodeTracker extends TableRowTracker {
770- private final StringBuilder builder;
771- private final UserTable outTable;
772- private int rowCount = 0;
773- private int curDepth = 0;
774-
775- public ImplodeTracker(UserTable outTable, UserTable inTable, int addlDepth) {
776- super(inTable, addlDepth);
777- assert inTable.isRoot() : "Expected root: " + inTable;
778- this.builder = new StringBuilder();
779- this.outTable = outTable;
780- }
781-
782- public StringBuilder getStringBuilder() {
783- return builder;
784- }
785-
786- public int getRowCount() {
787- return rowCount;
788- }
789-
790- @Override
791- public void pushRowType() {
792- super.pushRowType();
793- ++curDepth;
794- }
795-
796- @Override
797- public void popRowType() {
798- super.popRowType();
799- if(--curDepth == 0) {
800- String json = (builder.charAt(0) == ',') ? builder.substring(1) : builder.toString();
801- ModelBuilder.this.insert(null, outTable.getName(), json);
802- builder.setLength(0);
803- ++rowCount;
804- }
805- }
806- }
807-}
808
809=== modified file 'src/main/java/com/akiban/server/service/restdml/RestDMLService.java'
810--- src/main/java/com/akiban/server/service/restdml/RestDMLService.java 2013-04-17 17:29:33 +0000
811+++ src/main/java/com/akiban/server/service/restdml/RestDMLService.java 2013-07-29 15:32:48 +0000
812@@ -50,6 +50,4 @@
813 TableName procName, Map<String,List<String>> queryParams, String content) throws SQLException;
814
815 public void fullTextSearch(PrintWriter writer, IndexName indexName, Integer depth, String query, Integer limit);
816-
817- public String jonquilToSQL(TableName tableName, String jonquil) throws IOException;
818 }
819
820=== modified file 'src/main/java/com/akiban/server/service/restdml/RestDMLServiceImpl.java'
821--- src/main/java/com/akiban/server/service/restdml/RestDMLServiceImpl.java 2013-07-10 21:42:55 +0000
822+++ src/main/java/com/akiban/server/service/restdml/RestDMLServiceImpl.java 2013-07-29 15:32:48 +0000
823@@ -18,27 +18,17 @@
824 package com.akiban.server.service.restdml;
825
826 import com.akiban.ais.model.AkibanInformationSchema;
827-import com.akiban.ais.model.Column;
828 import com.akiban.ais.model.Index;
829 import com.akiban.ais.model.IndexName;
830-import com.akiban.ais.model.Join;
831-import com.akiban.ais.model.JoinColumn;
832 import com.akiban.ais.model.Routine;
833 import com.akiban.ais.model.TableName;
834 import com.akiban.ais.model.UserTable;
835-import com.akiban.jonquil.Jonquil;
836-import com.akiban.jonquil.JonquilException;
837-import com.akiban.jonquil.JonquilWriter;
838-import com.akiban.jonquil.JoinFields;
839-import com.akiban.jonquil.JoinStrategy;
840-import com.akiban.jonquil.actions.Action;
841 import com.akiban.server.Quote;
842 import com.akiban.server.error.AkibanInternalException;
843 import com.akiban.server.error.InvalidArgumentTypeException;
844 import com.akiban.server.error.WrongExpressionArityException;
845 import com.akiban.server.explain.format.JsonFormatter;
846 import com.akiban.server.service.Service;
847-import com.akiban.server.service.config.ConfigurationService;
848 import com.akiban.server.service.dxl.DXLService;
849 import com.akiban.server.service.externaldata.ExternalDataService;
850 import com.akiban.server.service.externaldata.JsonRowWriter;
851@@ -59,14 +49,7 @@
852 import com.akiban.util.tap.Tap;
853 import com.fasterxml.jackson.core.JsonGenerator;
854 import com.fasterxml.jackson.databind.JsonNode;
855-import com.google.common.base.Function;
856-import com.google.common.base.Functions;
857-import com.google.common.collect.Lists;
858 import com.google.inject.Inject;
859-import org.codehaus.jackson.JsonFactory;
860-import org.codehaus.jackson.JsonParser;
861-import org.codehaus.jackson.JsonToken;
862-import org.codehaus.jackson.map.ObjectMapper;
863
864 import javax.servlet.http.HttpServletRequest;
865
866@@ -78,13 +61,10 @@
867 import java.sql.PreparedStatement;
868 import java.sql.SQLException;
869 import java.sql.Statement;
870-import java.util.Collection;
871 import java.util.Collections;
872-import java.util.HashMap;
873 import java.util.Iterator;
874 import java.util.List;
875 import java.util.Map;
876-import java.util.NoSuchElementException;
877 import java.util.Properties;
878
879 import static com.akiban.server.service.transaction.TransactionService.CloseableTransaction;
880@@ -426,74 +406,6 @@
881 appender.append('}');
882 }
883
884- @Override
885- public String jonquilToSQL(TableName tableName, String jonquil) throws IOException {
886- final AkibanInformationSchema ais;
887- try (Session session = sessionService.createSession();
888- CloseableTransaction txn = transactionService.beginCloseableTransaction(session)) {
889- ais = dxlService.ddlFunctions().getAIS(session);
890- txn.commit();
891- }
892- JsonParser json = oldJsonFactory.createJsonParser(jonquil);
893- final String schema = tableName.getSchemaName();
894- // the JoinStrategy will assume all tables are in the same schema
895- JoinStrategy joinStrategy = new JoinStrategy() {
896- @Override
897- public Collection<? extends JoinFields> getJoins(String parent, String child) {
898- UserTable parentTable = ais.getUserTable(schema, parent);
899- if (parentTable == null)
900- throw new NoSuchElementException("parent table: " + parent);
901- Join groupingJoin = findGroupingJoin(parentTable, child);
902- return Lists.transform(groupingJoin.getJoinColumns(), new Function<JoinColumn, JoinFields>() {
903- @Override
904- public JoinFields apply(JoinColumn input) {
905- return new JoinFields(input.getParent().getName(), input.getChild().getName());
906- }
907- });
908- }
909-
910- private Join findGroupingJoin(UserTable parentTable, String childTable) {
911- for (Join join : parentTable.getChildJoins()) {
912- if (join.getChild().getName().getTableName().equals(childTable))
913- return join;
914- }
915- throw new NoSuchElementException("no child named " + childTable + " for table " + parentTable);
916- }
917- };
918- Map<String, Action> additionalActionsMap = new HashMap<>();
919- additionalActionsMap.put("fields", new Action() {
920- @Override
921- public void apply(JsonParser input, JonquilWriter output, String tableName) throws IOException {
922- JsonToken token = input.nextToken();
923- if (token == JsonToken.VALUE_STRING) {
924- String value = input.getText();
925- if (value.equalsIgnoreCase("all")) {
926- UserTable table = ais.getUserTable(schema, tableName);
927- for (Column column : table.getColumns())
928- output.addScalar(column.getName());
929- }
930- else {
931- throw new JonquilException("illegal string value for @fields (must be \"all\"): " + value);
932- }
933- }
934- else if (token == JsonToken.START_ARRAY) {
935- while (input.nextToken() != JsonToken.END_ARRAY) {
936- if (input.getCurrentToken() != JsonToken.VALUE_STRING) {
937- throw new JonquilException("illegal value for @attributes list: "
938- + input.getText() + " (" + token + ')');
939- }
940- output.addScalar(input.getText());
941- }
942- }
943- else {
944- throw new JonquilException("illegal value for @fields: " + input.getText() + " (" + token + ')');
945- }
946- }
947- });
948- Function<String, Action> additionalActions = Functions.forMap(additionalActionsMap, null);
949- return Jonquil.createSQL(tableName.getTableName(), json, joinStrategy, additionalActions);
950- }
951-
952 public interface ProcessStatement {
953 public Statement processStatement (int index) throws SQLException;
954 }
955@@ -693,6 +605,4 @@
956 ENTITY_TEXT.out();
957 }
958 }
959-
960- private static final JsonFactory oldJsonFactory = new JsonFactory(new ObjectMapper()); // for Jonquil
961 }
962
963=== modified file 'src/main/resources/com/akiban/server/error/error_code.properties'
964--- src/main/resources/com/akiban/server/error/error_code.properties 2013-07-19 19:40:21 +0000
965+++ src/main/resources/com/akiban/server/error/error_code.properties 2013-07-29 15:32:48 +0000
966@@ -251,7 +251,6 @@
967 ALTER_MADE_NO_CHANGE = ALTER TABLE on `{0}.`{1}` made no change to the definition
968 INVALID_ROUTINE = Invalid procedure `{0}.`{1}`: {2}
969 INVALID_INDEX_ID = Index `{0}.`{1}`.`{2}` has an invalid ID: {3}
970-MODEL_BUILDER_ERROR = Error building model for `{0}`.`{1}`: {2}
971 COLUMN_NOT_GENERATED = Column `{0}`.`{1}`.`{2}` is not generated
972 COLUMN_ALREADY_GENERATED = Column `{0}`.`{1}`.`{2}` already generated by sequence `{3}`.`{4}`
973 DROP_SEQUENCE_NOT_ALLOWED = Sequence `{0}` is in use by table `{1}`.`{2}` and can not be dropped
974
975=== modified file 'src/test/java/com/akiban/server/entity/changes/EntityParserIT.java'
976--- src/test/java/com/akiban/server/entity/changes/EntityParserIT.java 2013-04-09 22:15:20 +0000
977+++ src/test/java/com/akiban/server/entity/changes/EntityParserIT.java 2013-07-29 15:32:48 +0000
978@@ -24,8 +24,8 @@
979
980 import java.io.IOException;
981
982+import com.fasterxml.jackson.core.JsonProcessingException;
983 import com.fasterxml.jackson.databind.JsonNode;
984-import org.codehaus.jackson.JsonProcessingException;
985 import org.junit.Before;
986 import org.junit.Test;
987
988
989=== removed file 'src/test/java/com/akiban/server/service/restdml/ModelBuilderIT.java'
990--- src/test/java/com/akiban/server/service/restdml/ModelBuilderIT.java 2013-06-11 16:30:17 +0000
991+++ src/test/java/com/akiban/server/service/restdml/ModelBuilderIT.java 1970-01-01 00:00:00 +0000
992@@ -1,333 +0,0 @@
993-/**
994- * Copyright (C) 2009-2013 Akiban Technologies, Inc.
995- *
996- * This program is free software: you can redistribute it and/or modify
997- * it under the terms of the GNU Affero General Public License as published by
998- * the Free Software Foundation, either version 3 of the License, or
999- * (at your option) any later version.
1000- *
1001- * This program is distributed in the hope that it will be useful,
1002- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1003- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1004- * GNU Affero General Public License for more details.
1005- *
1006- * You should have received a copy of the GNU Affero General Public License
1007- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1008- */
1009-
1010-package com.akiban.server.service.restdml;
1011-
1012-import com.akiban.ais.model.TableName;
1013-import com.akiban.ais.model.UserTable;
1014-import com.akiban.server.entity.changes.EntityParser;
1015-import com.akiban.server.error.ModelBuilderException;
1016-import com.akiban.server.error.NoSuchTableException;
1017-import com.akiban.server.service.servicemanager.GuicedServiceManager;
1018-import com.akiban.server.test.it.ITBase;
1019-import com.akiban.util.JsonUtils;
1020-import com.fasterxml.jackson.databind.JsonNode;
1021-import org.junit.Before;
1022-import org.junit.Test;
1023-
1024-import java.io.IOException;
1025-import java.io.PrintWriter;
1026-import java.io.StringWriter;
1027-import java.io.Writer;
1028-import java.util.Arrays;
1029-import java.util.Map;
1030-import java.util.Set;
1031-import java.util.TreeSet;
1032-
1033-import static org.junit.Assert.assertEquals;
1034-import static org.junit.Assert.assertFalse;
1035-import static org.junit.Assert.assertNotNull;
1036-import static org.junit.Assert.assertTrue;
1037-
1038-public class ModelBuilderIT extends ITBase {
1039- private static final String SCHEMA = "test";
1040- private static final String TABLE = "t";
1041- private static final TableName TABLE_NAME = new TableName(SCHEMA, TABLE);
1042- private static final String SIMPLE_JSON_1 = "{ \"name\": \"foo\" }";
1043- private static final String SIMPLE_JSON_2 = "{ \"year\": \"2013\" }";
1044-
1045- private static final PrintWriter NULL_WRITER = new PrintWriter(new Writer() {
1046- @Override
1047- public void write(char[] cbuf, int off, int len) {
1048- }
1049-
1050- @Override
1051- public void flush() throws IOException {
1052- }
1053-
1054- @Override
1055- public void close() throws IOException {
1056- }
1057- });
1058-
1059-
1060- private ModelBuilder builder;
1061-
1062- @Override
1063- protected GuicedServiceManager.BindingsConfigurationProvider serviceBindingsProvider() {
1064- return super.serviceBindingsProvider()
1065- .bindAndRequire(RestDMLService.class, RestDMLServiceImpl.class);
1066- }
1067-
1068- @Override
1069- protected Map<String, String> startupConfigProperties() {
1070- return uniqueStartupConfigProperties(ModelBuilderIT.class);
1071- }
1072-
1073- @Before
1074- public void createBuilder() {
1075- RestDMLService restDMLService = serviceManager().getServiceByClass(RestDMLService.class);
1076- builder = new ModelBuilder(
1077- serviceManager().getSessionService(),
1078- txnService(),
1079- dxl(),
1080- store(),
1081- restDMLService
1082- );
1083- }
1084-
1085-
1086- @Test
1087- public void create() {
1088- builder.create(TABLE_NAME);
1089- assertNotNull("Created table", getUserTable(TABLE_NAME));
1090- }
1091-
1092- @Test
1093- public void createAndCheckIsBuilderTable() {
1094- builder.create(TABLE_NAME);
1095- assertTrue("Is builder table", builder.isBuilderTable(TABLE_NAME));
1096- }
1097-
1098- @Test
1099- public void isNotBuilderTable() {
1100- createTable(SCHEMA, TABLE, "foo int");
1101- assertFalse("Is builder table", builder.isBuilderTable(TABLE_NAME));
1102- }
1103-
1104- @Test
1105- public void createMulti() {
1106- builder.create(TABLE_NAME);
1107- builder.create(TABLE_NAME);
1108- assertTrue("Is builder table", builder.isBuilderTable(TABLE_NAME));
1109- }
1110-
1111- @Test
1112- public void insertCreates() {
1113- builder.insert(NULL_WRITER, TABLE_NAME, SIMPLE_JSON_1);
1114- assertNotNull("Table exists after insert", getUserTable(TABLE_NAME));
1115- }
1116-
1117- @Test
1118- public void insertAndCheckRow() {
1119- builder.insert(NULL_WRITER, TABLE_NAME, SIMPLE_JSON_1);
1120- updateAISGeneration();
1121- int id = tableId(TABLE_NAME);
1122- expectFullRows(id, createNewRow(id, 1L, SIMPLE_JSON_1));
1123- }
1124-
1125- @Test
1126- public void updateNoMatchCreates() {
1127- builder.update(NULL_WRITER, TABLE_NAME, "1", SIMPLE_JSON_1);
1128- assertNotNull("Table exists after insert", getUserTable(TABLE_NAME));
1129- }
1130-
1131- @Test
1132- public void insertUpdateCheckRow() {
1133- builder.insert(NULL_WRITER, TABLE_NAME, SIMPLE_JSON_1);
1134- builder.update(NULL_WRITER, TABLE_NAME, "1", SIMPLE_JSON_2);
1135- updateAISGeneration();
1136- int id = tableId(TABLE_NAME);
1137- expectFullRows(id, createNewRow(id, 1L, SIMPLE_JSON_2));
1138- }
1139-
1140- @Test
1141- public void explodeSingleRow() throws IOException {
1142- builder.insert(NULL_WRITER, TABLE_NAME, SIMPLE_JSON_1);
1143- builder.explode(NULL_WRITER, TABLE_NAME);
1144- updateAISGeneration();
1145- expectTables(TABLE);
1146- UserTable table = getUserTable(TABLE_NAME);
1147- assertEquals("Column count", 2, table.getColumns().size());
1148- assertEquals("Column 0", EntityParser.PK_COL_NAME, table.getColumn(0).getName());
1149- assertEquals("Column 1", "name", table.getColumn(1).getName());
1150- expectFullRows(table.getTableId(), createNewRow(table.getTableId(), 1L, "foo"));
1151- }
1152-
1153- @Test
1154- public void explodeMultiRowDifferentShapes() throws IOException {
1155- builder.insert(NULL_WRITER, TABLE_NAME, SIMPLE_JSON_1);
1156- builder.insert(NULL_WRITER, TABLE_NAME, SIMPLE_JSON_2);
1157- builder.explode(NULL_WRITER, TABLE_NAME);
1158- updateAISGeneration();
1159- expectTables(TABLE);
1160- UserTable table = getUserTable(TABLE_NAME);
1161- assertEquals("Column count", 2, table.getColumns().size());
1162- assertEquals("Column 0", EntityParser.PK_COL_NAME, table.getColumn(0).getName());
1163- assertEquals("Column 1", "year", table.getColumn(1).getName());
1164- expectFullRows(
1165- table.getTableId(),
1166- createNewRow(table.getTableId(), 1L, null),
1167- createNewRow(table.getTableId(), 2L, "2013")
1168- );
1169- }
1170-
1171- @Test
1172- public void explodeMultiLevelDifferentShapes() throws IOException {
1173- builder.insert(NULL_WRITER, TABLE_NAME, "{\"a\": 5}");
1174- builder.insert(NULL_WRITER, TABLE_NAME, "{\"a\": \"five\", \"b\": 10}");
1175- builder.insert(NULL_WRITER, TABLE_NAME, "{\"a\": \"six\", \"bs\": [{ \"x\" : 10}]}");
1176- builder.insert(NULL_WRITER, TABLE_NAME, "{\"a\": \"seven\", \"bs\": [{ \"y\" : 20}]}");
1177- builder.explode(NULL_WRITER, TABLE_NAME);
1178- updateAISGeneration();
1179- expectTables("bs", TABLE);
1180- int tid = tableId(TABLE_NAME);
1181- expectFullRows(
1182- tid,
1183- createNewRow(tid, 1L, "5"),
1184- createNewRow(tid, 2L, "five"),
1185- createNewRow(tid, 3L, "six"),
1186- createNewRow(tid, 4L, "seven")
1187- );
1188- int bsid = tableId(SCHEMA, "bs");
1189- expectFullRows(
1190- bsid,
1191- createNewRow(bsid, 1L, null, 3L),
1192- createNewRow(bsid, 2L, 20L, 4L)
1193- );
1194- }
1195-
1196- @Test
1197- public void implodeEmptyTable() {
1198- createTable(SCHEMA, TABLE, "foo int, bar int, zap int");
1199- builder.implode(NULL_WRITER, TABLE_NAME);
1200- expectTables(TABLE);
1201- assertTrue("Is builder table", builder.isBuilderTable(TABLE_NAME));
1202- }
1203-
1204- @Test
1205- public void implodeWithRows() {
1206- int id = createTable(SCHEMA, TABLE, "name varchar(32)");
1207- writeRow(id, "foo");
1208- writeRow(id, new Object[]{null});
1209- writeRow(id, "bar");
1210- builder.implode(NULL_WRITER, TABLE_NAME);
1211- updateAISGeneration();
1212- assertTrue("Is builder table", builder.isBuilderTable(TABLE_NAME));
1213- id = tableId(TABLE_NAME);
1214- expectFullRows(
1215- id,
1216- createNewRow(id, 1L, "{\"name\":\"foo\"}"),
1217- createNewRow(id, 2L, "{\"name\":null}"),
1218- createNewRow(id, 3L, "{\"name\":\"bar\"}")
1219- );
1220- }
1221-
1222- @Test
1223- public void insertExplodeImplode() throws IOException {
1224- builder.insert(NULL_WRITER, TABLE_NAME, SIMPLE_JSON_1);
1225- int tid = tableId(TABLE_NAME);
1226- updateAISGeneration();
1227- expectFullRows(tid, createNewRow(tid, 1L, SIMPLE_JSON_1));
1228-
1229- builder.explode(NULL_WRITER, TABLE_NAME);
1230- tid = tableId(TABLE_NAME);
1231- updateAISGeneration();
1232- expectFullRows(tid, createNewRow(tid, 1L, "foo"));
1233-
1234- builder.implode(NULL_WRITER, TABLE_NAME);
1235- tid = tableId(TABLE_NAME);
1236- updateAISGeneration();
1237- // Same contents, but ID is present and server didn't output spaces
1238- String expected = ("{\"_id\": 1," + SIMPLE_JSON_1.substring(1)).replaceAll(" ", "");
1239- expectFullRows(tid, createNewRow(tid, 1L, expected));
1240- }
1241-
1242- @Test
1243- public void getAll() throws IOException {
1244- builder.insert(NULL_WRITER, TABLE_NAME, SIMPLE_JSON_1);
1245- builder.insert(NULL_WRITER, TABLE_NAME, SIMPLE_JSON_1);
1246-
1247- StringWriter writer = new StringWriter();
1248- PrintWriter pw = new PrintWriter(writer);
1249- builder.getAll(pw, TABLE_NAME);
1250-
1251- String output = writer.toString();
1252- JsonNode node = JsonUtils.readTree(output);
1253- assertTrue("Array node type", node.isArray());
1254- assertEquals("Array size", 2, node.size());
1255- for(int i = 0; i < node.size(); ++i) {
1256- JsonNode subNode = node.get(i);
1257- assertEquals("field count", 2, subNode.size());
1258- assertEquals("id value", i+1, subNode.get(EntityParser.PK_COL_NAME).asInt());
1259- assertEquals("name value", "foo", subNode.get("name").asText());
1260- }
1261- }
1262-
1263- @Test
1264- public void getKeys() throws IOException {
1265- builder.insert(NULL_WRITER, TABLE_NAME, SIMPLE_JSON_1);
1266- builder.insert(NULL_WRITER, TABLE_NAME, SIMPLE_JSON_1);
1267-
1268- StringWriter writer = new StringWriter();
1269- PrintWriter pw = new PrintWriter(writer);
1270- builder.getKeys(pw, TABLE_NAME, "2");
1271-
1272- String output = writer.toString();
1273- JsonNode node = JsonUtils.readTree(output);
1274- assertTrue("Array node type", node.isArray());
1275- assertEquals("Array size", 1, node.size());
1276- JsonNode subNode = node.get(0);
1277- assertEquals("field count", 2, subNode.size());
1278- assertEquals("id value", 2, subNode.get(EntityParser.PK_COL_NAME).asInt());
1279- assertEquals("name value", "foo", subNode.get("name").asText());
1280- }
1281-
1282- @Test(expected=ModelBuilderException.class)
1283- public void implodeBuilderTable() {
1284- builder.create(TABLE_NAME);
1285- builder.implode(NULL_WRITER, TABLE_NAME);
1286- }
1287-
1288- @Test(expected=NoSuchTableException.class)
1289- public void implodeNoSuchTable() {
1290- builder.implode(NULL_WRITER, TABLE_NAME);
1291- }
1292-
1293- @Test(expected=ModelBuilderException.class)
1294- public void explodeEmpty() throws IOException {
1295- builder.create(TABLE_NAME);
1296- builder.explode(NULL_WRITER, TABLE_NAME);
1297- }
1298-
1299- @Test(expected=NoSuchTableException.class)
1300- public void explodeNoSuchTable() throws IOException {
1301- builder.explode(NULL_WRITER, TABLE_NAME);
1302- }
1303-
1304- @Test(expected=NoSuchTableException.class)
1305- public void checkNoSuchTable() {
1306- builder.isBuilderTable(TABLE_NAME);
1307- }
1308-
1309- @Test(expected=ModelBuilderException.class)
1310- public void createConflictsExisting() {
1311- createTable(SCHEMA, TABLE, "foo int");
1312- builder.create(TABLE_NAME);
1313- }
1314-
1315-
1316- private void expectTables(String... names) {
1317- Set<String> nameSet = new TreeSet<>();
1318- nameSet.addAll(Arrays.asList(names));
1319- assertEquals(
1320- "Tables in schema",
1321- nameSet.toString(),
1322- ais().getSchema(SCHEMA).getUserTables().keySet().toString()
1323- );
1324- }
1325-}
1326
1327=== removed file 'src/test/resources/com/akiban/rest/caoi/builder-implode.body'
1328=== removed file 'src/test/resources/com/akiban/rest/caoi/builder-implode.check'
1329--- src/test/resources/com/akiban/rest/caoi/builder-implode.check 2013-03-26 20:32:58 +0000
1330+++ src/test/resources/com/akiban/rest/caoi/builder-implode.check 1970-01-01 00:00:00 +0000
1331@@ -1,1 +0,0 @@
1332-/builder/entity/test.customers
1333\ No newline at end of file
1334
1335=== removed file 'src/test/resources/com/akiban/rest/caoi/builder-implode.check_expected'
1336--- src/test/resources/com/akiban/rest/caoi/builder-implode.check_expected 2013-04-15 21:43:37 +0000
1337+++ src/test/resources/com/akiban/rest/caoi/builder-implode.check_expected 1970-01-01 00:00:00 +0000
1338@@ -1,68 +0,0 @@
1339-[
1340- {
1341- "cid": 1,
1342- "first_name": "John",
1343- "last_name": "Smith",
1344- "addresses": [
1345- {
1346- "aid": 101,
1347- "cid": 1,
1348- "state": "MA",
1349- "city": "Boston"
1350- }
1351- ],
1352- "orders": [
1353- {
1354- "oid": 101,
1355- "cid": 1,
1356- "odate": "2011-03-01 00:00:00",
1357- "items": [
1358- {
1359- "iid": 1011,
1360- "oid": 101,
1361- "sku": 1234
1362- },
1363- {
1364- "iid": 1012,
1365- "oid": 101,
1366- "sku": 4567
1367- }
1368- ]
1369- },
1370- {
1371- "oid": 102,
1372- "cid": 1,
1373- "odate": "2011-03-02 00:00:00"
1374- }
1375- ],
1376- "_id": 1
1377- },
1378- {
1379- "cid": 2,
1380- "first_name": "Willy",
1381- "last_name": "Jones",
1382- "addresses": [
1383- {
1384- "aid": 201,
1385- "cid": 2,
1386- "state": "NY",
1387- "city": "New York"
1388- }
1389- ],
1390- "orders": [
1391- {
1392- "oid": 201,
1393- "cid": 2,
1394- "odate": "2011-03-03 00:00:00",
1395- "items": [
1396- {
1397- "iid": 2011,
1398- "oid": 201,
1399- "sku": 9876
1400- }
1401- ]
1402- }
1403- ],
1404- "_id": 2
1405- }
1406-]
1407\ No newline at end of file
1408
1409=== removed file 'src/test/resources/com/akiban/rest/caoi/builder-implode.expected'
1410--- src/test/resources/com/akiban/rest/caoi/builder-implode.expected 2013-03-26 20:32:58 +0000
1411+++ src/test/resources/com/akiban/rest/caoi/builder-implode.expected 1970-01-01 00:00:00 +0000
1412@@ -1,4 +0,0 @@
1413-{
1414- "imploded": "customers",
1415- "rows":2
1416-}
1417\ No newline at end of file
1418
1419=== removed file 'src/test/resources/com/akiban/rest/caoi/builder-implode.post'
1420--- src/test/resources/com/akiban/rest/caoi/builder-implode.post 2013-03-26 20:32:58 +0000
1421+++ src/test/resources/com/akiban/rest/caoi/builder-implode.post 1970-01-01 00:00:00 +0000
1422@@ -1,1 +0,0 @@
1423-/builder/implode/test.customers
1424\ No newline at end of file
1425
1426=== removed file 'src/test/resources/com/akiban/rest/caoi/builder-insert.body'
1427--- src/test/resources/com/akiban/rest/caoi/builder-insert.body 2013-03-26 20:32:58 +0000
1428+++ src/test/resources/com/akiban/rest/caoi/builder-insert.body 1970-01-01 00:00:00 +0000
1429@@ -1,4 +0,0 @@
1430-{
1431- "name": "joe",
1432- "age": 30
1433-}
1434\ No newline at end of file
1435
1436=== removed file 'src/test/resources/com/akiban/rest/caoi/builder-insert.check'
1437--- src/test/resources/com/akiban/rest/caoi/builder-insert.check 2013-04-15 21:43:37 +0000
1438+++ src/test/resources/com/akiban/rest/caoi/builder-insert.check 1970-01-01 00:00:00 +0000
1439@@ -1,1 +0,0 @@
1440-/builder/entity/test.foo/1
1441\ No newline at end of file
1442
1443=== removed file 'src/test/resources/com/akiban/rest/caoi/builder-insert.check_expected'
1444--- src/test/resources/com/akiban/rest/caoi/builder-insert.check_expected 2013-04-15 21:43:37 +0000
1445+++ src/test/resources/com/akiban/rest/caoi/builder-insert.check_expected 1970-01-01 00:00:00 +0000
1446@@ -1,7 +0,0 @@
1447-[
1448- {
1449- "_id": 1,
1450- "name": "joe",
1451- "age": 30
1452- }
1453-]
1454\ No newline at end of file
1455
1456=== removed file 'src/test/resources/com/akiban/rest/caoi/builder-insert.expected'
1457--- src/test/resources/com/akiban/rest/caoi/builder-insert.expected 2013-03-26 20:32:58 +0000
1458+++ src/test/resources/com/akiban/rest/caoi/builder-insert.expected 1970-01-01 00:00:00 +0000
1459@@ -1,3 +0,0 @@
1460-{
1461- "_id": 1
1462-}
1463\ No newline at end of file
1464
1465=== removed file 'src/test/resources/com/akiban/rest/caoi/builder-insert.post'
1466--- src/test/resources/com/akiban/rest/caoi/builder-insert.post 2013-03-26 20:32:58 +0000
1467+++ src/test/resources/com/akiban/rest/caoi/builder-insert.post 1970-01-01 00:00:00 +0000
1468@@ -1,1 +0,0 @@
1469-/builder/entity/test.foo
1470\ No newline at end of file
1471
1472=== removed file 'src/test/resources/com/akiban/rest/caoi/c1-jonquil-query.body'
1473--- src/test/resources/com/akiban/rest/caoi/c1-jonquil-query.body 2013-04-05 15:56:11 +0000
1474+++ src/test/resources/com/akiban/rest/caoi/c1-jonquil-query.body 1970-01-01 00:00:00 +0000
1475@@ -1,9 +0,0 @@
1476-{
1477- "first_name": [],
1478- "orders": {
1479- "@fields": "all",
1480- "items": {
1481- "@fields": "all"
1482- }
1483- }
1484-}
1485
1486=== removed file 'src/test/resources/com/akiban/rest/caoi/c1-jonquil-query.expected'
1487--- src/test/resources/com/akiban/rest/caoi/c1-jonquil-query.expected 2013-04-05 15:56:11 +0000
1488+++ src/test/resources/com/akiban/rest/caoi/c1-jonquil-query.expected 1970-01-01 00:00:00 +0000
1489@@ -1,46 +0,0 @@
1490-[
1491- {
1492- "first_name": "John",
1493- "orders": [
1494- {
1495- "items": [
1496- {
1497- "sku": 1234,
1498- "iid": 1011,
1499- "oid": 101
1500- },
1501- {
1502- "sku": 4567,
1503- "iid": 1012,
1504- "oid": 101
1505- }
1506- ],
1507- "oid": 101,
1508- "odate": "2011-03-01 00:00:00",
1509- "cid": 1
1510- },
1511- {
1512- "oid": 102,
1513- "odate": "2011-03-02 00:00:00",
1514- "cid": 1
1515- }
1516- ]
1517- },
1518- {
1519- "first_name": "Willy",
1520- "orders": [
1521- {
1522- "items": [
1523- {
1524- "sku": 9876,
1525- "iid": 2011,
1526- "oid": 201
1527- }
1528- ],
1529- "oid": 201,
1530- "odate": "2011-03-03 00:00:00",
1531- "cid": 2
1532- }
1533- ]
1534- }
1535-]
1536
1537=== removed file 'src/test/resources/com/akiban/rest/caoi/c1-jonquil-query.post'
1538--- src/test/resources/com/akiban/rest/caoi/c1-jonquil-query.post 2013-04-05 15:56:11 +0000
1539+++ src/test/resources/com/akiban/rest/caoi/c1-jonquil-query.post 1970-01-01 00:00:00 +0000
1540@@ -1,1 +0,0 @@
1541-/entity/test.customers/jonquil/query
1542
1543=== removed file 'src/test/resources/com/akiban/rest/caoi/c1-jonquil-tosql.body'
1544--- src/test/resources/com/akiban/rest/caoi/c1-jonquil-tosql.body 2013-04-05 15:56:11 +0000
1545+++ src/test/resources/com/akiban/rest/caoi/c1-jonquil-tosql.body 1970-01-01 00:00:00 +0000
1546@@ -1,9 +0,0 @@
1547-{
1548- "first_name": [],
1549- "orders": {
1550- "@fields": "all",
1551- "items": {
1552- "sku": 123
1553- }
1554- }
1555-}
1556
1557=== removed file 'src/test/resources/com/akiban/rest/caoi/c1-jonquil-tosql.expected'
1558--- src/test/resources/com/akiban/rest/caoi/c1-jonquil-tosql.expected 2013-04-05 15:56:11 +0000
1559+++ src/test/resources/com/akiban/rest/caoi/c1-jonquil-tosql.expected 1970-01-01 00:00:00 +0000
1560@@ -1,1 +0,0 @@
1561-SELECT "first_name", (SELECT "oid", "cid", "odate", (SELECT "sku" FROM "items" WHERE "sku"=123 AND "orders"."oid" = "items"."oid") "items" FROM "orders" WHERE "customers"."cid" = "orders"."cid") "orders" FROM "customers"
1562\ No newline at end of file
1563
1564=== removed file 'src/test/resources/com/akiban/rest/caoi/c1-jonquil-tosql.post'
1565--- src/test/resources/com/akiban/rest/caoi/c1-jonquil-tosql.post 2013-04-05 15:56:11 +0000
1566+++ src/test/resources/com/akiban/rest/caoi/c1-jonquil-tosql.post 1970-01-01 00:00:00 +0000
1567@@ -1,1 +0,0 @@
1568-/entity/test.customers/jonquil/to-sql

Subscribers

People subscribed via source and target branches