/* * Copyright (c) 2016 Couchbase, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.couchbase.client.java; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.util.Collections; import java.util.List; import java.util.ArrayList; import java.util.UUID; import com.couchbase.client.java.document.JsonDocument; import com.couchbase.client.java.document.json.JsonObject; import com.couchbase.client.java.error.TemporaryFailureException; import com.couchbase.client.java.query.AsyncN1qlQueryResult; import com.couchbase.client.java.query.AsyncN1qlQueryRow; import com.couchbase.client.java.query.DefaultN1qlQueryResult; import com.couchbase.client.java.query.N1qlMetrics; import com.couchbase.client.java.query.N1qlParams; import com.couchbase.client.java.query.N1qlQuery; import com.couchbase.client.java.query.N1qlQueryResult; import com.couchbase.client.java.query.N1qlQueryRow; import com.couchbase.client.java.query.consistency.ScanConsistency; import com.couchbase.client.java.query.core.N1qlQueryExecutor; import com.couchbase.client.java.util.CouchbaseTestContext; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import rx.Observable; import rx.functions.Func1; import rx.functions.Func7; /** * Integration tests of the N1QL Query features. * * @author Simon Baslé * @since 2.1 */ public class N1qlPreparedTest { private static CouchbaseTestContext ctx; private static final ScanConsistency CONSISTENCY = ScanConsistency.REQUEST_PLUS; private static N1qlQueryExecutor executor; private static int count = 0; @BeforeClass public static void init() throws InterruptedException { ctx = CouchbaseTestContext.builder() .adhoc(true) .bucketName("N1qlPrepared") .bucketQuota(100) .build() .ignoreIfNoN1ql() .ensurePrimaryIndex(); executor = new N1qlQueryExecutor(ctx.cluster().core(), ctx.bucketName(), ctx.bucketPassword(), false); final JsonObject jsonObject = JsonObject.create(); for (int i=0; i < 10; i++) { jsonObject.put("field" + i, UUID.randomUUID().toString()); } List<String> keys = new ArrayList<String>(); for (int i=0; i < 15000; i++) { keys.add("Key" + i); } List<JsonDocument> documents = Observable.from(keys) .flatMap(new Func1<String, Observable<JsonDocument>>() { @Override public Observable<JsonDocument> call(String key) { return ctx.bucket().async().upsert(JsonDocument.create(key, jsonObject)) ; } }) .onErrorResumeNext(new Func1<Throwable, Observable<JsonDocument>>() { @Override public Observable<JsonDocument> call(Throwable throwable) { if (throwable instanceof TemporaryFailureException) { return Observable.empty(); } else { return Observable.error(throwable); } } }) .toList() .toBlocking() .single(); count = documents.size(); assertTrue(count >= 10000); } @AfterClass public static void cleanup() { ctx.destroyBucketAndDisconnect(); } public static N1qlQueryResult query(N1qlQuery query) { return executor.execute(query) .flatMap(new Func1<AsyncN1qlQueryResult, Observable<N1qlQueryResult>>() { @Override public Observable<N1qlQueryResult> call(AsyncN1qlQueryResult aqr) { final boolean parseSuccess = aqr.parseSuccess(); final String requestId = aqr.requestId(); final String clientContextId = aqr.clientContextId(); return Observable.zip(aqr.rows().toList(), aqr.signature().singleOrDefault(JsonObject.empty()), aqr.info().singleOrDefault(N1qlMetrics.EMPTY_METRICS), aqr.errors().toList(), aqr.profileInfo().singleOrDefault(JsonObject.empty()), aqr.status(), aqr.finalSuccess().singleOrDefault(Boolean.FALSE), new Func7<List<AsyncN1qlQueryRow>, Object, N1qlMetrics, List<JsonObject>, JsonObject, String, Boolean, N1qlQueryResult>() { @Override public N1qlQueryResult call(List<AsyncN1qlQueryRow> rows, Object signature, N1qlMetrics info, List<JsonObject> errors, JsonObject profileInfo, String finalStatus, Boolean finalSuccess) { return new DefaultN1qlQueryResult(rows, signature, info, errors, profileInfo, finalStatus, finalSuccess, parseSuccess, requestId, clientContextId); } }); } }).toBlocking().singleOrDefault(null); } @Test public void testPreparedWithEncodedPlanDisabledExecutor() { N1qlQuery query = N1qlQuery.simple("SELECT * FROM `" + ctx.bucketName() + "` limit 2", N1qlParams.build().consistency(CONSISTENCY).adhoc(false)); N1qlQueryResult result = query(query); //this uses the executor with encodedPlan forcefully disabled List<N1qlQueryRow> list = result.allRows(); List<JsonObject> errors = result.errors(); assertEquals("error during first iteration: " + errors, Collections.emptyList(), errors); assertEquals("result set too small during first iteration", 2, list.size()); System.out.println("Prepare and execute: " + result.info().executionTime()); result = ctx.bucket().query(query); list = result.allRows(); errors = result.errors(); assertEquals("error during second iteration: " + errors, Collections.emptyList(), errors); assertEquals("result set too small during second iteration", 2, list.size()); } @Test public void testLongRunningPreparedQuery() { int fetzhSz = 10000; N1qlQuery query = N1qlQuery.simple("select * from `"+ ctx.bucketName() +"` limit " + fetzhSz, N1qlParams.build().adhoc(false)); N1qlQueryResult result = ctx.bucket().query(query); System.out.println("Elapsed time:" + result.info().elapsedTime()); assertEquals("Did not fetch all results", result.allRows().size(), fetzhSz); } }