Packages
ecto_tablestore
0.13.1
0.15.1
0.15.0
0.14.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.2
0.12.1
0.12.0
0.11.2
0.11.1
0.11.0
0.10.1
0.10.0
0.9.0
0.8.3
0.8.2
0.8.1
0.8.0
0.7.0
0.6.1
0.6.0
0.5.11
0.5.10
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.2
0.4.1
0.4.0
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.0
0.1.0
Alibaba Tablestore adapter for Ecto
Current section
Files
Jump to
Current section
Files
lib/ecto_tablestore/schema.ex
defmodule EctoTablestore.Schema do
@moduledoc """
Define an Ecto schema for Tablestore product use, there are some reasons make we do some wrapper base on `Ecto.Schema`:
* Since Tablestore product does not support(also not recommend) the first primary key(aka the partition key) autogenerated
in server side, e.g. an auto increment sequence integer in server is not supported, so we set `@primary_key`
as `false` by default when use `#{inspect __MODULE__}`.
* Since Tablestore product's attribute column does not support DateTime or similar type in server side, so we use
`@timestamps_opts` to pre-configure `Ecto.Schema.timestamps/1` macro as an integer type for the generated `inserted_at`
and `updated_at` fields.
If you have explicitly set `@primary_key` and `@timestamps_opts`(or `Ecto.Schema.timestamps/1`) in the defined schema,
and then you can write `use Ecto.Schema` to make the schema definition more compatible in Ecto use, for example:
defmodule User do
use Ecto.Schema
@primary_key {:id, :id, autogenerate: false}
schema "user" do
field(:name, :string)
timestamps(
type: :integer,
autogenerate: {System, :os_time, []}
)
end
end
It equals to:
defmodule User do
use EctoTablestore.Schema
schema "user" do
field(:id, :id, primary_key: true)
field(:name, :string)
timestamps()
end
end
### About primary key
* The primary key supports `:id` (integer()) and `:binary_id` (binary()).
* By default the `:primary_key` option is `false`.
* The first defined primary key by the written order in the `schema` is the partition key.
* Up to 4 primary key(s), it is limited by Tablestore product server side.
* Up to 1 primary key with `autogenerate: true` option, it is limited by Tablestore product
server side.
* The primary key set with `autogenerate: true` will use the Tablestore product server's
[AUTO_INCREMENT](https://www.alibabacloud.com/help/doc-detail/47745.htm) feature.
* If the partition key set as `autogenerate: true` is not allowed to take advantage of the
AUTO_INCREMENT feature which it is limited by server, but there is a built-in implement to use
the `Sequence` to achieve the same atomic increment operation in `ecto_tablestore` library.
Here is an example about the primary keys:
defmodule User do
use EctoTablestore.Schema
schema "user" do
field :outer_id, :binary_id, primary_key: true
field :internal_id, :id, primary_key: true, autogenerate: true
field :name, :string
field :desc
end
end
By default, if not explicitly set field type will process it as a `:string` type.
"""
defmacro __using__(_) do
quote do
use Ecto.Schema
import EctoTablestore.Schema, only: [tablestore_schema: 2]
@primary_key false
@timestamps_opts [
type: :integer,
autogenerate: {EctoTablestore.Schema, :__timestamps__, []}
]
end
end
def __timestamps__() do
System.os_time()
end
@doc """
Due to the previous implements, this macro is reserved to make compatible when `:hashids` or `EctoTablestore.Hashids`
type defined (changes in `0.13.0`).
We may deprecate it in the future, please use `Ecto.Schema.schema/2` instead.
"""
defmacro tablestore_schema(source, do: block) do
block = transfer_custom_type_fields(block)
quote do
Ecto.Schema.schema(unquote(source), do: unquote(block))
end
end
defp transfer_custom_type_fields({:__block__, info, fields}) do
fields = Enum.map(fields, &map_custom_type/1)
{:__block__, info, fields}
end
defp map_custom_type({:field, info, [field_name, :hashids, opts]}) do
{:field, info, [field_name, Ecto.Hashids, opts]}
end
defp map_custom_type({:field, info, [field_name, {:__aliases__, _, [:EctoTablestore, :Hashids]}, opts]}) do
# reserved for compatible with the deleted `EctoTablestore.Hashids` type
{:field, info, [field_name, Ecto.Hashids, opts]}
end
defp map_custom_type(field) do
field
end
end