All tables have a set_field_type()
method, which changes the types and/or
the NOT NULL
settings of one or more columns in the
target. It's a wrapper for the following
SQL constructs:
ALTER TABLE
... ALTER COLUMN
... SET TYPE
ALTER TABLE
... ALTER COLUMN
... SET NOT NULL
ALTER TABLE
... ALTER COLUMN
... DROP NOT NULL
But back to our story. As we left it in the previous section, the SQL
table points
conformed
to the table object newer_point
.
In particular, it had a REAL
column corresponding
to a member declared float height
.
But now we decide that heights will require double precision. In PostgreSQL
terms, that's a change from REAL
to DOUBLE
PRECISION
. But we work in C++, so for us it's a change from
float
to double
.
So our table is going to need a new value type (again). Let's define
it:
struct point_xhd { float x; double height; }; QUINCE_MAP_CLASS(point_xhd, (x)(height))
and let's construct the latest table object:
table<point_xhd> newest_points(db, "points", &point_xhd::x);
Now, to make the target conform to newest_points
,
we change the column type:
newest_points.set_field_type(newest_points->height);
which says:
In
newest_points
's target, change the type of the column thatnewest_points->height
represents, from whatever it might be now, to the SQL type thatnewest_points->height
uses.
The existing values in the affected column are converted from the old type to the new type, as if by a server-side cast.
Here we passed a double
mapper, so one column changed type; but we can pass a mapper for any
mapped type. If it is a multi-column type, then set_field_type()
will set the types of all the columns,
provided that columns already exist with the names
that the mapper expects.
We can use set_field_type()
to change optionals to non-optionals
or vice versa, again with the proviso that columns
already exist with the names that the mapper expects [14] . Then set_field_type()
will change the NOT NULL
settings, from whatever they might be now, to the settings that the mapper
expects (described here).
[14]
The only effect of the proviso is that we can't change a T
to a boost::optional<
T
>
when T
is a type that can be represented by all NULL
s.
E.g. you can't change a boost::optional<float>
to a boost::optional<boost::optional<float>>
. It's not a restriction you're
likely to run into.