aliasing with vector entities

30 views
Skip to first unread message

CGAT

unread,
May 22, 2013, 2:35:42 PM5/22/13
to sqlk...@googlegroups.com
I was trying to do a self-join and related things with Korma, and
after a bit of trial and error and some peeking in the code,
I found that vector entities work to create AS aliases.

For instance:

(select [widgets 'a]
  (from [widgets 'b])
  (from [vats 'c])
  (fields :a.id)
  (where (= :a.batch :b.batch))
  (where (= :a.source :c.id)))

produces

"SELECT \"a\".\"id\" FROM \"widgets\" AS \"a\", \"widgets\" AS \"b\", \"vats\" AS \"c\" WHERE \"a\".\"batch\" = \"b\".\"batch\" AND \"a\".\"source\" = \"c\".\"id\""

which  is just what I needed.  And it works with join as well

(select [widgets 'a]
  (from '[vats c])
  (join '[widgets b] (= :a.batch :b.batch))
  (fields :a.id)
  (where (= :a.source :c.id)))


This is terrific! But I think this should be in the documentation somewhere,
as it wasn't apparent and is not an uncommon situation.

One small issue that this raised, however, was that when using a vector entity
as the first argument to select/select*, the :ent field of the resulting query becomes
a vector of maps, not a single map.  As a result when korma.core/apply-transforms
is called during exec, the transforms field is not found and any transforms on the
unaliased entity are not applied.  (Version 0.3.0-RC5.)

Admittedly, it is unclear what transformations to apply with complex joins
or if it even makes sense to do so given the combination of data from
different tables. And in cases where transforming does make sense, like
simple self joins, one can often work around this by not aliasing the main table.
So perhaps this is a feature not a bug. 

But the transforms are applied (using the transforms for the main table)
when there are joins used without aliasing, which would seem to raise the same
concerns as above. This appears inconsistent, leading to different results
based on a tangentially related action (aliasing) by the user.

Should transforms be disallowed with joins or allowed with aliasing?

If the latter, something like the following appears to work:

(defn- apply-transforms
  [query results]
  (if (= (:type query) :delete)
    results
    (if-let [trans (seq (-> query :ent
                            (#(if (vector? %) (get % 0) %))
                            :transforms))]
      (let [trans-fn (apply comp trans)]
        (if (sequential? results)
          (map trans-fn results)
          (trans-fn results)))
      results))) 

in korma.core, with one line added, which extracts the first entity
in the vector case.

Thanks!  I've been very happy with Korma so far.


CGAT

unread,
May 24, 2013, 7:40:11 PM5/24/13
to sqlk...@googlegroups.com
Alas, as I feared, there are other situations in which
the entity field is a vector, so the change to apply-transforms
that I gave can cause problems. I'll try to track down the details and
give a more test version that still works with aliased entities.

CGAT

unread,
May 24, 2013, 8:52:05 PM5/24/13
to sqlk...@googlegroups.com
I was a bit hasty in the last post. My modification to apply-transforms
did not cause the problem I observed. I reloaded korma in a fresh
repl and the problem still occured.  I'm close to finding the real problem
and will report back.

CGAT

unread,
May 24, 2013, 11:51:59 PM5/24/13
to sqlk...@googlegroups.com
OK, I found what's been going on. The problem was not my modification.
The version of of 0.3.0-RC5 that lein downloaded had the following
for apply-transforms. The vector? has been replaced by sequential?
in the current version on github, which is important because the result
of the post-replies is often a sequence but not a vector (e.g., when
using a with statement in the query). In that case, the vector? version
gives an (improperly formed) map instead of a sequence of maps as the result.

(defn- apply-transforms
  [query results]
  (if (= (:type query) :delete)
    results
    (if-let [trans (seq (-> query :ent :transforms))]

      (let [trans-fn (apply comp trans)]
        (if (vector? results) (map trans-fn results) (trans-fn results)))
      results)))


This broke some queries with with's in actual use, so it is worth pushing
the fix to the repository.

About aliased entities, my modification does seem to be working fine.
It will of course take some checking to make sure that vectors in the :ent
field do not appear in any other cases, so consider it a proof of concept.
Reply all
Reply to author
Forward
0 new messages