use of com.google.firebase.firestore.model.ResourcePath in project firebase-android-sdk by firebase.
the class RemoteSerializer method encodeQueryTarget.
public QueryTarget encodeQueryTarget(com.google.firebase.firestore.core.Target target) {
// Dissect the path into parent, collectionId, and optional key filter.
QueryTarget.Builder builder = QueryTarget.newBuilder();
StructuredQuery.Builder structuredQueryBuilder = StructuredQuery.newBuilder();
ResourcePath path = target.getPath();
if (target.getCollectionGroup() != null) {
hardAssert(path.length() % 2 == 0, "Collection Group queries should be within a document path or root.");
builder.setParent(encodeQueryPath(path));
CollectionSelector.Builder from = CollectionSelector.newBuilder();
from.setCollectionId(target.getCollectionGroup());
from.setAllDescendants(true);
structuredQueryBuilder.addFrom(from);
} else {
hardAssert(path.length() % 2 != 0, "Document queries with filters are not supported.");
builder.setParent(encodeQueryPath(path.popLast()));
CollectionSelector.Builder from = CollectionSelector.newBuilder();
from.setCollectionId(path.getLastSegment());
structuredQueryBuilder.addFrom(from);
}
// Encode the filters.
if (target.getFilters().size() > 0) {
structuredQueryBuilder.setWhere(encodeFilters(target.getFilters()));
}
// Encode the orders.
for (OrderBy orderBy : target.getOrderBy()) {
structuredQueryBuilder.addOrderBy(encodeOrderBy(orderBy));
}
// Encode the limit.
if (target.hasLimit()) {
structuredQueryBuilder.setLimit(Int32Value.newBuilder().setValue((int) target.getLimit()));
}
if (target.getStartAt() != null) {
Cursor.Builder cursor = Cursor.newBuilder();
cursor.addAllValues(target.getStartAt().getPosition());
cursor.setBefore(target.getStartAt().isInclusive());
structuredQueryBuilder.setStartAt(cursor);
}
if (target.getEndAt() != null) {
Cursor.Builder cursor = Cursor.newBuilder();
cursor.addAllValues(target.getEndAt().getPosition());
cursor.setBefore(!target.getEndAt().isInclusive());
structuredQueryBuilder.setEndAt(cursor);
}
builder.setStructuredQuery(structuredQueryBuilder);
return builder.build();
}
use of com.google.firebase.firestore.model.ResourcePath in project firebase-android-sdk by firebase.
the class RemoteSerializer method decodeQueryTarget.
public com.google.firebase.firestore.core.Target decodeQueryTarget(String parent, StructuredQuery query) {
ResourcePath path = decodeQueryPath(parent);
String collectionGroup = null;
int fromCount = query.getFromCount();
if (fromCount > 0) {
hardAssert(fromCount == 1, "StructuredQuery.from with more than one collection is not supported.");
CollectionSelector from = query.getFrom(0);
if (from.getAllDescendants()) {
collectionGroup = from.getCollectionId();
} else {
path = path.append(from.getCollectionId());
}
}
List<Filter> filterBy;
if (query.hasWhere()) {
filterBy = decodeFilters(query.getWhere());
} else {
filterBy = Collections.emptyList();
}
List<OrderBy> orderBy;
int orderByCount = query.getOrderByCount();
if (orderByCount > 0) {
orderBy = new ArrayList<>(orderByCount);
for (int i = 0; i < orderByCount; i++) {
orderBy.add(decodeOrderBy(query.getOrderBy(i)));
}
} else {
orderBy = Collections.emptyList();
}
long limit = com.google.firebase.firestore.core.Target.NO_LIMIT;
if (query.hasLimit()) {
limit = query.getLimit().getValue();
}
Bound startAt = null;
if (query.hasStartAt()) {
startAt = new Bound(query.getStartAt().getValuesList(), query.getStartAt().getBefore());
}
Bound endAt = null;
if (query.hasEndAt()) {
endAt = new Bound(query.getEndAt().getValuesList(), !query.getEndAt().getBefore());
}
return new com.google.firebase.firestore.core.Target(path, collectionGroup, filterBy, orderBy, limit, startAt, endAt);
}
use of com.google.firebase.firestore.model.ResourcePath in project firebase-android-sdk by firebase.
the class SQLiteLruReferenceDelegate method removeOrphanedDocuments.
@Override
public int removeOrphanedDocuments(long upperBound) {
int[] count = new int[1];
boolean resultsRemaining = true;
List<DocumentKey> docsToRemove = new ArrayList<>();
while (resultsRemaining) {
int rowsProccessed = persistence.query("select path from target_documents group by path having COUNT(*) = 1 AND target_id = 0 AND sequence_number <= ? LIMIT ?").binding(upperBound, REMOVE_ORPHANED_DOCUMENTS_BATCH_SIZE).forEach(row -> {
ResourcePath path = EncodedPath.decodeResourcePath(row.getString(0));
DocumentKey key = DocumentKey.fromPath(path);
if (!isPinned(key)) {
count[0]++;
docsToRemove.add(key);
removeSentinel(key);
}
});
resultsRemaining = (rowsProccessed == REMOVE_ORPHANED_DOCUMENTS_BATCH_SIZE);
}
persistence.getRemoteDocumentCache().removeAll(docsToRemove);
return count[0];
}
use of com.google.firebase.firestore.model.ResourcePath in project firebase-android-sdk by firebase.
the class SQLiteRemoteDocumentCache method getAll.
@Override
public Map<DocumentKey, MutableDocument> getAll(String collectionGroup, IndexOffset offset, int limit) {
List<ResourcePath> collectionParents = indexManager.getCollectionParents(collectionGroup);
List<ResourcePath> collections = new ArrayList<>(collectionParents.size());
for (ResourcePath collectionParent : collectionParents) {
collections.add(collectionParent.append(collectionGroup));
}
if (collections.isEmpty()) {
return Collections.emptyMap();
} else if (BINDS_PER_STATEMENT * collections.size() < SQLitePersistence.MAX_ARGS) {
return getAll(collections, offset, limit);
} else {
// We need to fan out our collection scan since SQLite only supports 999 binds per statement.
Map<DocumentKey, MutableDocument> results = new HashMap<>();
int pageSize = SQLitePersistence.MAX_ARGS / BINDS_PER_STATEMENT;
for (int i = 0; i < collections.size(); i += pageSize) {
results.putAll(getAll(collections.subList(i, Math.min(collections.size(), i + pageSize)), offset, limit));
}
return firstNEntries(results, limit, IndexOffset.DOCUMENT_COMPARATOR);
}
}
use of com.google.firebase.firestore.model.ResourcePath in project firebase-android-sdk by firebase.
the class SQLiteRemoteDocumentCache method getAll.
/**
* Returns the next {@code count} documents from the provided collections, ordered by read time.
*/
private Map<DocumentKey, MutableDocument> getAll(List<ResourcePath> collections, IndexOffset offset, int count) {
Timestamp readTime = offset.getReadTime().getTimestamp();
DocumentKey documentKey = offset.getDocumentKey();
StringBuilder sql = repeatSequence("SELECT contents, read_time_seconds, read_time_nanos, path " + "FROM remote_documents " + "WHERE path >= ? AND path < ? AND path_length = ? " + "AND (read_time_seconds > ? OR ( " + "read_time_seconds = ? AND read_time_nanos > ?) OR ( " + "read_time_seconds = ? AND read_time_nanos = ? and path > ?)) ", collections.size(), " UNION ");
sql.append("ORDER BY read_time_seconds, read_time_nanos, path LIMIT ?");
Object[] bindVars = new Object[BINDS_PER_STATEMENT * collections.size() + 1];
int i = 0;
for (ResourcePath collection : collections) {
String prefixPath = EncodedPath.encode(collection);
bindVars[i++] = prefixPath;
bindVars[i++] = EncodedPath.prefixSuccessor(prefixPath);
bindVars[i++] = collection.length() + 1;
bindVars[i++] = readTime.getSeconds();
bindVars[i++] = readTime.getSeconds();
bindVars[i++] = readTime.getNanoseconds();
bindVars[i++] = readTime.getSeconds();
bindVars[i++] = readTime.getNanoseconds();
bindVars[i++] = EncodedPath.encode(documentKey.getPath());
}
bindVars[i] = count;
BackgroundQueue backgroundQueue = new BackgroundQueue();
Map<DocumentKey, MutableDocument> results = new HashMap<>();
db.query(sql.toString()).binding(bindVars).forEach(row -> processRowInBackground(backgroundQueue, results, row));
backgroundQueue.drain();
return results;
}
Aggregations