]> git.saurik.com Git - wxWidgets.git/blob - src/common/dbgrid.cpp
corrected Mac OS X resource file name
[wxWidgets.git] / src / common / dbgrid.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: dbgrid.cpp
3 // Purpose: Displays a wxDbTable in a wxGrid.
4 // Author: Roger Gammans, Paul Gammans
5 // Modified by:
6 // Created:
7 // RCS-ID: $Id$
8 // Copyright: (c) 1999 The Computer Surgery (roger@computer-surgery.co.uk)
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11 // Branched From : dbgrid.cpp,v 1.18 2000/12/19 13:00:58
12 ///////////////////////////////////////////////////////////////////////////////
13
14 #ifdef __GNUG__
15 #pragma implementation "dbgrid.h"
16 #endif
17
18 #include "wx/wxprec.h"
19
20 #ifdef __BORLANDC__
21 #pragma hdrstop
22 #endif
23
24
25 #if wxUSE_ODBC
26 #if wxUSE_NEW_GRID
27
28 #ifndef WX_PRECOMP
29 #include "wx/textctrl.h"
30 #include "wx/dc.h"
31 #endif // WX_PRECOMP
32
33 #include "wx/generic/gridctrl.h"
34 #include "wx/dbgrid.h"
35
36
37 wxDbGridCellAttrProvider::wxDbGridCellAttrProvider()
38 {
39 m_data=NULL;
40 m_ColInfo=NULL;
41 }
42
43 wxDbGridCellAttrProvider::wxDbGridCellAttrProvider(wxDbTable *tab, wxDbGridColInfoBase* ColInfo)
44 {
45 m_data=tab;
46 m_ColInfo=ColInfo;
47 }
48
49 wxDbGridCellAttrProvider::~wxDbGridCellAttrProvider()
50 {
51 }
52
53 wxGridCellAttr *wxDbGridCellAttrProvider::GetAttr(int row, int col,
54 wxGridCellAttr::wxAttrKind kind) const
55 {
56 wxGridCellAttr *attr = wxGridCellAttrProvider::GetAttr(row,col,kind);
57
58 if (m_data && m_ColInfo && (m_data->GetNumberOfColumns() > m_ColInfo[col].DbCol))
59 {
60 //FIXME: this test could.
61 // ??::InsertPending == m_data->get_ModifiedStatus()
62 // and if InsertPending use colDef[].InsertAllowed
63 if (!(m_data->GetColDefs()[(m_ColInfo[col].DbCol)].Updateable))
64 {
65 switch(kind)
66 {
67 case (wxGridCellAttr::Any):
68 if (!attr)
69 {
70 attr = new wxGridCellAttr;
71 // Store so we don't keep creating / deleting this...
72 wxDbGridCellAttrProvider * self = wxConstCast(this, wxDbGridCellAttrProvider) ;
73 attr->IncRef();
74 self->SetColAttr(attr, col);
75 attr->SetReadOnly();
76 }
77 else
78 {
79 //We now must check what we were returned. and do the right thing (tm)
80 wxGridCellAttr::wxAttrKind attrkind = attr->GetKind();
81 if ((attrkind == (wxGridCellAttr::Default)) || (attrkind == (wxGridCellAttr::Cell)) ||
82 (attrkind == (wxGridCellAttr::Col)))
83 {
84 wxGridCellAttr *attrtomerge = attr;
85 attr = new wxGridCellAttr;
86 attr->SetKind(wxGridCellAttr::Merged);
87 attr->MergeWith(attrtomerge);
88 attr->SetReadOnly();
89 attrtomerge->DecRef();
90 }
91 attr->SetReadOnly();
92 }
93 break;
94 case (wxGridCellAttr::Col):
95 //As we must have a Coll, and were setting Coll attributes
96 // we can based on wxdbTable's so just set RO if attr valid
97 if (!attr)
98 {
99 attr = new wxGridCellAttr;
100 wxDbGridCellAttrProvider * self = wxConstCast(this, wxDbGridCellAttrProvider) ;
101 attr->IncRef();
102 self->SetColAttr(attr, col);
103 }
104 attr->SetReadOnly();
105 break;
106 default:
107 //Dont add RO for...
108 // wxGridCellAttr::Cell - Not required, will inherit on merge from row.
109 // wxGridCellAttr::Row - If wxDbtable ever supports row locking could add
110 // support to make RO on a row basis also.
111 // wxGridCellAttr::Default - Don't edit this ! or all cell with a attr will become readonly
112 // wxGridCellAttr::Merged - This should never be asked for.
113 break;
114 }
115 }
116
117 }
118 return attr;
119 }
120
121 void wxDbGridCellAttrProvider::AssignDbTable(wxDbTable *tab)
122 {
123 m_data = tab;
124 }
125
126 wxDbGridTableBase::wxDbGridTableBase(wxDbTable *tab, wxDbGridColInfo* ColInfo,
127 int count, bool takeOwnership) :
128 m_keys(),
129 m_data(tab),
130 m_dbowner(takeOwnership),
131 m_rowmodified(false)
132 {
133
134 if (count == wxUSE_QUERY)
135 {
136 m_rowtotal = m_data ? m_data->Count() : 0;
137 }
138 else
139 {
140 m_rowtotal = count;
141 }
142 // m_keys.Size(m_rowtotal);
143 m_row = -1;
144 if (ColInfo)
145 {
146 m_nocols = ColInfo->Length();
147 m_ColInfo = new wxDbGridColInfoBase[m_nocols];
148 //Do Copy.
149 wxDbGridColInfo *ptr = ColInfo;
150 int i =0;
151 while (ptr && i < m_nocols)
152 {
153 m_ColInfo[i] = ptr->m_data;
154 ptr = ptr->m_next;
155 i++;
156 }
157 #ifdef __WXDEBUG__
158 if (ptr)
159 {
160 wxLogDebug(wxT("NoCols over length after traversing %i items"),i);
161 }
162 if (i < m_nocols)
163 {
164 wxLogDebug(wxT("NoCols under length after traversing %i items"),i);
165 }
166 #endif
167 }
168 }
169
170 wxDbGridTableBase::~wxDbGridTableBase()
171 {
172 wxDbGridCellAttrProvider *provider;
173
174 //Can't check for update here as
175
176 //FIXME: should i remove m_ColInfo and m_data from m_attrProvider if a wxDbGridAttrProvider
177 // if ((provider = dynamic_cast<wxDbGridCellAttrProvider *>(GetAttrProvider())))
178 // Using C casting for now until we can support dynamic_cast with wxWindows
179 if ((provider = (wxDbGridCellAttrProvider *)(GetAttrProvider())))
180 {
181 provider->AssignDbTable(NULL);
182 }
183 delete [] m_ColInfo;
184
185 Writeback();
186 if (m_dbowner)
187 {
188 delete m_data;
189 }
190 }
191
192 bool wxDbGridTableBase::CanHaveAttributes()
193 {
194 if (!GetAttrProvider())
195 {
196 // use the default attr provider by default
197 SetAttrProvider(new wxDbGridCellAttrProvider(m_data, m_ColInfo));
198 }
199 return true;
200 }
201
202
203 bool wxDbGridTableBase::AssignDbTable(wxDbTable *tab, int count, bool takeOwnership)
204 {
205 wxDbGridCellAttrProvider *provider;
206
207 //Remove Information from grid about old data
208 if (GetView())
209 {
210 wxGrid *grid = GetView();
211 grid->BeginBatch();
212 grid->ClearSelection();
213 if (grid->IsCellEditControlEnabled())
214 {
215 grid->DisableCellEditControl();
216 }
217 wxGridTableMessage msg(this, wxGRIDTABLE_NOTIFY_ROWS_DELETED,0,m_rowtotal);
218 grid->ProcessTableMessage(msg);
219 }
220
221 //reset our internals...
222 Writeback();
223 if (m_dbowner)
224 {
225 delete m_data;
226 }
227 m_keys.Empty();
228 m_data = tab;
229 //FIXME: Remove dynamic_cast before sumision to wxwin
230 // if ((provider = dynamic_cast<wxDbGridCellAttrProvider *> (GetAttrProvider())))
231 // Using C casting for now until we can support dynamic_cast with wxWindows
232 if ((provider = (wxDbGridCellAttrProvider *)(GetAttrProvider())))
233 {
234 provider->AssignDbTable(m_data);
235 }
236
237 if (count == wxUSE_QUERY)
238 {
239 m_rowtotal = m_data ? m_data->Count() : 0;
240 }
241 else
242 {
243 m_rowtotal = count;
244 }
245 m_row = -1;
246
247 //Add Information to grid about new data
248 if (GetView())
249 {
250 wxGrid * grid = GetView();
251 wxGridTableMessage msg(this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_rowtotal);
252 grid->ProcessTableMessage(msg);
253 grid->EndBatch();
254 }
255 m_dbowner = takeOwnership;
256 m_rowmodified = false;
257 return true;
258 }
259
260 wxString wxDbGridTableBase::GetTypeName(int row, int col)
261 {
262 if (col == 8)
263 int breakpoint = 1;
264
265 if (GetNumberCols() > col)
266 {
267 if (m_ColInfo[col].wxtypename == wxGRID_VALUE_DBAUTO)
268 {
269 if (m_data->GetNumberOfColumns() <= m_ColInfo[col].DbCol)
270 {
271 wxFAIL_MSG (_T("You can not use wxGRID_VALUE_DBAUTO for virtual columns"));
272 }
273 switch(m_data->GetColDefs()[(m_ColInfo[col].DbCol)].SqlCtype)
274 {
275 case SQL_C_CHAR:
276 return wxGRID_VALUE_STRING;
277 break;
278 case SQL_C_SSHORT:
279 return wxGRID_VALUE_NUMBER;
280 break;
281 case SQL_C_USHORT:
282 return wxGRID_VALUE_NUMBER;
283 break;
284 case SQL_C_SLONG:
285 return wxGRID_VALUE_NUMBER;
286 break;
287 case SQL_C_ULONG:
288 return wxGRID_VALUE_NUMBER;
289 break;
290 case SQL_C_FLOAT:
291 return wxGRID_VALUE_FLOAT;
292 break;
293 case SQL_C_DOUBLE:
294 return wxGRID_VALUE_FLOAT;
295 break;
296 case SQL_C_DATE:
297 return wxGRID_VALUE_DATETIME;
298 break;
299 case SQL_C_TIME:
300 return wxGRID_VALUE_DATETIME;
301 break;
302 case SQL_C_TIMESTAMP:
303 return wxGRID_VALUE_DATETIME;
304 break;
305 default:
306 return wxGRID_VALUE_STRING;
307 break;
308 }
309 }
310 else
311 {
312 return m_ColInfo[col].wxtypename;
313 }
314 }
315 wxFAIL_MSG (_T("unknown column"));
316 return wxString();
317 }
318
319 bool wxDbGridTableBase::CanGetValueAs(int row, int col, const wxString& typeName)
320 {
321 wxLogDebug(wxT("CanGetValueAs() on %i,%i"),row,col);
322 //Is this needed? As it will be validated on GetValueAsXXXX
323 ValidateRow(row);
324
325 if (typeName == wxGRID_VALUE_STRING)
326 {
327 //FIXME ummm What about blob field etc.
328 return true;
329 }
330
331 if (m_data->IsColNull(m_ColInfo[col].DbCol))
332 {
333 return false;
334 }
335
336 if (m_data->GetNumberOfColumns() <= m_ColInfo[col].DbCol)
337 {
338 //If a virtual column then we can't find it's type. we have to
339 // return false to get using wxVariant.
340 return false;
341 }
342 int sqltype = m_data->GetColDefs()[(m_ColInfo[col].DbCol)].SqlCtype;
343
344 if (typeName == wxGRID_VALUE_DATETIME)
345 {
346 if ((sqltype == SQL_C_DATE) ||
347 (sqltype == SQL_C_TIME) ||
348 (sqltype == SQL_C_TIMESTAMP))
349 {
350 return true;
351 }
352 return false;
353 }
354 if (typeName == wxGRID_VALUE_NUMBER)
355 {
356 if ((sqltype == SQL_C_SSHORT) ||
357 (sqltype == SQL_C_USHORT) ||
358 (sqltype == SQL_C_SLONG) ||
359 (sqltype == SQL_C_ULONG))
360 {
361 return true;
362 }
363 return false;
364 }
365 if (typeName == wxGRID_VALUE_FLOAT)
366 {
367 if ((sqltype == SQL_C_SSHORT) ||
368 (sqltype == SQL_C_USHORT) ||
369 (sqltype == SQL_C_SLONG) ||
370 (sqltype == SQL_C_ULONG) ||
371 (sqltype == SQL_C_FLOAT) ||
372 (sqltype == SQL_C_DOUBLE))
373 {
374 return true;
375 }
376 return false;
377 }
378 return false;
379 }
380
381 bool wxDbGridTableBase::CanSetValueAs(int row, int col, const wxString& typeName)
382 {
383 //Is this needed? As will be validated on SetValueAsXXXX
384 ValidateRow(row);
385
386 if (m_data->IsColNull(m_ColInfo[col].DbCol))
387 {
388 return false;
389 }
390
391 if (typeName == wxGRID_VALUE_STRING)
392 {
393 //FIXME ummm What about blob field etc.
394 return true;
395 }
396
397 if (!(m_data->GetColDefs()[(m_ColInfo[col].DbCol)].Updateable))
398 {
399 return false;
400 }
401
402 if (m_data->GetNumberOfColumns() <= m_ColInfo[col].DbCol)
403 {
404 //If a virtual column then we can't find it's type. we have to faulse to
405 //get using wxVairent.
406 return false;
407 }
408
409 int sqltype = m_data->GetColDefs()[(m_ColInfo[col].DbCol)].SqlCtype;
410 if (typeName == wxGRID_VALUE_DATETIME)
411 {
412 if ((sqltype == SQL_C_DATE) ||
413 (sqltype == SQL_C_TIME) ||
414 (sqltype == SQL_C_TIMESTAMP))
415 {
416 return true;
417 }
418 return false;
419 }
420 if (typeName == wxGRID_VALUE_NUMBER)
421 {
422 if ((sqltype == SQL_C_SSHORT) ||
423 (sqltype == SQL_C_USHORT) ||
424 (sqltype == SQL_C_SLONG) ||
425 (sqltype == SQL_C_ULONG))
426 {
427 return true;
428 }
429 return false;
430 }
431 if (typeName == wxGRID_VALUE_FLOAT)
432 {
433 if ((sqltype == SQL_C_SSHORT) ||
434 (sqltype == SQL_C_USHORT) ||
435 (sqltype == SQL_C_SLONG) ||
436 (sqltype == SQL_C_ULONG) ||
437 (sqltype == SQL_C_FLOAT) ||
438 (sqltype == SQL_C_DOUBLE))
439 {
440 return true;
441 }
442 return false;
443 }
444 return false;
445 }
446
447 long wxDbGridTableBase::GetValueAsLong(int row, int col)
448 {
449 ValidateRow(row);
450
451 if (m_data->GetNumberOfColumns() <= m_ColInfo[col].DbCol)
452 {
453 wxFAIL_MSG (_T("You can not use GetValueAsLong for virtual columns"));
454 return 0;
455 }
456 int sqltype = m_data->GetColDefs()[(m_ColInfo[col].DbCol)].SqlCtype;
457 if ((sqltype == SQL_C_SSHORT) ||
458 (sqltype == SQL_C_USHORT) ||
459 (sqltype == SQL_C_SLONG) ||
460 (sqltype == SQL_C_ULONG))
461 {
462 wxVariant val = m_data->GetCol(m_ColInfo[col].DbCol);
463 return val.GetLong();
464 }
465 wxFAIL_MSG (_T("unknown column, "));
466 return 0;
467 }
468
469 double wxDbGridTableBase::GetValueAsDouble(int row, int col)
470 {
471 wxLogDebug(wxT("GetValueAsDouble() on %i,%i"),row,col);
472 ValidateRow(row);
473
474 if (m_data->GetNumberOfColumns() <= m_ColInfo[col].DbCol)
475 {
476 wxFAIL_MSG (_T("You can not use GetValueAsDouble for virtual columns"));
477 return 0.0;
478 }
479 int sqltype = m_data->GetColDefs()[(m_ColInfo[col].DbCol)].SqlCtype;
480 if ((sqltype == SQL_C_SSHORT) ||
481 (sqltype == SQL_C_USHORT) ||
482 (sqltype == SQL_C_SLONG) ||
483 (sqltype == SQL_C_ULONG) ||
484 (sqltype == SQL_C_FLOAT) ||
485 (sqltype == SQL_C_DOUBLE))
486 {
487 wxVariant val = m_data->GetCol(m_ColInfo[col].DbCol);
488 return val.GetDouble();
489 }
490 wxFAIL_MSG (_T("unknown column"));
491 return 0.0;
492 }
493
494 bool wxDbGridTableBase::GetValueAsBool(int row, int col)
495 {
496 wxLogDebug(wxT("GetValueAsBool() on %i,%i"),row,col);
497 ValidateRow(row);
498
499 if (m_data->GetNumberOfColumns() <= m_ColInfo[col].DbCol)
500 {
501 wxFAIL_MSG (_T("You can not use GetValueAsBool for virtual columns"));
502 return 0;
503 }
504 int sqltype = m_data->GetColDefs()[(m_ColInfo[col].DbCol)].SqlCtype;
505 if ((sqltype == SQL_C_SSHORT) ||
506 (sqltype == SQL_C_USHORT) ||
507 (sqltype == SQL_C_SLONG) ||
508 (sqltype == SQL_C_ULONG))
509 {
510 wxVariant val = m_data->GetCol(m_ColInfo[col].DbCol);
511 return val.GetBool();
512 }
513 wxFAIL_MSG (_T("unknown column, "));
514 return 0;
515 }
516
517 void* wxDbGridTableBase::GetValueAsCustom(int row, int col, const wxString& typeName)
518 {
519 wxLogDebug(wxT("GetValueAsCustom() on %i,%i"),row,col);
520 ValidateRow(row);
521
522 if (m_data->GetNumberOfColumns() <= m_ColInfo[col].DbCol)
523 {
524 wxFAIL_MSG (_T("You can not use GetValueAsCustom for virtual columns"));
525 return NULL;
526 }
527 if (m_data->IsColNull(m_ColInfo[col].DbCol))
528 return NULL;
529
530 if (typeName == wxGRID_VALUE_DATETIME)
531 {
532 wxDbColDef *pColDefs = m_data->GetColDefs();
533 int sqltype = pColDefs[(m_ColInfo[col].DbCol)].SqlCtype;
534
535 if ((sqltype == SQL_C_DATE) ||
536 (sqltype == SQL_C_TIME) ||
537 (sqltype == SQL_C_TIMESTAMP))
538 {
539 wxVariant val = m_data->GetCol(m_ColInfo[col].DbCol);
540 return new wxDateTime(val.GetDateTime());
541 }
542 }
543 wxFAIL_MSG (_T("unknown column data type "));
544 return NULL;
545 }
546
547
548 void wxDbGridTableBase::SetValueAsCustom(int row, int col, const wxString& typeName, void* value)
549 {
550 wxLogDebug(wxT("SetValueAsCustom() on %i,%i"),row,col);
551 ValidateRow(row);
552
553 if (m_data->GetNumberOfColumns() <= m_ColInfo[col].DbCol)
554 {
555 wxFAIL_MSG (_T("You can not use SetValueAsCustom for virtual columns"));
556 return;
557 }
558
559 if (typeName == wxGRID_VALUE_DATETIME)
560 {
561 int sqltype = m_data->GetColDefs()[(m_ColInfo[col].DbCol)].SqlCtype;
562 if ((sqltype == SQL_C_DATE) ||
563 (sqltype == SQL_C_TIME) ||
564 (sqltype == SQL_C_TIMESTAMP))
565 {
566 //FIXME: you can't dynamic_cast from (void *)
567 //wxDateTime *date = wxDynamicCast(value, wxDateTime);
568 wxDateTime *date = (wxDateTime *)value;
569 if (!date)
570 {
571 wxFAIL_MSG (_T("Failed to convert data"));
572 return;
573 }
574 wxVariant val(date);
575 m_rowmodified = true;
576 m_data->SetCol(m_ColInfo[col].DbCol,val);
577 }
578 }
579 wxFAIL_MSG (_T("unknown column data type"));
580 return ;
581 }
582
583
584 wxString wxDbGridTableBase::GetColLabelValue(int col)
585 {
586 if (GetNumberCols() > col)
587 {
588 return m_ColInfo[col].Title;
589 }
590 wxFAIL_MSG (_T("unknown column"));
591 return wxString();
592 }
593
594 bool wxDbGridTableBase::IsEmptyCell(int row, int col)
595 {
596 wxLogDebug(wxT("IsEmtpyCell on %i,%i"),row,col);
597
598 ValidateRow(row);
599 return m_data->IsColNull(m_ColInfo[col].DbCol);
600 }
601
602
603 wxString wxDbGridTableBase::GetValue(int row, int col)
604 {
605 wxLogDebug(wxT("GetValue() on %i,%i"),row,col);
606
607 ValidateRow(row);
608 wxVariant val = m_data->GetCol(m_ColInfo[col].DbCol);
609 wxLogDebug(wxT("\tReturning \"%s\"\n"),val.GetString().c_str());
610
611 return val.GetString();
612 }
613
614
615 void wxDbGridTableBase::SetValue(int row, int col,const wxString& value)
616 {
617 wxLogDebug(wxT("SetValue() on %i,%i"),row,col);
618
619 ValidateRow(row);
620 wxVariant val(value);
621
622 m_rowmodified = true;
623 m_data->SetCol(m_ColInfo[col].DbCol,val);
624 }
625
626
627 void wxDbGridTableBase::SetValueAsLong(int row, int col, long value)
628 {
629 wxLogDebug(wxT("SetValueAsLong() on %i,%i"),row,col);
630
631 ValidateRow(row);
632 wxVariant val(value);
633
634 m_rowmodified = true;
635 m_data->SetCol(m_ColInfo[col].DbCol,val);
636 }
637
638
639 void wxDbGridTableBase::SetValueAsDouble(int row, int col, double value)
640 {
641 wxLogDebug(wxT("SetValueAsDouble() on %i,%i"),row,col);
642
643 ValidateRow(row);
644 wxVariant val(value);
645
646 m_rowmodified = true;
647 m_data->SetCol(m_ColInfo[col].DbCol,val);
648
649 }
650
651
652 void wxDbGridTableBase::SetValueAsBool(int row, int col, bool value)
653 {
654 wxLogDebug(wxT("SetValueAsBool() on %i,%i"),row,col);
655
656 ValidateRow(row);
657 wxVariant val(value);
658
659 m_rowmodified = true;
660 m_data->SetCol(m_ColInfo[col].DbCol,val);
661 }
662
663
664 void wxDbGridTableBase::ValidateRow(int row)
665 {
666 wxLogDebug(wxT("ValidateRow(%i) currently on row (%i). Array count = %i"),row,m_row,m_keys.GetCount());
667
668 if (row == m_row)
669 return;
670 Writeback();
671
672 //We add to row as Count is unsigned!
673 if ((unsigned)(row+1) > m_keys.GetCount())
674 {
675 wxLogDebug(wxT("\trow key unknown"));
676 // Extend Array, iterate through data filling with keys
677 m_data->SetRowMode(wxDbTable::WX_ROW_MODE_QUERY);
678 int trow;
679 for (trow = m_keys.GetCount(); trow <= row; trow++)
680 {
681 wxLogDebug(wxT("Fetching row %i.."), trow);
682 bool ret = m_data->GetNext();
683
684 wxLogDebug(wxT(" ...success=(%i)"),ret);
685 GenericKey k = m_data->GetKey();
686 m_keys.Add(k);
687 }
688 m_row = row;
689 }
690 else
691 {
692 wxLogDebug(wxT("\trow key known centering data"));
693 GenericKey k = m_keys.Item(row);
694 m_data->SetRowMode(wxDbTable::WX_ROW_MODE_INDIVIDUAL);
695 m_data->ClearMemberVars();
696 m_data->SetKey(k);
697 if (!m_data->QueryOnKeyFields())
698 {
699 wxDbLogExtendedErrorMsg("ODBC error during Query()\n\n", m_data->GetDb(),__FILE__,__LINE__);
700 }
701
702 m_data->GetNext();
703
704 m_row = row;
705 }
706 m_rowmodified = false;
707 }
708
709 bool wxDbGridTableBase::Writeback() const
710 {
711 if (!m_rowmodified)
712 {
713 return true;
714 }
715
716 bool result=true;
717 wxLogDebug(wxT("\trow key unknown"));
718
719 // FIXME: this code requires dbtable support for record status
720 #if 0
721 switch (m_data->get_ModifiedStatus())
722 {
723 case wxDbTable::UpdatePending:
724 result = m_data->Update();
725 break;
726 case wxDbTable::InsertPending:
727 result = (m_data->Insert() == SQL_SUCCESS);
728 break;
729 default:
730 //Nothing
731 break;
732 }
733 #else
734 wxLogDebug(wxT("WARNING : Row writeback not implemented "));
735 #endif
736 return result;
737 }
738
739 #include <wx/arrimpl.cpp>
740
741 WX_DEFINE_OBJARRAY(keyarray);
742
743 #endif // #if wxUSE_NEW_GRID
744 #endif // #if wxUSE_ODBC
745