       value_float double precision,
       value_string text,
       value_boolean boolean,
-      value jsonb
+      value jsonb not null
     );"
 
    "CREATE TABLE facts_transform (

     (str "ALTER TABLE ONLY edges"
          "  ADD CONSTRAINT edges_certname_source_target_type_unique_key"
          "  UNIQUE (certname, source, target, type)"))))
(defn add-latest-report-timestamp-to-certnames []
  (jdbc/do-commands
    "DROP INDEX IF EXISTS idx_certnames_latest_report_timestamp"

               AND fv.value_float   IS NOT DISTINCT FROM f.value_float
               AND fv.value_string  IS NOT DISTINCT FROM f.value_string
               AND fv.value_boolean IS NOT DISTINCT FROM f.value_boolean
               AND fv.value         = f.value")

  ;; populate fact_values.value_hash
  (jdbc/call-with-query-rows
   ["select id, value::text from fact_values"]
   (fn [rows]
     (doseq [batch (partition-all 5000 rows)]
       (let [ids (map :id rows)
             hashes (map #(-> (:value %)
                              json/parse
                              hash/generic-identity-hash
                              sutils/munge-hash-for-storage)
                         rows)]
         (jdbc/do-prepared
          "update fact_values set value_hash = in_data.hash
            from (select unnest(?) as id, unnest(?) as hash) in_data
            where fact_values.id = in_data.id"
          [(sutils/array-to-param "bigint" Long ids)
           (sutils/array-to-param "bytea" PGobject hashes)])))))

  (jdbc/do-commands
   "DROP TABLE facts"
