제가 몇년전에 올린 글이었는데 거의 필요 없겠지만서도 혹시 필요한 분 계실까봐 이렇게 다시 한번 올립니다.
예제1
Web에서 Oracle DB에 접근하는 CGI(Common Gateway Interface)를
Oracle 에서 제공하는 Pro C로 만들어 봅시다.
Pro C는 C언어를 기본으로 하고 있으니 C만 아시면 쉽게 이해하실 수 있구요
cgi를 작성하기 위하여 cgic library를 이용합니다.
cgic library에 대한 구체적인 함수나 환경변수들에 대한 설명은 http://www.boutell.com/cgic 에 있습니다.
오늘은 Oracle DB 에 접속하기 위한 기본적인 설정 및 접속 방법에 대하여 알아보도록 하겠습니다.
다음 코드를 살펴보면...
#include <stdio.h>
#include "/home/superman/cgic/cgic.h"
#define USERNAME "superman" // Username 을 저장
#define PASSWORD "superman" // Password 를 저장
#define DBSTRING "DB" // DBString을 저장
EXEC SQL BEGIN DECLARE SECTION; // SQL문에 연관되어 사용되어질 변수들에 대한 선언을 시작한다는 문구
char *username = USERNAME;
char *password = PASSWORD;
char *dbstring = DBSTRING;
...
...
EXEC SQL END DECLARE SECTION; // 선언종료
EXEC SQL INCLUDE sqlca;
void sqlerror(); // oracle DB error났을때 error처리 함수
int getCgiParameter(); // html파일에서 사용자가 입력했던 데이터를 받아들이는 함수
void setMemory ( void ); // 변수들을 초기화해주기 위한 함수
int cgiMain ( void ) // 시작
{
int result;
// 여기서 부터 4줄은 web에서 사용자들이 nobody로 접속하게 되므로 oracle 환경 설정이 필요하기 때문에 적어주는 것이다. //
putenv("ORACLE_HOME=/usr/oracle/733"); // oracle 홈 디렉토리 설정
putenv("ORACLE_SID=DB"); // SID 설정
putenv("NLS_LANG=American_America.ko16ksc5601"); // 언어 설정 ( 한국어 )
putenv("LD_LIBRARY_PATH=/usr/oracle/733/lib"); // oracle library 디렉토리 설정
// 여기까지 //
EXEC SQL WHENEVER SQLERROR DO sqlerror(); // oracle db error가 났을경우 sqlerror()함수를 실행시키라는 명령
EXEC ORACLE OPTION(HOLD_CURSOR=NO); // cursor를 무한정 잡을경우 no로 설정. 그렇지 않다면 yes로 설정
EXEC SQL CONNECT :username IDENTIFIED BY :password USING :dbstring; // oracle db에 접속
...
...
}
ps) 위의 문구중 Bold체로 되어 있는 것은 반드시 C code에 들어있어야만 하는 것들입니다.
위와 같은 코딩을 작성하면 기본적인 환경설정 및 접속이 완료됩니다. 그 다음부터 본인이 원하는 query등을 날려서 결과를 받은 후 web에 뿌려주면 됩니다.
아래에서 예제를 가지고 pro C를 이용하여 exam.cgi를 작성하여 보도록 히겠습니다.
[예제] - html로 입력받은 여러가지 입력자료들을 DB에 insert하는 cgi
<ex1.pc> :
#include "stdio.h"
#include "/home/superman/cgic/cgic.h"
#define USERNAME "superman"
#define PASSWORD "superman"
#define DBSTRING "DB"
EXEC SQL BEGIN DECLARE SECTION;
// DB에 관련된 변수들을 선언
char *username = USERNAME;
char *password = PASSWORD;
char *dbstring = DBSTRING;
int count1; VARCHAR re1[20];
int re2;
int re3;
VARCHAR re4[60];
VARCHAR re5[20];
VARCHAR re6[2000];
VARCHAR re7[8];
EXEC SQL END DECLARE SECTION;
EXEC SQL INCLUDE sqlca; void sqlerror();
int getCgiParameter();
void setMemory ( void );
int cgiMain ( void )
{
int result;
putenv("ORACLE_HOME=/oracle/733");
putenv("ORACLE_SID=DB");
putenv("NLS_LANG=American_America.ko16ksc5601");
putenv("LD_LIBRARY_PATH=/oracle/733/lib");
EXEC SQL WHENEVER SQLERROR DO sqlerror();
EXEC ORACLE OPTION(HOLD_CURSOR=NO);
EXEC SQL CONNECT :username IDENTIFIED BY :password USING :dbstring;
cgiHeaderContentType("text/html");
setMemory(); // 변수초기화
getCgiParameter(); // html에서 받은 입력자료를 위에서 선언한 변수로 대입시켜주는 함수
EXEC SQL SELECT to_char(SYSDATE,'YY-MM-DD') into re7 from sys.dual;
EXEC SQL SELECT max(S_ID) INTO :count1 FROM s_reg_db order by s_date;
count1++;
EXEC SQL INSERT INTO s_reg_db ( s_id , s_name , s_age , s_sex , s_address , s_telephone , s_date , s_memo )
VALUES ( :count1, :re1 , :re2 , :re3 , :re4 , :re5, SYSDATE , :re6 );
fprintf(cgiOut, "Insert ok\n");
fprintf(cgiOut, "끝!");
EXEC SQL COMMIT RELEASE; // commit을 한 후 연결을 계속 유지시킨다. 만약 EXEC SQL COMMIT하면 연결을 끊는다.
return 0;
}
void sqlerror()
{ // DB error 처리
EXEC SQL WHENEVER SQLERROR CONTINUE;
fprintf(cgiOut, "ORACLE Error detected: \n");
fprintf(cgiOut, "% .70s \n", sqlca.sqlerrm.sqlerrmc);
EXEC SQL ROLLBACK WORK RELEASE;
exit(1);
}
int getCgiParameter()
{
int result; char x[3];
result = cgiFormString ( "reg1", re1.arr , sizeof(re1.arr)); // reg1은 html에서 설정된 변수명
re1.len = strlen( (char *)re1.arr );
result = cgiFormString ( "reg4" , re4.arr , sizeof(re4.arr));
re4.len = strlen( (char *)re4.arr );
result = cgiFormString ( "reg5" , re5.arr , sizeof(re5.arr));
re5.len = strlen( (char *)re5.arr );
result = cgiFormString ( "reg6" , re6.arr , sizeof(re6.arr));
re6.len = strlen( (char *)re6.arr );
result = cgiFormString ( "reg2" , x , 3 );
re2 = atoi ( x ); result = cgiFormString ( "reg3" , x , 3 );
re3 = atoi ( x );
if ( result == cgiFormNotFound ) {
re3 = -1;
}
else {
re3 = atoi ( x );
}
fprintf(cgiOut," name : %s \n\n",re1.arr);
fprintf(cgiOut," age : %d\n\n",re2);
if ( re3 == 1 ) {
fprintf(cgiOut," sex : male\n");
}
else if ( re3 == 2 ) {
fprintf(cgiOut," sex : female\n");
}
fprintf(cgiOut," address : %s\n\n",re4.arr);
fprintf(cgiOut," telephone : %s\n\n",re5.arr);
fprintf(cgiOut,"memo : %s\n\n",re6.arr);
}
void setMemory ( void )
{
memset(re1.arr,0,sizeof(re1.arr)); // memset을 이용하여 문자열변수(varchar2)들을 초기화 해준다.
memset(re4.arr,0,sizeof(re4.arr));
memset(re5.arr,0,sizeof(re5.arr));
memset(re6.arr,0,sizeof(re6.arr));
memset(re7.arr,0,sizeof(re7.arr));
re2 = -1; re3 = -1; count1 = 0; // 숫자변수 초기화
}
[html 문서의 구성]
<html>
<body>
<form action=/cgi-bin/exam.cgi method=post>
<input type=text name=re1>
...
...
<input type=submit value="완료">
</form>
[MakeFile의 구성]
Oracle 7.3.3 Version에서 사용하는 예제입니다.
include ../env_precomp.mk
.SUFFIXES: .pc .c .o
LDSTRING=
PRODUCT_LIBHOME=
MAKEFILE=Makefile
PROCPLSFLAGS= dbms=v6 PROCPPFLAGS= code=cpp $(CCPSYSINCLUDE)
USERID=myUserName/myPassWord
INCLUDE=$(I_SYM). $(PRECOMPPUBLIC)
CGILIBHOME=/home/superman/cgic // cgic library가 있는 디렉토리
EXECDIR=/www/superman/cgi-bin/ex1 // ex1.cgi를 저장시킬 디렉토리, 만약 현재 작업디렉토리에 그냥 두려면 안써도 무방하다.
CGILIB=-lcb -lcgic -lmy
TARGETS=ex1 // cgi를 만들 파일명 ex1과 ex2 2개의 cgi를 만들어야 한다면 TARGETs=ex1 ex2 하면 됩니다. ( 꼭 필요합니다!! )
# Rule to compile any program (specify EXE= and OBJS= on command line)
build: $(OBJS)
$(CC) -o $(EXE) $(OBJS) ./printTemplet.o -L$(LIBHOME) -L$(CGILIBHOME) $(PROLDLIBS) $(CGILIB) // Library연결 ( 자신이 프로그램에서 특별히 사용했던 Library를 연결
all: $(TARGETS)
$(TARGETS):
$(MAKE) -f $(MAKEFILE) build OBJS=$@.o EXE=$@.cgi
.pc.c:
$(PROC) $(PROCFLAGS) $(PROCPLSFLAGS) iname=$*.pc
.pc.o:
$(PROC) $(PROCFLAGS) $(PROCPLSFLAGS) iname=$*.pc
$(CC) $(CFLAGS) -c $*.c
.c.o:
$(CC) $(CFLAGS) -c $*.c install: mv *.cgi $(EXECDIR)
결국 당신이 제작한 ex1.pc 를 cgi로 만들려면 $make ex1 하면 ex1.cgi가 생성됩니다.
다음 이시간에는 Pro*C를 이용하여 WEB에서 List 뿌려주기를 만들어 봅시다.
댓글 없음:
댓글 쓰기