728x90

단어 변환 프로그램입니다.

긴 함수를 짧은 함수로 변환하는 프로그램입니다. 어젯밤에 만들었죠.. (버그 있을 수 있음 )
프로프레임의 모든 소스는 xml 형태로  DB에 저장됩니다. 프로그램 내의 특정 문자열을 다른 것으로 바꾸기 위해서는 프로프레임 스튜디오에서 하나씩 열어서 전체바꾸기 를 일일이 수작업으로 해 줘야 합니다.
본 프로그램은 DB 에 직접 접속하여 XML 속에 있는 특정 문자열을 변경한 후 다시 UPDATE 시켜 주는 프로그램입니다.  본 프로그램은 티맥스소프트의 오은경 전임이 만든 프로그램을 약간 변형(개작) 한 것임을 밝혀 둡니다.

1. 설치

적당한 곳에 첨부의 2개 파일을 갖다 놓으세요. 자바가 실행될 수 있는 환경이 이미 되어 있어야 합니다.
돌릴려면 ojdbc14.jar 와 ConvWord.class 가 필요합니다.

2. 사용법

사용법은 convword 라고 치면 간단한 사용법 안내가 나옵니다.

예를 들어 C:\ConvWord 에 파일 2개를 갖다 놓았다고 한다면    

C:\ConvWord>convword
This programe will replace word in source!
you need additional action for source generation in proframe studio.
Usage : ConvWord [-s|-r] physical_name [data_file]
        -s : show the list
        -r : replace the word

example :  ConvWord sfee2929a -r C:/hanabank_dev/ProFrame/convlist.dat
           data_file must have separate word with space between old and new.


간단한 사용설명이 나오게 되죠.

C:\ConvWord>convword -r sirt5000a
sirt5000a : 금리목록관리메인 PGM
sirt5000a.c [272] pfmStringIsNull -> pfmStrIsNull
정상적으로 완료되었습니다.

여기서 파일명과 해당 라인수 이전 단어와 변경단어를 보여 줍니다. 변환단어 데이타 파일은  아래와 같이 스페이스로 분리해서 텍스트 파일을 만들어 주심 됩니다.  그러나 아래 로직을 보시면 알겠지만 간단한 프로그램이라 단순 변환시켜 버리기 때문에 다음과 같이 파일을 만드시면 예기치 않은 결과를 얻게 됩니다.

get      gt
getName  gtNm

이런 경우 먼저 get을 get 을 gt 로 먼저 바뀌게 되므로 정작 getName 을 바꿀 순서가 되었을 때는  getName 은 이미 gtName 으로 바뀌어져 있는 상태라 변환이 안 됩니다. 결국 getName 을 gtNm 으로 바꾸고자 하는 당초 의도대로 바뀌지 않고 gtName 으로 어중간 하게 바뀐 채로 남게 됩니다.

이것을 해결 방법은 프로그램을 고쳐서 데이타의 소팅 기능을 넣거나 아니면 데이타파일을 만들 때 아예 소팅을 역순으로 해 놓으면 됩니다.  이렇게요..

getName  gtNm
get      gt



3. 주의사항

a. 사용시 데이타파일을 특별히 지정하지 않는다면 디폴트 금지함수 리스트파일이 적용됩니다.
    파일이 바꿀 단어를 더 추가하고자한다면 직접 수정하시고 convword 실행할 때 직접 파일을 지정해야 합니다.
b. convword  프로그램은 DB 상의 소스 변경이기 때문에 스튜디오에서 소스생성 버튼을 눌러줘야
    실제 개발서버 디렉토리에도 소스가 생성된다는 점을 유념하세요.
c. 그리고  검증되지 않은 프로그램이니 부작용에 대하여 책임 지지 않습니다.


ConvWord.java

import java.sql.*;
import java.io.*;
import java.util.*;

import oracle.jdbc.*;
import oracle.sql.*;

public class ConvWord
{

  static int arrSize=10000;
  static private String datafile;
  static private String physicalName;
  static private String option;
  static String[]  sr = new String[arrSize];
  static String[]  tr = new String[arrSize];
  static int ix=0;

  public static void main (String args [])  throws Exception
  {
    if (args.length < 2) {
      showUsage();
      return;
    } else if (args.length == 2) {
      datafile = "convlist.dat";
    } else {
      datafile = args[2];
    }

    option  = args[0];
    physicalName = args[1];

    if ( !"-s".equals(option) && !"-r".equals(option) ) {
      showUsage();
      return;
    }

    FileReader fr = null;
    BufferedReader br = null;
    try {
      fr = new FileReader(datafile);
      br = new BufferedReader(fr);
    } catch (Exception e) {
      System.out.println("file read error. check the file "+datafile);
      return;
    }

    String txt;

    while((txt = br.readLine()) != null)
    {

      StringTokenizer token = new StringTokenizer(txt," ");
      sr[ix] = token.nextToken().trim();
      tr[ix] = token.nextToken().trim();
      ix++;
      if ( ix >= arrSize) {
        System.out.println("maximum word count cannot be over "+arrSize+". ");
        br.close();
        return;
      }
    }
    br.close();


    Connection conn = null;
    DriverManager.registerDriver( new oracle.jdbc.driver.OracleDriver() );

    try
    {

      conn = DriverManager.getConnection( "jdbc:oracle:thin:@xx.xx.xx.xx:port:SID", "id","passwd" );
      conn.setAutoCommit (false);
      Statement stmt_name = conn.createStatement();
      Statement stmt_meta = conn.createStatement();

      BLOB blob = null;
      String logicalName = null;
      String resourceId = null;
      String new_meta = null;

      ResultSet rs = stmt_name.executeQuery(" SELECT logical_name, resource_id "+
                                            " FROM dev_resource WHERE physical_name = '"+physicalName+"'");
      if (rs.next()) {
        logicalName = rs.getString("logical_name");
        resourceId  = rs.getString("resource_id");

        System.out.println( physicalName +" : " + logicalName);

      }else {
        System.out.println("등록된 프로그램이 없습니다. 프로그램명이 ["+physicalName+ "]이 맞는지 확인하세요");
        return;
      }

      ResultSet rset = stmt_meta.executeQuery ("SELECT meta FROM dev_resource_contents WHERE resource_id = " +
                                               "(SELECT resource_id FROM dev_resource " +
                                               " WHERE physical_name = '"+physicalName+"')" );
      if (rset.next()) {

         blob = ((OracleResultSet)rset).getBLOB("meta");
         new_meta = replaceWord(blob );
      } else {
         System.out.println("검색된 메타 결과가 없습니다.");
      }

      if ("-r".equals(option)) {
        if ( updateMetaData(conn, stmt_meta, new_meta, resourceId)) {
          System.out.println("정상적으로 완료되었습니다.");
        } else {
          System.out.println("작업을 실패하였습니다.");
        }
      }

      rs.close();
      rset.close();

      stmt_name.close();
      stmt_meta.close();
      conn.commit();
      conn.close();
    } catch (SQLException e) {
      System.out.println("다음과 같은 문제가 발생하였습니다.\n");
      System.out.println(e.getMessage());
      e.printStackTrace();
      conn.close();
    } catch(Exception ex){
      System.out.println("다음과 같은 문제가 발생하였습니다.\n");
      System.out.println(ex.getMessage());
      ex.printStackTrace();
      conn.close();
    }
  }


  static String replaceWord (BLOB blob  ) throws Exception
  {
    InputStream input = blob.getBinaryStream();
    BufferedReader reader = new BufferedReader( new InputStreamReader( input, "UTF8" ));
   
    String line;
    String new_meta = "";
    String newLine = "";
    int lineno=1;
    while ( (line = reader.readLine()) != null )
    {
      lineno++;
      if (line == null){
        break;
      }
       // loop needed
      for ( int i=0; i<ix; i++) {
        newLine = "";
        int idx = line.indexOf(sr[i]);
        int idx2 = idx + sr[i].length();
        if (idx != -1) {
          System.out.println(physicalName+".c ["+lineno+"] "+sr[i]+" -> "+tr[i]);
          newLine = newLine + line.substring(0, idx) + tr[i] + line.substring(idx2);
        } else {
          newLine = line;
        }
          line = newLine;
      }
   
      new_meta = new_meta + newLine + "\n";
    }
    return new_meta;
  }


  static boolean updateMetaData (Connection conn, Statement stmt_meta, String new_meta, String resource_id) throws Exception
  {
    boolean insertOK = true;
    BLOB blob = null;
 
    try { // empty 시킴
      stmt_meta.executeUpdate("UPDATE dev_resource_contents " +
                              "SET meta=empty_blob() " +
                              "WHERE resource_id ='" + resource_id +"'");
    } catch(SQLException e) {
      System.err.println("<debug>BbsInput.modifyData1 : " + e.getMessage());
      insertOK = false;
    }
 
    if (insertOK)
    {
      try
      { // 변경된 내용을 셋팅
         ResultSet rset = stmt_meta.executeQuery("SELECT meta FROM dev_resource_contents " +
                                                 "WHERE resource_id ='" + resource_id +"' FOR UPDATE");
         while(rset.next())
         {
           blob =((OracleResultSet)rset).getBLOB("meta");
           Writer out = new OutputStreamWriter(blob.getBinaryOutputStream(), "UTF8");
           out.write(new_meta);
           out.close();
         }
      }
      catch(Exception e) {
        System.out.println("업데이트를 실패하였습니다.");
        System.out.println(e.getMessage());
        e.printStackTrace();
        return false;
      }
    }
    return true;
  }
 
  static void showUsage() {
    System.out.println("This programe will replace word in source!");
    System.out.println("you need additional action for source generation in proframe studio.");
    System.out.println("Usage : ConvWord [-s|-r] physical_name [data_file] ");
    System.out.println("        -s : show the list");
    System.out.println("        -r : replace the word");
    System.out.println("");
    System.out.println("example :  ConvWord sfee2929a -r C:/hanabank_dev/ProFrame/convlist.dat ");
    System.out.println("           data_file must have separate word with space between old and new.");
  }

}

convword.bat

@echo off
java -cp ojdbc14.jar;ConvWord.class ConvWord  %1 %2 %3


출처 : http://pangate.com/71
728x90

프로매퍼에서 제공하는 강력한 기능 중에 하나가 가변배열이다. 이 가변 배열용 api를 이용하면 포인터라는 어려운 개념을 알지 못하는 사람도 충분히 메모리를 동적 할당(alloc)할 수 있도록 해 준다.  그렇지만 아래에 기술되어 있는 내용 정도는 정확히 이해를 해 줘야 문제를 야기하지 않고 즐거운 코딩을 할 수 있다.

1. 정의

Varray 의 타입에 대하여 pfmVarray.h  속에  다음과 같이 미리 선언되어 있다.

#define pfmVarray(type) \
    struct
{ \
        long
size; \
        long
count; \
        type *data; \
    }


따라서 가변배열 변수를 선언할 때는 다음과 같이 한다.

pfmVarray(sfee2105a_in_sub01) grid_id;

여기서 sfee2105a_in_sub01 은 타입이고 grid_id 는 변수명이다.  결국 위의 선언문장은 실제적으로는 다음과 같이 소스가 풀어지게 된다.

    struct {
        long
size;
        long
count;
        sfee2105a_in_sub01 *data;
    } grid_id;


위의 풀어진 가변 배열의 실체를 머릿속에 기억하고 있다면 프로그램을 짤 때 혼란이 적을 것이다.

2. 샘플 코드

다음과 같은 샘플 예제를 작성하여 돌려 보았다.

mfeebiz_sfee2105a_in_sub01  sub;
mfeebiz_sfee2105a_in in;

PFM_DBG(" mfeebiz_sfee2105a_in       = [%ld]", sizeof(mfeebiz_sfee2105a_in));
PFM_DBG(" mfeebiz_sfee2105a_in_sub01 = [%ld]", sizeof(mfeebiz_sfee2105a_in_sub01));

bzero( &in, sizeof(mfeebiz_sfee2105a_in));
PFM_DBG("Varray size           = [%ld]", pfmVarraySize(in.grid_id));
PFM_DBG("Varray count          = [%ld]", pfmVarrayCount(in.grid_id));
PFM_DBG("Varray Buffer Size    = [%ld]", pfmVarrayBufferSize(in.grid_id));
PFM_DBG("Varray Structure Size = [%ld]", pfmVarrayStructSize(in.grid_id));

for ( int ix = 0; ix < 102; ix++ ) {
    PFM_DBG("add [%d] =======", ix);
    pfmVarrayAppend( in.grid_id, &sub );
   
    PFM_DBG("Varray size           = [%ld]", pfmVarraySize(in.grid_id));
    PFM_DBG("Varray count          = [%ld]", pfmVarrayCount(in.grid_id));
    PFM_DBG("Varray Buffer Size    = [%ld]", pfmVarrayBufferSize(in.grid_id));
    PFM_DBG("Varray Structure Size = [%ld]", pfmVarrayStructSize(in.grid_id));
}


3. 수행결과

0153]  mfeebiz_sfee2105a_in       = [88]
0154]  mfeebiz_sfee2105a_in_sub01 = [336]
0157] Varray size           = [0]
0158] Varray count          = [0]
0159] Varray Buffer Size    = [0]
0160] Varray Structure Size = [336]
0163] add [0] =======
0166] Varray size           = [100]
0167] Varray count          = [1]
0168] Varray Buffer Size    = [33600]
0169] Varray Structure Size = [336]
0163] add [1] =======
0166] Varray size           = [100]
0167] Varray count          = [2]
0168] Varray Buffer Size    = [33600]
0169] Varray Structure Size = [336]

중간생략 --

0163] add [99] =======
0166] Varray size           = [100]
0167] Varray count          = [100]
0168] Varray Buffer Size    = [33600]
0169] Varray Structure Size = [336]
0163] add [100] =======
0166] Varray size           = [202]
0167] Varray count          = [101]
0168] Varray Buffer Size    = [67872]
0169] Varray Structure Size = [336]
0163] add [101] =======
0166] Varray size           = [202]
0167] Varray count          = [102]
0168] Varray Buffer Size    = [67872]
0169] Varray Structure Size = [336]

4. 결론

결론 초기에 추가할 수 있는 한계치로 100 을 설정해 놓고 있다가 100개를 초과하게 되면 size는 다시 자동 늘려준다.  메모리도 구조체의 사이즈 * size 만큼의 메모리를 미리 확보해 놓았다가 사이즈를 넘어서면 다시 추가로 더 늘려서 allocate 해 놓게 된다. 이 100 이라는 초기 배열의 개수를 정하는 알고리즘은 이 함수를 개발한 사람이 알고 있겠지만 늘상 100 으로 초기설정되는 것은 아니고 그 type 에 따라 달라지는 것을 보았다.
반면에 count 값은 몇번을 append 했는지의 회수 정보이다. 따라서 영원히 count  가 size 를 초과할 수는 없게된다.

특정 회수번지의 값을 찍어 보고자 한다면 다음과 같이  할 수 있다. 예를 들어 10번째의 것을 찍어본다면

PFM_DBG("  name = [%s]", grid_id.data[9].name );


5. 또 다른 예제

pfmVarray(long) vcnt;
long *cnt;
long *num;

bzero(&vcnt, sizeof(vcnt));

cnt = pfmVarrayAlloc(vcnt, 10);  /* 10개의 저장 공간 확보 */
cnt[1] = 1;  /* 두번째 배열에 값을 1 세팅함 */
PFM_DBG("sizeof(vcnt)          = [%ld]", sizeof(vcnt));
PFM_DBG("Varray size           = [%ld]", pfmVarraySize(vcnt));
PFM_DBG("Varray count          = [%ld]", pfmVarrayCount(vcnt));
PFM_DBG("Varray Buffer Size    = [%ld]", pfmVarrayBufferSize(vcnt));
PFM_DBG("Varray Structure Size = [%ld]", pfmVarrayStructSize(vcnt));

PFM_DBG("==== 출력 ====" );

PFM_DBG("vcnt.data[1]               = [%ld]", vcnt.data[1] );
PFM_DBG("pfmVarrayGet(vcnt, 1)      = [%p]", (long *)pfmVarrayGet(vcnt, 1));
PFM_DBG("pfmVarrayElementAt(vcnt,1) = [%p]", (long *)pfmVarrayElementAt(vcnt, 1));

/*좀 더 어렵게 출력해 보는 방법으로 */
PFM_DBG("*(_num = pfmVarrayGet(vcnt, 1)) = [%ld]", *(num=pfmVarrayGet(vcnt, 1)));



6. 실행결과


 sizeof(vcnt)          = [24]
 Varray size           = [10]
 Varray count          = [0]
 Varray Buffer Size    = [80]
 Varray Structure Size = [8]
 ==== 출력 ====
 vcnt.data[1]               = [1]
 pfmVarrayGet(vcnt, 1)      = [111593978]
 pfmVarrayElementAt(vcnt,1) = [111593978]
 *(_num = pfmVarrayGet(vcnt, 1)) = [1]



7. 결론

pfmVarrayGet() 과 pfmVarrayElementAt() 함수는 동일한 포인터를 리턴해 준다는 것을 기억해야 한다. 가변 배열 변수는 궁극적으로 스트럭쳐 라는 것을 기억한다면 이 변수의 초기화는 bzero(&vcnt, sizeof(vcnt)); 를 사용하거나 memset(&vcnt, 0x00, sizeof(vcnt)); 를 사용할 수 있다.

8. 위험한 상상

pfmVarrayAppend 로 값을 append 세팅해 놓은 다음 bzero(&vcnt, sizeof(vcnt)); 와 같이 초기화하는 것은 의미가 없으며 매우 위험하다. sizeof(vcnt) 의 값은 append 하기 전 선언당시의 구조체사이즈(24byte) 이기 때문이다. 추가로 할당된 메모리는 초기화되지 않게 된다. 심지어 vcnt.data 가 가지고 있던 포인터까지 지워버렸기 때문에 append 될 때 추가 할당된 메모리는 포인터를 잃어 버려서 free시킬 수도 없는 dangliing 상태에 놓이게 되며 memory leak 의 주요 원인이 된다.

또다른 예로서 memcpy( &another, &vcnt, sizeof(vcnt)); 뭐 이런식으로 sizeof를 사용했을 때는 딸랑 24byte 만 copy 된다는 것을 기억해야 한다. 왜냐면 Varray 변수의 사이즈는 24 byte ( long 변수 size와 count 로 2개, pointer 변수 data 로 1개 도합 8byte * 3 = 24 byte ) 이기 때문이다.
 

9. 가변배열의 메모리 해제

가변 배열에 구조체를 계속 append하다가 오류가 발생될 경우 PFM_TRY를 타고 프로그램이 종료된다. 프레임웍이 종료될 때 가변배열변수는 자동 해제를 시키지만 프레임웍의 시스템후처리를 지나기 전에 반복적으로 가변배열을 사용하는 모듈을 호출하게 되면 미처 해제되지 못한 가변배열이 쌓여서 시스템의 힙메모리가 부족해 지는 사태를 초래할 수 있다. 따라서 가변배열을 사용하는 모듈은 오류종료될 경우에는 아래와 같이 메모리를 직접 해제시키고 나가도록 코딩을 기술해 주면 시스템 안정성에 도움이 된다.

/*오류발생시 가변배열을 free 시켜서 메모리 leakage 방지 */
pfmVarrayFree(OUTPUT->grid_id);
/* 또한 그리드에 append한 개수를 관리하는 변수가 따로 있다면 이 값도 초기화 */
OUTPUT->rept_ncnt = 0; 

출처 : http://pangate.com/66
728x90

한책임..
 
그동안 수고가 많았습니다.  
내가 회사를 떠나면서 마지막으로 부탁하는 것이니 자세히 읽어 봐 주길 바래요..
 
 
DBIO 출력값을 출력변수로 MOVE 하는 소스는 strcpy 를 사용되고 있으나 보통의 경우 문제는 없다.
그러나  date 타입을 string(14) 로 출력시킬 경우에는 문제가 발생됩니다.
개발자가  일일이 to_char(ls_chg_dtm, 'YYYYMMDDHH24MISS')  과 같이 조작하여 출력할 수도 있겠고 dbms 의 date 타입의 출력 포맷을 고칠 수도 있겠으나
농협에서는 절충안 으로 date 타입을 그냥  char(14) 에 담고 그 데이타는 사용하지 않는 것으로 개발해 왔습니다..
 
문제는 출력변수를 move 하는 과정에서 strcpy 를 사용하면서 데이타가 깨져서 나오기 때문에 strncpy 를 사용해 주시길 요청합니다.

     24 static void _out_data_copy(_pdb_sample_edu_acct_ps215_out_t *s, PfmDbiosample_edu_acct_ps215Output *t) {
     25
     26          strcpy( t->cuno, (char*)s->cuno.arr );
     27          strcpy( t->acno, (char*)s->acno.arr );
     28          t->jan_amt = s->jan_amt;
     29          strcpy( t->tr_dt, (char*)s->tr_dt.arr );
     30          strcpy( t->lschg_dtm, (char*)s->lschg_dtm.arr  );
     31          strcpy( t->ls_cmeno, (char*)s->ls_cmeno.arr  );
     32
     33          PFM_DBG(" t->lschg_dtm=[%s], s->lschg_dtm.arr=[%s]", t->lschg_dtm, (char*)s->lschg_dtm.arr );
     34          PFM_DBG(" t->ls_cmeno =[%s], s->ls_cmeno.arr =[%s]", t->ls_cmeno, (char*)s->ls_cmeno.arr );
     35 }
 
  17779  :validation_proc                    :00129] >> PFMTRY [pfmDbioSelect("sample_edu_acct_ps215", &] 입구
  17780  :pfmAnalysisLogging                 :00102] DB EXEC SQL Query Elapse Time : [0 s / 623 ms] - mapid [sample_edu_acct_ps215] : DML [SELECT] - Error No[0] Record Count[1]
  17781 e:_out_data_copy                     :00033]  t->lschg_dtm=[2008-05-17 19:1pfmtcl123], s->lschg_dtm.arr=[2008-05-17 19:1]
  17782 e:_out_data_copy                     :00034]  t->ls_cmeno =[pfmtcl123], s->ls_cmeno.arr =[pfmtcl123]
  17783  :validation_proc                    :00129] << PFMTRY [pfmDbioSelect("sample_edu_acct_ps215", &] 출구 RC [0] TIME [00.005934]
  17784  :validation_proc                    :00135] ================================
  17785  :validation_proc                    :00135] sample_edu_acct_ps215Out
  17786  :validation_proc                    :00135] --------------------------------
  17787  :validation_proc                    :00135] cuno : cuno = [8000000011]
  17788  :validation_proc                    :00135] 계좌번호 : acno = [AC80000000]
  17789  :validation_proc                    :00135] 잔액 : jan_amt = [10]
  17790  :validation_proc                    :00135] 거래일자 : tr_dt = []
  17791  :validation_proc                    :00135] 최종변경자개인번호 : ls_cmeno = [2008-05-17 19:1pfmtcl123]
  17792  :validation_proc                    :00135] 최종변경일시 : lschg_dtm = [ 19:1pfmtcl123]
  17793  :validation_proc                    :00135] ================================
 
     24 static void _out_data_copy(_pdb_sample_edu_acct_ps215_out_t *s, PfmDbiosample_edu_acct_ps215Output *t) {
     25
     26          strncpy( t->cuno, (char*)s->cuno.arr, LEN_SAMPLE_EDU_ACCT_PS215_CUNO_O );
     27          strncpy( t->acno, (char*)s->acno.arr, LEN_SAMPLE_EDU_ACCT_PS215_ACNO_O );
     28          t->jan_amt = s->jan_amt;
     29          strcpy( t->tr_dt, (char*)s->tr_dt.arr, LEN_SAMPLE_EDU_ACCT_PS215_TR_DT_O );
     30          strncpy( t->lschg_dtm, (char*)s->lschg_dtm.arr, LEN_SAMPLE_EDU_ACCT_PS215_LSCHG_DTM_O );
     31          strncpy( t->ls_cmeno, (char*)s->ls_cmeno.arr, LEN_SAMPLE_EDU_ACCT_PS215_LS_CMENO_O );
     32
     33          PFM_DBG(" t->lschg_dtm=[%s], s->lschg_dtm.arr=[%s]", t->lschg_dtm, (char*)s->lschg_dtm.arr );
     34          PFM_DBG(" t->ls_cmeno =[%s], s->ls_cmeno.arr =[%s]", t->ls_cmeno, (char*)s->ls_cmeno.arr );
     35 }
    
    
  21211  :validation_proc                    :00129] >> PFMTRY [pfmDbioSelect("sample_edu_acct_ps215", &] 입구
  21212  :pfmAnalysisLogging                 :00102] DB EXEC SQL Query Elapse Time : [0 s / 661 ms] - mapid [sample_edu_acct_ps215] : DML [SELECT] - Error No[0] Record Count[1]
  21213 e:_out_data_copy                     :00033]  t->lschg_dtm=[2008-05-17 19:], s->lschg_dtm.arr=[2008-05-17 19:1]
  21214 e:_out_data_copy                     :00034]  t->ls_cmeno =[pfmtcl123], s->ls_cmeno.arr =[pfmtcl123]
  21215  :validation_proc                    :00129] << PFMTRY [pfmDbioSelect("sample_edu_acct_ps215", &] 출구 RC [0] TIME [00.003237]
  21216  :validation_proc                    :00135] ================================
  21217  :validation_proc                    :00135] sample_edu_acct_ps215Out
  21218  :validation_proc                    :00135] --------------------------------
  21219  :validation_proc                    :00135] cuno : cuno = [8000000011]
  21220  :validation_proc                    :00135] 계좌번호 : acno = [AC80000000]
  21221  :validation_proc                    :00135] 잔액 : jan_amt = [10]
  21222  :validation_proc                    :00135] 거래일자 : tr_dt = []
  21223  :validation_proc                    :00135] 최종변경일시 : lschg_dtm = [2008-05-17 19:]
  21224  :validation_proc                    :00135] 최종변경자개인번호 : ls_cmeno = [pfmtcl123]
  21225  :validation_proc                    :00135] ================================
 
 
이 때 사용되는 SQL 은 다음과 같으며 여기서  LSCHG_DTM 은 DATE 타입입니다.

     77         EXEC SQL SELECT  /*+ map_id(sample_edu_acct_ps215) */ CUNO
     78                         , ACNO
     79                         , JAN_AMT
     80                         , TR_DT
     81                         , LSCHG_DTM
     82                         , LS_CMENO
     83         INTO :pdb_out
     84         FROM SAMPLE_EDU_ACCT
     85         WHERE cuno = :pdb_in.cuno
     86         ;
 
 
 
     14 struct _pdb_sample_edu_acct_ps215_out_s {
     15     varchar cuno[LEN_SAMPLE_EDU_ACCT_PS215_CUNO_O+1];
     16     varchar acno[LEN_SAMPLE_EDU_ACCT_PS215_ACNO_O+1];
     17     long jan_amt;
     18     varchar tr_dt[LEN_SAMPLE_EDU_ACCT_PS215_TR_DT_O+1];
     19     varchar lschg_dtm[LEN_SAMPLE_EDU_ACCT_PS215_LSCHG_DTM_O+1];
     20     varchar ls_cmeno[LEN_SAMPLE_EDU_ACCT_PS215_LS_CMENO_O+1];
     21 };

출처 : http://pangate.com/51

+ Recent posts