DatabaseLayer Topic is solved

Talk here about issues with one of the components hosted at wxCode, or suggest features for it.
Post Reply
damir
Earned a small fee
Earned a small fee
Posts: 19
Joined: Thu Jan 12, 2006 11:59 am

DatabaseLayer

Post by damir »

Hi!
There is an error when getting DateTime record in FirebirdDataLayer.

Code:

Code: Select all

wxDateTime FirebirdResultSet::GetResultDate(const wxString& strField)
{
      ....

      if (nType == SQL_TIMESTAMP)
      {
        struct tm timeInTm;
		    isc_decode_timestamp((ISC_TIMESTAMP *)pVar->sqldata, &timeInTm);
        //dateReturn.Set(timeInTm);
        dateReturn.Set(timeInTm.tm_mday, wxDateTime::Month(timeInTm.tm_mon), timeInTm.tm_year, timeInTm.tm_hour, timeInTm.tm_min, timeInTm.tm_sec);
      }

    ....
}
I don't now why but function
dateReturn.Set(timeInTm.tm_mday, wxDateTime::Month(timeInTm.tm_mon), timeInTm.tm_year, timeInTm.tm_hour, timeInTm.tm_min, timeInTm.tm_sec);
don't set the year correct (instead of 2006 I get 0106), but when I use dateReturn.Set(timeInTm) it works fine.

I tested it under Windows. I'll check it on linux when I come home.

Bye[/code]
toxicBunny
Super wx Problem Solver
Super wx Problem Solver
Posts: 424
Joined: Tue Jul 12, 2005 8:44 pm
Location: Alabama, USA

Post by toxicBunny »

This is an issue caused by the tm struct. The tm struct indicates the year as the number of years since 1900. Therefore, the call to wxDateTime::Set() should be adding 1900 to the timeInTm.tm_year value. I submitted a patch for this, but I am not aware if it has been applied in CVS yet.

-Scott
wxMSW 2.6.2, VS 2002, 2003 and 2005, Code::Blocks and mingw, Windows XP Pro
damir
Earned a small fee
Earned a small fee
Posts: 19
Joined: Thu Jan 12, 2006 11:59 am

Post by damir »

Oh! Thanks! :-)

Bye
jb_coder
Super wx Problem Solver
Super wx Problem Solver
Posts: 267
Joined: Mon Oct 18, 2004 10:55 am

Post by jb_coder »

I'm having trouble duplicating the issue. I've add the following debugging line right after the isc_decode_timestamp line

wxPrintf("%d\n", timeInTm.tm_year);

The output that I get when running the unit tests under WinXP (VC 7.1) and Linux (gcc 3.3.5) is "2006", and "1904". So it appears that for some reason I'm getting the correct year.

The reason that I changed from the version of wxDateTime::Set() that takes a struct tm to the version that takes the date/time pieces individually is that the struct tm version wasn't working correctly for me under Linux. If the struct tm version is working for you under Win32 then maybe it would be better to use that version of Set() on Win32 and use the other version on non-Win32 systems?

I'd be interested to hear how others feel is the best way to fix this issue.

Thanks!

P.S. - Has anyone had success using DatabaseLayer on systems other than Linux/Win32?
jb_coder
Super wx Problem Solver
Super wx Problem Solver
Posts: 267
Joined: Mon Oct 18, 2004 10:55 am

Post by jb_coder »

Sorry, but one more question please. What column type are you retrieving from? The main testing that has been done was against the TIMESTAMP type.

Thanks
damir
Earned a small fee
Earned a small fee
Posts: 19
Joined: Thu Jan 12, 2006 11:59 am

Post by damir »

The column type is timestamp. I tested it under linux too and the function

Code: Select all

dateReturn.Set(timeInTm)
is correct one. With function

Code: Select all

dateReturn.Set(timeInTm.tm_mday, wxDateTime::Month(timeInTm.tm_mon), timeInTm.tm_year, timeInTm.tm_hour, timeInTm.tm_min, timeInTm.tm_sec);
I got 0106 under linux like under windows.

All the best,
Damir
jb_coder
Super wx Problem Solver
Super wx Problem Solver
Posts: 267
Joined: Mon Oct 18, 2004 10:55 am

Post by jb_coder »

Does the following code work in your situation?

Code: Select all

wxDateTime FirebirdResultSet::GetResultDate(const wxString& strField)
{
      ....

      if (nType == SQL_TIMESTAMP)
      {
        struct tm timeInTm;
        isc_decode_timestamp((ISC_TIMESTAMP *)pVar->sqldata, &timeInTm);
        dateReturn.Set(timeInTm);
        if (dateReturn == wxInvalidDateTime)
          dateReturn.Set(timeInTm.tm_mday, wxDateTime::Month(timeInTm.tm_mon), timeInTm.tm_year, timeInTm.tm_hour, timeInTm.tm_min, timeInTm.tm_sec);
      }

    ....
}
damir
Earned a small fee
Earned a small fee
Posts: 19
Joined: Thu Jan 12, 2006 11:59 am

Post by damir »

I tryed the code above on windows (I'm don't have linux right now) and the code is working. I mean it compiles without errors and it runs well. But:
when I use code:

Code: Select all


wxDateTime FirebirdResultSet::GetResultDate(const wxString& strField)
{
      ....

      if (nType == SQL_TIMESTAMP)
      {
        struct tm timeInTm;
        isc_decode_timestamp((ISC_TIMESTAMP *)pVar->sqldata, &timeInTm);
        dateReturn.Set(timeInTm);
        if (dateReturn == wxInvalidDateTime)
          dateReturn.Set(timeInTm.tm_mday, wxDateTime::Month(timeInTm.tm_mon), timeInTm.tm_year, timeInTm.tm_hour, timeInTm.tm_min, timeInTm.tm_sec);
      }

    ....
}
it gives me correct value because function dateReturn.Set(timeInTm); works fine at me. I tryed the next code also:

Code: Select all


wxDateTime FirebirdResultSet::GetResultDate(const wxString& strField)
{
      ....

      if (nType == SQL_TIMESTAMP)
      {
        struct tm timeInTm;
        isc_decode_timestamp((ISC_TIMESTAMP *)pVar->sqldata, &timeInTm);
        dateReturn.Set(timeInTm.tm_mday, wxDateTime::Month(timeInTm.tm_mon), timeInTm.tm_year, timeInTm.tm_hour, timeInTm.tm_min, timeInTm.tm_sec);

        if (dateReturn == wxInvalidDateTime)
           dateReturn.Set(timeInTm);
      }

    ....
}
and it gaved me incorrect value (0106). I don't think that the code you write will be solution because dateReturn will never be wxInvalidDateTime (or maybe it will in some extreme cases).
I think that you should recheck your tests. Use isql and read the correct date and then try it with your program.
I'm sure that the problem is in (wxWidgets lib) dateReturn.Set(timeInTm.tm_mday, wxDateTime::Month(timeInTm.tm_mon), timeInTm.tm_year, timeInTm.tm_hour, timeInTm.tm_min, timeInTm.tm_sec); function as described above.

HTH,
Damir[/code]
jb_coder
Super wx Problem Solver
Super wx Problem Solver
Posts: 267
Joined: Mon Oct 18, 2004 10:55 am

Post by jb_coder »

Here is what seems to be happening for me:

1) timeInTm.tm_year = 2006
2) dateReturn.Set(timeInTm) leads to wxInvalidDate

and here is what seems to be happening for you and toxicBunny:

1) timeInTm.tm_year = 106
2) dateReturn.Set(timeInTm) leads to the correct wxDateTime

The wxDateTime::Set() that takes individual parameters will always return a valid date (as long as the paraneters are valid) in both of our cases. That's why that version of Set was only used after checking if the original Set(struct tm) failed.
damir
Earned a small fee
Earned a small fee
Posts: 19
Joined: Thu Jan 12, 2006 11:59 am

Post by damir »

Ok. The code realy does what you explained but now it's a question why is this happening to you? :? :?:
What wx and firebird version are you using? I use the last stable version which is v2.6.2 and firebird is v1.5.2.4731.
But if problem persist then I think there is no other solution than this one. :?

I won't be available until tomorow. So read you tomorow!

P.S.: I sended you an e-mail (I think so) about development.

Bye!
jb_coder
Super wx Problem Solver
Super wx Problem Solver
Posts: 267
Joined: Mon Oct 18, 2004 10:55 am

Post by jb_coder »

Okay, I think that I've been able to figure this one out a little better. I've added a unit test which adds a TIMESTAMP field value as '01/01/06 16:42:23' and this caused the issue to show up. All my previous testing used prepared statements to insert the TIMESTAMP field value. I'll have to take a look at how other applications see the value set by the prepared statement values.

For now, I'll commit the fix (maybe workaround is a better word) and the new unit test into CVS and start researching to see how the prepared statement values are seen by programs like isql, flamerobin, and SQL Manager .
Post Reply