Last active
August 9, 2016 07:40
-
-
Save x/cb4580dc23e08b7cb98ff0139a340278 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(require '[clojure.string :refer [join]]) | |
(defprotocol ExpressionBuilderProtocol | |
(ensureExprAttrName [this val]) | |
(ensureExprAttrVal [this val]) | |
(ADD [this attr amnt]) | |
(SET [this attr val]) | |
(toArgs [this])) | |
(defrecord ExpressionBuilder | |
[expr-map expr-attr-vals expr-attr-names] | |
ExpressionBuilderProtocol | |
(ensureExprAttrName [this attr] | |
(if (get expr-attr-names attr) | |
expr-attr-names | |
(assoc expr-attr-names | |
attr | |
(str "#attr" (count expr-attr-names))))) | |
(ensureExprAttrVal [this val] | |
(if (get expr-attr-vals val) | |
expr-attr-vals | |
(assoc expr-attr-vals | |
val | |
(str ":val" (count expr-attr-vals))))) | |
(ADD [this attr amnt] | |
(let [expr-attr-names (.ensureExprAttrName this attr) | |
expr-attr-vals (.ensureExprAttrVal this amnt) | |
attr (get expr-attr-names attr) | |
amnt (get expr-attr-vals amnt) | |
add-expr (format "%s = %s + %s" attr attr amnt) | |
expr-map (update expr-map ::ADD (fnil conj []) add-expr)] | |
(ExpressionBuilder. expr-map expr-attr-vals expr-attr-names))) | |
(SET [this attr val] | |
(let [expr-attr-names (.ensureExprAttrName this attr) | |
expr-attr-vals (.ensureExprAttrVal this val) | |
attr (get expr-attr-names attr) | |
val (get expr-attr-vals val) | |
add-expr (format "%s = %s" attr val) | |
expr-map (update expr-map ::SET (fnil conj #{}) add-expr)] | |
(ExpressionBuilder. expr-map expr-attr-vals expr-attr-names))) | |
(toArgs | |
[{:keys [expr-attr-vals expr-attr-names expr-map]}] | |
{:expr-attr-vals (clojure.set/map-invert expr-attr-vals) | |
:expr-attr-names (clojure.set/map-invert expr-attr-names) | |
:expr (join " " (map (fn [[k exprs]] (str (name k) " " (join "," exprs))) | |
expr-map))})) | |
(defn table-fn | |
[_] | |
"table_foo") | |
(defn part-key-fn | |
[{:keys [host hour]}] | |
(str host "::" hour)) | |
(defn sort-key-fn | |
[{:keys [source_path target_path]}] | |
(str source_path "::" target_path)) | |
(->> | |
[{:host "h1" | |
:source_path "sp1" | |
:target_path "tp1" | |
:hour 7 | |
:minute 10 | |
:weight 100} | |
{:host "h2" | |
:source_path "sp2" | |
:target_path "tp2" | |
:hour 7 | |
:minute 10 | |
:weight 100} | |
{:host "h1" | |
:source_path "sp1" | |
:target_path "tp1" | |
:hour 7 | |
:minute 10 | |
:weight 200} | |
{:host "h1" | |
:source_path "sp1" | |
:target_path "tp1" | |
:hour 7 | |
:minute 11 | |
:weight 100}] | |
(reduce (fn [exprs click] | |
(update exprs | |
((juxt table-fn part-key-fn sort-key-fn) click) | |
#(-> (or % (ExpressionBuilder. {} {} {})) | |
(.ADD (str "M" (:minute click)) (:weight click)) | |
(.SET "SourcePath" (:source_path click)) | |
(.SET "TargetPath" (:target_path click))))) | |
{}) | |
(map (fn [[[table-name part-key sort-key] expr]] | |
(println "apply update to " | |
(merge {:table-name table-name | |
:part-key part-key | |
:sort-key sort-key} | |
(.toArgs expr)))))) | |
;=> apply update to {:table-name table_foo, :part-key h1::7, :sort-key sp1::tp1, :expr-attr-vals {:val0 100, :val1 sp1, :val2 tp1, :val3 200}, :expr-attr-names {#attr0 M10, #attr1 SourcePath, #attr2 TargetPath, #attr3 M11}, :expr ADD #attr0 = #attr0 + :val0,#attr0 = #attr0 + :val3,#attr3 = #attr3 + :val0 SET #attr1 = :val1,#attr2 = :val2} | |
;=> apply update to {:table-name table_foo, :part-key h2::7, :sort-key sp2::tp2, :expr-attr-vals {:val0 100, :val1 sp2, :val2 tp2}, :expr-attr-names {#attr0 M10, #attr1 SourcePath, #attr2 TargetPath}, :expr ADD #attr0 = #attr0 + :val0 SET #attr1 = :val1,#attr2 = :val2} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment