Skip to content

Implementing Matcher protocol only matters if used as expected value #224

Open
@NoahTheDuke

Description

Problem statement

I use jsonb columns in Postgres to store arbitrary data. I don't automatically convert these columns when I query, preferring to wait until it's necessary. I can convert those columns before passing the results to match?, but it would be nice to perform that automatically within the matcher.

However, implementing Matcher for the PGObject or PGArray doesn't work if I use a normal sequence or object in the expected position, as the built-in matcher implementations check the type of actual to short-circuit an otherwise lengthy check. For example, here's sequence-match as used by EqualSeq.

(if-not (sequential? actual)
{::result/type :mismatch
::result/value (model/->Mismatch expected actual)
::result/weight 1}

Proposed solution

I'm not sure the right way to go about this, as there's a step of transformation that must happen before the actual can be checked, which I'm seeking to automate. Maybe that's outside the purview of matcher-combinators?

Thanks so much.

Repro:

(ns postgres-mc-example
  (:require
   [cheshire.core :as json]
   [clojure.test :refer [deftest is]]
   [matcher-combinators.core :as mc]
   [matcher-combinators.result :as-alias mcr]
   [matcher-combinators.test :refer [match?]])
  (:import
   [org.postgresql.util PGobject]))

(defn from-pg-json
  [^PGobject obj & cheshire-options]
  (when obj (apply json/parse-string (.getValue obj) cheshire-options)))

(defn to-pg-json
  [data]
  (doto (PGobject.)
    (.setType "jsonb")
    (.setValue (json/generate-string data))))

(extend-protocol mc/Matcher
  PGobject
  (-matcher-for [this] this)
  (-matcher-for [this _t->m] this)
  (-name [this] 'PGobjectEquals)
  (-match [this actual] (mc/match (from-pg-json this) actual)))

(deftest matcher-smoke-test
  (is (match? [1 2 3] (to-pg-json [1 2 3]))))

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions