2002-10-01 Luis Fernandez <luifer@onetel.net.uk>
[mono.git] / mcs / class / System.Data / System.Data / DataTable.cs
1 //
2 // System.Data.DataTable.cs
3 //
4 // Author:
5 //   Franklin Wise <gracenote@earthlink.net>
6 //   Christopher Podurgiel (cpodurgiel@msn.com)
7 //   Daniel Morgan <danmorg@sc.rr.com>
8 //   Rodrigo Moya <rodrigo@ximian.com>
9 //
10 // (C) Chris Podurgiel
11 // (C) Ximian, Inc 2002
12 //
13
14 using System;
15 using System.Collections;
16 using System.ComponentModel;
17 using System.Globalization;
18 using System.Runtime.Serialization;
19
20 namespace System.Data
21 {
22         /// <summary>
23         /// Represents one table of in-memory data.
24         /// </summary>
25         [Serializable]
26         public class DataTable : ISerializable
27                 //MarshalByValueComponent, IListSource, ISupportInitialize
28         {
29                 internal DataSet dataSet;   
30                 
31                 private bool _caseSensitive;
32                 private DataColumnCollection _columnCollection;
33                 private ConstraintCollection _constraintCollection;
34                 private DataView _defaultView;
35
36                 private string _displayExpression;
37                 private PropertyCollection _extendedProperties;
38                 private bool _hasErrors;
39                 private CultureInfo _locale;
40                 private int _minimumCapacity;
41                 private string _nameSpace;
42                 // FIXME: temporarily commented
43                 // private DataTableRelationCollection _childRelations; 
44                 // private DataTableRelationCollection _parentRelations;
45                 private string _prefix;
46                 private DataColumn[] _primaryKey;
47                 private DataRowCollection _rows;
48                 private ISite _site;
49                 private string _tableName;
50                 private bool _containsListCollection;
51                 private string _encodedTableName;
52                 
53                 /// <summary>
54                 /// Initializes a new instance of the DataTable class with no arguments.
55                 /// </summary>
56                 
57                 public DataTable()
58                 {
59                         dataSet = null;
60                         _columnCollection = new DataColumnCollection(this);
61                         _constraintCollection = new ConstraintCollection(); 
62                         _extendedProperties = new PropertyCollection();
63                         _tableName = "";
64                         _nameSpace = null;
65                         _caseSensitive = false;         //default value
66                         _displayExpression = null;
67                         _primaryKey = null;
68                         _site = null;
69                         _rows = new DataRowCollection (this);
70                         _locale = CultureInfo.CurrentCulture;
71
72                         //LAMESPEC: spec says 25 impl does 50
73                         _minimumCapacity = 50;
74                         
75                         // FIXME: temporaily commented DataTableRelationCollection
76                         // _childRelations = new DataTableRelationCollection();
77                         // _parentRelations = new DataTableRelationCollection();
78
79                 
80                         _defaultView = new DataView(this);
81                 }
82
83                 /// <summary>
84                 /// Intitalizes a new instance of the DataTable class with the specified table name.
85                 /// </summary>
86                 
87                 public DataTable(string tableName) : this ()
88                 {
89                         _tableName = tableName;
90                 }
91
92                 /// <summary>
93                 /// Initializes a new instance of the DataTable class with the SerializationInfo and the StreamingContext.
94                 /// </summary>
95                 
96                 [MonoTODO]
97                 protected DataTable(SerializationInfo info, StreamingContext context)
98                         : this ()
99                 {
100                         //
101                         // TODO: Add constructor logic here
102                         //
103                 }
104
105                 /// <summary>
106                 /// Indicates whether string comparisons within the table are case-sensitive.
107                 /// </summary>
108                 
109                 public bool CaseSensitive 
110                 {
111                         get {
112                                 return _caseSensitive;
113                         }
114                         set {
115                                 _caseSensitive = value;
116                         }
117                 }
118
119
120                 /// <summary>
121                 /// Gets the collection of child relations for this DataTable.
122                 /// </summary>
123                 [MonoTODO]      
124                 public DataRelationCollection ChildRelations
125                 {
126                         get {
127                                 // FIXME: temporarily commented to compile
128                                 // return (DataRelationCollection)_childRelations;
129                                 
130                                 //We are going to have to Inherit a class from 
131                                 //DataRelationCollection because DRC is abstract
132                                 
133                                 throw new NotImplementedException ();
134                         }
135                 }
136
137                 /// <summary>
138                 /// Gets the collection of columns that belong to this table.
139                 /// </summary>
140
141                 public DataColumnCollection Columns
142                 {
143                         get {
144                                 return _columnCollection;
145                         }
146                 }
147
148                 /// <summary>
149                 /// Gets the collection of constraints maintained by this table.
150                 /// </summary>
151                 
152                 public ConstraintCollection Constraints
153                 {
154                         get {
155                                 return _constraintCollection;
156                         }
157                 }
158
159                 /// <summary>
160                 /// Gets the DataSet that this table belongs to.
161                 /// </summary>
162                 public DataSet DataSet {
163                         get { return dataSet; }
164                 }
165
166                 
167
168                 /// <summary>
169                 /// Gets a customized view of the table which may 
170                 /// include a filtered view, or a cursor position.
171                 /// </summary>
172                 [MonoTODO]      
173                 public DataView DefaultView
174                 {
175                         get
176                         {
177                                 return _defaultView;
178                         }
179                 }
180                 
181
182                 /// <summary>
183                 /// Gets or sets the expression that will return 
184                 /// a value used to represent this table in the user interface.
185                 /// </summary>
186                 
187                 public string DisplayExpression 
188                 {
189                         get {
190                                 return "" + _displayExpression;
191                         }
192                         set {
193                                 _displayExpression = value;
194                         }
195                 }
196
197                 /// <summary>
198                 /// Gets the collection of customized user information.
199                 /// </summary>
200                 public PropertyCollection ExtendedProperties
201                 {
202                         get {
203                                 return _extendedProperties;
204                         }
205                 }
206
207                 /// <summary>
208                 /// Gets a value indicating whether there are errors in 
209                 /// any of the_rows in any of the tables of the DataSet to 
210                 /// which the table belongs.
211                 /// </summary>
212                 public bool HasErrors
213                 {
214                         get {
215                                 return _hasErrors;
216                         }
217                 }
218
219                 /// <summary>
220                 /// Gets or sets the locale information used to 
221                 /// compare strings within the table.
222                 /// </summary>
223                 public CultureInfo Locale
224                 {
225                         get {
226                                 return _locale;
227                         }
228                         set {
229                                 _locale = value;
230                         }
231                 }
232
233                 /// <summary>
234                 /// Gets or sets the initial starting size for this table.
235                 /// </summary>
236                 public int MinimumCapacity
237                 {
238                         get {
239                                 return _minimumCapacity;
240                         }
241                         set {
242                                 _minimumCapacity = value;
243                         }
244                 }
245
246                 /// <summary>
247                 /// Gets or sets the namespace for the XML represenation 
248                 /// of the data stored in the DataTable.
249                 /// </summary>
250                 public string Namespace
251                 {
252                         get {
253                                 return "" + _nameSpace;
254                         }
255                         set {
256                                 _nameSpace = value;
257                         }
258                 }
259
260                 /// <summary>
261                 /// Gets the collection of parent relations for 
262                 /// this DataTable.
263                 /// </summary>
264                 [MonoTODO]
265                 public DataRelationCollection ParentRelations
266                 {
267                         get {   
268                                 // FIXME: temporarily commented to compile
269                                 // return _parentRelations;
270                                 throw new NotImplementedException ();
271                         }
272                 }
273
274                 /// <summary>
275                 /// Gets or sets the namespace for the XML represenation
276                 ///  of the data stored in the DataTable.
277                 /// </summary>
278                 public string Prefix
279                 {
280                         get {
281                                 return "" + _prefix;
282                         }
283                         set {
284                                 _prefix = value;
285                         }
286                 }
287
288                 /// <summary>
289                 /// Gets or sets an array of columns that function as 
290                 /// primary keys for the data table.
291                 /// </summary>
292                 public DataColumn[] PrimaryKey
293                 {
294                         get {
295                                 UniqueConstraint uc = UniqueConstraint.GetPrimaryKeyConstraint( Constraints);
296                                 if (null == uc) return new DataColumn[] {};
297                                 return uc.Columns;
298                         }
299                         set {
300
301                                 //YUK: msft removes a previous unique constraint if it is flagged as a pk  
302                                 //when a new pk is set 
303
304                                 //clear Primary Key if value == null
305                                 if (null == value)
306                                 {
307                                         UniqueConstraint.SetAsPrimaryKey(this.Constraints, null);
308                                         return;
309                                 }
310                         
311
312                                 //Does constraint exist for these columns
313                                 UniqueConstraint uc = UniqueConstraint.GetUniqueConstraintForColumnSet(
314                                                 this.Constraints, (DataColumn[]) value);
315
316                                 //if constraint doesn't exist for columns
317                                 //create new unique primary key constraint
318                                 if (null == uc)
319                                 {
320                                         uc = new UniqueConstraint( (DataColumn[]) value, true);
321                                 }
322                                 else //set existing constraint as the new primary key
323                                 {
324                                         UniqueConstraint.SetAsPrimaryKey(this.Constraints, uc);
325                                 }
326                                 
327                         }
328                 }
329
330                 /// <summary>
331                 /// Gets the collection of_rows that belong to this table.
332                 /// </summary>
333                 
334                 public DataRowCollection Rows
335                 {
336                         get { return _rows; }
337                 }
338
339                 /// <summary>
340                 /// Gets or sets an System.ComponentModel.ISite 
341                 /// for the DataTable.
342                 /// </summary>
343                 
344                 public virtual ISite Site
345                 {
346                         get {
347                                 return _site;
348                         }
349                         set {
350                                 _site = value;
351                         }
352                 }
353
354                 /// <summary>
355                 /// Gets or sets the name of the the DataTable.
356                 /// </summary>
357                 
358                 public string TableName
359                 {
360                         get {
361                                 return "" + _tableName;
362                         }
363                         set {
364                                 _tableName = value;
365                         }
366                 }
367
368                 /* FIXME: implement IListSource
369                 public bool IListSource.ContainsListCollection
370                 {
371                         get {
372                                 return _containsListCollection;
373                         }
374                 }
375                 */
376
377                 /// <summary>
378                 /// Commits all the changes made to this table since the 
379                 /// last time AcceptChanges was called.
380                 /// </summary>
381                 
382                 public void AcceptChanges()
383                 {
384
385                         //FIXME: Do we need to validate anything here or
386                         //try to catch any errors to deal with them?
387
388                         foreach(DataRow myRow in _rows)
389                         {
390                                 myRow.AcceptChanges();
391                         }
392
393                 }
394
395                 /// <summary>
396                 /// Begins the initialization of a DataTable that is used 
397                 /// on a form or used by another component. The initialization
398                 /// occurs at runtime.
399                 /// </summary>
400                 
401                 public void BeginInit()
402                 {
403                 }
404
405                 /// <summary>
406                 /// Turns off notifications, index maintenance, and 
407                 /// constraints while loading data.
408                 /// </summary>
409                 
410                 public void BeginLoadData()
411                 {
412                 }
413
414                 /// <summary>
415                 /// Clears the DataTable of all data.
416                 /// </summary>
417                 
418                 public void Clear()
419                 {
420                         _rows.Clear ();
421                 }
422
423                 /// <summary>
424                 /// Clones the structure of the DataTable, including
425                 ///  all DataTable schemas and constraints.
426                 /// </summary>
427                 
428                 [MonoTODO]
429                 public virtual DataTable Clone()
430                 {
431                         //FIXME:
432                         return this; //Don't know if this is correct
433                 }
434
435                 /// <summary>
436                 /// Computes the given expression on the current_rows that 
437                 /// pass the filter criteria.
438                 /// </summary>
439                 
440                 [MonoTODO]
441                 public object Compute(string expression, string filter)
442                 {
443                         //FIXME: //Do a real compute
444                         object obj = "a";
445                         return obj;
446                 }
447
448                 /// <summary>
449                 /// Copies both the structure and data for this DataTable.
450                 /// </summary>
451                 [MonoTODO]      
452                 public DataTable Copy()
453                 {
454                         //FIXME: Do a real copy
455                         return this;
456                 }
457
458                 /// <summary>
459                 /// Ends the initialization of a DataTable that is used 
460                 /// on a form or used by another component. The 
461                 /// initialization occurs at runtime.
462                 /// </summary>
463                 
464                 public void EndInit()
465                 {
466                 }
467
468                 /// <summary>
469                 /// Turns on notifications, index maintenance, and 
470                 /// constraints after loading data.
471                 /// </summary>
472                 
473                 public void EndLoadData()
474                 {
475                 }
476
477                 /// <summary>
478                 /// Gets a copy of the DataTable that contains all
479                 ///  changes made to it since it was loaded or 
480                 ///  AcceptChanges was last called.
481                 /// </summary>
482                 [MonoTODO]
483                 public DataTable GetChanges()
484                 {
485                         //TODO:
486                         return this;
487                 }
488
489                 /// <summary>
490                 /// Gets a copy of the DataTable containing all 
491                 /// changes made to it since it was last loaded, or 
492                 /// since AcceptChanges was called, filtered by DataRowState.
493                 /// </summary>
494                 [MonoTODO]      
495                 public DataTable GetChanges(DataRowState rowStates)
496                 {
497                         //TODO:
498                         return this;
499                 }
500
501                 /// <summary>
502                 /// Gets an array of DataRow objects that contain errors.
503                 /// </summary>
504                 
505                 [MonoTODO]
506                 public DataRow[] GetErrors()
507                 {
508                         throw new NotImplementedException ();
509                 }
510
511                 /// <summary>
512                 /// This member supports the .NET Framework infrastructure
513                 /// and is not intended to be used directly from your code.
514                 /// </summary>
515                 
516                 //protected virtual Type GetRowType()
517                 //{     
518                 //}
519
520                 /// <summary>
521                 /// This member supports the .NET Framework infrastructure 
522                 /// and is not intended to be used directly from your code.
523                 /// </summary>
524                 
525                 /* FIXME: implement IListSource
526                 public IList IListSource.GetList()
527                 {
528                         IList list = null;
529                         return list;
530                 }
531                 */
532                 
533                 /// <summary>
534                 /// Copies a DataRow into a DataTable, preserving any 
535                 /// property settings, as well as original and current values.
536                 /// </summary>
537                 [MonoTODO]
538                 public void ImportRow(DataRow row)
539                 {
540                 }
541
542                 /// <summary>
543                 /// This member supports the .NET Framework infrastructure
544                 ///  and is not intended to be used directly from your code.
545                 /// </summary>
546                 
547                 [MonoTODO]
548                 void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
549                 {
550                 }
551
552                 /// <summary>
553                 /// Finds and updates a specific row. If no matching row
554                 ///  is found, a new row is created using the given values.
555                 /// </summary>
556                 [MonoTODO]
557                 public DataRow LoadDataRow(object[] values, bool fAcceptChanges)
558                 {
559                         //FIXME: implemente
560                         DataRow dataRow = null;
561                         return dataRow;
562                 }
563
564                 /// <summary>
565                 /// Creates a new DataRow with the same schema as the table.
566                 /// </summary>
567                 public DataRow NewRow()
568                 {
569                         return this.NewRowFromBuilder (new DataRowBuilder (this, 0, 0));
570                 }
571
572                 /// <summary>
573                 /// This member supports the .NET Framework infrastructure
574                 ///  and is not intended to be used directly from your code.
575                 /// </summary>
576                 [MonoTODO]
577                 protected internal DataRow[] NewRowArray(int size)
578                 {
579                         DataRow[] dataRows = {null};
580                         return dataRows;
581                 }
582
583                 /// <summary>
584                 /// Creates a new row from an existing row.
585                 /// </summary>
586                 
587                 protected virtual DataRow NewRowFromBuilder(DataRowBuilder builder)
588                 {
589                         return new DataRow (builder);
590                 }
591         
592
593                 /// <summary>
594                 /// Rolls back all changes that have been made to the 
595                 /// table since it was loaded, or the last time AcceptChanges
596                 ///  was called.
597                 /// </summary>
598                 
599                 [MonoTODO]
600                 public void RejectChanges()
601                 {
602                 }
603
604                 /// <summary>
605                 /// Resets the DataTable to its original state.
606                 /// </summary>
607                 
608                 [MonoTODO]
609                 public virtual void Reset()
610                 {
611                 }
612
613                 /// <summary>
614                 /// Gets an array of all DataRow objects.
615                 /// </summary>
616                 
617                 [MonoTODO]
618                 public DataRow[] Select()
619                 {
620                         //FIXME:
621                         DataRow[] dataRows = {null};
622                         return dataRows;
623                 }
624
625                 /// <summary>
626                 /// Gets an array of all DataRow objects that match 
627                 /// the filter criteria in order of primary key (or 
628                 /// lacking one, order of addition.)
629                 /// </summary>
630                 
631                 [MonoTODO]
632                 public DataRow[] Select(string filterExpression)
633                 {
634                         DataRow[] dataRows = {null};
635                         return dataRows;
636                 }
637
638                 /// <summary>
639                 /// Gets an array of all DataRow objects that 
640                 /// match the filter criteria, in the the 
641                 /// specified sort order.
642                 /// </summary>
643                 [MonoTODO]
644                 public DataRow[] Select(string filterExpression, string sort)
645                 {
646                         DataRow[] dataRows = {null};
647                         return dataRows;
648                 }
649
650                 /// <summary>
651                 /// Gets an array of all DataRow objects that match
652                 /// the filter in the order of the sort, that match 
653                 /// the specified state.
654                 /// </summary>
655                 [MonoTODO]
656                 public DataRow[] Select(string filterExpression, string sort, DataViewRowState recordStates)
657                 {
658                         DataRow[] dataRows = {null};
659                         return dataRows;
660                 }
661
662                 /// <summary>
663                 /// Gets the TableName and DisplayExpression, if 
664                 /// there is one as a concatenated string.
665                 /// </summary>
666                 public override string ToString()
667                 {
668                         //LAMESPEC: spec says concat the two. impl puts a 
669                         //plus sign infront of DisplayExpression
670                         return TableName + " " + DisplayExpression;
671                 }
672
673                 
674                 #region Events /////////////////
675                 
676                 /// <summary>
677                 /// Raises the ColumnChanged event.
678                 /// </summary>
679                 protected virtual void OnColumnChanged(DataColumnChangeEventArgs e)
680                 {
681                         if (null != ColumnChanged)
682                         {
683                                 ColumnChanged(this, e);
684                         }
685                 }
686
687                 /// <summary>
688                 /// Raises the ColumnChanging event.
689                 /// </summary>
690                 protected virtual void OnColumnChanging(DataColumnChangeEventArgs e)
691                 {
692                         if (null != ColumnChanging)
693                         {
694                                 ColumnChanging(this, e);
695                         }
696                 }
697
698                 /// <summary>
699                 /// Raises the PropertyChanging event.
700                 /// </summary>
701                 [MonoTODO]
702                 protected internal virtual void OnPropertyChanging(PropertyChangedEventArgs pcevent)
703                 {
704 //                      if (null != PropertyChanging)
705 //                      {
706 //                              PropertyChanging(this, e);
707 //                      }
708                 }
709
710                 /// <summary>
711                 /// Notifies the DataTable that a DataColumn is being removed.
712                 /// </summary>
713                 [MonoTODO]
714                 protected internal virtual void OnRemoveColumn(DataColumn column)
715                 {
716 //                      if (null != RemoveColumn)
717 //                      {
718 //                              RemoveColumn(this, e);
719 //                      }
720                 }
721
722                 /// <summary>
723                 /// Raises the RowChanged event.
724                 /// </summary>
725                 
726                 protected virtual void OnRowChanged(DataRowChangeEventArgs e)
727                 {
728                         if (null != RowChanged)
729                         {
730                                 RowChanged(this, e);
731                         }
732                 }
733
734                 /// <summary>
735                 /// Raises the RowChanging event.
736                 /// </summary>
737                 
738                 protected virtual void OnRowChanging(DataRowChangeEventArgs e)
739                 {
740                         if (null != RowChanging)
741                         {
742                                 RowChanging(this, e);
743                         }
744                 }
745
746                 /// <summary>
747                 /// Raises the RowDeleted event.
748                 /// </summary>
749                 protected virtual void OnRowDeleted(DataRowChangeEventArgs e)
750                 {
751                         if (null != RowDeleted)
752                         {
753                                 RowDeleted(this, e);
754                         }
755                 }
756
757                 /// <summary>
758                 /// Raises the RowDeleting event.
759                 /// </summary>
760                 protected virtual void OnRowDeleting(DataRowChangeEventArgs e)
761                 {
762                         if (null != RowDeleting)
763                         {
764                                 RowDeleting(this, e);
765                         }
766                 }
767
768                 /// <summary>
769                 /// Occurs when after a value has been changed for 
770                 /// the specified DataColumn in a DataRow.
771                 /// </summary>
772                 
773                 public event DataColumnChangeEventHandler ColumnChanged;
774
775                 /// <summary>
776                 /// Occurs when a value is being changed for the specified 
777                 /// DataColumn in a DataRow.
778                 /// </summary>
779                 
780                 public event DataColumnChangeEventHandler ColumnChanging;
781
782                 /// <summary>
783                 /// Occurs after a DataRow has been changed successfully.
784                 /// </summary>
785                 
786                 public event DataRowChangeEventHandler RowChanged;
787
788                 /// <summary>
789                 /// Occurs when a DataRow is changing.
790                 /// </summary>
791                 
792                 public event DataRowChangeEventHandler RowChanging;
793
794                 /// <summary>
795                 /// Occurs after a row in the table has been deleted.
796                 /// </summary>
797                 
798                 public event DataRowChangeEventHandler RowDeleted;
799
800                 /// <summary>
801                 /// Occurs before a row in the table is about to be deleted.
802                 /// </summary>
803                 
804                 public event DataRowChangeEventHandler RowDeleting;
805                 
806                 #endregion //Events
807         }
808
809 }