View Source Vtc.Ecto.Postgres.PgFramestamp.Range (vtc v0.13.11)

Defines a custom Range type for dealing with Framestamp ranges.

The new range types are defined as follows:

CREATE TYPE framestamp_range AS RANGE (
  subtype = framestamp,
  subtype_diff = framestamp_range_private.subtype_diff
  canonical = framestamp_range_private.canonicalization
);

Framestamp ranges can be created in SQL expressions like so:

SELECT framestamp_range(stamp_1, stamp_2, '[)')

Framestamp fastranges can be created in SQL expressions like so:

SELECT framestamp_fastrange(stamp_1, stamp_2)

Indexing

framestamp_range is currently VERY slow when using a GiST index, consider using a framestamp_fastrange instead.

canonicalization

Canonicalization

Postgres framestamp_range values are ALWAYS coerced to exclusive out ranges. That means that even if a Framestamp.Range has :out_type set to :inclusive when it is sent to the database, it will come back from the database with :out_type set to :exclusive, and the :out field will be adjusted accordingly.

Further, when a Range operation, like a union, would result in an in and out point with different framerates, the higher rate will always be selected.

This unlike the application behavior of Vtc.Framestamp.Range, which always inherets the rate of the value that apears on the left side. This behavior may be updated to match Vtc's application behavior in the future.

framestamp-fast-range

Framestamp Fast Range

In addition to framestamp_range, a framestamp_fastrange type is defined as well:

CREATE TYPE framestamp_fastrange AS RANGE (
  subtype = double precision,
  subtype_diff = float8mi
);

Fast ranges are meant to support GiST indexing, as in most cases, framestamp_range will be VERY slow to index.

Frame-accurate

Unlike framestamp_range, framestamp_fastrange is NOT frame-accurate and should not be used where frame-accuracy is desired or required.

field-migrations

Field migrations

You can create framestamp_range fields during a migration like so:

alias Vtc.Framerate

create table("framestamp_ranges") do
  add(:a, Framestamp.Range.type())
  add(:b, Framestamp.Range.type())
end

Framestamp.Range re-exports the Ecto.Type implementation of this module, and can be used any place this module would be used.

schema-fields

Schema fields

Then in your schema module:

defmodule MyApp.FramestampRanges do
@moduledoc false
use Ecto.Schema

alias Vtc.Framestamp

@type t() :: %__MODULE__{
        a: Framestamp.Range.t(),
        b: Framestamp.Range.t()
      }

schema "rationals_01" do
  field(:a, Framestamp.Range)
  field(:b, Framestamp.Range)
end

changesets

Changesets

With the above setup, changesets should just work:

def changeset(schema, attrs) do
  schema
  |> Changeset.cast(attrs, [:a, :b])
  |> Changeset.validate_required([:a, :b])
end

Framestamp.Range values can be cast from the following values in changesets:

fragments

Fragments

Framerate values must be explicitly cast using type/2:

stamp_in = Framestamp.with_frames!("01:00:00:00", Rates.f23_98())
stamp_out = Framestamp.with_frames!("02:00:00:00", Rates.f23_98())
stamp_range = Framestamp.new!(stamp_in, stamp_out)

query = Query.from(
  f in fragment("SELECT ? as r", type(^stamp_range, Framerate.Range)), select: f.r
)

Link to this section Summary

Types

Type of the raw composite value that will be sent to / received from the database.

Functions

Callback implementation for Ecto.Type.embed_as/1.

Callback implementation for Ecto.Type.equal?/2.

The database type for PgFramerate.

Link to this section Types

@type db_record() :: %Postgrex.Range{
  lower: Vtc.Ecto.Postgres.PgFramestamp.db_record(),
  lower_inclusive: boolean(),
  upper: Vtc.Ecto.Postgres.PgFramestamp.db_record(),
  upper_inclusive: boolean()
}

Type of the raw composite value that will be sent to / received from the database.

Link to this section Functions

Callback implementation for Ecto.Type.embed_as/1.

Callback implementation for Ecto.Type.equal?/2.

@spec type() :: atom()

The database type for PgFramerate.

Can be used in migrations as the fields type.