TN042: Recomendaciones para desarrolladores de controladores ODBC
Nota:
La nota técnica siguiente no se ha actualizado desde que se incluyó por primera vez en la documentación en línea. Como resultado, algunos procedimientos y temas podrían estar obsoletos o ser incorrectos. Para obtener información más reciente, se recomienda buscar el tema de interés en el índice de la documentación en línea.
Esta nota describe las directrices para los escritores de controladores ODBC. Describe los requisitos generales y las suposiciones de la funcionalidad ODBC que realizan las clases de la base de datos MFC y varios detalles semánticos esperados. Se describe la funcionalidad del controlador necesaria para admitir los tres modos Open CRecordset
(forwardOnly, snapshot y dynaset).
Biblioteca de cursores de ODBC
Las clases de base de datos MFC presentan una funcionalidad al usuario que en muchos casos supera la funcionalidad proporcionada por la mayoría de los controladores ODBC de nivel 1. Afortunadamente, la biblioteca de cursores de ODBC se superpone entre las clases de base de datos y el controlador, además proporcionará automáticamente gran parte de esta funcionalidad adicional.
Por ejemplo, la mayoría de los controladores 1.0 no admiten el desplazamiento hacia atrás. La biblioteca de cursores puede detectar esto y almacenará en caché las filas del controlador y las presentará como solicitadas en las llamadas FETCH_PREV en SQLExtendedFetch
.
Otro ejemplo importante de dependencia de la biblioteca de cursores son las actualizaciones posicionadas. La mayoría de los controladores 1.0 tampoco tienen actualizaciones posicionadas, pero la biblioteca de cursores generará instrucciones de actualización que identifican una fila de destino en el origen de datos de acuerdo a sus valores de datos almacenados en caché actuales o un valor de marca de tiempo almacenado en caché.
La biblioteca de clases nunca usa varios conjuntos de filas. Por lo tanto, las pocas instrucciones SQLSetPos
siempre se aplican a la fila 1 del conjunto de filas.
CDatabases
Cada CDatabase
asigna un único HDBC. (Si se usa la función ExecuteSQL
de CDatabase
se asigna temporalmente un HSTMT ). Por lo tanto, si se requieren varios CDatabase
, se deben admitir varios HDBCpor HENV.
Las clases de base de datos requieren la biblioteca de cursores. Esto se refleja en una llamada SQLSetConnections
a SQL_ODBC_CURSORS, SQL_CUR_USE_ODBC.
SQLDriverConnect
, SQL_DRIVER_COMPLETE se usa por CDatabase::Open
para establecer la conexión con el origen de datos.
El controlador debe admitir SQLGetInfo SQL_ODBC_API_CONFORMANCE
>= SQL_OAC_LEVEL1, SQLGetInfo SQL_ODBC_SQL_CONFORMANCE
>= SQL_OSC_MINIMUM.
Para que las transacciones sean compatibles con CDatabase
y sus conjuntos de registros dependientes, SQLGetInfo SQL_CURSOR_COMMIT_BEHAVIOR
y SQL_CURSOR_ROLLBACK_BEHAVIOR deben tener SQL_CR_PRESERVE. De lo contrario, se omitirán los intentos de realizar el control de transacciones.
SQLGetInfo SQL_DATA_SOURCE_READ_ONLY
se debe admitir. Si devuelve "Y", no se realizarán las operaciones de actualización en el origen de datos.
Si CDatabase
se abre como ReadOnly, se realizará un intento de establecer el origen de datos de solo lectura con SQLSetConnectOption SQL_ACCESS_MODE
, SQL_MODE_READ_ONLY.
Si los identificadores requieren comillas, esta información debe devolverse desde el controlador con una llamada a SQLGetInfo SQL_IDENTIFIER_QUOTE_CHAR
.
Con fines de depuración, SQLGetInfo SQL_DBMS_VER
y SQL_DBMS_NAME se recuperan del controlador.
SQLSetStmtOption SQL_QUERY_TIMEOUT
y SQL_ASYNC_ENABLE pueden ser llamados en el HDBC de CDatabase
.
SQLError
se puede llamar con cualquier argumento o todos los argumentos NULL.
Por supuesto, es necesario admitir a SQLAllocEnv
, SQLAllocConnect
, SQLDisconnect
y SQLFreeConnect
.
ExecuteSQL
Además de asignar y liberar un HSTMT temporal, ExecuteSQL
llama a SQLExecDirect
, SQLFetch
, SQLNumResultCol
y SQLMoreResults
. SQLCancel
se puede llamar en HSTMT.
GetDatabaseName
SQLGetInfo SQL_DATABASE_NAME
se llamará.
BeginTrans, CommitTrans, Rollback
SQLSetConnectOption SQL_AUTOCOMMIT
y SQLTransact SQL_COMMIT
, SQL_ROLLBACK y SQL_AUTOCOMMIT se llamarán si se realizan solicitudes de transacción.
CRecordsets
SQLAllocStmt
, SQLPrepare
, SQLExecute
(para Open
y Requery
), SQLExecDirect
(para las operaciones de actualización), y SQLFreeStmt
se deben admitir. SQLNumResultCols
y SQLDescribeCol
se llamará en el conjunto de resultados en varias ocasiones.
SQLSetParam
se usa ampliamente para enlazar los datos de parámetros y la funcionalidad DATA_AT_EXEC.
SQLBindCol
se usa ampliamente para registrar las ubicaciones del almacenamiento de datos de la columna de salida con ODBC.
Se usan dos llamadas SQLGetData
para recuperar los datos de SQL_LONG_VARCHAR y SQL_LONG_VARBINARY. La primera llamada intenta encontrar la longitud total del valor de la columna al llamar a SQLGetData
con cbMaxValue de 0, pero con un pcbValue válido. Si pcbValue contiene SQL_NO_TOTAL, se produce una excepción. De lo contrario, se asigna un HGLOBAL y se realiza otra llamada SQLGetData
para recuperar todo el resultado.
Actualizando
Si se solicita el bloqueo pesimista, se consultará a SQLGetInfo SQL_LOCK_TYPES
. Si no se admite a SQL_LCK_EXCLUSIVE, se producirá una excepción.
Los intentos de actualizar una CRecordset
(instantánea o dynaset) harán que se asigne un segundo HSTMT. Para los controladores que no admitan el segundo HSTMT, la biblioteca de cursores simulará esta funcionalidad. Desafortunadamente, esto a veces puede significar el forzar la consulta actual en el primer HSTMT hasta su finalización antes de procesar la segunda solicitud de HSTMT.
SQLFreeStmt SQL_CLOSE
y SQL_RESET_PARAMS y SQLGetCursorName
se llamarán durante las operaciones de actualización.
Si hay un CLongBinarys en la outputColumns, se debe admitir la funcionalidad de DATA_AT_EXEC de ODBC. Esto incluye devolver SQL_NEED_DATA de SQLExecDirect
, SQLParamData
y SQLPutData
.
SQLRowCount
se llama después de la ejecución para comprobar que solo 1 registro fue actualizado por SQLExecDirect
.
Cursores forwardOnly
Solo SQLFetch
es necesario para las operaciones Move
. Tenga en cuenta que los cursores forwardOnly no admiten actualizaciones.
Cursores de instantánea
La funcionalidad de instantánea requiere la compatibilidad SQLExtendedFetch
. Como se indicó anteriormente, la biblioteca de cursores ODBC detectará cuándo un controlador no admite SQLExtendedFetch
y proporcionará la compatibilidad necesaria.
SQLGetInfo
, SQL_SCROLL_OPTIONS deben admitir SQL_SO_STATIC.
Cursores dynaset
A continuación se muestra la compatibilidad mínima necesaria para abrir un conjunto dinámico:
SQLGetInfo
, SQL_ODBC_VER deben devolver > "01".
SQLGetInfo
, SQL_SCROLL_OPTIONS deben admitir SQL_SO_KEYSET_DRIVEN.
SQLGetInfo
, SQL_ROW_UPDATES debe devolver "Y".
SQLGetInfo
, SQL_POSITIONED_UPDATES deben admitir SQL_PS_POSITIONED_DELETE y SQL_PS_POSITIONED_UPDATE.
Además, si se solicita el bloqueo pesimista, se realizará una llamada a SQLSetPos
con irow 1, fRefresh FALSE y fLock SQL_LCK_EXCLUSIVE.