Solved

Borland Database Engine date decoding errors

Posted on 1997-05-23
10
613 Views
Last Modified: 2012-06-21
Hi, I'm learning-on-the-go as I develop a database application for a small business.  I'm running into a lot of trouble reading numerical and date data from a dBase III file using the Borland Database Engine and IDAPI.

The function was returning wierd values, so as an error-check I encoded then immediately decoded a date.  What I get back is not what I put in.

Help, please!

DbiDateEncode (2, 29, 80, &dte);
DbiDateDecode (dte, (pUINT16)&mm, (pUINT16)&dd, (pINT16)&yy);
sprintf (str, "%i/%i/%i", mm, dd, yy);
MessageBox (hDlg, str, "", MB_OK);

Theoretically, the messagebox should display "2/29/80" but it actually displays something like "901286/13/3248237"

Any ideas?
0
Comment
Question by:Klaxxon
  • 5
  • 3
  • 2
10 Comments
 
LVL 4

Expert Comment

by:AVaulin
ID: 1163662
You use DbiDateEncode and DbiDateDecode not correctly. 1st parameter in DbiDateEncode and 2nd, 3rd and 4th parameters in DbiDateDecode are references. You must write:
DbiDateEncode( 2, 29, 80, dte );
DbiDateDecode( dte, mm, dd, yy );
I hope this will help. Good luck.
0
 

Author Comment

by:Klaxxon
ID: 1163663
Thanks for your answer, but it does not work.

My variables are declared as follows (as the online help file says they should be):

DBIDATE dte;
pUINT16 mm, dd;
pINT16 yy;

My code looks as you suggested:

DbiDateEncode (2, 29, 80, dte);
DbiDateDecode (dte, mm, dd, yy);
sprintf (str, "%i/%i/%i", mm, dd, yy);
MessageBox (hDlg, str, "", MB_OK);            

But will not compile due to the following error:

Error:  superaje.c(583,34):Type mismatch in parameter 'pdateD' in call to 'DbiDateEncode'

I can get the code to compile as follows:

DbiDateEncode (2, 29, 80, &dte);
DbiDateDecode (dte, mm, dd, yy);
sprintf (str, "%i/%i/%i", mm, dd, yy);
MessageBox (hDlg, str, "", MB_OK);            

(I added a '&' to dte in DbiDateEncode), but it crashes with a "Thread Stopped" message saying there was an "access violation".

Obviously, my understanding of pointers is rudimentary, so if you could help further, it would be appreciated.
0
 
LVL 4

Expert Comment

by:AVaulin
ID: 1163664
Let's try this way:

long dte;
Word mm, dd;
short yy;

DbiDateEncode (2, 29, 80, dte);
sprintf (str, "%li", dte);
MessageBox (hDlg, str, "", MB_OK);
DbiDateDecode( dte, mm, dd, yy );
sprintf (str, "%hi/%hi/%hi", mm, dd, yy); // see h specifier
MessageBox (hDlg, str, "", MB_OK);

What both MessageBox says?
0
Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

 

Author Comment

by:Klaxxon
ID: 1163665
Nope ... doesn't work.
I get a bunch of "type mismatch" messages because the types need to be DBIDATE, pUINT16, and pINT16.

I'm working in Borland C++ 32-bit with Borland Database Engine 32-bit.
0
 

Accepted Solution

by:
rlayton earned 100 total points
ID: 1163666
I believe DbiDateEncode requires 4 digits to calculate the correct date.  Try it, you'll like it!
0
 

Author Comment

by:Klaxxon
ID: 1163667
Thanks for the advise, unfortunately it didn't help.  For furthur clarification, here is the exact code I'm using, plus the exact results I get:

The variables are declared as follows:
DBIDATE dte;
pUINT16 mm, dd;
pINT16 yy;

This is the code:
/*  "Chk()" is simply an error-message printing function.  It's source can be found under "chk" in the bde32.hlp file  */

Chk (DbiDateEncode (4, 28, 96, &dte));
Chk (DbiDateDecode (dte, (pUINT16)&mm, (pUINT16)&dd, (pINT16)&yy));
sprintf (str, "%i/%i/%i", mm, dd, yy);
MessageBox (hDlg, str, "", MB_OK);

Here's the results with different dates:

when I encode:  5, 28, 1997
I get:  2064515077/28/133069
(at least the day works!)

encode:  5, 28, 97
get:  2064515077/28/131169

encode:  4, 28, 97
get:  2064515076/28/131169

encode:  4, 28, 96
get:  2064515076/28/131168

These results imply that I get simply subtract a particular value from each answer to get the right one.  This is the first time I actually did a trial-and-error check of the return values, and now it looks like they're always off by a consistant ammount.

I'd still like to have the function work properly, though.... I really bothers me to have to hack an answer out.

BTW, I ran the DbiGetDateFormat() function, and it returned the following:
DateFormat = 0
4 digit year = 0
Year biased = 1
date separator = '/'

The explanations of those are in the help file, but those values are as they should be.

As some additional background, I'm writing a program that reads in a dBase III .DBF file.  I was getting weird values when reading dates, so *that's* why I encoded then decoded a date... It's purpose is simply an error check.

Thanks for your help, I hope I've clarified a few things, and I hope you can assist me further...  My employer is getting anxious to see some results and this problem has been a major roadblock.
       - Klaxxon
0
 

Expert Comment

by:rlayton
ID: 1163668
Here is the exact code I use to encode/decode this stuff:

int Month, int Day, int Year;
DBIDATE Td;
 
DbiDateEncode(Month, Day, Year, &Td);
DbiDateDecode(Td, &Month, &Day, &Year);

This stuff is actually quite straight forward, and I haven't had any problems with it once I got it all setup and working correctly.  

The only other problem I can see is if the memory for the table buffer isn't allocated correctly.  Also, view the contents of the Td  ( the DBIDATE / double) variable after encoding each of the different trial dates, and see what relationship they have.  

I've never used the BDE with dBaseIII, but I've plenty of success using it with Paradox, MS SQL Server, and Sybase, which should basically be the same using it with any other DataBase

Anyway, Good luck!


PS. I have a DataBase/Table wrapper class I've written which encapsulates all this stuff, automating file opening, record access, etc...,  which really makes it much easier to manage (at least for me.)  If you're interested let me know,  I'd consider letting somebody else try it out!  However it may take you longer to get it set up than you have to waste.


0
 

Author Comment

by:Klaxxon
ID: 1163669
aaaallllllrrrriiiiiigggggghhhhhhtttttttt!!!!!

(you'll have to excuse me, but this problem has been really bothering me... and now it's FIXED!!!)  :o)

For some unknown reason, if the month, day, and year variables have not been assigned a value (it appears any value will do) before DbiDateDecode (dte, &mm, &dd, &yy); is called, then I get screwy answers.  All I did was assign mm = dd = yy = 1; at the top of the function, and now DbiDateDecode returns everything correctly!!  Wahoo!

I figured that out because in your code you fed DbiDateEncode preassigned values while I was trying to pass numbers directly to the function.  This led me to do a little playing around, and I figured it out.

Thank you *VERY* much.

.....Now, on with my program!

PS:  You *may* see a question posted here soon about reading regular numerical data (as opposed to strings) from a database.  But I'll see what I can do first.  Thanks a bunch.
0
 

Author Comment

by:Klaxxon
ID: 1163670
Yup.... I'm having problems with reading numerical data.  YaSee, this is the first time I've ever used BDE so I'm learning as I go.

Say a field contains an integer.  Do I just do the following?

int num;
DbiGetField (VarCur, FieldNum, RecBuff, (pBYTE)num, ...);

or do I use:
..., (pBYTE)&num, ...

or do I declare num as a string or perhaps a double?

If you could send me some sample source either as a comment to this question or to rogersa@superaje.com ,  I'd really appreciate it.

If you like, I can submit it as a 25 or 50 point question and then grade you.

Thanks in advance.
0
 

Expert Comment

by:rlayton
ID: 1163671
I'll give this one to you, just treat me well when the opportunity arises.

If the value you are retrieving is a double, then pass in a double, likewise with int, char*,etc...

Here is a snippet from my table class...

char * Table::GetField (UINT16 FieldNum, char *Src)
{
      BOOL Blank;

      strcpy(Action, "GetField");

      Status = DbiGetField (Cursor, FieldNum, DBRec, (pBYTE)Src, &Blank);

//Not always blank in SQL Server
      if(Blank)
      {
            switch(NumberType)
            {
                  case NINT:
                        memset(Src, 0, sizeof(int));
                        break;

                  case NDOUBLE:
                        memset(Src, 0, sizeof(double));
                        break;

                  case NLONG:
                        memset(Src, 0, sizeof(long));
                        break;

                  default:
                        strcpy(Src, "");

            }
      }


      if(Status)
            ErrorHandler();

      return Src;

}


double Table::GetField(UINT16 FieldNum, double &Number)
{
      NumberType = NDOUBLE;

      GetField(FieldNum, (char *)&Number);

      return Number;
}


int Table::GetField(UINT16 FieldNum, int &Number)
{
      NumberType = NINT;

      GetField(FieldNum, (char *)&Number);

      return Number;
}


long Table::GetField(UINT16 FieldNum, long &Number)
{
      NumberType = NLONG;

      GetField(FieldNum, (char *)&Number);

      return Number;
}


As you can see, I simply pass in the variable of the type I want to retrieve, which forces the correct function to be called, and the variable is also returned for ease of use!  Each function calls the top (top as in top of this listing) function, so you could look at that one for reference.  The Cursor and Record are both part of the class, so you'll need to pass those in as well.

Quick examples for use:

double Double;
int Integer;
char Str[MAX_SIZE];

wsprintf(Temp, "%d \t %lf", GetField(FieldNum, Integer), GetField(FieldNum, Double));
MessageBox(0, GetField(FieldNum, Str), Title, MB_OK);

etc...


Good Luck!
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

839 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question