New test.
[mono.git] / mcs / class / System.Data / System.Data.Common / DbDataAdapter.cs
index 1d401152cb5e1892661422f8fea70d5ade2af285..9e98ef92d97a5e6efc2cfd8738d734ced793260f 100644 (file)
@@ -51,6 +51,13 @@ namespace System.Data.Common {
                public const string DefaultSourceTableName = "Table";
                const string DefaultSourceColumnName = "Column";
 
+#if NET_2_0
+               IDbCommand _selectCommand;
+               internal IDbCommand _updateCommand;
+               internal IDbCommand _deleteCommand;
+               internal IDbCommand _insertCommand;
+#endif
+
                #endregion // Fields
                
                #region Constructors
@@ -59,7 +66,6 @@ namespace System.Data.Common {
                {
                }
 
-               [MonoTODO]
                protected DbDataAdapter(DbDataAdapter adapter) : base(adapter)
                {
                }
@@ -68,98 +74,65 @@ namespace System.Data.Common {
 
                #region Properties
 
-#if NET_2_0
-               [MonoTODO]
-               protected virtual IDbConnection BaseConnection {
-                       get { throw new NotImplementedException (); }
-                       set { throw new NotImplementedException (); }
-               }
-
-               public IDbConnection Connection { 
-                       get { return BaseConnection; }
-                       set { BaseConnection = value; }
-               }
-#endif
-
-
 #if NET_2_0
                protected internal CommandBehavior FillCommandBehavior {
                        get { throw new NotImplementedException (); }
                        set { throw new NotImplementedException (); }
                }
-#endif
-
-
-#if NET_2_0
-               [MonoTODO]
-               protected virtual IDbCommand this [[Optional] StatementType statementType] {
-                       get { throw new NotImplementedException (); }
-                       set { throw new NotImplementedException (); }
-               }
 
-               [MonoTODO]
-               protected virtual DbProviderFactory ProviderFactory {
-                       get { throw new NotImplementedException (); }
-               }
-
-               [MonoTODO]
                IDbCommand IDbDataAdapter.SelectCommand {
-                       get { return ((IDbDataAdapter) this).SelectCommand; }
-                       set { throw new NotImplementedException(); }
+                       get { return _selectCommand; }
+                       set { _selectCommand = value; }
                }
 
-               [MonoTODO]
                IDbCommand IDbDataAdapter.UpdateCommand{
-                       get { return ((IDbDataAdapter) this).UpdateCommand; }
-                       set { throw new NotImplementedException(); }
+                       get { return _updateCommand; }
+                       set { _updateCommand = value; }
                }
 
-               [MonoTODO]
                IDbCommand IDbDataAdapter.DeleteCommand{
-                       get { return ((IDbDataAdapter) this).DeleteCommand; }
-                       set { throw new NotImplementedException(); }
+                       get { return _deleteCommand; }
+                       set { _deleteCommand = value; }
                }
 
-               [MonoTODO]
                IDbCommand IDbDataAdapter.InsertCommand{
-                       get { return ((IDbDataAdapter) this).InsertCommand; }
-                       set { throw new NotImplementedException(); }
+                       get { return _insertCommand; }
+                       set { _insertCommand = value; }
                }
                
-               [MonoTODO]
+               [Browsable (false)]
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                public DbCommand SelectCommand {
                        get { return (DbCommand) ((IDbDataAdapter) this).SelectCommand; }
-                       set { throw new NotImplementedException(); }
+                       set { ((IDbDataAdapter) this).SelectCommand = value; }
                }
 
-               [MonoTODO]
+               [Browsable (false)]
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                public DbCommand DeleteCommand {
                        get { return (DbCommand) ((IDbDataAdapter) this).DeleteCommand; }
-                       set { throw new NotImplementedException(); }
+                       set { ((IDbDataAdapter) this).DeleteCommand = value; }
                }
 
-               [MonoTODO]
+               [Browsable (false)]
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                public DbCommand InsertCommand {
                        get { return (DbCommand) ((IDbDataAdapter) this).InsertCommand; }
-                       set { throw new NotImplementedException(); }
+                       set { ((IDbDataAdapter) this).InsertCommand = value; }
                }
 
-               [MonoTODO]
+               [Browsable (false)]
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                public DbCommand UpdateCommand {
                        get { return (DbCommand) ((IDbDataAdapter) this).UpdateCommand; }
-                       set { throw new NotImplementedException(); }
+                       set { ((IDbDataAdapter) this).UpdateCommand = value; }
                }
 
                [MonoTODO]
-               public IDbTransaction Transaction {
-                       get { throw new NotImplementedException (); }
-                       set { throw new NotImplementedException (); }
-               }
-
-               [MonoTODO]
-               public int UpdateBatchSize {
-                       get { throw new NotImplementedException (); }
-                       set { throw new NotImplementedException (); }
+               [DefaultValue (1)]
+               public virtual int UpdateBatchSize {
+                       get { return 1; }
+                       set { throw new NotSupportedException (); }
                }
 #else
                IDbCommand SelectCommand {
@@ -195,15 +168,44 @@ namespace System.Data.Common {
                #region Methods
 
 #if NET_2_0
+               protected virtual RowUpdatedEventArgs CreateRowUpdatedEvent (DataRow dataRow, IDbCommand command,
+                                                                            StatementType statementType,
+                                                                            DataTableMapping tableMapping)
+               {
+                       return new RowUpdatedEventArgs (dataRow, command, statementType, tableMapping);
+               }
+
+               protected virtual RowUpdatingEventArgs CreateRowUpdatingEvent (DataRow dataRow, IDbCommand command,
+                                                                              StatementType statementType,
+                                                                              DataTableMapping tableMapping)
+               {
+                       return new RowUpdatingEventArgs (dataRow, command, statementType, tableMapping);
+               }
+
+               [MonoTODO]
+               protected virtual void OnRowUpdated (RowUpdatedEventArgs value)
+               {
+                       throw new NotImplementedException ();
+               }
+
                [MonoTODO]
-               public virtual void BeginInit ()
+               protected virtual void OnRowUpdating (RowUpdatingEventArgs value)
                {
                        throw new NotImplementedException ();
                }
+#else
+               protected abstract RowUpdatedEventArgs CreateRowUpdatedEvent (DataRow dataRow, IDbCommand command,
+                                                                            StatementType statementType,
+                                                                            DataTableMapping tableMapping);
+
+               protected abstract RowUpdatingEventArgs CreateRowUpdatingEvent (DataRow dataRow, IDbCommand command,
+                                                                              StatementType statementType,
+                                                                              DataTableMapping tableMapping);
+
+               protected abstract void OnRowUpdated (RowUpdatedEventArgs value);
+               protected abstract void OnRowUpdating (RowUpdatingEventArgs value);
 #endif
 
-               protected abstract RowUpdatedEventArgs CreateRowUpdatedEvent (DataRow dataRow, IDbCommand command, StatementType statementType, DataTableMapping tableMapping);
-               protected abstract RowUpdatingEventArgs CreateRowUpdatingEvent (DataRow dataRow, IDbCommand command, StatementType statementType, DataTableMapping tableMapping);
 
                private FillErrorEventArgs CreateFillErrorEvent (DataTable dataTable, object[] values, Exception e)
                {
@@ -236,14 +238,6 @@ namespace System.Data.Common {
                        }
                }
 
-#if NET_2_0
-               [MonoTODO]
-               public virtual void EndInit ()
-               {
-                       throw new NotImplementedException ();
-               }
-#endif
-
                public override int Fill (DataSet dataSet)
                {
                        return Fill (dataSet, 0, 0, DefaultSourceTableName, ((IDbDataAdapter) this).SelectCommand, CommandBehavior.Default);
@@ -263,10 +257,12 @@ namespace System.Data.Common {
                }
 
 #if NET_2_0
-               protected override int Fill (DataTable dataTable, IDataReader dataReader) 
+               [MonoTODO ("This needs to be moved to DataAdapter.For now, just override")]
+               protected override
 #else
-                       protected virtual int Fill (DataTable dataTable, IDataReader dataReader) 
+               protected virtual 
 #endif
+               int Fill (DataTable dataTable, IDataReader dataReader) 
                {
                        if (dataReader.FieldCount == 0) {
                                dataReader.Close ();
@@ -301,32 +297,33 @@ namespace System.Data.Common {
                        return Fill (dataTable, command.ExecuteReader (commandBehavior));
                }
 
+               public int Fill (DataSet dataSet, int startRecord, int maxRecords, string srcTable) 
+               {
+                       return this.Fill (dataSet, startRecord, maxRecords, srcTable, ((IDbDataAdapter) this).SelectCommand, CommandBehavior.Default);
+               }
+
 #if NET_2_0
                [MonoTODO]
                public int Fill (int startRecord, int maxRecords, DataTable[] dataTables)
                {
                        throw new NotImplementedException ();
                }
-#endif
-
-               public int Fill (DataSet dataSet, int startRecord, int maxRecords, string srcTable) 
-               {
-                       return this.Fill (dataSet, startRecord, maxRecords, srcTable, ((IDbDataAdapter) this).SelectCommand, CommandBehavior.Default);
-               }
 
-#if NET_2_0
                [MonoTODO]
                protected virtual int Fill (DataTable[] dataTables, int startRecord, int maxRecords, IDbCommand command, CommandBehavior behavior)
                {
                        throw new NotImplementedException ();
                }
 #endif
-
+               
+               
 #if NET_2_0
-               protected override int Fill (DataSet dataSet, string srcTable, IDataReader dataReader, int startRecord, int maxRecords) 
+               [MonoTODO ("This needs to be moved to DataAdapter.For now, just override")]
+               protected override
 #else
-               protected virtual int Fill (DataSet dataSet, string srcTable, IDataReader dataReader, int startRecord, int maxRecords) 
+               protected virtual
 #endif
+               int Fill (DataSet dataSet, string srcTable, IDataReader dataReader, int startRecord, int maxRecords) 
                {
                        if (dataSet == null)
                                throw new ArgumentNullException ("DataSet");
@@ -414,13 +411,12 @@ namespace System.Data.Common {
                                dataReader.Read ();
                        }
 
+                       dataTable.BeginLoadData ();
                        while (dataReader.Read () && (maxRecords == 0 || (counter - counterStart) < maxRecords)) {
                                try {
-                                       dataTable.BeginLoadData ();
                                        dataTable.LoadDataRow (dataReader, sortedMapping, length, AcceptChangesDuringFill);
-                                       dataTable.EndLoadData ();
                                        counter++;
-                               } 
+                               }
                                catch (Exception e) {
                                        object[] readerArray = new object[dataReader.FieldCount];
                                        object[] tableArray = new object[mapping.Length];
@@ -434,20 +430,22 @@ namespace System.Data.Common {
                                        }
                                        FillErrorEventArgs args = CreateFillErrorEvent (dataTable, tableArray, e);
                                        OnFillError (args);
-                                       if(!args.Continue) {
-                                               return false;
-                                       }
+
+                                       // if args.Continue is not set to true or if a handler is not set, rethrow the error..
+                                       if(!args.Continue)
+                                               throw e;
                                }
                        }
+                       dataTable.EndLoadData ();
                        return true;
                }
 
 #if NET_2_0
-                /// <summary>
-                ///     Fills the given datatable using values from reader. if a value 
-                ///     for a column is  null, that will be filled with default value. 
-                /// </summary>
-                /// <returns>No. of rows affected </returns>
+               /// <summary>
+               ///     Fills the given datatable using values from reader. if a value 
+               ///     for a column is  null, that will be filled with default value. 
+               /// </summary>
+               /// <returns>No. of rows affected </returns>
                internal static int FillFromReader (DataTable table,
                                                     IDataReader reader,
                                                     int start, 
@@ -478,6 +476,46 @@ namespace System.Data.Common {
                         return counter;
                 }
 
+               internal static int FillFromReader (DataTable table,
+                                                    IDataReader reader,
+                                                    int start, 
+                                                    int length,
+                                                    int [] mapping,
+                                                    LoadOption loadOption,
+                                                    FillErrorEventHandler errorHandler)
+                {
+                        if (reader.FieldCount == 0)
+                               return 0 ;
+
+                        for (int i = 0; i < start; i++)
+                                reader.Read ();
+
+                        int counter = 0;
+                        object [] values = new object [mapping.Length];
+                        while (reader.Read () &&
+                               (length == 0 || counter < length)) {
+                                
+                                for (int i = 0 ; i < mapping.Length; i++)
+                                        values [i] = mapping [i] < 0 ? null : reader [mapping [i]];
+                                        
+                                table.BeginLoadData ();
+                               try {
+                                       table.LoadDataRow (values, loadOption);
+                               } catch (Exception e) {
+                                       FillErrorEventArgs args = new FillErrorEventArgs (table, values);
+                                       args.Errors = e;
+                                       args.Continue = false;
+                                       errorHandler (table, args);
+                                       // if args.Continue is not set to true or if a handler is not set, rethrow the error..
+                                       if(!args.Continue)
+                                               throw e;
+                               }
+                                table.EndLoadData ();
+                                counter++;
+                        }
+                        return counter;
+                }
+
 #endif // NET_2_0
 
                public override DataTable[] FillSchema (DataSet dataSet, SchemaType schemaType) 
@@ -495,7 +533,6 @@ namespace System.Data.Common {
                        return FillSchema (dataSet, schemaType, ((IDbDataAdapter) this).SelectCommand, srcTable, CommandBehavior.Default);
                }
 
-               [MonoTODO ("Verify")]
                protected virtual DataTable FillSchema (DataTable dataTable, SchemaType schemaType, IDbCommand command, CommandBehavior behavior) 
                {
                        if (dataTable == null)
@@ -513,7 +550,15 @@ namespace System.Data.Common {
                                string tableName =  SetupSchema (schemaType, dataTable.TableName);
                                if (tableName != null)
                                {
-                                       BuildSchema (reader, dataTable, schemaType);
+                                       // FillSchema should add the KeyInfo unless MissingSchemaAction
+                                       // is set to Ignore or Error.
+                                       MissingSchemaAction schemaAction = MissingSchemaAction;
+                                       if (!(schemaAction == MissingSchemaAction.Ignore ||
+                                               schemaAction == MissingSchemaAction.Error))
+                                               schemaAction = MissingSchemaAction.AddWithKey;
+
+                                       BuildSchema (reader, dataTable, schemaType, schemaAction,
+                                               MissingMappingAction, TableMappings);
                                }
                        }
                        finally
@@ -523,7 +568,6 @@ namespace System.Data.Common {
                        return dataTable;
                }
 
-               [MonoTODO ("Verify")]
                protected virtual DataTable[] FillSchema (DataSet dataSet, SchemaType schemaType, IDbCommand command, string srcTable, CommandBehavior behavior) 
                {
                        if (dataSet == null)
@@ -542,6 +586,13 @@ namespace System.Data.Common {
                        DataTable table;
                        try
                        {
+                               // FillSchema should add the KeyInfo unless MissingSchemaAction
+                               // is set to Ignore or Error.
+                               MissingSchemaAction schemaAction = MissingSchemaAction;
+                               if (!(MissingSchemaAction == MissingSchemaAction.Ignore ||
+                                       MissingSchemaAction == MissingSchemaAction.Error))
+                                       schemaAction = MissingSchemaAction.AddWithKey;
+
                                do {
                                        tableName = SetupSchema (schemaType, tableName);
                                        if (tableName != null)
@@ -550,10 +601,14 @@ namespace System.Data.Common {
                                                        table = dataSet.Tables [tableName];     
                                                else
                                                {
-                                                       table = new DataTable(tableName);
-                                                       dataSet.Tables.Add (table);
+                                                       // Do not create schema if MissingSchemAction is set to Ignore
+                                                       if (this.MissingSchemaAction == MissingSchemaAction.Ignore)
+                                                               continue;
+                                                       table =  dataSet.Tables.Add (tableName);
                                                }
-                                               BuildSchema (reader, table, schemaType);
+                                               
+                                               BuildSchema (reader, table, schemaType, schemaAction,
+                                                       MissingMappingAction, TableMappings);
                                                output.Add (table);
                                                tableName = String.Format ("{0}{1}", srcTable, ++index);
                                        }
@@ -566,20 +621,6 @@ namespace System.Data.Common {
                        return (DataTable[]) output.ToArray (typeof (DataTable));
                }
 
-#if NET_2_0
-               [MonoTODO]
-               public DataSet GetDataSet ()
-               {
-                       throw new NotImplementedException ();
-               }
-
-               [MonoTODO]
-               public DataTable GetDataTable ()
-               {
-                       throw new NotImplementedException ();
-               }
-#endif
-
                private string SetupSchema (SchemaType schemaType, string sourceTableName)
                {
                        DataTableMapping tableMapping = null;
@@ -598,7 +639,7 @@ namespace System.Data.Common {
                [EditorBrowsable (EditorBrowsableState.Advanced)]
                public override IDataParameter[] GetFillParameters () 
                {
-                       IDataParameter[] parameters = new IDataParameter[SelectCommand.Parameters.Count];
+                       IDataParameter[] parameters = new IDataParameter [SelectCommand.Parameters.Count];
                        SelectCommand.Parameters.CopyTo (parameters, 0);
                        return parameters;
                }
@@ -607,7 +648,6 @@ namespace System.Data.Common {
                // "array[ordinal of datatable column] == index of source column in data reader".
                // each column in the datatable has a mapping to a specific column in the datareader,
                // the int array represents this match.
-               [MonoTODO ("Test")]
                private int[] BuildSchema (IDataReader reader, DataTable table, SchemaType schemaType)
                {
                        return BuildSchema (reader, table, schemaType, MissingSchemaAction,
@@ -703,21 +743,25 @@ namespace System.Data.Common {
                                                                mapping = tmp;
                                                        }                               
 
-                                                       object value = (AllowDBNullCol != null) ? schemaRow[AllowDBNullCol] : null;
-                                                       bool allowDBNull = value is bool ? (bool)value : true;
-                                                       col.AllowDBNull = allowDBNull; 
-                                                       value = (IsKeyCol != null) ? schemaRow[IsKeyCol] : null;
-                                                       bool isKey = value is bool ? (bool)value : false;
 
                                                        if (missingSchAction == MissingSchemaAction.AddWithKey) {
                                    
+                                                               object value = (AllowDBNullCol != null) ? schemaRow[AllowDBNullCol] : null;
+                                                               bool allowDBNull = value is bool ? (bool)value : true;
+
+                                                               value = (IsKeyCol != null) ? schemaRow[IsKeyCol] : null;
+                                                               bool isKey = value is bool ? (bool)value : false;
+
                                                                value = (IsAutoIncrementCol != null) ? schemaRow[IsAutoIncrementCol] : null;
                                                                bool isAutoIncrement = value is bool ? (bool)value : false;
+
                                                                value = (IsReadOnlyCol != null) ? schemaRow[IsReadOnlyCol] : null;
                                                                bool isReadOnly = value is bool ? (bool)value : false;
+
                                                                value = (IsUniqueCol != null) ? schemaRow[IsUniqueCol] : null;
                                                                bool isUnique = value is bool ? (bool)value : false;
                                                                
+                                                               col.AllowDBNull = allowDBNull;
                                                                // fill woth key info                                                           
                                                                if (isAutoIncrement && DataColumn.CanAutoIncrement(columnType)) {
                                                                        col.AutoIncrement = true;
@@ -739,15 +783,20 @@ namespace System.Data.Common {
                                                                        if (!allowDBNull)
                                                                                col.AllowDBNull = false;
                                                                }
-                                                       }
+                                                               
+                                                               // This might not be set by all DataProviders
+                                                               bool isHidden = false;
+                                                               if (schemaTable.Columns.Contains ("IsHidden")) {
+                                                                       value = schemaRow["IsHidden"];
+                                                                       isHidden = ((value is bool) ? (bool)value : false);
+                                                               }
 
-                                                       bool isHidden = (bool) schemaRow ["IsHidden"];
-                                                       if (isKey && !isHidden) {
-                                                               primaryKey.Add (col);
-                                                               if (allowDBNull)
-                                                                       createPrimaryKey = false;
+                                                               if (isKey && !isHidden) {
+                                                                       primaryKey.Add (col);
+                                                                       if (allowDBNull)
+                                                                               createPrimaryKey = false;
+                                                               }
                                                        }
-                                                       
                                                        // add the ordinal of the column as a key and the index of the column in the datareader as a value.
                                                        mapping[col.Ordinal] = readerIndex++;
                                                }
@@ -780,7 +829,6 @@ namespace System.Data.Common {
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
                public int Update (DataRow[] dataRows) 
                {
                        if (dataRows == null)
@@ -894,7 +942,6 @@ namespace System.Data.Common {
                        return Update (rows, tableMapping);
                }
 
-               [MonoTODO]
                protected virtual int Update (DataRow[] dataRows, DataTableMapping tableMapping) 
                {
                        int updateCount = 0;
@@ -952,20 +999,28 @@ namespace System.Data.Common {
                                try {
                                        if (command != null) {
                                                DataColumnMappingCollection columnMappings = tableMapping.ColumnMappings;
+                                               IDataParameter nullCheckParam = null;
                                                foreach (IDataParameter parameter in command.Parameters) {
                                                        if ((parameter.Direction & ParameterDirection.Input) != 0) {
                                                                string dsColumnName = parameter.SourceColumn;
                                                                if (columnMappings.Contains(parameter.SourceColumn))
                                                                        dsColumnName = columnMappings [parameter.SourceColumn].DataSetColumn;
-                                                               if (dsColumnName == null || dsColumnName.Length <= 0)
+                                                               if (dsColumnName == null || dsColumnName.Length <= 0) {
+                                                                       nullCheckParam = parameter;
                                                                        continue;
-                                                               
+                                                               }
+
                                                                DataRowVersion rowVersion = parameter.SourceVersion;
                                                                // Parameter version is ignored for non-update commands
                                                                if (statementType == StatementType.Delete) 
                                                                        rowVersion = DataRowVersion.Original;
 
                                                                parameter.Value = row [dsColumnName, rowVersion];
+                                                               if (nullCheckParam != null && (parameter.Value != null
+                                                                       && parameter.Value != DBNull.Value)) {
+                                                                       nullCheckParam.Value = 0;
+                                                                       nullCheckParam = null;
+                                                               }
                                                        }
                                                }
                                        }
@@ -1081,6 +1136,10 @@ namespace System.Data.Common {
                                        case UpdateStatus.SkipAllRemainingRows:
                                                return updateCount;
                                        }
+#if NET_2_0
+                                       if (!AcceptChangesDuringUpdate)
+                                               continue;
+#endif
                                        row.AcceptChanges ();
                                } catch(Exception e) {
                                        row.RowError = e.Message;
@@ -1111,6 +1170,41 @@ namespace System.Data.Common {
                                                                            sourceTable));
                        return Update (dataTable, tableMapping);
                }
+               
+#if NET_2_0
+               // All the batch methods, should be implemented, if supported,
+               // by individual providers 
+
+               protected virtual int AddToBatch (IDbCommand cmd)
+               {
+                       throw new NotSupportedException ();
+               }
+
+               protected virtual void ClearBatch ()
+               {
+                       throw new NotSupportedException ();
+               }
+
+               protected virtual int ExecuteBatch ()
+               {
+                       throw new NotSupportedException ();
+               }
+
+               protected virtual IDataParameter GetBatchedParameter (int commandIdentifier, int parameterIdentifer)
+               {
+                       throw new NotSupportedException ();
+               }
+
+               protected virtual void InitializeBatching ()
+               {
+                       throw new NotSupportedException ();
+               }
+
+               protected virtual void TerminateBatching ()
+               {
+                       throw new NotSupportedException ();
+               }
+#endif
 
 #if ONLY_1_0 || ONLY_1_1
                protected virtual void OnFillError (FillErrorEventArgs value) 
@@ -1120,9 +1214,6 @@ namespace System.Data.Common {
                }
 #endif
 
-               protected abstract void OnRowUpdated (RowUpdatedEventArgs value);
-               protected abstract void OnRowUpdating (RowUpdatingEventArgs value);
-               
                #endregion // Methods
        }
 }