Skip to content

Commit 5521283

Browse files
authored
Merge pull request #225 from dearrudam/issue-381-382
Create integration tests on the repositories databases[Couchbase]
2 parents d958f83 + 3c1eb54 commit 5521283

19 files changed

+983
-218
lines changed

CHANGELOG.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ and this project adheres to https://semver.org/spec/v2.0.0.html[Semantic Version
2121

2222
- Fix the ArangoDBDocumentManager implementation to shut down the ArangoDB instance.
2323
- Fix integration on MongoDBTemplate
24+
- Fix DocumentQuery conversion to the N1QLQuery in order to follow the N1QL spec regarding identifiers declarations
2425

2526
== [1.0.0-b6] - 2023-03-11
2627

jnosql-couchbase/src/main/java/org/eclipse/jnosql/databases/couchbase/communication/CouchbaseBucketManager.java

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import java.time.Duration;
2929
import java.util.Optional;
30+
import java.util.function.Supplier;
3031

3132
import static java.util.Objects.requireNonNull;
3233
import static java.util.stream.Collectors.toList;
@@ -67,8 +68,7 @@ public String name() {
6768
public <K, V> void put(K key, V value) {
6869
requireNonNull(key, "key is required");
6970
requireNonNull(value, "value is required");
70-
collection.upsert(key.toString(), value);
71-
71+
waitBucketBeReadyAndGet(() -> collection.upsert(key.toString(), value));
7272
}
7373

7474
@Override
@@ -78,13 +78,14 @@ public void put(KeyValueEntity entity) throws NullPointerException {
7878
}
7979

8080
@Override
81-
public void put(KeyValueEntity entity, Duration ttl) {
81+
public void put(final KeyValueEntity entity, final Duration ttl) {
8282
requireNonNull(entity, "entity is required");
8383
requireNonNull(ttl, "ttl is required");
84-
String key = entity.key(String.class);
85-
Object value = convert(Value.of(entity.value()));
86-
collection.upsert(key, value, UpsertOptions.upsertOptions().expiry(ttl));
87-
84+
waitBucketBeReadyAndDo(() -> {
85+
String key = entity.key(String.class);
86+
Object value = convert(Value.of(entity.value()));
87+
collection.upsert(key, value, UpsertOptions.upsertOptions().expiry(ttl));
88+
});
8889
}
8990

9091
@Override
@@ -104,8 +105,10 @@ public void put(Iterable<KeyValueEntity> keyValueEntities, Duration ttl) {
104105
public <K> Optional<Value> get(K key) throws NullPointerException {
105106
requireNonNull(key, "key is required");
106107
try {
107-
GetResult result = this.collection.get(key.toString());
108-
return Optional.of(new CouchbaseValue(result));
108+
return waitBucketBeReadyAndGet(() -> {
109+
GetResult result = this.collection.get(key.toString());
110+
return Optional.of(new CouchbaseValue(result));
111+
});
109112
} catch (DocumentNotFoundException exp) {
110113
return Optional.empty();
111114
}
@@ -124,9 +127,21 @@ public <K> Iterable<Value> get(Iterable<K> keys) {
124127
@Override
125128
public <K> void delete(K key) {
126129
requireNonNull(key, "key is required");
127-
collection.remove(key.toString());
130+
waitBucketBeReadyAndDo(() -> collection.remove(key.toString()));
131+
}
132+
133+
private void waitBucketBeReadyAndDo(Runnable runnable) {
134+
bucket.waitUntilReady(bucket.environment().timeoutConfig().kvDurableTimeout());
135+
runnable.run();
128136
}
129137

138+
139+
private <T> T waitBucketBeReadyAndGet(Supplier<T> supplier) {
140+
bucket.waitUntilReady(bucket.environment().timeoutConfig().kvDurableTimeout());
141+
return supplier.get();
142+
}
143+
144+
130145
@Override
131146
public <K> void delete(Iterable<K> keys) {
132147
requireNonNull(keys, "keys is required");

jnosql-couchbase/src/main/java/org/eclipse/jnosql/databases/couchbase/communication/CouchbaseConfiguration.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
import org.eclipse.jnosql.communication.Configurations;
1919
import org.eclipse.jnosql.communication.Settings;
2020

21-
import java.util.ArrayList;
22-
import java.util.List;
21+
import java.util.LinkedHashSet;
2322
import java.util.Objects;
23+
import java.util.Set;
2424
import java.util.stream.Stream;
2525

2626
import static java.util.Arrays.asList;
@@ -41,7 +41,7 @@ public abstract class CouchbaseConfiguration {
4141
protected String index;
4242

4343
protected String collection;
44-
protected List<String> collections = new ArrayList<>();
44+
protected Set<String> collections = new LinkedHashSet<>();
4545

4646

4747
protected void update(Settings settings) {
@@ -75,8 +75,8 @@ private String getIndex(Settings settings) {
7575
.map(Object::toString).orElse(null);
7676
}
7777

78-
private List<String> getCollections(Settings settings) {
79-
List<String> collections = new ArrayList<>();
78+
private Set<String> getCollections(Settings settings) {
79+
Set<String> collections = new LinkedHashSet<>();
8080
settings.get(CouchbaseConfigurations.COLLECTIONS)
8181
.map(Object::toString).stream()
8282
.flatMap(s -> Stream.of(s.split(",\\s*")))
@@ -159,7 +159,7 @@ public void addCollection(String collection) {
159159
*/
160160
public CouchbaseSettings toCouchbaseSettings() {
161161
return new CouchbaseSettings(this.host, this.user, this.password,
162-
this.scope, this.index, this.collection, this.collections);
162+
this.scope, this.index, this.collection, this.collections.stream().toList());
163163
}
164164

165165
@Override

jnosql-couchbase/src/main/java/org/eclipse/jnosql/databases/couchbase/communication/CouchbaseSettings.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,15 +157,15 @@ public void setUp(String database) {
157157
Objects.requireNonNull(database, "database is required");
158158

159159
long start = System.currentTimeMillis();
160-
LOGGER.log(Level.FINEST, "starting the setup with database: " + database);
160+
LOGGER.log(Level.FINEST, "starting the setup with database: " + database);
161161

162162
try (Cluster cluster = getCluster()) {
163163

164164
BucketManager buckets = cluster.buckets();
165165
try {
166166
buckets.getBucket(database);
167167
} catch (BucketNotFoundException exp) {
168-
LOGGER.log(Level.FINEST, "The database/bucket does not exist, creating it: " + database);
168+
LOGGER.log(Level.FINEST, "The database/bucket does not exist, creating it: " + database);
169169
buckets.createBucket(BucketSettings.create(database));
170170
}
171171
Bucket bucket = cluster.bucket(database);
@@ -190,11 +190,24 @@ public void setUp(String database) {
190190
queryIndexManager.createPrimaryIndex(database, createPrimaryQueryIndexOptions()
191191
.scopeName(finalScope).collectionName(index));
192192
}
193+
194+
for (String collection : collections) {
195+
queryIndexManager = cluster.queryIndexes();
196+
indexes = queryIndexManager.getAllIndexes(database, getAllQueryIndexesOptions()
197+
.scopeName(finalScope).collectionName(collection));
198+
if (indexes.isEmpty()) {
199+
LOGGER.log(Level.FINEST, "Index for " + collection + " collection does not exist, creating primary key with scope "
200+
+ scope + " collection " + collection + " at database " + database);
201+
queryIndexManager.createPrimaryIndex(database, createPrimaryQueryIndexOptions()
202+
.scopeName(finalScope).collectionName(collection));
203+
}
204+
}
205+
193206
}
194207

195208
long end = System.currentTimeMillis() - start;
196-
LOGGER.log(Level.FINEST, "Finished the setup with database: " + database + " end with millis "
197-
+ end);
209+
LOGGER.log(Level.FINEST, "Finished the setup with database: " + database + " end with millis "
210+
+ end);
198211
}
199212
}
200213

jnosql-couchbase/src/main/java/org/eclipse/jnosql/databases/couchbase/communication/DefaultCouchbaseDocumentManager.java

Lines changed: 81 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import java.util.ArrayList;
3434
import java.util.List;
3535
import java.util.Objects;
36+
import java.util.function.Supplier;
3637
import java.util.logging.Level;
3738
import java.util.logging.Logger;
3839
import java.util.stream.Collectors;
@@ -67,27 +68,29 @@ public String name() {
6768
@Override
6869
public DocumentEntity insert(DocumentEntity entity) throws NullPointerException {
6970
requireNonNull(entity, "entity is required");
70-
entity.add(EntityConverter.COLLECTION_FIELD, entity.name());
71-
JsonObject json = EntityConverter.convert(entity);
72-
Document id = entity.find(EntityConverter.ID_FIELD)
73-
.orElseThrow(() -> new CouchbaseNoKeyFoundException(entity.toString()));
74-
75-
Collection collection = bucket.collection(entity.name());
76-
collection.insert(id.get(String.class), json);
77-
return entity;
71+
return waitBucketBeReadyAndGet(() -> {
72+
entity.add(EntityConverter.COLLECTION_FIELD, entity.name());
73+
JsonObject json = EntityConverter.convert(entity);
74+
Document id = entity.find(EntityConverter.ID_FIELD)
75+
.orElseThrow(() -> new CouchbaseNoKeyFoundException(entity.toString()));
76+
Collection collection = bucket.collection(entity.name());
77+
collection.insert(id.get(String.class), json);
78+
return entity;
79+
});
7880
}
7981

8082
@Override
8183
public DocumentEntity insert(DocumentEntity entity, Duration ttl) {
8284
requireNonNull(entity, "entity is required");
8385
requireNonNull(ttl, "ttl is required");
84-
JsonObject json = EntityConverter.convert(entity);
85-
Document id = entity.find(EntityConverter.ID_FIELD)
86-
.orElseThrow(() -> new CouchbaseNoKeyFoundException(entity.toString()));
87-
88-
Collection collection = bucket.collection(entity.name());
89-
collection.insert(id.get(String.class), json, InsertOptions.insertOptions().expiry(ttl));
90-
return entity;
86+
return waitBucketBeReadyAndGet(() -> {
87+
JsonObject json = EntityConverter.convert(entity);
88+
Document id = entity.find(EntityConverter.ID_FIELD)
89+
.orElseThrow(() -> new CouchbaseNoKeyFoundException(entity.toString()));
90+
Collection collection = bucket.collection(entity.name());
91+
collection.insert(id.get(String.class), json, InsertOptions.insertOptions().expiry(ttl));
92+
return entity;
93+
});
9194
}
9295

9396
@Override
@@ -108,14 +111,15 @@ public Iterable<DocumentEntity> insert(Iterable<DocumentEntity> entities, Durati
108111
@Override
109112
public DocumentEntity update(DocumentEntity entity) {
110113
requireNonNull(entity, "entity is required");
111-
entity.add(EntityConverter.COLLECTION_FIELD, entity.name());
112-
JsonObject json = EntityConverter.convert(entity);
113-
Document id = entity.find(EntityConverter.ID_FIELD)
114-
.orElseThrow(() -> new CouchbaseNoKeyFoundException(entity.toString()));
115-
116-
Collection collection = bucket.collection(entity.name());
117-
collection.upsert(id.get(String.class), json);
118-
return entity;
114+
return waitBucketBeReadyAndGet(() -> {
115+
entity.add(EntityConverter.COLLECTION_FIELD, entity.name());
116+
JsonObject json = EntityConverter.convert(entity);
117+
Document id = entity.find(EntityConverter.ID_FIELD)
118+
.orElseThrow(() -> new CouchbaseNoKeyFoundException(entity.toString()));
119+
Collection collection = bucket.collection(entity.name());
120+
collection.upsert(id.get(String.class), json);
121+
return entity;
122+
});
119123
}
120124

121125
@Override
@@ -127,47 +131,59 @@ public Iterable<DocumentEntity> update(Iterable<DocumentEntity> entities) {
127131

128132
@Override
129133
public void delete(DocumentDeleteQuery query) {
130-
Objects.requireNonNull(query, "query is required");
134+
waitBucketBeReadyAndDo(() -> {
135+
Objects.requireNonNull(query, "query is required");
136+
Collection collection = bucket.collection(query.name());
137+
DocumentQuery delete = DeleteQueryWrapper.of(query);
138+
Stream<DocumentEntity> entities = select(delete);
139+
entities.flatMap(d -> d.find(EntityConverter.ID_FIELD).stream())
140+
.filter(Objects::nonNull)
141+
.map(d -> d.get(String.class))
142+
.forEach(collection::remove);
143+
});
144+
}
131145

132-
Collection collection = bucket.collection(query.name());
133-
DocumentQuery delete = DeleteQueryWrapper.of(query);
134-
Stream<DocumentEntity> entities = select(delete);
135-
entities.flatMap(d -> d.find(EntityConverter.ID_FIELD).stream())
136-
.filter(Objects::nonNull)
137-
.map(d -> d.get(String.class))
138-
.forEach(collection::remove);
146+
private void waitBucketBeReadyAndDo(Runnable runnable) {
147+
bucket.waitUntilReady(bucket.environment().timeoutConfig().kvDurableTimeout());
148+
runnable.run();
149+
}
139150

151+
152+
private <T> T waitBucketBeReadyAndGet(Supplier<T> supplier) {
153+
bucket.waitUntilReady(bucket.environment().timeoutConfig().kvDurableTimeout());
154+
return supplier.get();
140155
}
141156

142157
@Override
143-
public Stream<DocumentEntity> select(DocumentQuery query) throws NullPointerException {
158+
public Stream<DocumentEntity> select(final DocumentQuery query) throws NullPointerException {
144159
Objects.requireNonNull(query, "query is required");
145-
N1QLQuery n1QLQuery = N1QLBuilder.of(query, database, bucket.defaultScope().name()).get();
146-
List<JsonObject> jsons = new ArrayList<>();
147-
148-
if (n1QLQuery.hasIds()) {
149-
Collection collection = bucket.collection(query.name());
150-
for (String id : n1QLQuery.getIds()) {
151-
try {
152-
GetResult result = collection.get(id);
153-
jsons.add(result.contentAsObject());
154-
} catch (DocumentNotFoundException exp) {
155-
LOGGER.log(Level.FINEST, "The id was not found: " + id);
160+
return waitBucketBeReadyAndGet(() -> {
161+
N1QLQuery n1QLQuery = N1QLBuilder.of(query, database, bucket.defaultScope().name()).get();
162+
List<JsonObject> jsons = new ArrayList<>();
163+
if (n1QLQuery.hasIds()) {
164+
Collection collection = bucket.collection(query.name());
165+
for (String id : n1QLQuery.getIds()) {
166+
try {
167+
GetResult result = collection.get(id);
168+
jsons.add(result.contentAsObject());
169+
} catch (DocumentNotFoundException exp) {
170+
LOGGER.log(Level.FINEST, "The id was not found: " + id);
171+
}
156172
}
157173
}
158-
}
159-
160-
if (!n1QLQuery.hasOnlyIds()) {
161-
QueryResult result;
162-
if (n1QLQuery.hasParameter()) {
163-
result = cluster.query(n1QLQuery.getQuery());
164-
} else {
165-
result = cluster.query(n1QLQuery.getQuery(), QueryOptions
166-
.queryOptions().parameters(n1QLQuery.getParams()));
174+
175+
if (!n1QLQuery.hasOnlyIds()) {
176+
QueryResult result;
177+
if (n1QLQuery.hasParameter()) {
178+
result = cluster.query(n1QLQuery.getQuery());
179+
} else {
180+
result = cluster.query(n1QLQuery.getQuery(), QueryOptions
181+
.queryOptions().parameters(n1QLQuery.getParams()));
182+
}
183+
jsons.addAll(result.rowsAsObject());
167184
}
168-
jsons.addAll(result.rowsAsObject());
169-
}
170-
return EntityConverter.convert(jsons, database);
185+
return EntityConverter.convert(jsons, database);
186+
});
171187
}
172188

173189
@Override
@@ -177,21 +193,24 @@ public long count(String documentCollection) {
177193

178194

179195
@Override
180-
public Stream<DocumentEntity> n1qlQuery(String n1ql, JsonObject params) throws NullPointerException {
196+
public Stream<DocumentEntity> n1qlQuery(final String n1ql, final JsonObject params) throws NullPointerException {
181197
requireNonNull(n1ql, "n1qlQuery is required");
182198
requireNonNull(params, "params is required");
183-
184-
QueryResult query = cluster.query(n1ql, QueryOptions
185-
.queryOptions().parameters(params));
186-
return EntityConverter.convert(query.rowsAsObject(), database);
199+
return waitBucketBeReadyAndGet(() -> {
200+
QueryResult query = cluster.query(n1ql, QueryOptions
201+
.queryOptions().parameters(params));
202+
return EntityConverter.convert(query.rowsAsObject(), database);
203+
});
187204
}
188205

189206

190207
@Override
191208
public Stream<DocumentEntity> n1qlQuery(String n1ql) throws NullPointerException {
192209
requireNonNull(n1ql, "n1qlQuery is required");
193-
QueryResult query = cluster.query(n1ql);
194-
return EntityConverter.convert(query.rowsAsObject(), database);
210+
return waitBucketBeReadyAndGet(() -> {
211+
QueryResult query = cluster.query(n1ql);
212+
return EntityConverter.convert(query.rowsAsObject(), database);
213+
});
195214
}
196215

197216

jnosql-couchbase/src/main/java/org/eclipse/jnosql/databases/couchbase/communication/N1QLBuilder.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ private void condition(DocumentCondition condition, StringBuilder n1ql, JsonObje
135135
private void predicateBetween(StringBuilder n1ql, JsonObject params, Document document) {
136136
n1ql.append(" BETWEEN ");
137137
ThreadLocalRandom random = ThreadLocalRandom.current();
138-
String name = '\'' + document.name() + '\'';
138+
String name = identifierOf(document.name());
139139

140140
List<Object> values = new ArrayList<>();
141141
((Iterable<?>) document.get()).forEach(values::add);
@@ -162,13 +162,17 @@ private void predicate(StringBuilder n1ql,
162162
Document document,
163163
JsonObject params) {
164164
ThreadLocalRandom random = ThreadLocalRandom.current();
165-
String name = '\'' + document.name() + '\'';
165+
String name = identifierOf(document.name());
166166
Object value = document.get();
167167
String param = "$".concat(document.name()).concat("_").concat(Integer.toString(random.nextInt(0, 100)));
168168
n1ql.append(name).append(condition).append(param);
169169
params.put(param, value);
170170
}
171171

172+
private String identifierOf(String name) {
173+
return ' ' + name + ' ';
174+
}
175+
172176
private String select() {
173177
String documents = query.documents().stream()
174178
.collect(Collectors.joining(", "));

0 commit comments

Comments
 (0)