public void AlterTable( string schemaName, string tableName, G.List<AlterAction> alist, Exec e )
  {
    Table t = (Table) GetTable( schemaName, tableName, e );

    var names = new G.List<string>( t.Cols.Names );
    var types = new G.List<DataType>( t.Cols.Types );
    var map = new G.List<int>();
    for ( int i = 0; i < names.Count; i += 1 ) map.Add( i );

    foreach ( AlterAction aa in alist )
    {
      int ix = names.IndexOf( aa.Name );
      if ( aa.Operation != Action.Add && ix == -1 )
        e.Error( "Column " + aa.Name + " not found" );

      switch ( aa.Operation )
      {
        case Action.Add: 
          if ( ix != -1 ) e.Error( "Column " + aa.Name + " already exists" );
          names.Add( aa.Name );
          types.Add( aa.Type );
          map.Add( 0 );
          Sql( "INSERT INTO sys.Column( Table, Name, Type ) VALUES ( " + t.TableId + "," + Util.Quote(aa.Name) + "," + (int)aa.Type + ")" );
          break;
        case Action.Drop:
          names.RemoveAt( ix );
          types.RemoveAt( ix );
          map.RemoveAt( ix );
          Sql( "DELETE FROM sys.Column WHERE Table = " + t.TableId + " AND Name = " + Util.Quote(aa.Name) ); 
          Sql( "EXEC sys.DroppedColumn(" + t.TableId + "," + ix + ")" );
          break;
        case Action.ColumnRename:
          names.RemoveAt( ix );
          names.Insert( ix, aa.NewName );
          Sql( "UPDATE sys.Column SET Name = " + Util.Quote(aa.NewName) + " WHERE Table=" + t.TableId + " AND Name = " + Util.Quote(aa.Name) );
          break;
        case Action.Modify:
          if ( DTI.Base( aa.Type ) != DTI.Base( types[ ix ] ) )
            e.Error( "Modify cannot change base type" );
          if ( DTI.Scale( aa.Type ) != DTI.Scale( types[ ix ] ) )
            e.Error( "Modify cannot change scale" );
          types.RemoveAt( ix );
          types.Insert( ix, aa.Type );
          Sql( "UPDATE sys.Column SET Type = " + (int)aa.Type + " WHERE Table=" + t.TableId + " AND Name = " + Util.Quote(aa.Name) );
          Sql( "EXEC sys.ModifiedColumn(" + t.TableId + "," + ix + ")" );
          break;
      }
    }
    var newcols = ColInfo.New( names, types );
    t.AlterData( newcols, map.ToArray() );
    Sql( "EXEC sys.RecreateModifiedIndexes()" );
    t.OpenIndexes();
    ResetCache();
  }