             LoggingRetryPolicy DefaultRetryPolicy DowngradingConsistencyRetryPolicy FallthroughRetryPolicy
             RetryPolicy ConstantReconnectionPolicy ExponentialReconnectionPolicy]))
 
+(def prepared-statement-cache (atom {}))
+
+(defn flush-prepared-statement-cache!
+  []
+  (reset! prepared-statement-cache {}))
+
 ;;
 ;; Load Balancing policies
 ;;

(defn ^Session connect
  "Connects to the Cassandra cluster. Use `build` function to build cluster with all required options."
  ([^Cluster cluster]
     (.connect cluster))
  ([^Cluster cluster keyspace]
     (.connect cluster (name keyspace))))

(defn connect!
  "Connects and sets *default-cluster* and *default-session* for default cluster and session, that
   cql/execute is going to use."
  [hosts & {:keys [keyspace] :as options}]
  (let [cluster (build-cluster (assoc options :contact-points hosts))
        session (if keyspace
                  (connect cluster keyspace)

  ([^String query]
     (prepare *default-session* query))
  ([^Session session ^String query]
     (if-let [cached (get @prepared-statement-cache [session query])]
       cached
       (let [prepared (.prepare ^Session session query)]
         (swap! prepared-statement-cache #(assoc % [session query] prepared))
         prepared))))

(defn build-cluster
  "Builds an instance of Cluster you can connect to.
