바라기의 이야기

ODBC를 이용한 Select 쿼리 에이전트 원형 III 본문

Develop/Domino

ODBC를 이용한 Select 쿼리 에이전트 원형 III

baragi76 2010. 10. 8. 18:56
# 첨부

ODBCConnection.txt



Update 쿼리를 호출할 수 있도록 기능이 추가되었습니다.

-> 다음과 같이 URL을 구성하면...
http://server_url/db.nsf/agent?openagent&order=update&set-i=2&setn-1=aaa&set-1=1111&setn-2=bbb&set-2=2222&where-i=2&wheren-1=ccc&where-1=123&wheren-2=ddd&where-2=456
결 과는 update SQL_TABLE(Declarations의 설정값) set aaa = '1111', bbb = '2222' where ccc = '123' and ddd = '456' 이렇게 RDB 서버로 Query를 전송합니다.

파라메터가 추가가 된것인데요~
set-i : 설정컬럼 수
setn-1 ~ n : 설정컬럼명( set-i로 지정한 값 만큼 설정해야 합니다.(클케하지 않으면 어떤 오류가 뜰지 모릅니다... ㅡ_ㅡ;; )
set-1 ~ n : 설정컬럼값 ( set-i로 지정한 값 만큼 설정해야 합니다.(클케하지 않으면 어떤 오류가 뜰지 모릅니다... ㅡ_ㅡ;; )
where-i : 조건컬럼 수
wheren-1 ~ n : 조건컬럼명 ( where-i로 지정한 값 만큼 설정해야 합니다.(클케하지 않으면 어떤 오류가 뜰지 모릅니다... ㅡ_ㅡ;; )
where-1 ~ n : 조건컬럼 값 ( where-i로 지정한 값 만큼 설정해야 합니다.(클케하지 않으면 어떤 오류가 뜰지 모릅니다... ㅡ_ㅡ;; )



자 아래부터는 Full 코드입니다.
이전 버전에서 변경된 부분은 파란색으로 표현하겠습니다.
----------------------------------------------------------------------------------------

****************************
(Options)
****************************

Option Public
Uselsx "*LSXODBC"


****************************
(Declarations)
****************************

Dim ss As NotesSession
Dim curDb As NotesDatabase
Dim curDoc As NotesDocument
Dim curAgent As NotesAgent                                '// 현재 Agent
Dim con As ODBCConnection
Dim query As ODBCQuery
Dim result As ODBCResultSet

Dim order As String

Const SQL_DNS                                 = "ODBC DNS"
Const SQL_ID                                         = "USER ID"
Const SQL_PASSWORD                 = "USER PASSWORD"
Const SQL_TABLE_SCHEMA        = "dbo"
Const SQL_TABLE                                = "TABLE NAME or PROCEDURE NAME"
'//★ 아래의 코드는 RDB Table과 같은 형식이어야 함. ( 코드마다 틀리게 구성해야 함. )
Const SQL_TABLE_FIELD                                        = |a,b,c,d,e,f|                        '// 결과 필드 목록
Const SQL_TABLE_FIELDTYPE                        = |STRING,STRING,STRING,INTEGER,INTEGER,STRING|                        '// 결과 필드 목록 타입
Const SQL_TABLE_FIELD_AROUND         = |^,^,^,^,^,|                                                                '// 결과 필드 둘러싸기 옵션
Dim TableDoc As NotesDocument
Dim fieldAround As Variant




****************************
Initialize
****************************

Sub Initialize
        On Error Goto ErrorHandle
        Dim qs As String
        Dim resultField As String                        '// 결과
        Set ss = New NotesSession
        Set curDb = ss.CurrentDatabase
        Set curAgent = ss.CurrentAgent
        Set curDoc = ss.DocumentContext
        qs                                                         = curDoc.Query_String_Decoded(0)
        Print |Content-type: text/xml|
        Print ||
        Call SetTableDoc( qs )        
        '// SYBASE Server 연결
        If( SQLConnection( SQL_DNS ) = False ) Then Exit Sub
        If( GetTableInfo(TableDoc.result(0)) = False ) Then Goto ProcessEnd
ProcessEnd:
        con.Disconnect
        Exit Sub
ErrorHandle:
        Print |
                                error
                                | + Error() + |
                                | + Cstr( Erl() ) + |
                        |
        Msgbox curDb.Filepath + "/" + curAgent.Name + "::initialize ERROR[" + Cstr( Erl() ) + "] : " + Error()
        Print ""
        Print curDb.Filepath + "/" + curAgent.Name + "::initialize ERROR[" + Cstr( Erl() ) + "] : " + Error()
        Print ""
        If( con.IsConnected ) Then
                con.Disconnect
        End If
        Exit Sub
End Sub



****************************
GetQueryType
****************************

Function GetQueryType( source As String ) As String
%REM
함수명 :         GetQueryType
인자        :        source                        - Query에 포함되는 필드명
반환        :        String                                - STRING, INTEGER
목적        :        Query를 구성할때 작은따옴표(')를 추가하여 Query를 구성할지에 대한 여부 체크를 위하여
작성정보        :         v1.0 / 바라기 / 2006-06-07
%END REM
        On Error Goto ErrorHandle
        GetQueryType = ""
        Dim FieldList As Variant
        Dim FieldType As Variant
        Dim index As Integer
        FieldList = Evaluate(|@Trim( @Explode("| & SQL_TABLE_FIELD & |";",") )|)
        FieldType = Evaluate(|@Trim( @Explode("| & SQL_TABLE_FIELDTYPE & |";",") )|)
        index = 0
        Forall ufl In FieldList
                If( source = Cstr( ufl ) ) Then
                        If( Ubound( FieldType ) >= index ) Then
                                GetQueryType = Cstr( FieldType(index) )
                        Else
                                GetQueryType = ""
                        End If
                End If
                index = index + 1
        End Forall
        Exit Function
ErrorHandle:
        Call WriteLog( Err(), curDb.Filepath + "/" + curAgent.Name + "::GetQueryType ERROR[" + Cstr( Erl() ) + "] : " + Error() )
        GetQueryType = ""
        Exit Function
End Function



****************************
GetTableInfo
****************************

Function GetTableInfo( res As String ) As Integer
%REM
함수명 :         GetTableInfo
인자        :        res                        - Query 결과
반환        :        Boolean                - Query 처리 결과
                                - True         : 정상처리
                                - False         : 비정상 종료
목적        :        테이블의 정보를 가져오기 위함
작성정보        :         v1.0 / 바라기 / 2006-05-25/2006-05-26
%END REM
        On Error Goto ErrorHandle
        Dim index As Integer
        Dim rowIndex As Integer
        Dim whereFlag As Boolean
        Dim writeData As String
        whereFlag = False
        query.SQL = MakeQuery( res )
'        Print || & query.SQL & ||
'        Exit Function
        If( query.SQL = "" ) Then
                Msgbox "Query를 조합하지 못하였습니다."
                GetTableInfo = False
                Exit Function
        End If
        If Not result.Execute Then
               
                If( order = "update" ) Then
                        Print |
                                        error
                                        정보 기록에 실패하였습니다.(update)
                                        | & Erl & |
                                |
                        Exit Function
                Else
               

                        Messagebox result.GetExtendedErrorMessage + "/" + result.GetErrorMessage
               
                End If
               

                GetTableInfo = False
                Exit Function
        End If

       
        '// 갱신 코드 처리완료
        If( order = "update" ) Then
                Print |갱신 처리가 완료되었습니다.|
                GetTableInfo = True
                Exit Function
        End If
       


        result.MaxRows = 14000
        If( result.NumRows = 0 ) Then
                Print "검색한 결과가 없습니다."
                GetTableInfo = False
                Exit Function
        End If
        Print ||
        index = 0
        Do
                result.NextRow
                Print ""
                If( result.CurrentRow <> 0 ) Then
                        If( res = "" Or Lcase( res ) = "all" ) Then
                                rowIndex = 1
                                Forall utdi In TableDoc.GetItemValue( "FieldList" )
                                        If( Trim( result.GetValue( rowIndex ) ) >< "" ) Then
                                                writeData = result.GetValue( rowIndex )
                                                While( Asc( Right( writeData, 1 ) ) = 0 Or ( Asc( Right( writeData, 1 ) ) > 126 And Asc( Right( writeData, 1 ) ) < 256 ))
                                                        writeData = Left( writeData, Len( writeData )-1 )
                                                Wend
                                                Print |<| & Cstr( utdi ) & |>|
                                                Print Strleft( fieldAround(rowIndex-1), "^" )
                                                Print Trim( writeData )
                                                Print Strright( fieldAround(rowIndex-1), "^" )
                                                Print ||
                                        Else
                                                Print "<" & Cstr( utdi ) & "/>"
                                        End If
                                        rowIndex = rowIndex + 1
                                End Forall
                        Else
                                If( Trim( Strrightback( res, " " ) ) <> "" ) Then
                                        Print "<" + Strrightback( res, " " ) + ">" + result.GetValue(1) + "                                 Elseif( Strleft( res, "(" ) <> "" ) Then
                                        Print "<" + Strleft( res, "(" ) + ">" + result.GetValue(1) + "                                 Else
                                        Print "<" + res + ">" + result.GetValue(1) + "                                 End If
                        End If
                Else
                        Print "Completed"
                End If
                Print ""
                index = index + 1
        Loop Until result.IsEndOfData
        Print ||
        GetTableInfo = True
        Exit Function
ErrorHandle:
        Call WriteLog( Err(), curDb.Filepath + "/" + curAgent.Name + "::GetTableInfo ERROR[" + Cstr( Erl() ) + "] : " + Error() )
        GetTableInfo = False
        Exit Function
End Function




****************************
MakeQuery
****************************

Function MakeQuery( res As String )As String
%REM
함수명 :         MakeQuery
인자        :        res                - Query 결과
반환        :        String                - Query 조합 결과
목적        :        테이블의 데이터를 가져오기위한 Query 조합
작성정보        :         v1.0 / 바라기 / 2006-05-24 / 2006-05-26
%END REM
        On Error Goto ErrorHandle
        Dim returnQuery As String                        '// Query
        Dim whereFlag As Boolean                        '// where절 추가상태 여부
        Dim curItemName As String                        '// Query 구성 Item명
        Dim separator As String                                '// 파라메터간 구분자
        If( Lcase( TableDoc.Order(0) ) = "select" Or Lcase( TableDoc.Order(0) ) = "" ) Then
                '// Select 구문인 경우
                If( res = "" Or Lcase( res ) = "all" ) Then
                        returnQuery = "Select * from " + SQL_TABLE
                Else
                        returnQuery = "Select " + res + " from " + SQL_TABLE
                End If
                Forall utdi In TableDoc.Items
                        curItemName = Lcase( utdi.Name )
                        '// result, fieldlist, order 필드는 Query에 포함되지 않음.
                        If( curItemName <> "result" And curItemName <> "fieldlist" And curItemName <> "fieldtype" And curItemName <> "order" And Left( curItemName, 6 ) <> "param-" ) Then
                                '// n_로 시작하는 필드는 n_ 다음 String으로 쿼리를 구성함.
                                If( Left( utdi.Name, 2 ) = "n_" ) Then
                                        returnQuery = returnQuery + MakeQueryElement( Rightbp( utdi.Name, Len(utdi.Name)-2 ), utdi.Values(0), False, whereFlag )
                                Else
                                        returnQuery = returnQuery + MakeQueryElement( utdi.Name, utdi.Values(0), True, whereFlag )
                                End If
                        End If        
                End Forall
       
        Elseif( Lcase( TableDoc.Order(0) ) = "update" ) Then
                '// Update 구문인 경우
                returnQuery = TableDoc.Order(0)+ " " + SQL_TABLE
                For i% = 1 To Cint( TableDoc.GetItemValue( "setItem-i" )(0) )
                        If( i% > 1 ) Then
                                separator = |, |
                        Else
                                separator = | set |
                        End If
                        returnQuery = returnQuery + separator + TableDoc.GetItemValue( "setItemName-" & Cstr(i%) )(0) + |='|
                        returnQuery = returnQuery + TableDoc.GetItemValue( "setitem-" & Cstr(i%) )(0) + |'|
                Next
                For i% = 1 To Cint( TableDoc.GetItemValue( "whereItem-i" )(0) )
                        If( i% > 1 ) Then
                                separator = | and |
                        Else
                                separator = | where |
                        End If
                        returnQuery = returnQuery + separator + TableDoc.GetItemValue( "whereItemName-" & Cstr(i%) )(0) + | = '|
                        returnQuery = returnQuery + TableDoc.GetItemValue( "whereItem-" & Cstr(i%) )(0) + |'|
                Next
       

        Else
                '// 프로시저 호출일 경우
                returnQuery = TableDoc.Order(0) + " " + SQL_TABLE
                For i%=1 To Cint( TableDoc.GetItemValue( "param-i" )(0) )
                        If( i% > 1 ) Then
                                separator = |,'|
                        Else
                                separator = | '|
                        End If
                        returnQuery = returnQuery + separator + TableDoc.GetItemValue( "param-" & Cstr(i%) )(0) + |'|
                Next
        End If
        MakeQuery = returnQuery
        Exit Function
ErrorHandle:
        Call WriteLog( Err(), curDb.Filepath + "/" + curAgent.Name + "::MakeQuery ERROR[" + Cstr( Erl() ) + "] : " + Error() )
        MakeQuery = ""
        Exit Function
End Function




****************************
MakeQueryElement
****************************

Function MakeQueryElement( itemName As String, source As String, equalOption As Boolean, whereFlag As Boolean )As String
%REM
함수명 :         MakeQueryElement
인자        :        itemName         - Query 필드
                        source                - Query 필드 값
                        equalOption        - 포함되는 값을 찾으려면 True, 포함되지 않는 값을 찾으려면 False
                        whereFlag         - where 구문 삽입 유무
반환        :        String                - Query 조합 결과
목적        :        Query 부분 조합
                        - 2006-06-07 : Integer를 Query에 포함시키기 위하여 기능 추가
작성정보        :         v1.0 / 바라기 / 2006-05-24 / 2006-06-07
%END REM
        On Error Goto ErrorHandle
        Dim pluralValue As Variant        '// source 값 복수시 Explode
        Dim returnQuery As String        '// 결과 반환값
        Const REF_CALCULATE_BLOCK = " AND "                '//조건 블럭간 조건
        Dim valueCompare As String                        '// 등호, 같음 또는 같지 않음 체크
        Dim bitCalculator As String                        '// 같음 일때는 OR, 다름 일때는 AND 여야 함.
        Dim itemType As String                                '// Query에 포함될 Item의 속성(STRING, INTEGER ... )
        Dim quotationValue As String                '// Query에 포함될 Item의 속성에 따른 인용부호
        If( equalOption ) Then
                valueCompare = " = "
                bitCalculator = " OR "
        Else
                valueCompare = " <> "
                bitCalculator = " AND "
        End If
        itemType = GetQueryType( itemName )
        If( Ucase( itemType ) = "STRING" Or Ucase( itemType ) = "" ) Then
                quotationValue = "'"
        Else
                quotationValue = ""
        End If
        If( Trim( source ) <> "" ) Then
                If( Strleft( source, "," ) <> "" ) Then
                        '// 복수
                        If( whereFlag ) Then
                                returnQuery = returnQuery + REF_CALCULATE_BLOCK
                        End If
                        pluralValue = Evaluate(|@Unique( @Trim( @Explode("| & source & |";",") ) )|)
                        Forall upv In pluralValue
                                If( whereFlag ) Then
                                        If( Cstr( upv ) = Cstr( pluralValue(0) ) ) Then
                                                '// 첫번째 조건값
                                                If( Left( Cstr( upv ), 1 ) = "[" And Strleft( Cstr( upv ), "]" ) <> "" ) Then
                                                        '// LIKE와 같은 구문이 있는 경우 (ex: [LIKE]AA%)
                                                        returnQuery = returnQuery + " ( " + itemName + " " + Strleft( Strright( Cstr( upv ) , "[" ), "]" ) + " " + quotationValue + Strright( Cstr( upv ), "]" ) + quotationValue
                                                Else
                                                        returnQuery = returnQuery + " ( " + itemName + valueCompare + quotationValue + Cstr( upv ) + quotationValue
                                                End If
                                        Else
                                                '// 두번째 이후 조건값
                                                If( Left( Cstr( upv ), 1 ) = "[" And Strleft( Cstr( upv ), "]" ) <> "" ) Then
                                                        '// LIKE와 같은 구문이 있는 경우 (ex: [LIKE]AA%)
                                                        returnQuery = returnQuery + bitCalculator + itemName + " " + Strleft( Strright( Cstr( upv ) , "[" ), "]" ) + " " + quotationValue + Strright( Cstr( upv ), "]" ) + quotationValue
                                                Else
                                                        returnQuery = returnQuery + bitCalculator + itemName + valueCompare + quotationValue + Cstr( upv ) + quotationValue
                                                End If
                                        End If
                                Else
                                        '// where절이 없는 경우 추가
                                        If( Left( Cstr( upv ), 1 ) = "[" And Strleft( Cstr( upv ), "]" ) <> "" ) Then
                                                '// LIKE와 같은 구문이 있는 경우 (ex: [LIKE]AA%)
                                                returnQuery = returnQuery + " where ( " + itemName + " " + Strleft( Strright( Cstr( upv ) , "[" ), "]" ) + " " + quotationValue + Strright( Cstr( upv ), "]" ) + quotationValue
                                        Else
                                                returnQuery = returnQuery + " where ( " + itemName + valueCompare + quotationValue + Cstr( upv ) + quotationValue
                                        End If
                                        whereFlag = True
                                End If
                        End Forall
                        returnQuery = returnQuery + ")"
                Else
                        '// 단수
                        If( whereFlag ) Then
                                '// where 절을 이미 삽입한 경우
                                If( Left( source, 1 ) = "[" And Strleft( source, "]" ) <> "") Then
                                        '// LIKE와 같은 구문이 있는 경우 (ex: [LIKE]AA%)
                                        returnQuery = returnQuery + REF_CALCULATE_BLOCK + itemName + " " + Strleft( Strright( source , "[" ), "]" ) + " " + quotationValue + Strright( source, "]" ) + quotationValue
                                Else
                                        returnQuery = returnQuery + REF_CALCULATE_BLOCK + itemName + valueCompare + quotationValue + source + quotationValue
                                End If
                        Else
                                '// where 절이 없는 경우 추가
                                If( Left( source, 1 ) = "[" And Strleft( source, "]" ) <> "" ) Then
                                        '// LIKE와 같은 구문이 있는 경우 (ex: [LIKE]AA%)
                                        returnQuery = returnQuery + " where " + itemName + " " + Strleft( Strright( source , "[" ), "]" ) + " " + quotationValue + Strright( source, "]" ) + quotationValue
                                Else
                                        returnQuery = returnQuery + " where " + itemName + valueCompare + quotationValue + source + quotationValue
                                End If
                        End If
                End If
                whereFlag = True
        End If
        MakeQueryElement = returnQuery
        Exit Function
ErrorHandle:
        Call WriteLog( Err(), curDb.Filepath + "/" + curAgent.Name + "::MakeQueryElement ERROR[" + Cstr( Erl() ) + "] : " + Error() )
        Print source
        MakeQueryElement = ""
        Exit Function
End Function




****************************
SetTableDoc
****************************

Sub SetTableDoc( source As String )
%REM
함수명 :         SetTableDoc
인자        :        source                        - Query_String_Decoded
반환        :        -
목적        :        Query_String_Decoded로 넘어온 값 중에서 원하는 Query를 잘라내어 TableDoc의 Item으로 생성함.
                        이를 MakeQuery, GetTableInfo 함수에서 사용함으로 각 코드에 Table 형식에 맞게끔 코딩하는 것을 방지할 수 있음.
작성정보        :         v1.0 / 바라기 / 2006-05-26
%END REM
        On Error Goto ErrorHandle
        Dim FieldList As Variant
        Dim FieldType As Variant
        Set TableDoc = New NotesDocument( curDb )
        FieldList = Evaluate(|@Trim( @Explode("| & SQL_TABLE_FIELD & |";",") )|)
        FieldType = Evaluate(|@Trim( @Explode("| & SQL_TABLE_FIELDTYPE & |";",") )|)
        fieldAround = Evaluate(|@Explode("| & SQL_TABLE_FIELD_AROUND & |";",")|)
        Forall ufl In FieldList
                Call TableDoc.ReplaceItemValue( Cstr( ufl ), GetArgumentValue( Cstr( ufl ) & "=", source ) )
                Call TableDoc.ReplaceItemValue( "n_" & Cstr( ufl ), GetArgumentValue( Cstr( ufl ) & "!=", source ) )
        End Forall
        Call TableDoc.ReplaceItemValue( "FieldList", FieldList        )                                                                                '// 결과 Field 목록
        Call TableDoc.ReplaceItemValue( "FieldType", FieldType )                                                                                '// 결과 Field 종류
        Call TableDoc.ReplaceItemValue( "result", GetArgumentValue( "result=", source ) )                        '// 결과
        Call TableDoc.ReplaceItemValue( "order", GetArgumentValue( "order=", source ) )                                '// 명령( select, exec ...