Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SQLBindCol description & SQL_DATA_AT_FETCH #98

Open
matthew-wozniczka opened this issue Feb 16, 2017 · 13 comments
Open

SQLBindCol description & SQL_DATA_AT_FETCH #98

matthew-wozniczka opened this issue Feb 16, 2017 · 13 comments
Assignees

Comments

@matthew-wozniczka
Copy link
Contributor

The current description of SQLBindCol on MSDN talks about the valid values for StrLen_or_IndPtr, and says that SQLFetch/SQLFetchScroll return values into that buffer, but for the SQL_DATA_AT_FETCH case it will be using it for input, so that description will need to be changed.

@matthew-wozniczka
Copy link
Contributor Author

On that note, would it be possible to increase the scope of this repo to include the 'rest' of the spec?

@matthew-wozniczka
Copy link
Contributor Author

If TargetValuePtr is a null pointer, the driver unbinds the data buffer for the column

How does this interact with SQL_DATA_AT_FETCH? Should a non-null (dummy) pointer be provided here? Does a column 'bound' as SQL_DATA_AT_FETCH count as bound for the purposes of SQL_DESC_COUNT? Seems like no, does that cause problems?

@mikepizzo
Copy link
Contributor

Proposal:

  1. If DynamicColumns is true, client must ensure that str_len_or_indicator_ptr is initialized to SQL_DATA_AT_FETCH or SQL_DATA_UNAVAILABLE.
  2. If DynamicColumns is false, the driver must ensure that str_len_or_indicator_ptr is set for every bound column described by the IRD (same rules as today in 3.x)
  3. Driver/DM should never write SQL_DATA_UNAVAILABLE (they just leave the buffer unchanged).

@mikepizzo
Copy link
Contributor

Alternatively, we could say that client sets the value referenced by str_len_or_indicator_ptr to any value other than SQL_DATA_AT_FETCH (typically SQL_DATA_UNAVAILABLE for the first fetch) and that the driver sets the value of unused bound columns (not those marked as SQL_DATA_AT_FETCH) to SQL_DATA_UNAVAILABLE. That would allow the client not to have to reset the status between each call to SQLFetch/SQLFetchScroll.

@matthew-wozniczka
Copy link
Contributor Author

"If DynamicColumns is true" == SQL_ATTR_DYNAMIC_COLUMNS is true?

IIRC SQL_DATA_AT_FETCH is still supported even when dynamic columns are turned off, right? Will it only be supported when the ODBC version is set to 4+? Otherwise it could still break applications.

@mikepizzo
Copy link
Contributor

mikepizzo commented May 2, 2017

No; you're right. SQL_DATA_AT_FETCH is supported even when dynamic columns is turned off; the driver just doesn't need to set DATA_UNAVAILABLE in those cases.

SO I think what we're left with is that the 4.0 application must initialize the buffer to some value other than SQL_DATA_AT_FETCH. Typically this will be the value from the previous fetch, and applications can initialize it to SQL_DATA_UNAVAILABLE.

@matthew-wozniczka
Copy link
Contributor Author

Sorry, just want to be clear on this, is SQL_DATA_AT_FETCH only supported when SQL_ATTR_ODBC_VERSION is set to 4 (or 'greater', 380 notwithstanding)?

@mikepizzo
Copy link
Contributor

Correct.

@mikepizzo
Copy link
Contributor

We could add a (statement?) option that the application set to enable data_at_fetch (SQL_STMT_ATTR_ENABLE_FETCH_I_PROMISE_TO_INITIALIZE_MY_STR_LEN_OR_IND_PTRS), but that would basically have the same effect as setting the version to 4.0 so might not be worth it...

@matthew-wozniczka
Copy link
Contributor Author

Not sure if it belongs in this issue, but another issue I have with the current definition of SQL_DATA_AT_FETCH is that it modifies the behavior of bindings on a per-row basis (we had that for streamed input/output parameters already, but not for column bindings AFAIK).

What I mean is that the driver actually has to look at the value for each cell, and check it against SQL_DATA_AT_FETCH, whereas before it could do a little bit of setup per-binding, and then 'blit' that column across the rowset with very tight code that didn't have to do many checks. (you could check as a pre-processing step, but then you slow down all fetches, even if they would have only fetched a couple (or no) rows)

IMO it would be better if you had to specify it per-column, as opposed to per-cell. (Just off the top of my head, a new descriptor field, something like SQL_DESC_BIND_TYPE which defaults to the current behaviour, and you could set it to SQL_DATA_AT_FETCH, which makes it ignore the data ptr and interrupt fetches instead). Would avoid some of the issues raised as well, since we're no longer re-purposing the length indicator.

@mikepizzo
Copy link
Contributor

mikepizzo commented Jul 18, 2017

Agree that having a descriptor field for data-at-fetch addresses a lot of issues with overloading str_len_or_ind_ptr as an input/output field. This means that the application will have to set this outside of calling SQLBindCol, but that's probably fine.

There is already a SQL_DESC_BIND_TYPE used for row-wise/column-wise binding.

Proposal:

  1. Add a new SQL_DESC_DATA_AT_FETCH descriptor field, used for ARDs, whose SQLSMALLINT value is SQL_FALSE (the default) or SQL_TRUE (for retrieving the data at fetch).

  2. Setting SQL_DESC_DATA_PTR to a non-null value (directly, or through SQLBindCol) sets SQL_DESC_DATA_AT_FETCH to false for the column.

  3. Setting SQL_DESC_DATA_AT_FETCH to SQL_TRUE clears any binding for the column by setting SQL_DESC_DATA_PTR to null.

  4. SQL_DESC_DATA_AT_FETCH can be changed during an interrupted fetch if rowsetsize =1, and applies to the next SQLFetch/SQLFetchScroll.

@mikepizzo
Copy link
Contributor

Applied.

@mikepizzo mikepizzo reopened this Jul 20, 2017
@mikepizzo
Copy link
Contributor

Need to add to headers: SQL_DESC_DATA_AT_FETCH.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants