Skip to content
This repository has been archived by the owner on Sep 12, 2018. It is now read-only.

Simple aggregates again #584

Merged
merged 14 commits into from
Mar 12, 2018
Merged

Simple aggregates again #584

merged 14 commits into from
Mar 12, 2018

Conversation

rnewman
Copy link
Collaborator

@rnewman rnewman commented Mar 6, 2018

Obsoletes #498. Rebased on top of current master.

Still to do:

  • TODOs for constant queries. This will involve implementing known-value aggregation: e.g., (count ?x) where ?x is bound ➡️ 1.
  • Porting forward the conflicting tests from tests/query.rs.
  • Figuring out what to do with these commented-out tests
  • Fixing the distinct/non-distinct case: we need to always generate a projecting subquery and aggregate in an enclosing query. :with controls the projection in the inner query. The simplest case is where the outer projection list is the same as the inner, and neither features aggregation — that's what we already do! — and aggregation means slightly untangling that.

@rnewman
Copy link
Collaborator Author

rnewman commented Mar 7, 2018

This is ready for you to look at, @fluffyemily.

@rnewman rnewman force-pushed the rnewman/simple-aggregates-3 branch from aff2758 to 15a42e6 Compare March 7, 2018 20:41
@rnewman rnewman force-pushed the rnewman/simple-aggregates-3 branch from 15a42e6 to c6a5464 Compare March 8, 2018 21:39
@@ -173,6 +173,13 @@ impl Store {
sqlite: connection,
})
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really kinda surprised we didn't already have this.

self.value_bindings.contains_key(var)
}

pub fn value_bindings(&self, variables: &BTreeSet<Variable>) -> VariableBindings {
self.value_bindings.with_intersected_keys(variables)
}

/// Return an interator over the variables externally bound to values.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit iterator

@@ -283,6 +283,9 @@ pub enum Inequality {
GreaterThan,
GreaterThanOrEquals,
NotEquals,

// Ref operators.
Differ,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we have a differ test?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

tests/query.rs Outdated

;; Alice danced with Beli.
[:db/add "a" :foo/dance "ab"]
[:db/add "b" :foo/dance "ab"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what would happen if I did [:db/add "b" :foo/dance "ba"] here? Does this rely upon the 'dance' ordering being identical for unpermute to work?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would add a second dance for Beli, one in which she doesn't dance with anyone else. The only set of bindings for ?left and ?right would be her, and naturally she doesn't unpermute with herself, so that solo dance wouldn't contribute anything to the output.

If you were to add both Alice and Beli to that second dance, the output would be unchanged: the inner query would generate [Alice, Beli] [Alice, Alice] [Beli, Alice] [Beli, Beli] twice, once for each of the two dances; the unpermute step would remove [x, x] pairs and one half of the orders; and then the internal DISTINCT would remove duplicates.

I've added this to the test.

@@ -134,14 +134,21 @@ impl ConjoiningClauses {
// We expect the intersection to be Long, Long+Double, Double, or Instant.
let left_v;
let right_v;
if shared_types.is_empty() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already check shared_types.is_empty() in line 115. The result of that check, if the set is empty, is to mark_known_empty and return Ok(()). As we do nothing else between that check and this, this code will never succeed. Do we really need it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Probably a screwup when rebasing a very old branch.

This allows for a corresponding value to be returned when a query
includes one 'min' or 'max' aggregate.
Copy link
Contributor

@fluffyemily fluffyemily left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about the being an understandable keyword, but I get what it is doing. I've racked my brains and can't think of a better one though. Naming things has never been my strong point.

@rnewman rnewman merged commit 833ff92 into master Mar 12, 2018
@rnewman rnewman deleted the rnewman/simple-aggregates-3 branch March 12, 2018 22:19
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants