Changeset: 075cac9cdbd4 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/075cac9cdbd4
Modified Files:
sql/backends/monet5/sql_cat.c
sql/server/rel_schema.c
sql/server/sql_mvc.c
sql/server/sql_mvc.h
sql/server/sql_parser.y
sql/storage/bat/bat_storage.c
sql/storage/sql_storage.h
sql/storage/store.c
Branch: Mar2025
Log Message:
add initial support for alter table tn alter column cn type;
ie alter the type of a column
(grafted from c039848dc29e5ab0b791594dfbad3e666263c5a5)
diffs (truncated from 320 to 300 lines):
diff --git a/sql/backends/monet5/sql_cat.c b/sql/backends/monet5/sql_cat.c
--- a/sql/backends/monet5/sql_cat.c
+++ b/sql/backends/monet5/sql_cat.c
@@ -1195,7 +1195,7 @@ alter_table(Client cntxt, mvc *sql, char
}
for (n = ol_first_node(t->columns); n; n = n->next) {
- /* null or default value changes */
+ /* null, default value or type changes */
sql_column *c = n->data;
if (c->base.new)
@@ -1273,6 +1273,17 @@ alter_table(Client cntxt, mvc *sql, char
break;
}
}
+ if (subtype_cmp(&c->type, &nc->type) != 0) {
+ switch (mvc_subtype(sql, nc, &c->type)) {
+ case -1:
+ throw(SQL,"sql.alter_table",
SQLSTATE(HY013) MAL_MALLOC_FAIL);
+ case -2:
+ case -3:
+ throw(SQL,"sql.alter_table",
SQLSTATE(42000) "ALTER TYPE: transaction conflict detected");
+ default:
+ break;
+ }
+ }
}
/* handle new columns */
for (; n; n = n->next) {
diff --git a/sql/server/rel_schema.c b/sql/server/rel_schema.c
--- a/sql/server/rel_schema.c
+++ b/sql/server/rel_schema.c
@@ -1178,6 +1178,9 @@ table_element(sql_query *query, symbol *
case SQL_DROP_CONSTRAINT:
msg = "drop constraint from";
break;
+ case SQL_TYPE:
+ msg = "alter column type";
+ break;
default:
sql_error(sql, 02, SQLSTATE(M0M03) "%s: Unknown table
element (%p)->token = %s\n", action, s, token2string(s->token));
return SQL_ERR;
@@ -1440,6 +1443,39 @@ table_element(sql_query *query, symbol *
case SQL_DROP_CONSTRAINT:
res = SQL_OK;
break;
+ case SQL_TYPE:
+ {
+ dlist *l = s->data.lval;
+ char *cname = l->h->data.sval;
+ sql_subtype *tv = &l->h->next->data.typeval;
+ sql_column *col = mvc_bind_column(sql, t, cname);
+
+ assert(l->h->next->type == type_type);
+ (void)tv;
+ if (col == NULL) {
+ sql_error(sql, ERR_NOTFOUND, SQLSTATE(42S22) "ALTER
TYPE: no such column '%s'\n", cname);
+ return SQL_ERR;
+ }
+ if (t->system) {
+ sql_error(sql, 02, SQLSTATE(42000) "ALTER TYPE: cannot
alter type of column '%s': table is a system table\n", cname);
+ return SQL_ERR;
+ }
+ if (mvc_check_dependency(sql, col->base.id, COLUMN_DEPENDENCY,
NULL)) {
+ sql_error(sql, 02, SQLSTATE(2BM37) "ALTER TYPE: cannot
alter type of column '%s': there are database objects which depend on it\n",
cname);
+ return SQL_ERR;
+ }
+ switch (mvc_subtype(sql, col, tv)) {
+ case -1:
+ (void) sql_error(sql, 02, SQLSTATE(HY013)
MAL_MALLOC_FAIL);
+ return SQL_ERR;
+ case -2:
+ case -3:
+ (void) sql_error(sql, 02, SQLSTATE(42000) "NULL
CONSTRAINT: transaction conflict detected");
+ return SQL_ERR;
+ default:
+ break;
+ }
+ } break;
default:
res = SQL_ERR;
}
diff --git a/sql/server/sql_mvc.c b/sql/server/sql_mvc.c
--- a/sql/server/sql_mvc.c
+++ b/sql/server/sql_mvc.c
@@ -1529,6 +1529,18 @@ mvc_storage(mvc *m, sql_column *col, cha
}
int
+mvc_subtype(mvc *m, sql_column *col, sql_subtype *t)
+{
+ TRC_DEBUG(SQL_TRANS, "Type: %s %s\n", col->base.name,
t->type->base.name);
+ if (col->t->persistence == SQL_DECLARED_TABLE) {
+ col->type = *t;
+ return 0;
+ } else {
+ return sql_trans_alter_type(m->session->tr, col, t);
+ }
+}
+
+int
mvc_access(mvc *m, sql_table *t, sht access)
{
TRC_DEBUG(SQL_TRANS, "Access: %s %d\n", t->base.name, access);
diff --git a/sql/server/sql_mvc.h b/sql/server/sql_mvc.h
--- a/sql/server/sql_mvc.h
+++ b/sql/server/sql_mvc.h
@@ -229,6 +229,7 @@ extern int mvc_default(mvc *c, sql_colum
extern int mvc_check(mvc *m, sql_column *col, char *check);
extern int mvc_drop_default(mvc *c, sql_column *col);
extern int mvc_storage(mvc *c, sql_column *col, char *storage);
+extern int mvc_subtype(mvc *m, sql_column *col, sql_subtype *t);
extern int mvc_access(mvc *m, sql_table *t, sht access);
extern int mvc_is_sorted(mvc *c, sql_column *col);
extern int mvc_is_unique(mvc *m, sql_column *col);
diff --git a/sql/server/sql_parser.y b/sql/server/sql_parser.y
--- a/sql/server/sql_parser.y
+++ b/sql/server/sql_parser.y
@@ -1450,6 +1450,11 @@ alter_table_element:
append_string(l, $1);
append_string(l, NULL);
$$ = _symbol_create_list( SQL_STORAGE, l); }
+ | column data_type
+ { dlist *l = L();
+ append_string(l, $1);
+ append_type(l, &$2);
+ $$ = _symbol_create_list( SQL_TYPE, l); }
;
drop_table_element:
diff --git a/sql/storage/bat/bat_storage.c b/sql/storage/bat/bat_storage.c
--- a/sql/storage/bat/bat_storage.c
+++ b/sql/storage/bat/bat_storage.c
@@ -3009,6 +3009,62 @@ col_not_null(sql_trans *tr, sql_column *
}
static int
+swap_bats(sql_trans *tr, sql_column *col, BAT *bn)
+{
+ bool update_conflict = false;
+
+ if (segments_in_transaction(tr, col->t))
+ return LOG_CONFLICT;
+
+ sql_delta *d = NULL, *odelta = ATOMIC_PTR_GET(&col->data);
+
+ if ((d = bind_col_data(tr, col, &update_conflict)) == NULL)
+ return update_conflict ? LOG_CONFLICT : LOG_ERR;
+ assert(d && d->cs.ts == tr->tid);
+ if (odelta != d)
+ trans_add_obj(tr, &col->base, d, &tc_gc_col,
&commit_update_col, NOT_TO_BE_LOGGED(col->t)?NULL:&log_update_col);
+ if (d->cs.bid)
+ temp_destroy(d->cs.bid);
+ if (d->cs.uibid)
+ temp_destroy(d->cs.uibid);
+ if (d->cs.uvbid)
+ temp_destroy(d->cs.uvbid);
+ bat_set_access(bn, BAT_READ);
+ d->cs.bid = temp_create(bn);
+ d->cs.uibid = 0;
+ d->cs.uvbid = 0;
+ d->cs.ucnt = 0;
+ d->cs.cleared = true;
+ d->cs.ts = tr->tid;
+ ATOMIC_INIT(&d->cs.refcnt, 1);
+ return LOG_OK;
+}
+
+static int
+col_subtype(sql_trans *tr, sql_column *col, sql_subtype *t)
+{
+ int res = LOG_ERR;
+ assert(tr->active);
+ if (!isTable(col->t) || !col->t->s)
+ return res;
+
+ if (col && ATOMIC_PTR_GET(&col->data)) {
+ BAT *b = bind_col(tr, col, RDONLY);
+
+ if (!b)
+ return res;
+
+ BAT *bn = BATconvert(b, NULL /* could use tids, but need NILS
*/, t->type->localtype, col->type.scale, t->scale, t->digits);
+ if (!bn)
+ return res;
+ BBPreclaim(b);
+ res = swap_bats(tr, col, bn);
+ BBPreclaim(bn);
+ }
+ return res;
+}
+
+static int
load_cs(sql_trans *tr, column_storage *cs, int type, sqlid id)
{
sqlstore *store = tr->store;
@@ -4974,38 +5030,6 @@ bind_cands(sql_trans *tr, sql_table *t,
}
static int
-swap_bats(sql_trans *tr, sql_column *col, BAT *bn)
-{
- bool update_conflict = false;
-
- if (segments_in_transaction(tr, col->t))
- return LOG_CONFLICT;
-
- sql_delta *d = NULL, *odelta = ATOMIC_PTR_GET(&col->data);
-
- if ((d = bind_col_data(tr, col, &update_conflict)) == NULL)
- return update_conflict ? LOG_CONFLICT : LOG_ERR;
- assert(d && d->cs.ts == tr->tid);
- if (odelta != d)
- trans_add_obj(tr, &col->base, d, &tc_gc_col,
&commit_update_col, NOT_TO_BE_LOGGED(col->t)?NULL:&log_update_col);
- if (d->cs.bid)
- temp_destroy(d->cs.bid);
- if (d->cs.uibid)
- temp_destroy(d->cs.uibid);
- if (d->cs.uvbid)
- temp_destroy(d->cs.uvbid);
- bat_set_access(bn, BAT_READ);
- d->cs.bid = temp_create(bn);
- d->cs.uibid = 0;
- d->cs.uvbid = 0;
- d->cs.ucnt = 0;
- d->cs.cleared = true;
- d->cs.ts = tr->tid;
- ATOMIC_INIT(&d->cs.refcnt, 1);
- return LOG_OK;
-}
-
-static int
vacuum_col(sql_trans *tr, sql_column *c, bool force)
{
if (segments_in_transaction(tr, c->t))
@@ -5149,6 +5173,7 @@ bat_storage_init( store_functions *sf)
sf->col_stats = &col_stats;
sf->col_set_range = &col_set_range;
sf->col_not_null = &col_not_null;
+ sf->col_subtype = &col_subtype;
sf->col_dup = &col_dup;
sf->idx_dup = &idx_dup;
diff --git a/sql/storage/sql_storage.h b/sql/storage/sql_storage.h
--- a/sql/storage/sql_storage.h
+++ b/sql/storage/sql_storage.h
@@ -152,6 +152,7 @@ typedef int (*prop_col_fptr) (sql_trans
typedef int (*proprec_col_fptr) (sql_trans *tr, sql_column *c, bool *nonil,
bool *unique, double *unique_est, ValPtr min, ValPtr max);
typedef int (*col_set_range_fptr) (sql_trans *tr, sql_column *c, sql_part *pt,
bool add_range);
typedef int (*col_not_null_fptr) (sql_trans *tr, sql_column *c, bool not_null);
+typedef int (*col_subtype_fptr) (sql_trans *tr, sql_column *c, sql_subtype *t);
/*
-- create the necessary storage resources for columns, indices and tables
@@ -242,6 +243,7 @@ typedef struct store_functions {
proprec_col_fptr col_stats;
col_set_range_fptr col_set_range; /* set range properties to the column
low level structures */
col_not_null_fptr col_not_null; /* switch not null property */
+ col_subtype_fptr col_subtype; /* switch types */
col_dup_fptr col_dup;
idx_dup_fptr idx_dup;
@@ -400,6 +402,7 @@ extern int sql_trans_drop_column(sql_tra
extern int sql_trans_alter_null(sql_trans *tr, sql_column *col, int isnull);
extern int sql_trans_alter_default(sql_trans *tr, sql_column *col, char *val);
extern int sql_trans_alter_storage(sql_trans *tr, sql_column *col, char
*storage);
+extern int sql_trans_alter_type(sql_trans *tr, sql_column *col, sql_subtype
*t);
extern int sql_trans_alter_check(sql_trans *tr, sql_column *col, char *check);
extern int sql_trans_is_sorted(sql_trans *tr, sql_column *col);
extern int sql_trans_is_unique(sql_trans *tr, sql_column *col);
diff --git a/sql/storage/store.c b/sql/storage/store.c
--- a/sql/storage/store.c
+++ b/sql/storage/store.c
@@ -6494,6 +6494,45 @@ sql_trans_alter_storage(sql_trans *tr, s
}
int
+sql_trans_alter_type(sql_trans *tr, sql_column *col, sql_subtype *t)
+{
+ int res = LOG_OK;
+ sqlstore *store = tr->store;
+
+ if (subtype_cmp(&col->type, t) != 0) {
+ sql_schema *syss = find_sql_schema(tr,
isGlobal(col->t)?"sys":"tmp");
+ sql_table *syscolumn = find_sql_table(tr, syss, "_columns");
+ sql_column *col_ids = find_sql_column(syscolumn, "id");
+ sql_column *col_type = find_sql_column(syscolumn, "type");
+ sql_column *col_digits = find_sql_column(syscolumn,
"type_digits");
+ sql_column *col_scale = find_sql_column(syscolumn,
"type_scale");
+ oid rid = store->table_api.column_find_row(tr, col_ids,
&col->base.id, NULL);
+ sql_column *dup = NULL;
+ int digits = type_digits(t);
+ int scale = t->type->scale;
+
+ if (is_oid_nil(rid))
+ return -1;
+ if ((res = store->table_api.column_update_value(tr, col_type,
rid, t->type->base.name)))
+ return res;
+ if ((res = store->table_api.column_update_value(tr, col_digits,
rid, &digits)))
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]