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