All tables have an add_field() method, which adds one or more columns to the target. It's a wrapper for SQL's ALTER TABLE ... ADD COLUMN.

Suppose the SQL table points already exists, with its columns x and y (perhaps as a result of running the code examples in the previous section), and now we want to add a new mapped member float z to each record. We start (at a suitable spot in the code, i.e. in a namespace but not in a function) by defining the value type that we want the table to have:

struct point_3d {
    float x;
    float y;
    float z;
QUINCE_MAP_CLASS(point_3d, (x)(y)(z))

And then, some time after the construction of db, we construct the table object:

table<point_3d> points(db, "points", &point_3d::x);

The state of affairs right now is:

Therefore we cannot call If we tried, it would throw a table_mismatch_exception.

So we do this:


This adds a column to the target, with the name (z), type (REAL) and the NOT NULL setting (set) that the mapper points->z expects. (And yes, it really does add the column. Table alteration methods do things, unlike specify_index() etc. that leave notes to ask open() to do things.)

Now the target conforms to the table points, so we can go ahead and call, and then proceed with querying and data manipulation.

In this example we passed add_field() a float mapper, so it added a single REAL column; but we can pass a mapper for any mapped type. If it is a multi-column type, then add_field() will add multiple columns.

Populating the new field

By default, add_field() fills the new columns with a default-constructed value. That is to say, table.add_field(mapper) makes a default-constructed value of the mapped type (float in this case), and initializes the new columns (just the z column in this case) with an SQL representation of that default-constructed value (0.0f in this case).

Alternatively you can specify the value as a second argument:

points.add_field(points->z, -12.6f);

or use a server-side expression:

points.add_field(points->z, points->x + points->y);

The rules governing the arguments are the same as for update(): the first argument must be a mapper for some type T, and then the second argument can be T or abstract_mapper<T>. The table's value mapper is visible to the second argument.