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".

  FUNCTION Seek

  PARAMETERS inHandle as INTEGER, inKeyValue AS STRING

  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)
        NEXT

        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)
          ENDIF
        ENDIF
      ENDIF

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

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

Thanks, Geoff.

asked 21 Jul '14, 11:31

gverge393's gravatar image

gverge393
126111118
accept rate: 100%

edited 21 Jul '14, 12:32

Mark%20Wilkins's gravatar image

Mark Wilkins
7.2k226133


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.

link

answered 21 Jul '14, 12:44

Mark%20Wilkins's gravatar image

Mark Wilkins
7.2k226133
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

By RSS:

Answers

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

Tags:

×172
×24

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.