markusheilig

markusheilig

Ecto, myxql and zero-datetime

Hi everyone,

I have a table in a MySQL database with a ‘timestamp’ column called ‘created’ which may contain zero datetimes, i.e. ‘0000-00-00 00:00:00’.
My schema definition looks as follows:

defmodule MySchema do
  use Ecto.Schema

  schema "my_schema" do    
    field :created, :naive_datetime    
  end

end

I use the following dependencies (mix.exs) to access the database:

defp deps do
  [      
    {:ecto_sql, "~> 3.0"},
    {:myxql, git: "https://github.com/elixir-ecto/myxql.git", ref: "e01ebc7", override: true},
  ]
end

I use the e01ebc7 commit for myxql since it converts a zero datetime into an atom called ‘:zero_datetime’.

But when I try to query data using Repo.all(MySchema), I get the following error:

 (ArgumentError) cannot load `:zero_datetime` as type :naive_datetime for field :created in %MySchema{__meta__: #Ecto.Schema.Metadata<:loaded, "my_schema">, created: nil, id: nil }
    (ecto) lib/ecto/repo/queryable.ex:345: Ecto.Repo.Queryable.struct_load!/6
    (ecto) lib/ecto/repo/queryable.ex:201: anonymous fn/5 in Ecto.Repo.Queryable.preprocessor/3
    (elixir) lib/enum.ex:1336: Enum."-map/2-lists^map/1-0-"/2
    (elixir) lib/enum.ex:1336: Enum."-map/2-lists^map/1-0-"/2
    (ecto) lib/ecto/repo/queryable.ex:158: Ecto.Repo.Queryable.execute/4
    (ecto) lib/ecto/repo/queryable.ex:18: Ecto.Repo.Queryable.all/3
    (my_app) lib/my_app/application.ex:23: MyApp.Application.example/0

Is there a way to convert data with :zero_datetime to MySchema?

Currently, I have to drop rows with zero-datetimes like this:

min_date = ~N[0000-01-01 00:00:00]
query = from m in MySchema,
        where: m.created >= ^min_date,
        select: m
Repo.all(query)

I’m looking forward for answers :slight_smile:

Most Liked

dimitarvp

dimitarvp

For future reference and for whomever might need this, here’s what worked for me:

defmodule YourApp.Types.ZeroableDateTime do
  use Ecto.Type

  def type, do: :naive_datetime

  def cast(data), do: {:ok, data}

  # Just return `nil` datetime instead of crashing.
  def load(:zero_datetime), do: {:ok, nil}
  def load(%NaiveDateTime{} = data), do: {:ok, data}

  def dump(%NaiveDateTime{} = data), do: {:ok, data}
  def dump(_), do: :error
end
LostKobrakai

LostKobrakai

You can create a custom Ecto.Type implemetation, which knows how to handle zero’d dates, because 0000-00-00 00:00:00 is not a valid iso8601 datetime. There’s no month or day 0.

wojtekmach

wojtekmach

Hex Core Team

Yes, custom type is the way to go. I would however take a step back and ask what we are representing by this zero datetime? MySQL uses it to represent invalid values, eg result of some arithmetic, and only when appropriate sql mode is set, by default on newer versions you would get an error instead. This also brings the question that even if we add a custom type what would we cast/load/dump this value to - keep it as :zero_datetime? Then any time we work with this value we would have to check if its non-zero. Without knowing about the usecase I’d either use a NULL or smallest valid date instead of the zero one.

Last Post!

dimitarvp

dimitarvp

Yep, the final code is exactly how it should be. You do NOT use the module, you either alias it or you use the fully-qualified name (as you did).

Where Next?

Popular in Questions Top

vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New

Other popular topics Top

grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 54260 488
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 31586 112
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New

We're in Beta

About us Mission Statement