sql.ur 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. fun sqexps [env] [fields] (fl : folder fields) (inj : $(map sql_injectable fields)) (r : $fields) =
  2. @map2 [sql_injectable] [ident] [sql_exp env [] []]
  3. (fn [t] => @sql_inject)
  4. fl inj r
  5. fun selector [tn :: Name] [fs] [ofs] [fs ~ ofs] (fl : folder fs) (m : $(map sql_injectable fs)) (r : $fs)
  6. : sql_exp [tn = ofs ++ fs] [] [] bool =
  7. @foldR2 [sql_injectable] [ident]
  8. [fn key => rest :: {Type} -> [rest ~ key] => sql_exp [tn = key ++ rest] [] [] bool]
  9. (fn [nm :: Name] [t :: Type] [key :: {Type}] [[nm] ~ key]
  10. (inj : sql_injectable t) (v : t)
  11. (exp : rest :: {Type} -> [rest ~ key] => sql_exp [tn = key ++ rest] [] [] bool)
  12. [rest :: {Type}] [rest ~ [nm = t] ++ key] =>
  13. (WHERE {{tn}}.{nm} = {@sql_inject inj v} AND {exp [[nm = t] ++ rest]}))
  14. (fn [rest :: {Type}] [rest ~ []] => (WHERE TRUE))
  15. fl m r [_] !
  16. fun joiner [tn1 :: Name] [tn2 :: Name] [fs] [ofs1] [ofs2] [[tn1] ~ [tn2]] [fs ~ ofs1] [fs ~ ofs2]
  17. (fl : folder fs) : sql_exp [tn1 = ofs1 ++ fs, tn2 = ofs2 ++ fs] [] [] bool =
  18. @fold
  19. [fn key => rest1 :: {Type} -> rest2 :: {Type} -> [rest1 ~ key] => [rest2 ~ key] => sql_exp [tn1 = key ++ rest1, tn2 = key ++ rest2] [] [] bool]
  20. (fn [nm :: Name] [t :: Type] [key :: {Type}] [[nm] ~ key]
  21. (exp : rest1 :: {Type} -> rest2 :: {Type} -> [rest1 ~ key] => [rest2 ~ key]
  22. => sql_exp [tn1 = key ++ rest1, tn2 = key ++ rest2] [] [] bool)
  23. [rest1 :: {Type}] [rest2 :: {Type}] [rest1 ~ [nm = t] ++ key] [rest2 ~ [nm = t] ++ key] =>
  24. (WHERE {{tn1}}.{nm} = {{tn2}}.{nm} AND {exp [[nm = t] ++ rest1] [[nm = t] ++ rest2]}))
  25. (fn [rest1 :: {Type}] [rest2 :: {Type}] [rest1 ~ []] [rest2 ~ []] => (WHERE TRUE))
  26. fl [_] [_] ! !
  27. fun insertIfMissing [keyCols ::: {Type}] [otherCols ::: {Type}] [otherKeys ::: {{Unit}}]
  28. [keyCols ~ otherCols] [[Pkey] ~ otherKeys]
  29. (kfl : folder keyCols) (kinj : $(map sql_injectable keyCols))
  30. (ofl : folder otherCols) (oinj : $(map sql_injectable otherCols))
  31. (t : sql_table (keyCols ++ otherCols) ([Pkey = map (fn _ => ()) keyCols] ++ otherKeys))
  32. (vs : $(keyCols ++ otherCols))
  33. : transaction bool =
  34. alreadyThere <- oneRowE1 (SELECT COUNT( * ) > 0
  35. FROM t
  36. WHERE {@selector [#T] ! kfl kinj (vs --- _)});
  37. if alreadyThere then
  38. return False
  39. else
  40. dml (insert t (@sqexps kfl kinj (vs --- _)
  41. ++ @sqexps ofl oinj (vs --- _)));
  42. return True
  43. fun deleteByKey [keyCols ::: {Type}] [otherCols ::: {Type}] [otherKeys ::: {{Unit}}]
  44. [keyCols ~ otherCols] [[Pkey] ~ otherKeys]
  45. (kfl : folder keyCols) (kinj : $(map sql_injectable keyCols))
  46. (t : sql_table (keyCols ++ otherCols) ([Pkey = map (fn _ => ()) keyCols] ++ otherKeys))
  47. (vs : $keyCols) =
  48. dml (delete t (@selector [#T] ! kfl kinj vs))
  49. fun lookup [keyCols ::: {Type}] [otherCols ::: {Type}] [otherKeys ::: {{Unit}}]
  50. [keyCols ~ otherCols] [[Pkey] ~ otherKeys]
  51. (kfl : folder keyCols) (kinj : $(map sql_injectable keyCols))
  52. (t : sql_table (keyCols ++ otherCols) ([Pkey = map (fn _ => ()) keyCols] ++ otherKeys))
  53. (vs : $keyCols)
  54. : transaction (option $otherCols) =
  55. oneOrNoRows1 (SELECT t.{{otherCols}}
  56. FROM t
  57. WHERE {@selector [#T] ! kfl kinj (vs --- _)})
  58. fun listify [lead :: Name] [cols ::: {Type}] [rest ::: {{Type}}] [[lead] ~ rest]
  59. (fl : folder cols) (eqs : $(map eq cols)) (q : sql_query [] [] ([lead = cols] ++ rest) []) =
  60. query q
  61. (fn r acc =>
  62. return (case acc of
  63. [] => (r.lead, (r -- lead) :: []) :: []
  64. | (key, ls) :: acc' =>
  65. if @Record.equal eqs fl r.lead key then
  66. (key, (r -- lead) :: ls) :: acc'
  67. else
  68. (r.lead, (r -- lead) :: []) :: acc))
  69. []