Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: congomongo/congomongo
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: circleci/congomongo
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
Can’t automatically merge. Don’t worry, you can still create the pull request.

Commits on Aug 24, 2021

  1. Merge pull request #9 from congomongo/master

    Update master from upstream
    marcomorain authored Aug 24, 2021
    Copy the full SHA
    97b1a82 View commit details
  2. Merge pull request #10 from marcomorain/circleci

    Add CircleCI config
    marcomorain authored Aug 24, 2021

    Verified

    This commit was signed with the committer’s verified signature.
    bostonaholic Matthew Boston
    Copy the full SHA
    be93773 View commit details

Commits on Aug 25, 2021

  1. Publish snapshots to Clojars

    On every build of master, publish a new snapshot to Clojars.
    marcomorain committed Aug 25, 2021

    Verified

    This commit was signed with the committer’s verified signature.
    bostonaholic Matthew Boston
    Copy the full SHA
    d856e93 View commit details
  2. Merge pull request #13 from circleci/clojars

    Publish snapshots to Clojars
    marcomorain authored Aug 25, 2021

    Verified

    This commit was signed with the committer’s verified signature.
    bostonaholic Matthew Boston
    Copy the full SHA
    48e2316 View commit details
  3. Verified

    This commit was signed with the committer’s verified signature.
    bostonaholic Matthew Boston
    Copy the full SHA
    618fbdc View commit details
  4. Merge pull request #14 from circleci/clojars

    Release requires tests pass
    marcomorain authored Aug 25, 2021
    Copy the full SHA
    a2dba87 View commit details

Commits on Aug 30, 2021

  1. Remove uses of deprecated JSON API

    The version 3.12 of the Java driver deprecates `com.mongodb.util.JSON`
    in favour of the JSON functions on the DBObject class. The deprecated
    API will be removed in driver version 4.x.
    
    In order to prepare for the upgrade to 4.x we can upgrade from driver
    `3.10` to `3.12` and remove calls to the decprecated API.
    marcomorain committed Aug 30, 2021
    Copy the full SHA
    2235286 View commit details
  2. Correctly convert more shapes of data to json

    What we get out of the database can be a mix of java types that
    clojure.data.json understands and mongo objects with a .toJson method. Extend
    clojure.data.json's JSONWriter to be able to convert the mongo types, and use
    write-str.
    circlecai authored and marcomorain committed Aug 30, 2021
    Copy the full SHA
    b61ad22 View commit details
  3. make it work with mongo driver 4.3

    A lot of things have been removed from the underlying driver so we will not be
    able to make this backwards compatible.
    circlecai authored and marcomorain committed Aug 30, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    9840ec9 View commit details
  4. Make write-concern-map backwards compatible

    Using the docs on deprecations in [1], replace the removed value with
    their recommended replacements.
    
    [1] https://www.javadoc.io/doc/org.mongodb/mongo-java-driver/latest/com/mongodb/WriteConcern.html
    marcomorain committed Aug 30, 2021
    Copy the full SHA
    363dfc8 View commit details
  5. Merge pull request #11 from marcomorain/four

    Draft: Upgrade to Mongo 4.x
    circlecai authored Aug 30, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    4dce6a5 View commit details

Commits on Sep 2, 2021

  1. Copy the full SHA
    6bc99fb View commit details

Commits on Sep 3, 2021

  1. Merge pull request #16 from circleci/new-release

    Increment version, non-snapshot
    marcomorain authored Sep 3, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    d11c7f2 View commit details
  2. Don't sign release JARs

    marcomorain committed Sep 3, 2021

    Unverified

    This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
    Copy the full SHA
    dfb1e2c View commit details

Commits on Sep 4, 2021

  1. Update to reference clojars-publish context

    The current configuration does not specify the `clojars-publish` context so any jar publish will be done using the LEIN_USERNAME environment variable.
    
    This change assigns the context so that we can then remove the explicit reference to LEIN_USERNAME and LEIN_PASSWORD
    
    The impetus for this change is to remove specific engineer credentials from the publish flow and also to shift from specific project configurations to a global context.
    
    No code impact is expected and the referenced context has been used to push to Clojars already so it should not generate any errors.
    bear authored Sep 4, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    1336f3d View commit details

Commits on Sep 5, 2021

  1. Merge pull request #17 from circleci/add-reference-to-clojars-context

    Update to reference clojars-publish context
    marcomorain authored Sep 5, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    eda85f0 View commit details

Commits on Sep 7, 2021

  1. The context has different env var names

    In the previous commit we changed how we access credentials from project
    env vars to contexts. The var names in the context have different names,
    however:
    
    ```
    LEIN_USERNAME -> CLOJARS_USERNAME
    LEIN_PASSOWRD -> CLOJARS_TOKEN
    ```
    marcomorain committed Sep 7, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    b5a2cc0 View commit details
  2. Merge pull request #18 from circleci/clojars-creds

    The context has different env var names
    marcomorain authored Sep 7, 2021
    Copy the full SHA
    e56f3ea View commit details

Commits on Jan 13, 2023

  1. [SECOPS-2716] Add CODEOWNERS file

    No action required. This PR will be merged by @circleci/security-operations.
    circleci-bot committed Jan 13, 2023
    Copy the full SHA
    80b58a6 View commit details

Commits on Jan 16, 2023

  1. Merge pull request #20 from circleci/backplane-bot/add-secops-codeowners

    [SECOPS-2716] Add CODEOWNERS file
    bear authored Jan 16, 2023
    Copy the full SHA
    c8003ac View commit details

Commits on Feb 2, 2024

  1. Copy the full SHA
    7c3c85f View commit details

Commits on Feb 5, 2024

  1. Merge pull request #21 from circleci/SECENG_update-default-codeowners

    Replace Security-Operations with Default-Security-Operations
    ryan-wren authored Feb 5, 2024
    Copy the full SHA
    b7cf0b6 View commit details

Commits on Mar 27, 2024

  1. Update CODEOWNERS

    vallieres authored Mar 27, 2024
    Copy the full SHA
    6c526e0 View commit details

Commits on Mar 28, 2024

  1. Merge pull request #22 from circleci/SECENG_update-co

    Update CODEOWNERS
    geoffnichols authored Mar 28, 2024
    Copy the full SHA
    1a9aa47 View commit details
Showing with 150 additions and 59 deletions.
  1. +19 −1 .circleci/config.yml
  2. +3 −0 CODEOWNERS
  3. +6 −0 docker-compose.yml
  4. +10 −4 project.clj
  5. +42 −32 src/somnium/congomongo.clj
  6. +36 −8 src/somnium/congomongo/coerce.clj
  7. +34 −14 test/somnium/test/congomongo.clj
20 changes: 19 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
version: 2.1

jobs:
build:
test:
docker:
- image: cimg/clojure:1.10.1
- image: mongo:3.6
steps:
- checkout
- run: lein test

release:
docker:
- image: cimg/clojure:1.10.1
steps:
- checkout
- run: lein deploy

workflows:
ci:
jobs:
- test
- release:
context: clojars-publish
requires: [test]
filters:
branches:
only: master
3 changes: 3 additions & 0 deletions CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Placeholder CODEOWNERS file as this repo did not have one
# Please make a PR adding the correct owner or request that this repo be archived
* @circleci/maintainers-monolith
6 changes: 6 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
version: '2'
services:
mongodb:
image: mongo:3.6
ports:
- '127.0.0.1:27017:27017'
14 changes: 10 additions & 4 deletions project.clj
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
(defproject congomongo
"2.2.2"
(defproject circleci/congomongo
"2.2.3.1" ;; the upstream version is 2.2.3
:description "Clojure-friendly API for MongoDB"
:url "https://github.com/congomongo/congomongo"
:mailing-list {:name "CongoMongo mailing list"
@@ -10,9 +10,15 @@
:distribution :repo}
:min-lein-version "2.0.0"
:dependencies [[org.clojure/data.json "0.2.7"]
[org.mongodb/mongo-java-driver "3.10.2"]
[org.mongodb/mongodb-driver-legacy "4.3.1"]
[org.clojure/clojure "1.10.1" :scope "provided"]]
:deploy-repositories {"releases" {:url "https://repo.clojars.org" :creds :gpg}}
:repositories [["releases" {:url "https://repo.clojars.org"
:sign-releases false
:username :env/clojars_username
:password :env/clojars_token}]
["snapshots" {:url "https://repo.clojars.org"
:username :env/clojars_username
:password :env/clojars_token}]]
;; if a :dev profile is added, remember to update :aliases below to
;; use it in each with-profile group!
:profiles {:1.9 {:dependencies [[org.clojure/clojure "1.9.0"]]}
74 changes: 42 additions & 32 deletions src/somnium/congomongo.clj
Original file line number Diff line number Diff line change
@@ -28,8 +28,9 @@
[somnium.congomongo.coerce :refer [coerce coerce-fields coerce-index-fields]])
(:import [com.mongodb MongoClient MongoClientOptions MongoClientOptions$Builder
MongoClientURI MongoCredential
DB DBCollection DBObject DBRef ServerAddress ReadPreference WriteConcern Bytes
AggregationOptions AggregationOptions$OutputMode
DB DBCollection CursorType DBObject DBRef
ServerAddress ReadPreference WriteConcern
AggregationOptions
MapReduceCommand MapReduceCommand$OutputType]
[com.mongodb.gridfs GridFS]
[org.bson.types ObjectId]
@@ -142,7 +143,7 @@
(MongoCredential/createCredential username db (.toCharArray password))))

mongo (if credential
(make-mongo-client addresses [credential] options)
(make-mongo-client addresses credential options)
(make-mongo-client addresses options))

n-db (if db (.getDB mongo db) nil)]
@@ -262,20 +263,20 @@ When with-mongo and set-connection! interact, last one wins"

(def write-concern-map
{:acknowledged WriteConcern/ACKNOWLEDGED
:fsynced WriteConcern/FSYNCED
:fsynced WriteConcern/JOURNALED
:journaled WriteConcern/JOURNALED
:majority WriteConcern/MAJORITY
:replica-acknowledged WriteConcern/REPLICA_ACKNOWLEDGED
:replica-acknowledged WriteConcern/W2
:unacknowledged WriteConcern/UNACKNOWLEDGED
;; these are pre-2.10.x names for write concern:
:fsync-safe WriteConcern/FSYNC_SAFE ;; deprecated - use :fsynced
:journal-safe WriteConcern/JOURNAL_SAFE ;; deprecated - use :journaled
:normal WriteConcern/NORMAL ;; deprecated - use :unacknowledged
:replicas-safe WriteConcern/REPLICAS_SAFE ;; deprecated - use :replica-acknowledged
:safe WriteConcern/SAFE ;; deprecated - use :acknowledged
:fsync-safe WriteConcern/JOURNALED
:journal-safe WriteConcern/JOURNALED
:normal WriteConcern/UNACKNOWLEDGED
:replicas-safe WriteConcern/W2
:safe WriteConcern/ACKNOWLEDGED
;; these are left for backward compatibility but are deprecated:
:replica-safe WriteConcern/REPLICAS_SAFE
:strict WriteConcern/SAFE
:replica-safe WriteConcern/W2
:strict WriteConcern/ACKNOWLEDGED
})

(defn set-write-concern
@@ -349,20 +350,6 @@ When with-mongo and set-connection! interact, last one wins"
^String (named collection)
(coerce options [:clojure :mongo])))

(def query-option-map
{:tailable Bytes/QUERYOPTION_TAILABLE
:slaveok Bytes/QUERYOPTION_SLAVEOK
:oplogreplay Bytes/QUERYOPTION_OPLOGREPLAY
:notimeout Bytes/QUERYOPTION_NOTIMEOUT
:awaitdata Bytes/QUERYOPTION_AWAITDATA})

(defn calculate-query-options
"Calculates the cursor's query option from a list of options"
[options]
(reduce bit-or 0 (map query-option-map (if (keyword? options)
(list options)
options))))

(def ^:private read-preference-map
"Private map of facory functions of ReadPreferences to aliases."
{:nearest (fn nearest ([] (ReadPreference/nearest)) ([^List tags] (ReadPreference/nearest tags)))
@@ -414,6 +401,20 @@ When with-mongo and set-connection! interact, last one wins"
[collection]
(.getReadPreference (get-coll collection)))

(defn set-options!
"sets the options on the cursor"
[cursor {:keys [tailable secondary-preferred slaveok oplog notimeout awaitdata]}]
(when tailable
(.cursorType cursor CursorType/Tailable))
(when awaitdata
(.cursorType cursor CursorType/TailableAwait))
(when (or secondary-preferred slaveok)
(.setReadPreference cursor (ReadPreference/secondaryPreferred)))
(when oplog
(.oplogReplay cursor true))
(when notimeout
(.noCursorTimeout cursor true)))

(defn fetch
"Fetches objects from a collection.
Note that MongoDB always adds the _id and _ns
@@ -482,13 +483,12 @@ You should use fetch with :limit 1 instead."))); one? and sort should NEVER be c
; (with negative limit) doesn't match expectations therefore changed to keep limit as is.
n-limit (or limit 0)
n-sort (when sort (coerce sort [from :mongo]))
n-options (calculate-query-options options)
n-preferences (cond
(nil? read-preferences) nil
(instance? ReadPreference read-preferences) read-preferences
:else (somnium.congomongo/read-preference read-preferences))]
(cond
count? (.getCount n-col n-where n-only)
count? (.getCount n-col n-where)

;; The find command isn't documented so there's no nice way to build a
;; find command that adds read-preferences when necessary
@@ -504,10 +504,21 @@ You should use fetch with :limit 1 instead."))); one? and sort should NEVER be c
(.setReadPreference cursor n-preferences))
(when hint
(if (string? hint)
(.hint cursor ^String hint)
;; hint no longer supports strings
;; .hintString exists for DBCollectionCountOptions but not
;; for DBCursor. It would be possible to hack support by
;; creating a DBCollectionCountOptions that is not used
;; except for setting a hint string on it and getting the
;; hint out as an object. For now follow the mongo
;; deprecation and let this be a place where we don't have
;; backwards compatibility. They have also added the string
;; hint functionality back into the non-legacy client so it
;; is possible that support will be restored via the java
;; client.
(throw (IllegalArgumentException. "String hints are not currently supported. Use a seq instead."))
(.hint cursor ^DBObject (coerce-index-fields hint))))
(when n-options
(.setOptions cursor n-options))
(when options
(set-options! cursor options))
(when n-sort
(.sort cursor n-sort))
(when skip
@@ -725,7 +736,6 @@ You should use fetch with :limit 1 instead."))); one? and sort should NEVER be c
cursor (.aggregate (get-coll coll)
^List (coerce (conj ops op) [from :mongo])
^AggregationOptions (-> (AggregationOptions/builder)
(.outputMode AggregationOptions$OutputMode/CURSOR)
(.build)))]
{:serverUsed (.toString (.getServerAddress cursor))
:result (coerce cursor [:mongo to] :many true)
44 changes: 36 additions & 8 deletions src/somnium/congomongo/coerce.clj
Original file line number Diff line number Diff line change
@@ -19,12 +19,19 @@
; THE SOFTWARE.

(ns somnium.congomongo.coerce
(:require [clojure.data.json :refer [write-str read-str]])
(:import [clojure.lang IPersistentMap IPersistentVector Keyword]
(:require [clojure.data.json :as json :refer [write-str read-str]])
(:import [clojure.lang IPersistentMap Keyword]
[java.util Map List Set]
[com.mongodb DBObject BasicDBObject BasicDBList]
[com.mongodb.gridfs GridFSFile]
[com.mongodb.util JSON]))
[org.bson.json JsonWriterSettings JsonMode]
[org.bson.types ObjectId]))

(def ^:private json-settings
; Create a settings object to allow us to serialize an object with "RELAXED" JSON.
; https://github.com/mongodb/specifications/blob/df6be82f865e9b72444488fd62ae1eb5fca18569/source/extended-json.rst
(-> (JsonWriterSettings/builder)
(.outputMode JsonMode/RELAXED)
(.build)))

(def ^{:dynamic true
:doc "Set this to false to prevent coercion from setting string keys to keywords"
@@ -47,6 +54,26 @@
(string? x)
(instance? java.util.Map x))))

(defn json->mongo [^String s]
(BasicDBObject/parse s))

(defn- write-basic-db-object
[^BasicDBObject dbo ^Appendable out]
(.append out (.toJson dbo json-settings)))

(extend BasicDBObject clojure.data.json/JSONWriter {:-write write-basic-db-object})

(defn write-object-id
[^ObjectId id ^Appendable out]
(.append out "\"")
(.append out (str id))
(.append out "\""))

(extend ObjectId json/JSONWriter {:-write write-object-id})

(defn mongo->json [o]
(write-str o))

;;; Converting data from mongo into Clojure data objects

(defprotocol ConvertibleFromMongo
@@ -126,11 +153,11 @@
*translations* {[:clojure :mongo ] #'clojure->mongo
[:clojure :json ] #'write-str
[:mongo :clojure] #(mongo->clojure ^DBObject % ^boolean *keywordize*)
[:mongo :json ] #(JSON/serialize %)
[:mongo :json ] #'mongo->json
[:json :clojure] #(read-str % :key-fn (if *keywordize*
keyword
identity))
[:json :mongo ] #(JSON/parse %)})
[:json :mongo ] #'json->mongo})

(defn coerce
"takes an object, a vector of keywords:
@@ -150,8 +177,9 @@
(f obj))
(throw (RuntimeException. "unsupported keyword pair"))))))

(defn ^DBObject dbobject [& args]
"Create a DBObject from a sequence of key/value pairs, in order."
(defn ^DBObject dbobject
"Create a DBObject from a sequence of key/value pairs, in order."
[& args]
(let [dbo (BasicDBObject.)]
(doseq [[k v] (partition 2 args)]
(.put dbo
48 changes: 34 additions & 14 deletions test/somnium/test/congomongo.clj
Original file line number Diff line number Diff line change
@@ -246,7 +246,7 @@
uri (str "mongodb://" userpass test-db-host ":" test-db-port "/congomongotest-db-a?maxpoolsize=123&w=1&safe=true")
a (make-connection uri)
^MongoClient m (:mongo a)
opts (.getMongoOptions m)]
opts (.getMongoClientOptions m)]
(testing "make-connection parses options from URI"
(is (= 123 (.getConnectionsPerHost opts)))
(is (= WriteConcern/W1 (.getWriteConcern opts))))
@@ -285,15 +285,6 @@
(close-connection a)
(is (= nil *mongo-config*)))))))

(deftest query-options
(are [x y] (= (calculate-query-options x) y)
nil 0
[] 0
[:tailable] 2
[:tailable :slaveok] 6
[:tailable :slaveok :notimeout] 22
:notimeout 16))

(deftest fetch-with-options
(with-test-mongo
(insert! :thingies {:foo 1})
@@ -501,31 +492,32 @@
(add-index! :test_col [[:key1 -1]]) ;; index3
(add-index! :test_col [:key1 [:key2 -1]]) ;; index 4

(testing "index1"
;; strings supplied as hints are not currently supported
#_(testing "index1"
(let [plan (-> (fetch :test_col :where {:key1 1} :explain? true :hint "key1_1"))]
(is (= "key1_1" (-> plan :queryPlanner :winningPlan :inputStage :indexName)))))

(testing "index1 seq"
(let [plan (-> (fetch :test_col :where {:key1 1} :explain? true :hint [:key1]))]
(is (= "key1_1" (-> plan :queryPlanner :winningPlan :inputStage :indexName)))))

(testing "index2"
#_(testing "index2"
(let [plan (-> (fetch :test_col :where {:key1 1} :explain? true :hint "key1_1_key2_1"))]
(is (= "key1_1_key2_1" (-> plan :queryPlanner :winningPlan :inputStage :indexName)))))

(testing "index2 seq"
(let [plan (-> (fetch :test_col :where {:key1 1} :explain? true :hint [:key1 :key2]))]
(is (= "key1_1_key2_1" (-> plan :queryPlanner :winningPlan :inputStage :indexName)))))

(testing "index3"
#_(testing "index3"
(let [plan (-> (fetch :test_col :where {:key1 1} :explain? true :hint "key1_-1"))]
(is (= "key1_-1" (-> plan :queryPlanner :winningPlan :inputStage :indexName)))))

(testing "index3 seq"
(let [plan (-> (fetch :test_col :where {:key1 1} :explain? true :hint [[:key1 -1]]))]
(is (= "key1_-1" (-> plan :queryPlanner :winningPlan :inputStage :indexName)))))

(testing "index4"
#_(testing "index4"
(let [plan (-> (fetch :test_col :where {:key1 1} :explain? true :hint "key1_1_key2_-1"))]
(is (= "key1_1_key2_-1" (-> plan :queryPlanner :winningPlan :inputStage :indexName)))))

@@ -649,6 +641,7 @@
"suffusion of yellow")))))


;; TODO: this is failing on the json branch too
(deftest test-distinct-values
(with-test-mongo
(insert! :distinct {:genus "Pan" :species "troglodytes" :common-name "chimpanzee"})
@@ -1097,3 +1090,30 @@
(is (= 3 (count index-info)))
(is (set/subset? #{"key1_1" "key1_-1"}
(set (map :name index-info))))))))


(deftest test-json-serialization
(with-test-mongo
(drop-coll! :json-test)
(insert! :json-test {:fruit "bananas" :count 1})
(let [bananas (fetch-one :json-test :as :json)
parsed (read-str bananas)]
(is (= {"fruit" "bananas"
"count" 1}
(select-keys parsed ["fruit" "count"]))))
(insert! :json-test

(clojure.data.json/write-str
{:fruit "apples" :count 2})

:from :json)
(let [fruits (->>
(fetch :json-test :as :json)
(map read-str)
(map #(select-keys % ["fruit" "count"]))
(set))]
(is (= #{{"fruit" "bananas"
"count" 1}
{"fruit" "apples"
"count" 2}}
fruits)))))