I've built a VFP wrapper around the complete set of ADS Client API. In Unit Testing, I've found that all my navigation calls (Go Top, Go Bottom, Skip, etc.) function perfectly - except for my SEEK function. Wanting to implement the SEEK so it is both simple and consistent to use, it uses only the ADS_RAWKEY option. The function gets the key expression via an ADS call and dynamically sets the key values from a passed in expression that mimicks the key expression.

The following function returns true, but always leaves the current record at the top of the table instead of the bottom, where the actual sought-after record is! Other info: at time of call, the connection format is set to "MM/DD/YYYY" and the table is set to the Index "UNITID;DATETIME" and filtered on "UnitID = 19".



  LOCAL result AS INTEGER, locValue AS SHORT, locLen AS INTEGER, locExprWords AS STRING

    ** inHandle is a valid Index Handle
    ** inKeyValue = "19;07/17/2014 16:21"
    ** locKeyExpr below returned from this.GetIndexExpr(inHandle) = "UNITID;DATETIME"
    ** This record exists and is the last record in the table, but this method always 
    ** returns true and leaves the current record at the top of the table:  
    ** positioned on "19;07/07/2014 15:36"!!!

    inKeyValue  = ALLTRIM(inKeyValue)
    locLen      = LEN(inKeyValue)

    IF inHandle > 0
      locKeyExpr = this.GetIndexExpr(inHandle)

      result = AdsInitRawKey(inHandle)
      IF result == 0
        locCount  = Words(locKeyExpr, ";")
        FOR locI = 1 TO locCount
          locExpr = LOWER(ALLTRIM(Wordnum(locKeyExpr, locI, ";")))
          locVal  = LOWER(ALLTRIM(Wordnum(inKeyValue, locI, ";")))
          locLen  = LEN(locVal)
          result  = AdsSetString(inHandle, locExpr, locVal, locLen)

        locValue = 0
        result = AdsGetKeyLength(inHandle, @locLen)
        IF result == 0
          locKey = SPACE(200)
          result = AdsBuildRawKey(inHandle, @locKey, @locLen)
          IF result == 0
            result = AdsSeek(inHandle, locKey, locLen, 1, 1, @locValue)

      IF result != 0
        locLen  = 200
        locCode = 0
        locMsg  = SPACE(locLen)
        result  = AdsGetLastError(@locCode, @locMsg, @locLen)
        =THROW("clsADSTable.Seek: " + locMsg, locCode * -1, "")
      =THROW("clsADSTable.Seek: Not a valid handle.", -1, "")

    ** current record ends up being positioned on "19;07/07/2014 15:36" 
    RETURN (locValue != 0)

Thanks, Geoff.

asked 21 Jul '14, 11:31

gverge393's gravatar image

accept rate: 100%

edited 21 Jul '14, 12:32

Mark%20Wilkins's gravatar image

Mark Wilkins

In general, the logic appears correct to me. One potential issue is the use of the variable locLen in the calls to AdsGetKeyLength and AdsBuildRawKey. The output parameter of those functions (the last param) is supposed to be a 16-bit integer. It looks like locLen is declared as a 4 byte integer. I'm not sure fixing that will change the behavior, but it should be fixed.


answered 21 Jul '14, 12:44

Mark%20Wilkins's gravatar image

Mark Wilkins
accept rate: 26%

Thanks Mark. I changed the locLen to a VFP SHORT, but did not fix the behaviour. I put some debug statements immediately after the AdsBuildRawKey function: return = 0, locLen = 0 and locKey = a single glyph, the one that looks like a rounded, stylized E. What should the Key look like? As you can see, Key Values are an integer and a timestamp.

(22 Jul '14, 05:52) gverge393

Printing the key value of text probably is not effective. The key should be 16 bytes long and contains the binary sortable key data. I just now created an index and extracted the key value for the given integer and datetime and I get: 0xc03300000000000000257d18038221e1. You could maybe use AdsExtractKey to find out what the key value should be. Position to the desired record and call that API and it should return 16 bytes with (I think) the values I just showed.

(22 Jul '14, 07:06) Mark Wilkins
Your answer to the original question.
If responding to a request for additional information, please edit the question or use the comment functionality.
toggle preview

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here



Answers and Comments

Markdown Basics

  • *italic* or _italic_
  • **bold** or __bold__
  • link:[text](http://url.com/ "Title")
  • image?![alt text](/path/img.jpg "Title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported



Asked: 21 Jul '14, 11:31

Seen: 1,427 times

Last updated: 22 Jul '14, 07:06

Advantage Developer Zone Contact Us Privacy Policy Copyright Info

Powered by Advantage Database Server and OSQA
Disclaimer: Opinions expressed here are those of the poster and do not necessarily reflect the views of the company.