Example #1
0
    private VxSchemaErrors ApplyChangedColumn(VxSchemaTable table, 
        VxSchemaTableElement oldelem, VxSchemaTableElement newelem, 
        VxSchemaError expected_err, VxPutOpts opts)
    {
        VxSchemaErrors errs = new VxSchemaErrors();
        log.print("Altering {0}\n", newelem.ToString());

        bool destructive = (opts & VxPutOpts.Destructive) != 0;
        string colname = newelem.GetParam("name");

        // Remove any old default constraint; even if it doesn't change, it 
        // can get in the way of modifying the column.  We'll add it again
        // later if needed.
        if (oldelem.HasDefault())
        {
            string defquery = wv.fmt("ALTER TABLE [{0}] DROP CONSTRAINT {1}", 
                table.name, table.GetDefaultDefaultName(colname));

            log.print("Executing {0}\n", defquery);

            dbi.execute(defquery);
        }

        bool did_default_constraint = false;

        // Don't try to alter the table if we know it won't work.
        if (expected_err == null)
        {
            string query = wv.fmt("ALTER TABLE [{0}] ALTER COLUMN {1}",
                table.name, table.ColumnToSql(newelem, false));

            log.print("Executing {0}\n", query);
            
            dbi.execute(query);
        }
        else
        {
            // Some table attributes can't be changed by ALTER TABLE, 
            // such as changing identity values, or data type changes that
            // would truncate data.  If the client has set the Destructive
            // flag though, we can try to drop and re-add the column.
            if (destructive)
            {
                log.print("Alter column would fail, dropping and adding.\n");
                log.print("Expected error message: {0} ({1})\n", 
                    expected_err.msg, expected_err.errnum);
                string delquery = wv.fmt("ALTER TABLE [{0}] " + 
                    "DROP COLUMN [{1}]",
                    table.name, colname);
                // We need to include the default value here (the second
                // parameter to ColumnToSql), otherwise adding a column to a
                // table with data in it might not work.
                string addquery = wv.fmt("ALTER TABLE [{0}] ADD {1}", 
                    table.name, table.ColumnToSql(newelem, true));

                log.print("Executing {0}\n", delquery);
                dbi.execute(delquery);
                log.print("Executing {0}\n", addquery);
                dbi.execute(addquery);
                did_default_constraint = true;
            }
            else
            {
                // Error 515: Can't modify a column because it contains nulls 
                // and the column requires non-nulls.
                if (expected_err.errnum == 515)
                {
                    log.print("Couldn't modify column due to null " + 
                        "restriction.  Making column nullable.\n");
                    var nullable = GetNullableColumn(newelem);

                    string query = wv.fmt("ALTER TABLE [{0}] ALTER COLUMN {1}",
                        table.name, table.ColumnToSql(nullable, false));

                    log.print("Executing {0}\n", query);
                    
                    dbi.execute(query);
                }
                else
                {
                    log.print("Can't alter table and destructive flag " + 
                        "not set.  Giving up.\n");
                    string key = table.key;
                    string errmsg = wv.fmt("Refusing to drop and re-add " +
                            "column [{0}] when the destructive option " +
                            "is not set.  Error when altering was: '{1}'",
                            colname, expected_err.msg);
                    errs.Add(key, new VxSchemaError(key, errmsg, -1));
                }
            }
        }

        // No errors so far, let's try to add the new default values if we
        // didn't do it already.
        // FIXME: Check for actual errors, don't care about warnings.
        if (errs.Count == 0 && newelem.HasDefault() && !did_default_constraint)
        {
            string defquery = wv.fmt("ALTER TABLE [{0}] ADD CONSTRAINT {1} " + 
                "DEFAULT {2} FOR {3}", 
                table.name, table.GetDefaultDefaultName(colname), 
                newelem.GetParam("default"), colname);

            log.print("Executing {0}\n", defquery);

            dbi.execute(defquery);
        }

        if (errs.Count != 0)
            log.print("Altering column had errors: " + errs.ToString());

        return errs;
    }
Example #2
0
    // Create a new table element that allows nulls
    private VxSchemaTableElement GetNullableColumn(VxSchemaTableElement elem)
    {
        var nullable = new VxSchemaTableElement(elem.elemtype);
        foreach (var kvp in elem.parameters)
            if (kvp.Key == "null")
                nullable.AddParam("null", "1");
            else
                nullable.AddParam(kvp.Key, kvp.Value);

        return nullable;
    }
Example #3
0
    private void DropTableColumn(VxSchemaTable table, VxSchemaTableElement col)
    {
        string colname = col.GetParam("name");
        if (col.HasDefault())
        {
            string defquery = wv.fmt("ALTER TABLE [{0}] " + 
                "DROP CONSTRAINT {1}", 
                table.name, table.GetDefaultDefaultName(colname));

            dbi.execute(defquery);
        }

        string query = wv.fmt("ALTER TABLE [{0}] DROP COLUMN [{1}]",
            table.name, colname);

        dbi.execute(query);
    }
Example #4
0
    private VxSchemaError PutSchemaTableIndex(string key, VxSchemaTable table, 
        VxSchemaTableElement elem)
    {
        string query = "";
        if (elem.elemtype == "primary-key")
            query = table.PrimaryKeyToSql(elem);
        else if (elem.elemtype == "index")
            query = table.IndexToSql(elem);
        else
            return new VxSchemaError(key, wv.fmt(
                "Unknown table element '{0}'.", elem.elemtype), -1);

        try 
        {
            if (query != "")
                dbi.execute(query);
        }
        catch (SqlException e)
        {
            return new VxSchemaError(key, e);
        }

        return null;
    }