exceptions.ex (7621B)
1 defmodule Ecto.Query.CompileError do 2 @moduledoc """ 3 Raised at compilation time when the query cannot be compiled. 4 """ 5 defexception [:message] 6 end 7 8 defmodule Ecto.Query.CastError do 9 @moduledoc """ 10 Raised at runtime when a value cannot be cast. 11 """ 12 defexception [:type, :value, :message] 13 14 def exception(opts) do 15 value = Keyword.fetch!(opts, :value) 16 type = Keyword.fetch!(opts, :type) 17 msg = Keyword.fetch!(opts, :message) 18 %__MODULE__{value: value, type: type, message: msg} 19 end 20 end 21 22 defmodule Ecto.QueryError do 23 @moduledoc """ 24 Raised at runtime when the query is invalid. 25 """ 26 defexception [:message] 27 28 def exception(opts) do 29 message = Keyword.fetch!(opts, :message) 30 query = Keyword.fetch!(opts, :query) 31 hint = Keyword.get(opts, :hint) 32 33 message = """ 34 #{message} in query: 35 36 #{Inspect.Ecto.Query.to_string(query)} 37 """ 38 39 file = opts[:file] 40 line = opts[:line] 41 42 message = 43 if file && line do 44 relative = Path.relative_to_cwd(file) 45 Exception.format_file_line(relative, line) <> " " <> message 46 else 47 message 48 end 49 50 message = 51 if hint do 52 message <> "\n" <> hint <> "\n" 53 else 54 message 55 end 56 57 %__MODULE__{message: message} 58 end 59 end 60 61 defmodule Ecto.SubQueryError do 62 @moduledoc """ 63 Raised at runtime when a subquery is invalid. 64 """ 65 defexception [:message, :exception] 66 67 def exception(opts) do 68 exception = Keyword.fetch!(opts, :exception) 69 query = Keyword.fetch!(opts, :query) 70 71 message = """ 72 the following exception happened when compiling a subquery. 73 74 #{Exception.format(:error, exception, []) |> String.replace("\n", "\n ")} 75 76 The subquery originated from the following query: 77 78 #{Inspect.Ecto.Query.to_string(query)} 79 """ 80 81 %__MODULE__{message: message, exception: exception} 82 end 83 end 84 85 defmodule Ecto.InvalidChangesetError do 86 @moduledoc """ 87 Raised when we cannot perform an action because the 88 changeset is invalid. 89 """ 90 defexception [:action, :changeset] 91 92 def message(%{action: action, changeset: changeset}) do 93 changes = extract_changes(changeset) 94 errors = Ecto.Changeset.traverse_errors(changeset, & &1) 95 96 """ 97 could not perform #{action} because changeset is invalid. 98 99 Errors 100 101 #{pretty errors} 102 103 Applied changes 104 105 #{pretty changes} 106 107 Params 108 109 #{pretty changeset.params} 110 111 Changeset 112 113 #{pretty changeset} 114 """ 115 end 116 117 defp pretty(term) do 118 inspect(term, pretty: true) 119 |> String.split("\n") 120 |> Enum.map_join("\n", &" " <> &1) 121 end 122 123 defp extract_changes(%Ecto.Changeset{changes: changes}) do 124 Enum.reduce(changes, %{}, fn({key, value}, acc) -> 125 case value do 126 %Ecto.Changeset{action: :delete} -> acc 127 _ -> Map.put(acc, key, extract_changes(value)) 128 end 129 end) 130 end 131 defp extract_changes([%Ecto.Changeset{action: :delete} | tail]), 132 do: extract_changes(tail) 133 defp extract_changes([%Ecto.Changeset{} = changeset | tail]), 134 do: [extract_changes(changeset) | extract_changes(tail)] 135 defp extract_changes(other), 136 do: other 137 end 138 139 defmodule Ecto.CastError do 140 @moduledoc """ 141 Raised when a changeset can't cast a value. 142 """ 143 defexception [:message, :type, :value] 144 145 def exception(opts) do 146 type = Keyword.fetch!(opts, :type) 147 value = Keyword.fetch!(opts, :value) 148 msg = opts[:message] || "cannot cast #{inspect value} to #{inspect type}" 149 %__MODULE__{message: msg, type: type, value: value} 150 end 151 end 152 153 defmodule Ecto.InvalidURLError do 154 defexception [:message, :url] 155 156 def exception(opts) do 157 url = Keyword.fetch!(opts, :url) 158 msg = Keyword.fetch!(opts, :message) 159 msg = "invalid url #{url}, #{msg}. The parsed URL is: #{inspect(URI.parse(url))}" 160 %__MODULE__{message: msg, url: url} 161 end 162 end 163 164 defmodule Ecto.NoPrimaryKeyFieldError do 165 @moduledoc """ 166 Raised at runtime when an operation that requires a primary key is invoked 167 with a schema that does not define a primary key by using `@primary_key false` 168 """ 169 defexception [:message, :schema] 170 171 def exception(opts) do 172 schema = Keyword.fetch!(opts, :schema) 173 message = "schema `#{inspect schema}` has no primary key" 174 %__MODULE__{message: message, schema: schema} 175 end 176 end 177 178 defmodule Ecto.NoPrimaryKeyValueError do 179 @moduledoc """ 180 Raised at runtime when an operation that requires a primary key is invoked 181 with a schema missing value for its primary key 182 """ 183 defexception [:message, :struct] 184 185 def exception(opts) do 186 struct = Keyword.fetch!(opts, :struct) 187 message = "struct `#{inspect struct}` is missing primary key value" 188 %__MODULE__{message: message, struct: struct} 189 end 190 end 191 192 defmodule Ecto.ChangeError do 193 defexception [:message] 194 end 195 196 defmodule Ecto.NoResultsError do 197 defexception [:message] 198 199 def exception(opts) do 200 query = Keyword.fetch!(opts, :queryable) |> Ecto.Queryable.to_query 201 202 msg = """ 203 expected at least one result but got none in query: 204 205 #{Inspect.Ecto.Query.to_string(query)} 206 """ 207 208 %__MODULE__{message: msg} 209 end 210 end 211 212 defmodule Ecto.MultipleResultsError do 213 defexception [:message] 214 215 def exception(opts) do 216 query = Keyword.fetch!(opts, :queryable) |> Ecto.Queryable.to_query 217 count = Keyword.fetch!(opts, :count) 218 219 msg = """ 220 expected at most one result but got #{count} in query: 221 222 #{Inspect.Ecto.Query.to_string(query)} 223 """ 224 225 %__MODULE__{message: msg} 226 end 227 end 228 229 defmodule Ecto.MultiplePrimaryKeyError do 230 defexception [:message] 231 232 def exception(opts) do 233 operation = Keyword.fetch!(opts, :operation) 234 source = Keyword.fetch!(opts, :source) 235 params = Keyword.fetch!(opts, :params) 236 count = Keyword.fetch!(opts, :count) 237 238 msg = """ 239 expected #{operation} on #{source} to return at most one entry but got #{count} entries. 240 241 This typically means the field(s) set as primary_key in your schema/source 242 are not enough to uniquely identify entries in the repository. 243 244 Those are the parameters sent to the repository: 245 246 #{inspect params} 247 """ 248 249 %__MODULE__{message: msg} 250 end 251 end 252 253 defmodule Ecto.MigrationError do 254 defexception [:message] 255 end 256 257 defmodule Ecto.StaleEntryError do 258 defexception [:message, :changeset] 259 260 def exception(opts) do 261 action = Keyword.fetch!(opts, :action) 262 changeset = Keyword.fetch!(opts, :changeset) 263 264 msg = """ 265 attempted to #{action} a stale struct: 266 267 #{inspect changeset.data} 268 """ 269 270 %__MODULE__{message: msg, changeset: changeset} 271 end 272 end 273 274 defmodule Ecto.ConstraintError do 275 defexception [:type, :constraint, :message] 276 277 def exception(opts) do 278 type = Keyword.fetch!(opts, :type) 279 constraint = Keyword.fetch!(opts, :constraint) 280 changeset = Keyword.fetch!(opts, :changeset) 281 action = Keyword.fetch!(opts, :action) 282 283 constraints = 284 case changeset.constraints do 285 [] -> 286 "The changeset has not defined any constraint." 287 constraints -> 288 "The changeset defined the following constraints:\n\n" <> 289 Enum.map_join(constraints, "\n", &" * #{&1.constraint} (#{&1.type}_constraint)") 290 end 291 292 msg = """ 293 constraint error when attempting to #{action} struct: 294 295 * #{constraint} (#{type}_constraint) 296 297 If you would like to stop this constraint violation from raising an 298 exception and instead add it as an error to your changeset, please 299 call `#{type}_constraint/3` on your changeset with the constraint 300 `:name` as an option. 301 302 #{constraints} 303 """ 304 305 %__MODULE__{message: msg, type: type, constraint: constraint} 306 end 307 end