You are on page 1of 7

AS400 Armar una aplicación cliente servidor con pocos pasos utilizando los APIS de ODBC

Categoría : Programación
Autor : Jaime Miur
Título : Armar una aplicación cliente servidor con pocos pasos utilizando los APIS de ODBC

Descripción del truco:


En realidad no es un truco, considero una ayuda para los desarrolladores que se han encontrado con la necesidad de
accesar tablas desde el AS/400 que tienen millones de registros y a través de ADO o paquetes comerciales se tornan
lento, utilizando los APIS de ODBC el tiempo de respuesta es impresionante.

Código en formato texto


Fecha 28-04-2004

'CONSTANTES
Public Const SQL_CHAR = 1
Public Const SQL_NUMERIC = 2
Public Const SQL_DECIMAL = 3
Public Const SQL_INTEGER = 4
Public Const SQL_SMALLINT = 5
Public Const SQL_FLOAT = 6
Public Const SQL_REAL = 7
Public Const SQL_DOUBLE = 8
Public Const SQL_VARCHAR = 12
Public Const SQL_NTS = -3 ' NTS = Null Terminated String

'---------------------------------------------------------------------
' Extended SQL datatypes
'---------------------------------------------------------------------
Public Const SQL_DATE = 9
Public Const SQL_TIME = 10
Public Const SQL_TIMESTAMP = 11
Public Const SQL_LONGVARCHAR = -1
Public Const SQL_BINARY = -2
Public Const SQL_VARBINARY = -3
Public Const SQL_LONGVARBINARY = -4
Public Const SQL_BIGINT = -5
Public Const SQL_TINYINT = -6
Public Const SQL_BIT = -7
Public Const SQL_TYPE_DRIVER_START = -80
Public Const SQL_SIGNED_OFFSET = -20
Public Const SQL_UNSIGNED_OFFSET = -22

'---------------------------------------------------------------------
' C datatype to SQL datatype mapping
'---------------------------------------------------------------------
Public Const SQL_C_CHAR = SQL_CHAR
Public Const SQL_C_LONG = SQL_INTEGER
Public Const SQL_C_SLONG = SQL_INTEGER
Public Const SQL_C_SHORT = SQL_SMALLINT
Public Const SQL_C_FLOAT = SQL_REAL
Public Const SQL_C_DOUBLE = SQL_DOUBLE
Public Const SQL_C_DATE = SQL_DATE
Public Const SQL_DRIVER_COMPLETE = 1
Public Const SQL_AUTOCOMMIT = 102
Public Const SQL_NO_DATA_FOUND = 100
Public Const SQL_SUCCESS = 0

Global henv As Long


Global hDbc As Long

'----------------------------------------------------------------------
' ODBC DLL Function Declarations
'----------------------------------------------------------------------
Declare Function SQLAllocConnect Lib "odbc32.dll" (ByVal henv As Long, phdbc As Long) As
Integer
Declare Function SQLAllocEnv Lib "odbc32.dll" (phenv As Long) As Integer
Declare Function SQLAllocStmt Lib "odbc32.dll" (ByVal hDbc As Long, phstmt As Long) As Integer
Declare Function SQLBindCol Lib "odbc32.dll" (ByVal hstmt As Long, ByVal icol As Integer,
ByVal fCType As Integer, rgbValue As Any, ByVal cbValueMax As Long, pcbValue As Long) As
Integer
Declare Function SQLBindParameter Lib "odbc32.dll" (ByVal hstmt As Long, ByVal ipar As
Integer, ByVal fParamType As Integer, ByVal fCType As Integer, ByVal fSqlType As Integer,
ByVal cbColDef As Long, ByVal ibScale As Integer, rgbValue As Any, ByVal cbValueMax As Long,
pcbValue As Long) As Integer
Declare Function SQLConnect Lib "odbc32.dll" (ByVal hDbc As Long, ByVal szDSN As String, ByVal
cbDSN As Integer, ByVal szUID As String, ByVal cbUID As Integer, ByVal szAuthStr As String,
ByVal cbAuthStr As Integer) As Integer
Declare Function SQLDisconnect Lib "odbc32.dll" (ByVal hDbc As Long) As Integer
Declare Function SQLError Lib "odbc32.dll" (ByVal henv&, ByVal hDbc&, ByVal hstmt&, ByVal
szSqlState$, pfNativeError&, ByVal szErrorMsg$, ByVal cbErrorMsgMax%, pcbErrorMsg%) As Integer
Declare Function SQLDriverConnect Lib "odbc32.dll" (ByVal hDbc As Long, ByVal hWnd As Integer,
ByVal szConnStrIn As String, ByVal cbConnStrIn As Integer, ByVal szConnStrOut As String, ByVal
cbConnStrOutMax As Integer, pcbConnStrOut As Integer, ByVal fDriverCompletion As Integer) As
Integer
Declare Function SQLDrivers Lib "odbc32.dll" (ByVal henv As Long, ByVal fDirection As Integer,
ByVal szDriverDesc As String, ByVal cbDriverDescMax As Integer, pcbDriverDesc As Integer,
ByVal szDriverAttributes As String, ByVal cbDrvrAttrMax As Integer, pcbDrvrAttr As Integer) As
Integer
Declare Function SQLExecDirect Lib "odbc32.dll" (ByVal hstmt As Long, ByVal szSqlStr As
String, ByVal cbSqlStr As Long) As Integer
Declare Function SQLExecute Lib "odbc32.dll" (ByVal hstmt As Long) As Integer
Declare Function SQLFetch Lib "odbc32.dll" (ByVal hstmt As Long) As Integer
Declare Function SQLFreeConnect Lib "odbc32.dll" (ByVal hDbc As Long) As Integer
Declare Function SQLFreeEnv Lib "odbc32.dll" (ByVal henv As Long) As Integer
Declare Function SQLFreeStmt Lib "odbc32.dll" (ByVal hstmt As Long, ByVal fOption As Integer)
As Integer
Declare Function SQLGetConnectOption Lib "odbc32.dll" (ByVal hDbc As Long, ByVal fOption As
Integer, ByVal pvParam As String) As Integer
Declare Function SQLPrepare Lib "odbc32.dll" (ByVal hstmt As Long, ByVal szSqlStr As String,
ByVal cbSqlStr As Long) As Integer
Declare Function SQLNumResultCols Lib "odbc32.dll" (ByVal hstmt As Long, pccol As Integer) As
Integer
Declare Function SQLGetData Lib "odbc32.dll" (ByVal hstmt As Long, ByVal icol As Integer,
ByVal fCType As Integer, ByVal rgbValue As Any, ByVal cbValueMax As Long, pcbValue As Long) As
Integer
Declare Function SQLSetConnectOption Lib "odbc32.dll" (ByVal hDbc As Long, ByVal fOption As
Integer, ByVal vParam As Long) As Integer
Declare Function SQLRowCount Lib "odbc32.dll" (ByVal hstmt As Long, pcrow&) As Integer
Declare Function SQLDescribeCol Lib "odbc32.dll" (ByVal hstmt As Long, ByVal icol As Integer,
ByVal szColName As String, ByVal cbColNameMax As Integer, pcbColName As Integer, pfSqlType As
Integer, pcbColDef As Long, pibScale As Integer, pfNullable As Integer) As Integer
Declare Function SQLMoreResults Lib "odbc32.dll" (ByVal hstmt&) As Integer

' Estructura para parametros de búsqueda


Type busqueda

BufferLen As Long
Buffer As String * 256
CntColum As Integer
SenSelect As Long

End Type

Global parametros_busqueda As busqueda

' --------------------------------------------------------------------------------------------
-------------------------------------------
' Función para conectarnos al AS/400 a través de un, el cual ya debe estar configurado
' Valores retornado
' 1 = Conexión Satisfactoria
' 0= Falla en la conexión
' --------------------------------------------------------------------------------------------
-------------------------------------------
Function ConectarAS400(Sistema As String, forma As Form) As Integer

Dim inconnect$
Dim outconnect$
Dim ptroutconnect%
Dim CodResp As Integer

ConectarAS400 = 1

' Memoria de alloc para el manejo del ambiente


DoEvents
CodResp = SQLAllocEnv(henv&)
If CodResp <> SQL_SUCCESS Then
ConectarAS400 = 0
Exit Function
End If

' Memoria de alloc para la conexión


DoEvents
CodResp = SQLAllocConnect(ByVal henv&, hDbc&)
If CodResp <> SQL_SUCCESS Then
ConectarAS400 = 0
Exit Function
End If

inconnect$ = Sistema
outconnect$ = String$(256, 0)

CodResp = SQLConnect(ByVal hDbc&, ByVal inconnect$, SQL_NTS, "", SQL_NTS, "", SQL_NTS)
If CodResp <> SQL_SUCCESS And CodResp <> SQL_SUCCESS_WITH_INFO Then
ConectarAS400 = 0
Exit Function
End If

End Function

' --------------------------------------------------------------------------------------------
-------------------------------------------
' Función para Desconectarnos del AS/400.
' --------------------------------------------------------------------------------------------
-------------------------------------------
Sub DesconectarAS400()

Dim CodResp As Integer

CodResp = SQLDisconnect(hDbc)
CodResp = SQLFreeConnect(hDbc)
CodResp = SQLFreeEnv(henv)

End Sub

' --------------------------------------------------------------------------------------------
----------------
' Buscar información en el AS/400, a través de una setencia SELECT
' Parámetro de entrada :
' SetenciaSql = Se envía la senencia SQL, ejemplo "Select *from tablax"
' Valores retornado
' 1 = Fallo la búsqueda
' 2 = Registro no encontrado
' 0 = Búsqueda satisfactoria
' --------------------------------------------------------------------------------------------
----------------
Function BuscarRegistro(SentenciaSql As String) As Integer

Dim CodResp As Integer


Dim campos As Integer
Dim cuenta As Long

BuscarRegistro = 0

parametros_busqueda.Buffer = String(256, 0)

' Alocar memoria para el manejador de sentencia SQL.


DoEvents
CodResp = SQLAllocStmt(ByVal hDbc&, parametros_busqueda.SenSelect)
If CodResp <> SQL_SUCCESS Then
BuscarRegistro = 1
Exit Function
End If
' Preparar sentencia SQL
DoEvents
CodResp = SQLPrepare(parametros_busqueda.SenSelect&, SentenciaSql, Len(SentenciaSql))
If CodResp <> SQL_SUCCESS Then
BuscarRegistro = 1
Exit Function
End If

' Ejecutar sentencia SQL


CodResp = SQLExecute(parametros_busqueda.SenSelect)
If CodResp <> SQL_SUCCESS Then
BuscarRegistro = 1
Exit Function
End If

' Cantidad de columna


CodResp = SQLNumResultCols(parametros_busqueda.SenSelect, parametros_busqueda.CntColum)

' Buscar el registro


If SQLFetch(parametros_busqueda.SenSelect) <> SQL_NO_DATA_FOUND Then
BuscarRegistro = 0
Else
BuscarRegistro = 2
End If

End Function

' --------------------------------------------------------------------------------------------
-------------------------------------------
' Busca el siguiente registroa partir de la ejecució de la función BuscarRegistro
' Valores retornado
' 1 = No hay más registro
' 0= Hay un siguiente registro que cumple con la condición inicial
'
' --------------------------------------------------------------------------------------------
-------------------------------------------
Function BuscarNextRegistro() As Integer

' Buscar información en el AS/400

Dim CodResp As Integer

parametros_busqueda.Buffer = String(256, 0)

If SQLFetch(parametros_busqueda.SenSelect) <> SQL_NO_DATA_FOUND Then

BuscarNextRegistro = 0
Else
BuscarNextRegistro = 1

End If
End Function

' --------------------------------------------------------------------------------------------
-------------------------------------------
' Función para ejcutar la sentencia INSERT
' Valores retornado
' La variable CodResp tiene el resultado
' --------------------------------------------------------------------------------------------
-------------------------------------------
Function AddReg(SentenciaSql As String) As Integer

Dim CodResp As Integer

' Alocar memoria para el manejador de sentencia SQL.


CodResp = SQLAllocStmt(ByVal hDbc&, parametros_busqueda.SenSelect)
If CodResp <> SQL_SUCCESS Then
AddReg= CodResp
Exit Function
End If

CodResp = SQLExecDirect(parametros_busqueda.SenSelect, SentenciaSql, SQL_NTS)


If CodResp <> SQL_SUCCESS Then
AddReg= CodResp
Exit Function
End If

CodResp = SQLFreeStmt(parametros_busqueda.SenSelect, 0)
AddReg = CodResp

End Function

' --------------------------------------------------------------------------------------------
-------------------------------------------
' Después de ejecutar la función BuscarRegistro o BuscarNextRegistro, se debe recuperar la
data.
' Esta función de utiliza para tal propósito
' Ejemplo de su uso.
' Si la sentencia Select fue la siguiente SELECT CAMPO1, CAMPO2 FROM TABLAX
' Para buscar la data correspondiente a CAMPO1 escribo lo siguiente
' codresp = GetData(1, SQL_CHAR, 6, registro)
' Para buscar la data correspondiente a CAMPO2 escribo lo siguiente
' codresp = GetData(1, SQL_CHAR, 10, registro)
' Asumo que el campo1 es de 6 posiciones y el campo2 de 10 respectivamente
' La data queda en la variable registro
'
' --------------------------------------------------------------------------------------------
-------------------------------------------
Function GetData(campo As Integer, tipodato As Integer, longitud As Integer, registro As
Variant)

Dim ColumnaEntera As Integer


Dim ColumnaAlfa As String
Select Case tipodato

Case SQL_CHAR

ColumnaAlfa = Space$(longitud + 1)

CodResp = SQLGetData(ByVal parametros_busqueda.SenSelect, campo, tipodato,


ColumnaAlfa, longitud + 1, parametros_busqueda.BufferLen)
registro = Mid(ColumnaAlfa, 1, parametros_busqueda.BufferLen)

Case SQL_DECIMAL, SQL_NUMERIC

ColumnaAlfa = Space$(longitud + 3)
CodResp = SQLGetData(ByVal parametros_busqueda.SenSelect, campo, SQL_CHAR,
ColumnaAlfa, longitud + 3, parametros_busqueda.BufferLen)
registro = Mid(ColumnaAlfa, 1, parametros_busqueda.BufferLen)

End Select

End Function

' --------------------------------------------------------------------------------------------
-------------------------------------------
' Función para ejcutar la sentencia INSERT
' Valores retornado
' La variable CodResp tiene el resultado
' --------------------------------------------------------------------------------------------
-------------------------------------------
Function AddReg(SentenciaSql As String) As Integer

Dim CodResp As Integer

' Alocar memoria para el manejador de sentencia SQL.


CodResp = SQLAllocStmt(ByVal hDbc&, parametros_busqueda.SenSelect)
If CodResp <> SQL_SUCCESS Then
AddReg= CodResp
Exit Function
End If

CodResp = SQLExecDirect(parametros_busqueda.SenSelect, SentenciaSql, SQL_NTS)


If CodResp <> SQL_SUCCESS Then
AddReg= CodResp
Exit Function
End If

CodResp = SQLFreeStmt(parametros_busqueda.SenSelect, 0)
AddReg = CodResp

End Function

You might also like