제 목 : [번역]Postgres95 User's Manual(1-10) 올린이 : 엠브리오(유형목 ) 97/08/24 04:46 읽음 : 20 관련자료 없음 ----------------------------------------------------------------------------- #61 유형목 (Embryo ) [번역] postgres 1.0 메뉴얼 (1) 08/16 22:08 141 line 제 목 : Postgres95 User Manual 번 역 : 유형목 (1 -3 chapter) embryo@nownuri.net 한동훈 (4-11 chapter) ddoch@home.hite.net 저작권: GPL을 준수하며 상업적 목적으로 악용할수 없음. The POSTGRES95 User Manual Version 1.0 (September 5, 1995) 1. 소개 이 문서는 버클리 소재 캘리포니아 대학에서 개발된 postgres95 데이터 베이스 시스 템의 사용자 설명서이다. postgres95는 postgres release 4.2에 그 기반을 두고 있 다. postgres 프로젝트는 Michale Stonebraker 교수에 의해 주도 되었으며, 다음과 같은 기관들의 후원을 받았다. - DRAPA : Defence Advanced Research Projects Agency - ARO : Army Research Office - NSF : National Science Foundation (미 국립과학재단) - ELS 기타 등등 1.1. postgres란 무엇인가? 전통적인 데이터 베이스 시스템들은 관계라는 이름의 집합체인 데이터 모델을 제공 한다. 이것은 특별한 형식의 속성을 포함하고 있다. 현재의 상업용 시스템에서는 고 정 소수점 방식의 수치, 정수형, 문자형, 금전형, 날짜형 등의 데이터형이 가능하다. 그러나 일반적으로 이러한 데이터 모델 들은 미래의 데이터 처리 프로그램에서는 불 충분한 것으로 여겨지고 있다. 관계형 데이터 모델은 성공적으로 기존의 데이터 모델들을 바꾸어 나가고 있는데, 그 것은 엄격한 단순성 때문이다. 그러나 이러한 단순함이 때로는 어떤 프로그램을 구현 하는데 있어서는 어려움으로 작용하기도 한다. postgres 는 사용자가 시스템을 쉽게 확장시킬수 있는 다음의 기본적인 네 가지 구성을 제공하며, 이것을 통하여 협동함으 로서 진정한 위력을 발휘하게 된다. - classes(클래스) - inheritance(상속성) - types(데이터형) - functions(함수) 부가적으로 postgres는 강력한 rule 시스템을 제공한다. 주) ------------------------------------------------------------------------ 개인적인 생각으로는 이것이 바로 객체지향 데이터 베이스를 지칭하는 것이 아닌가 한다. 즉, 과거에는 별로 필요하지 않았던 그래픽 데이터 혹은 사운드 데이터, 혹은 지리정보에 관한 데이터, 등등의 새로운 데이터 형식을 다루는데 있어서 객체지향 데이터 베이스의 필요성을 암시 하면서, 앞으로 데이터 베이스에 필요한 새로운 어떤 방향 제시를 하고 있는 듯 하다. 1.2 postgres 프로젝트에 대한 간단한 역사 postgres DBMS는 1986년부터 구현되기 시작하였다. 이 시스템에 대한 최초의 개념은 [STON86] 에서 제시 되었으며, [ROWE87]에서 데이터 모델에 대한 최초의 정의가 나타 나 있다. rule 시스템에 대한 개념은 [STON87a] 에서 처음 기술되었으며, 데이터 처 리부에 대한 이론적 근거와 아키텍처에 대한 내용은 [STON87b] 에 상세하게 기술되어 있다. postgres는 몇 번의 주요한 발표를 거쳤으며, 첫 번째 데모 프로그램이 1987년에 처 음 동작하게 되었고, 1988년에 ACM-SIGMOD 회의에서 보여지게 되었다. [STON90a] 에 서 언급하고 있는 버전1은 1989년 6월에 내부의 몇 몇 사용자들에게만 한정적으로 발 표되었다. [STON89]에서 구현된 첫 번째 rule 시스템의 평가에 대응하여 [STON90b]에 서 새로 디자인 되었으며, 1990년 6월에 새로운 rule 시스템을 가진 버전 2가 발표되 었다. 1991년의 버전 3에서는 다중 데이터 처리부에 대한 지원과 개선된 질의 실행 화일, 그리고 새로 작성된 rule 시스템이 추가 되었다. postgres는 서로 다르면서도 매우 많은 연구와 응용된 결과 들을 구현 하는데 사용되 어져 왔으며 그 내용들을 살펴보면, 금융상의 데이터 분석 시스템, 제트 엔진의 성능 을 모니터링하는 패키지, 소행성의 운동을 추적하는 데이터 베이스, 의학 정보 데이 터 베이스, 몇 개의 지리정보 시스템 등 등을 포함하고 있다. postgres 는 또한 여러대학에서 교육용으로 쓰여져 왔다. 마침내 Illustra Informat- on Technologies 에서는 일부의 코드를 사용하여 그것을 상업화 하였다. 1992년에 postgres는 Sequoia 2000 scientific computing project의 주요한 데이터 처리기로 선정되었다. 나아가서 1993년에는 내부 사용자의 집단의 크기가 두배에 가 까워졌다. 이것은 코드의 원형을 관리하고 그것을 지원하는 일에 데이터 베이스 연구 중 더 많은 시간이 할당되어 가고 있다는 점을 명백하게 말해준다. 이러한 힘든 수고 를 줄이기 위해서 공식적으로 이 프로젝트는 버전 4.2를 마지막으로 종료되었다. 주) ------------------------------------------------------------------------- [ ] 안의 내용은 postgres를 연구하면서 발표된 논문의 약자를 뜻한다. 1.3 postgres 95란 무엇인가? postgres 95는 postgres의 마지막 공식버전인 4.2 로부터 파생된 것이다. 코드는 현재 완전히 ANSI C 로 작성되었으며, 코드의 크기도 약 25% 가 줄었고, 성능개선과 코드 유지 부분에 대한 많은 내부적 변화가 있었다. postgres95는 버전 4.2와 비교할 때 약 30% - 50% 정도의 빠른 실행속도를 보인다. 버그수정 문제를 제외한 나머지 중 요한 성능 개선 사항은 다음과 같다. - 질의어가 postquel 에서 서버상에 구현된 SQL 로 교체되었다. 그러나 아직은 subq- ueries 를 지원하지 않는다. (subqueries에 대한 것은 사용자 정의함수로 비슷 한 효과를 낼수 있다.) Aggregate(집함함수)가 다시 구현되었으며, group by 에 대한 지원이 추가 되었다. LIBPQ 부분은 아직도 C 언어가 유효하다. - 새로운 모니터링 프로그램인 psql 프로그램이 추가 되었으며, GNU readline을 지원 한다. - Tcl 을 기반으로 하여 데이터 베이스와의 연결할 수 있는 새로운 라리브러리로 li- bpgtcl 을 추가하였다. 샘플 쉘인 pgtclsh은 tcl 프로그램을 가지고 postgres와 연 결할수 있는 새로운 Tcl 명령어를 제공한다. - 대규모 객체의 연결 방법에서는 철저한 조사가 있었다. 대규모 객체의 변환은 단 지 대규모 객체를 저장하는 방식에 대한 것에만 역점을 두었다. ( 이미 제거된 화 일 시스템의 변환으로 인한 혼동이 아님에 유의 할것. ) - 예제수준의 rule 시스템은 제거 되었으며, 새로 쓰여진 rule 시스템은 아직도 유효 하다. - 일반적인 SQL 이 무엇인지를 소개하는 짧고 교육적인 소스 코드들을 같이 배포하였 다. - 프로그램을 생성하는데 있어서 GNU make (BSD make 대신) 가 사용되었고, 또한 수 정되지 않은 gcc 에서 컴파일 되어질수도 있다. (더블에서 데이터 배열이 수정되었 다.) 1.4 이 배포판에 대하여 postgres는 무료이다. 본 설명서는 Postgres95 버전 1.0 에 대하여 설명하고 있다. 저자는 다음과 같은 플랫폼에서컴파일과 테스트를 거쳤다. +--------------------------+------------+------------------------------------+ | architecture | processor | Operation System | +--------------------------+------------+------------------------------------+ | DECstation 3000 | Alpha AX | OSF/1 2.1, 3.0, 3.2 | | DECstation 5000 | MIPS | ULTRIX 4.4 | | Sun4 | SPARC | SonOS 4.1.3, 4.1.3_U1,Solaris 2.4 | | HP - 9000/700 and 800 | PA-RISC | HP-UX 9.00 9.01 9.03 | | Intel | X86 | Linux 1.2.8 ELF | +--------------------------+------------+------------------------------------+ 1.5 이 설명서의 개요. 지금부터 Postgres는 Postgres95를 의미하는 뜻으로 쓰일것이며, 이 설명서의 전반부 에서는 시스템에 대한 기본적이 개념과 Postgres 시스템을 시작하는 절차에 대해 설 명한다. 그리고 나서 Postgres의 데이터 모델과 SQL 에 대해서 개략적으로 살펴보고 조금은 수준이 높은 부분에 대해서도 설명하도록 한다. 다음으로 사용자 정의 형태의 연산자, 집합 함수를 추가함으로써, 어떻게 Postgres를 확장시킬수 있는지, 그리고 질의 언어와 프로그래밍 언어함수 양쪽에서도 그것들이 가능한지를 설명한다. Postgres rule 시스템을 개략적으로 살펴본 다음, 그에 대한 자세한 내용은 부록에서 고유의 OS별로 시스템 확장을 포함하여 논의하는 것으로 결론을 내린다. 여러분들은 이미 유닉스와 C 프로그래밍에 숙달된 것으로 가정한다. #70 유형목 (Embryo ) [번역] postgres 1.0 메뉴얼 (2,3) 08/24 04:24 240 line 2. Postgres95의 동작방식에 대한 개념. 설명을 계속하기 전에 기본적으로 Postgres 시스템이 동작하는 방식에 대하여 이해 를 하여야 한다. Postgres의 일부가 어떻게 반응하는지를 이해하면 다음 섹션이 다 소나마 명확해 질 것이다. Postgres에서는 간단한 프로세스 대 사용자의 클라이언트/서버 모델을 사용한다. Po stgres 세션은 유닉스 프로세스로 구성되어 있다. - 일종의 데몬 프로세스인 postmaster - 전위 응용 프로그램(예를 들어, psql 프로그램, 기타 사용자 프로그램) - 한개, 또는 그 이상의 후위 데이터 베이스 서버(postgres 프로세스 자체를 뜻 함) postmaster 는 하나의 호스트에 주어진 데이터 베이스 집합을 관리한다. 이러한 데 이터 베이스 집합을 설비 혹은 site 라 부른다. 전위의 응용 프로그램들이 데이터 베이스에 접근하려면 LIBPQ 라이브러리를 거쳐야 한다. 이 라이브러리는 사용자의 요구를 네트워크를 통하여 postmaster 에게 요청하고, po stmaster는 새로운 프로세스를 연결시켜 또 하나의 후위 서버를 만든다. 이러한 점 에서 전위의 프로세스와 후위의 서버는 postmaster 간섭없이도 통신을 할수가 있다. 그러므로 사용자의 요구를 기다리기 위해서 postmaster는 항상 실행중이다. LIBPQ 라이브러리는 하나의 전위프로그램이 여러 후위 프로세스와 연결하는 것을 가 능하도록 해준다. 그러나 전위의 응용 프로그램들은 아직 단일 thread 프로세스이며 Multi-thread 방식의 전위/후위의 연결은 아직 LIBPQ에서 지원하지 않는다. 전위의 프로그램들은 어디서나 실행될수 있지만, postmaster 와 후위서버는 항상 같 은 곳에서 실행되어야 한다. 이러한 사항을 머리속에서 명심하고 있어야 하는데, 그 이유는 클라이언트에서는 접근가능한 파일이 데이터 베이스 서버에서는 불가능해 질 수도 있기 때문이다. 또한, postmaster와 postgres가 Postgres의 superuser 인지를 확인해야 한다. Postgres superuser는 특별한 사용자가 아니다. (단지 postgres라는 계정을 가진 사용자를 뜻한다.) 나아가서 Posgres superuser 는 절대로 root가 아니 다. 어떠한 경우라도 데이터 베이스와 관계가 있는 모든 화일은 Postgres supreuser 에 속해 있다. 주) ------------- 일반적으로 우리는 데이터 베이스를 로딩하고 셋팅할수 있는 권한을 가진 계정을 DBA(Data Base Adminstrator)계정이라 부른다. 일반적으로 모든 프로그램의 설치는 root 권한을 가지고 실행하도록 되어 있으나 DB 에서는 이러한 권한을 가진 계정을 따로 둔다. 이것은 워낙 데이터 베이스의 권한 이 방대하기 때문에 root 에게 주어지는 부담을 줄여 보자는 것과, DBA가 시스템의 루트 권한을 가지는 것을 방지하기 위한 목적으로 해석된다. 또한 데이터 베이스에 는 상당히 중요한 자료들이 많이 수록되어 있으므로 시스템의 루트권한이라 하더라 도 그 내용을 볼수 없도록 해야할 필요가 있다. 즉 물리적인 데이터 베이스의 내용 은 루트의 권한으로 지울수 있지만 내용은 볼수 없도록 해 야 할 필요성도 있다. 특히 상업용 DB인 오라클의 경우가 좋은 예라고 할수 있다. 3. Postgres 시작하기. 이 부분에서는 전위의 응용 프로그램을 사용하기 위해서 Postgres를 시작하는 방법 과 자신의 환경에 맞도록 셋팅하는 방법에 대해 논의한다. 이미 Postgres는 성공적 으로 설치되었다고 가정한다. ( Postgres를 설치하기 위해서는 설치 note를 참조하 라.) 이 부분에서 제시된 몇 가지 단계는 모든 Postgres 사용자와 데이터 베이스 관리자 에 해당 되는 사항이다. 데이터 베이스 시스템 관리자는 소프트웨어를 설치하고, 데 이터 베이스를 만들고, postmaster를 실행시키는 사람이다. 데이터 베이스 관리자가 유닉스 의 수퍼유저인 root이거나, 컴퓨터의 하드웨어 적인 관리자일 필요는 없다. 여기서는 일반 사용자를 User로 표현하고, 데이터 베이스 관리자를 Admin 으로 표시 하도록 하겠다. 이 설명서의 예제중 % 기호로 시작되는 문장은 유닉스 쉘상의 명령어를 의미하며, * 기호는 Postgres SQL 질의어상의 명령을 뜻한다. 3.1 Admin / User : 사용자 환경 조정 단순함을 위하여 Postgres가 /usr/local/postgres95 디렉토리에 설치되어 있다고 가 정 하도록 한다. 그러므로 /usr/local/postgres95 라는 디렉토리를 볼때마다 여러분 들은 실제 Postgres가 설치된 디렉토리와 바꾸어 생각해야 한다. (혼동을 피하기 위 하여 아예 처음부터 /usr/local/postgres95 디렉토리에 설치하는 것도 좋은 방법일 것이다.) 모든 명령어들은 /usr/local/postgres95/bin 디렉토리에 설치되어 있다. 그러므로 쉘 명령어 상태에서는 이 디렉토리를 path 에 추가해야 한다. 당신이 만약 Berkeley C Shell 의 변종이나, tcsh 을 사용하고 있다면 .login 파일에 다음과 같은 줄을 추 가한다. % set path = ( /usr/local/postgres95/bin $path ) Bourne shell 의 변종이나 ksh, bash 인 경우에는 .profile 에 다음과 같이 쓴다. $ PATH=/usr/local/postgres95/bin:$PATH $ export PATH 이제 Postgres 의 bin 디렉토리가 path에 추가되었다고 가정하겠다. 부가적으로 이 설명서를 통하여 쉘변수 지정 또는 환경변수 지정이라는 것을 자주 참조하게 될 것 이다. path를 변경하는데 있어서 위 문단의 내용들을 충분히 이해할수 없었다면, 다음으로 넘어가기 전에 당신이 사용중인 쉘을 기술해 놓은 유닉스 설명서를 참고하 여야 한다. 3.2 Admin : Postmaster 시작하기. 논의에 앞서 postmaster 프로세스가 실행되어 있지 않으면 데이터 베이스에 대한 어 떠한 작업도 불가능하다는 것을 명백히 하고자 한다. 당신이 만약 Admin 이라면 pos tmaster를 실행하기 전에 몇 가지 기억해 두어야만 하는것이 있다. 이 설명서에서는 'Administering Postgres' 라는 제목이 있는 부분에서 그것을 다루기로 한다. 그러 나 여기 쓰여진 것과 같이 정확하게 Postgres가 설치되어 있다면, 다음과같은 간단 한 명령어로 postmaster 를 시작할수 있다. % postmaster & postmaster는 문제가 발생할 경우 도움이 되는 어떤 메세지를 내보내곤 한다. 만 약 postmaster로 부터 디버깅 메세지를 보고 싶은 경우에는 -d 옵션을 주고, 그것을 redirect 로 받아서 저장하면 된다. % postmaster -d >& pm.log & 메세지를 보고 싶지 않은 경우에는 다음과 같이 한다. % postmaster -S 그러면 postmaster 는 아무것도 표시하지 않을 것이다. 끝에 & 가 붙지 않았음에 유 의하라. 3.3 Admin : 사용자의 추가 및 삭제. createuser 명령어는 어떤 특별한 사용자가 Postgres에 접근 가능하도록 해준다. 이 와 반대로 destroyuser 명령어는 사용자를 삭제하고, Postgres에 접근할 수 없도록 한다. 이러한 명령어들은 단지 Postgres사용자에 대해서만 효과가 있다는 것에 유의 하라. OS 를 관리하는 사용자에게는 아무 효과가 없다. 3.4 User : 응용 프로그램 시작하기. 데이터 베이스 관리자 (site adminstrator)가 적절하게 postmaster 프로세스를 시작 하 였고, 당신이 사용자로서 데이터 베이스에 접근할수 있는 권한을 부여 받았으면 응용 프로그램을 시작할 수 있다. 앞에서 언급했던 것 처럼 당신은 path에 /usr/lo- cal/postgres95/bin 디렉토리를 추가해야 한다. 대부분의 경우 이 정도가 당신이 준 비해야 할 내용의 전부이다. 만약 Postgres 명령어 (psql이나 createdb) 실행 도중에 다음과 같은 에러메세지를 났다면, 그것은 다음과 같은 경우에 해당한다. connectDB() failed : Is the postmaster running at 'localhost' on port '4322' ? postmaster 가 실행되지 않았거나, 잘못된 server host 에 연결을 시도하려고 했을 경우이다. 만약 다음과 같은 에러메세지를 만났다면 데이터 베이스 관리자가 올바른 계정으로 postmaster 를 실행시키지 않았다는 뜻이다. FATAL 1:Feb 17 23:19:55:process userid (2360) != database owner (268) 이럴때는 다시 postmaster를 수행하도록 Postgres superuser 에게 알려주어야 한다. 3.5 User : Database 관리하기 Postgres가 실행중이라면 시험삼아 몇 개의 데이터 베이스를 만들수 있다. 여기 기 본적인 데이터 베이스 명령어들을 소개한다. Data Base 작성하기 자, 당신이 mydb 라는 이름의 데이터 베이스를 만들고저 한다. 그렇다면 다음과 같 은 명령어를 주면 된다. % createdb mydb Postgres는 주어진 곳에 얼마든지 여러개의 데이터 베이스를 만들 수 있도록 해 주 며, 그 순간에는 자동으로 여러분이 데이터 시스템 관리자가 된다. 데이터 베이스의 이름은 알파벳 글자가 처음에 와야 하고, 길이는 16글자로 제한된다. 모든 사용자가 데이터 베이스를 만들수 있는 권한을 부여받는 것은 아니다. 만약 당 신이 Postgres에서 데이터 베이스를 만들수 없다면 데이터 베이스 관리자로 부터 데 이터 베이스를 생성할수 있는 허가권을 얻어야 한다. 이럴 때는 데이터 베이스 관리 자와 의 논하도록 하자. Data Base 접근하기 데이터 베이스를 만들었으면 다음과 같은 방법으로 접근할수 있다. - Postgres 터미널 모니터링 프로그램을 수행한다.(monitor 또는 psql). 여기서는 대화방식으로 입력, 수정, SQL 명령어의 수행 등이 가능하다. - LIBPQ 의 서브 루틴을 사용하는 C 프로그램을 작성한다. 이것을 사용하면 C 에 서 SQL 명령어를 사용할수 있으며, 당신의 프로그램에서 결과와 상황 메세지 들을 얻을 수 있다. 이러한 방법에 대해서는 다음 부분에서 논의 한다. 이 설명서의 예제를 시험해 보려면 psql을 수행하여야 한다. 다음과 같은 명령어로 mydb에 접근할 수 있는 상태가 된다. % psql mydb 다음과 같은 환영 메세지(?)를 받게 될 것이다. Welcome to the Postgres95 interactive sql monitor type \? for help on slash commands type \q to quit type \g to terminate with semicolon to excute query You are currently conneted to the database: mydb mydb => 이 프롬프트는 터미널모니터가 이제부터 당신의 명령을 받아들일 수 있다는 뜻이다. 이제 터미널 모니터가 제공하는작업 영역에서 SQL 쿼리를 쓸 수 있다. psql은 역슬 래시(\)로 시작하는 escape코드에 응답한다. 예를 들어, Postgres에 대한 여러 가지 문법적 도움말을 얻기 위해서는 명령어 라인에서 다음과 같이 입력한다. mydb => \h 쿼리 문장이 끝났음을 알리고, 작업공간의 내용을 Postgres서버에 알려주기 위해 다 음과 같이 입력한다. mydb => \g 이것은 서버에게 퀴리의 내용을 실행하라는 뜻이다. 만약 문장 끝에 세미콜론을 사 용 했다면 \g 는 필요없다. 세미콜론이 붙으면 psql 은 자동으로 쿼리를 처리한다. 외부 화일로 부터 쿼리 내용을 읽어들이기 위해서는 대화형 방식대신 다음과 같이 입력한다. mydb => \i filename 유닉스로 빠져나가기 위해서는 다음과 같이 한다. mydb => \q 그러면 psql이 종료되고, 유닉스 명령어를 쓸 수 있는 쉘 상태가 된다. ( 더 자세한 것은 \h를 입력해 보라.) 탭 혹은 빈칸은 SQL 쿼리내에서 얼마든지 쓸수 있다. dash 이후에 쓰여진 모든 줄들은 무시되며, 그것은 곧 주석으로 처리됨을 의미한다. Data Base 삭제하기 당신이 mydb 에 대한 데이터 베이스 관리자라면 다음과 같은 명령어를 써서 삭제 할 수있다. % destroydb mydb 이러한 명령어는 데이터 베이스에 관계된 모든 유닉스 화일을 물리적으로 지워버리 기 때문에 복구 할 수 없게 된다. 그러므로 작업에 앞서서 더욱 신중하게 생각해야 할 것이다. #57 한동훈 (ddoch ) [번역] postgres 1.0 메뉴얼 (4-1) 08/10 04:23 154 line ---------------------------------------- Postgres95 1.0 사용자 메뉴얼 한글 번역 ---------------------------------------- 번역 : 한동훈 active@soback.kornet.nm.kr 날짜 : Sun Aug 10 04:18:20 KST 1997 본 내용은 Postgres95 의 1.0 사용자 메뉴얼을 한글로 번역하는 것입니다. 틈틈히 번역하여 올릴 예정입니다. ---------- 4. 질의어 POSTGRES 에서 사용하는 질의어는 SQL-3 의 변형이다. POSTGRES 의 질어의에는 확장가능한 형태의 시스템, 상속, 함수, 생성규칙과 같은 것을 가지고 있다. 이러한 특징은 원래의POSTGRES 질의어인 POSTQUEL 에서 나왔다. 이장에서는 간단한 작동을 POSTGRES SQL 을 사용하여 시행해 본다. 이 매뉴얼은 SQL 의 행동양식을 보여줄 뿐, 완전한 SQL 교재는 아니다. SQL 에 대한 책은 시중에 많이 나와있다. 그리고 여기에 나오는 몇몇 특징들은 ANSI 표준이 아니다. 아래에 예를 들어보자. 여기에서는, 바로 앞장에서 나왔던 것과 같이 mydb 라는 데이터베이스를 만들어 두었고, psql 을 실행한다고 가정해보자. 이 메뉴얼에 나오는 예제는 /usr/local/postgres95/src/tutorial 에도 나와있다. 이 예제들을 어떻게 사용하는 지는 해당 디렉토리에 있는 README 파일을 잘 읽어 보면 된다. 다음과 같이 따라하자. % cd /usr/local/postgres95/src/tutorial % psql -s mydb Welcome to the POSTGRES95 interactive sql monitor: type \? for help on slash commands type \q to quit type \g or terminate with semicolon to execute query You are currently connected to the database: jolly mydb=> \i basics.sql '\i' 명령을 사용하면 특정한 외부파일에서 질의어를 읽어서 처리할 수 있다. 명령행에서의 '-s' 옵션은 하나의 커리를 backend 로 보내기 전에 정지하는 싱글 스텝 모드로 설정하는 것이다. 4.1 개념 POSTGRES 에서 기본적인 개념은 클래스(class) 이다. 클래스는 객체로서의 인스턴 스 (instances) 의 결집체이다. 각각의 인스턴스는 같은 속성(attributes)의 집합 을 가지고 있고, 각각의 속성은 특정한 형(type)이다. 더 나아가, 각각의 인스턴스 는 영구적인 객체 식별자(object identifier - OID)를 가지게 되며, 이 식별자는 설 치 시부터 중복되지 않는 유일한 것이다. SQL 문법은 테이블(table)을 참조하기 때 문에, 클래스(class) 라는 개념대신 테이블(table)이라는 말을 사용할 수 있다. 마 찬 가지로, 열(row) 는 인스턴스(instance)이고, 컬럼(columns)은 속성(attributes) 이다. 앞에서 살펴본 바와 같이, 클래스는 그룹화되어 데이터베이스를 이루고, 데이터베 이스의 집합은 하나의 postmaster 프로세스에 의해 관리된다. 4.2 새로운 클래스의 생성 클래스의 이름을 지정하여 새로운 클래스를 만들 수 있다. 이때 모든 속성과 형 을 명시한다. CREATE TABLE weather ( cityvarchar(80), temp_lo int, - 최저온도 temp_hi int, - 최고온도 prcp real, - 강수량 date date ); 예약어(keyword)에는 무신경해도 되지만 식별자에는 주의하여야 한다. POSTGRES SQL 은 평범한 SQL 타입으로 int, float, real, smallint, char(N), varchar(N), date, time 을 제공한다. 나중에 살펴보겠지만, POSTGRES 에서는 사용자가 데이 터 형을 자신이 마음대로 정할 수 있다. 결과적으로, 형의 명칭은 예약어가 아니 다. 나아가, POSTGRES 의 'create' 명령어는 전통적인 관계형 시스템에서 테이블을 생 성 하는 데 사용하는 명령어와 아주 유사하다. 그러나, 클래스는 관계형 모델을 확장하는 독자적인 특성을 가지고 있음을 곧 알아볼 것이다. 4.3 클래스에 인스턴스를 삽입하기 클래스에 인스턴스를 삽입하는 데는 'insert' 구문을 사용한다. INSERT INTO weather VALUES ('San Francisco', 46, 50, 0.25, '11/27/1994') 'copy' 명령을 사용하면, 평범한 아스키 파일에서 대규모의 데이터를 적재할 수 있다. 4.4 클래스에 질의하기 weather 클래스에 보통의 관계형 선택, 계획 커리를 던질 수 있다. SQL 'select' 구문을 이러한 목적에 사용할 수 있다. 구문은 대상 목록 부분(target list - 반환될 속성 목록부분) 과 질의부분(어떠한 제한을 명시하는 부분)으로 나눌 수 있다. 예를 들자면, weather 의 모든 열(row)을 알아보기 위해서는 다음과 같이 하면 될 것이다. SELECT * FROM WEATHER; 그러면, 출력은 다음과 같을 것이다. city |temp_lo|temp_hi|prcp| date -------------+-------+-------+----+---------- San Francisco| 46| 50|0.25|11-27-1994 San Francisco| 43| 57| 0|11-29-1994 Hayward | 37| 54| |11-29-1994 (3 rows) 아울러, 대상 리스트에 표현식을 마음대로 지정할 수 있다. 예를 들면, 다음과 같이 질의를 할 수 도 있다. SELECT city, (temp_hi+temp_lo)/2 AS temp_avg, date FROM weather; 커리 시에 커리부분에 부울런 오퍼레이터(and, or, not) 을 사용할 수 있다. 예를 들면, 다음과 같다. SELECT * FROM weather WHERE city = 'San Francisco' and prcp > 0.0; city |temp_lo|temp_hi|prcp| date -------------+-------+-------+----+---------- San Francisco| 46| 50|0.25|11-27-1994 (1 row) 마지막 참고사항으로, select 의 결과를 순서대로 정렬하거나, 중복되는 인스턴스 를 제거할 수도 있다. SELECT * FROM weather ORDER BY city; 4.5 select 결과를 리다이렉트하기 select 커리는 새로운 클래스로 리다이렉트 하도록 사용할 수 있다. SELECT * INTO temp from weather; 이러한 select 의 사용은, 묵시적인 create 명령어를 생성하여, 새로운 클래스로 temp 를 생성하는 데, 이 때 속성과 형은 'SELECT INTO' 명령어에서 대상 리스트에 명시된 속성 명칭과 형이 사용된다. 물론, 다른 클래스상에서 결과적으로 생성된 클래스에서도 어떠한 동작도 수행할 수 있다. #58 한동훈 (ddoch ) [번역] postgres 1.0 메뉴얼 (4-2) 08/10 22:06 95 line 4.6 클래스간의 결합 지금까지, 하나의 질의는 한번에 하나의 클래스만을 억세스 해왔다. 질의는 한번에 여러 클래스를 억세스하거나, 클래스의 여러 인스턴스를 동시에 다루는 방법으로 동일한 클래스를 억세스 할 수 있다. 한번에 같은 클래스나 서로다른 클래스의 여러 인스턴스에 접근하는 질의를 '결합 질의(join query)' 라고 부른다. 하나의 예로, 다른 레코드의 온도 범위에 있는 모든 레코드를 찾고 싶을 때를 가정 해보자. 결과적으로, 우리는 각각의 EMP 인스턴스의 temp_lo 와 temp_hi 속성을 다른 모든 EMP 인스턴스의 temp_lo 와 temp_hi 속성과 비교할 필요가 있다. (주2 - 이것은 단지 개념적인 모델일 뿐이다. 실제적인 결합은 좀더 효율적인 방법 으로 이루어 질 것이지만, 사용자의 눈에는 보이지 않는다. ) 이러한 작업은 다음의 커리로 할 수 있다. SELECT W1.city, W1.temp_lo, W1.temp_hi, W2.city, W2.temp_lo, W2.temp_hi FROM weather W1, weather W2 WHERE W1.temp_lo < W2.temp_lo and W1.temp_hi > W2.temp_hi; city |temp_lo|temp_hi|city |temp_lo|temp_hi -------------+-------+-------+-------------+-------+------- San Francisco| 43| 57|San Francisco| 46| 50 Hayward | 37| 54|San Francisco| 46| 50 (2 rows) 이 경우에, W1 과 W2 는 클래스 weather 의 인스턴스를 위한 대용이며, 양쪽의 범위 는 클래스의 모든 인스턴스를 넘는다. (데이터베이스 시스템의 전문용어로 W1 과 W2 는 "범위 변수(range variables)"라 한다.) 하나의 질의는 클래스 이름과 그의 대용을 자유롭게 포함할 수 있다. (주3 - 이러한 결합의 의미는, 질의부분은 데카르트의 product 에서 정의한 클래스 식의 진리값의 표현이라는 것이다. 질의부분이 참인 데카르트의 product 에서의 이러한 인스턴스를 위해서, POSTGRES 는 대상 리스트에서 지정한 값을 계산 하여 반환한다. POSTGRES SQL 은 이러한 표현에서 값을 복사하는 데 어떠한 의미도 부여하지 않는다. 이 의미는 POSTGRES 는 가끔 같은 대상 리스트를 여러번 재계산 한다는 것을 의미한다. - 이것은 자주 부울런 표현이 'or' 로 연결되었을 때 나타 난다. 이러한 복사를 피하기 위해서는, 'select distinct' 구문을 사용하여야 한 다.) 4.7 갱신 'update' 명령을 사용하면 존재하는 인스턴스를 갱신할 수 있다. 11월 28일 이후의 최고온도와 최저온도를 2도씩 감소시켜야 할 필요성이 있다고 생각해보자. 이러한 갱신은 다음의 질의로 처리할 수 있을 것이다. UPDATE weather SET temp_hi = temp_hi - 2, temp_lo = temp_lo - 2 WHERE date > '11/28/1994'; 4.8 삭제 삭제는 'delete' 명령을 사용한다. DELETE FROM weather WHERE city = 'Hayward'; Hayward 에 관련된 모든 날씨기록은 삭제한다. 다음과 같은 사용은 조심해야 한다. DELETE FROM classname; 'delete' 명령은 여러분에게 물어보지도 않고 지정한 클래스의 모든 인스턴스를 간 단히 삭제해서 공허만이 남게 된다. 시스템은 이러한 삭제작업 이전에 확인을 요구 하지 않을 것이다. 4.9 전체 함수의 사용 다른 질의어와 마찬가지로, POSTGRES 는 전체 함수를 제공한다. 그러나, 현재의 POSTGRES의 전체 함수는 매우 제한적이다. 특별히, 횟수, 합계, 평균, 최대, 최소 등의 계산에 관련된 전체 함수를 제공한다. 이들 함수는 인스턴스의 집합에 적용되 며, 질의의 대상 리스트에만 나타나며, 질의부분(where 절)에는 나타나지 않는다. 예를 들어보자. SELECT max(temp_lo) FROM weather; 전체 함수와 함께 'GROUP BY' 절을 사용할 수 있다. SELECT city, max(temp_lo) FROM weather GROUP BY city; #59 한동훈 (ddoch ) [번역] postgres 1.0 메뉴얼 (5) 08/12 20:40 198 line 5. 진보적인 POSTGRES SQL 의 특징 이제 기본적인 데이터 관리와는 구별되는 POSTGRES 의 특징에 대해서 논의해 볼 것이다. 이러한 특징에는 상속, 시간 여행, 비원자화 데이터 값들 (array- 와 set-valued 속성) 등이 있다. 이장에서 나오는 예는 교재(tutorial) 디렉토리에 'advance.sql' 에 나와있다. (이것을 어떻게 사용하는 지는 앞장의 서론 부분을 참조하자.) 5.1 상속 두개의 클래스를 만들어 보자. 'capitals' 클래스는 하나의 도시, 주의 수도 를 포함한다. 자연스럽게, 'capitals' 클래스는 'cities' 로부터 상속받아야 한 다. CREATE TABLE cities ( name text, population float, altitude int -- (in ft) ); CREATE TABLE capitals ( state char2 ) INHERITS (cities); 이 경우에, 'capitals' 의 인스턴스는 그의 부모로부터 모든 속성 ('name', 'population', 'altitude') 를 상속받는다. 속성 'name' 의 타입은 'text' 이다. 'text' 는 가변 길이의 아스키 문자열에 사용되는 POSTGRES 에 내장되어 있는 타입 이다. 속성 'population' 의 타입은 'float4' 이며, 이 타입은 더블 정밀도의 부동 소수에 사용되는 POSTGRES 내장형이다. 주의 수도(state capitals)는 또다른 속성으로 주를 나타내는 'state' 를 가지고 있다. POSTGRES 에서, 하나의 클래 스는 0개 이상의 클래스로부터 상속받을 수 있고,(주4)하나의 질의는 어떤 클래스의 모든 인스턴스나 이것과 함께 인스턴스의 자손까지 참조할 수 있다. 예를 들면, 아래의 질의는 고도 500 피트 보다 높은 곳에 있는 도시를 검색하는 것이다. 주4) 상속체계는 바로 acyclic 그래프이다. SELECT name, altitude FROM cities WHERE altitude > 500; name |altitude ---------+-------- Las Vegas| 2174 Mariposa | 1953 (2 rows) 500 피트 이상에 있는 모든 도시를 주의 수도를 포함하여 찾고자 한다면, 해당 질의는 다음과 같다. SELECT c.name, c.altitude FROM cities* c WHERE c.altitude > 500; 결과는 다음과 같다. name |altitude ---------+-------- Las Vegas| 2174 Mariposa | 1953 Madison | 845 (3 rows) 'cities' 다음의 '*' 는 'cities' 와 'cities' 에서 상속받은 모든 클래스를 나타 낸다. 이미 앞에서 살펴본 많은 명령 - select, update, delete - 은 'alter' 명령 과 유사한 이러한 '*' 표기를 제공한다. 5.2 시간 여행 POSTGRES 는 시간 여행에 대한 표기법을 지원한다. 이러한 특징은 사용자로 하여금 역사적인 질의를 할 수 있도록 한다. 예를 들면, Mariposa 도시의 현재의 인구를 검색하려면, 다음과 같이 사용할 수 있을 것이다. SELECT * FROM cities WHERE name = 'Mariposa'; name |population|altitude --------+----------+-------- Mariposa| 1320| 1953 (1 row) POSTGRES 는 자동적으로 현재 싯점에서의 유효한 Mariposa 도시의 레코드를 찾을 것 이다. 여기에서 시간범위를 부여할 수 있다. Mariposa 도시의 과거의 인구를 알아보려면, 다음과 같이 질의하면 된다. SELECT name, population FROM cities['epoch', 'now'] WHERE name = 'Mariposa'; 'epoch' 는 시스템 시간의 시작싯점을 나타낸다. (주5) 지금까지의 모든 예제를 실 행시켰다면, 질의의 결과는 다음과 같을 것이다. 주5) UNIX 시스템에서는, 이 싯점은 항상1970 GMT 1월 1일 00시이다. name |population --------+---------- Mariposa| 1200 Mariposa| 1320 (2 row) 시간범위에서 디폴트 시작싯점은 시스템이 시간을 표시할 수 있는 최초의 시각이며, 디폴트 끝지점은 현재 시각이다. 따라서, 위의 시간범위는 "[,]." 와 같이 단축하 여 사용할 수 있다. 5.3 원자화되지 않은 값 관계형 모델에서의 관계의 속성은 보통 원자화(atomic)된다는 것이다. POSTGRES 에는 이러한 제한이 없다. 속성은 질의어로 접근할 수 있는 보조값(sub-values) 을 가질 수 있다. 예를 들면, 하나의 속성을 기본 타입의 배열로 만들 수 있 다. 5.3.1 배열 POSTGRES 에서는 하나의 인스턴스의 속성은 고정길이 또는 가변길이의 다차원 배열 로 정의 될 수 있다. 어떠한 기본형이나 사용자 정의형의 배열도 만들 수 있다. 실례를 보이기 위해, 여기서는 먼저 기본형의 배열을 사용하여 클래스를 만들어 보 겠다. CREATE TABLE SAL_EMP ( name text, pay_by_quarter int4[], schedule char16[][] ); 위의 질의는 SAL_EMP 로 불리우는 클래스를, text 문자열('name')과 int4의 1차원 배열('pay_by_quarter'), 그리고 char16 의 2차원 배열('schedule')의 구성으로 생 성한다. 'pay_by_quarter' 는 사원들에게 지급되는 4등분된 급료이며, 'schedule' 는 사원들의 주간계획이다. 이제 데이터를 조금 삽입해보자. 배열에 데이터를 추가할 때는, 해당값은 중괄호 사이에 와야 하고, 콤마에 의해 구분된다. C 를 알고 있다면, 구조체의 초기화 문법과 별로 다르지 않다는 것을 알 수 있을 것이다. INSERT INTO SAL_EMP VALUES ('Bill', '{10000, 10000, 10000, 10000}', '{{"meeting", "lunch"}, {}}'); INSERT INTO SAL_EMP VALUES ('Carol', '{20000, 25000, 25000, 25000}', '{{"talk", "consult"}, {"meeting"}}'); POSTGRES 에서는 기본적으로 배열에서 번호를 붙일 때 1부터 시작한다. n 개의 원소를 가진 배열은 배열[1] 에서 시작하여 배열[n]으로 끝난다. 이제, SAL_EMP 에 몇개의 질의를 던져보자. 먼저, 어느 한 싯점에서 배열중 하나 의 원소에 접근하는 방법을 알아보자. 다음의 질의는 사원들 중 급료의 두번째 배당금이 변경된 사람을 검색한다. SELECT name FROM SAL_EMP WHERE SAL_EMP.pay_by_quarter[1] <> SAL_EMP.pay_by_quarter[2]; name ----- Carol (1 row) 다음의 질의는 모든 사원들의 급료중 세번째 배당금을 보여준다. SELECT SAL_EMP.pay_by_quarter[3] FROM SAL_EMP; pay_by_quarter -------------- 10000 25000 (2 rows) POSTGRES 에서는 배열의 조각(slices), 또는 보조배열(subarrays)에 접근할 수 있 다. 다음의 질의는 Bill 의 주간계획에서 처음 두번째날의 첫번째 아이템을 검 색한다. SELECT SAL_EMP.schedule[1:2][1:1] FROM SAL_EMP WHERE SAL_EMP.name = 'Bill'; schedule ------------------ {{"meeting"},{""}} (1 row) #60 한동훈 (ddoch ) [번역] postgres 1.0 메뉴얼 (6) 08/13 02:34 121 line 6. 확장 SQL : 미리보기 다음장부터, 다음의 내용을 추가하여 POSTGRES SQL 질의어를 확장할 수 있는 방법을 알아볼 것이다. * 함수 (functions) * 형 (types) * 오퍼레이터 (operators) * 합계 (aggregates) 6.1 확장은 어떻게 작동하나 POSTGRES 는 그 작동이 카탈로그 운영(catalog-driven)방식이기 때문에 확장가능하 다. 여러분들이 표준 관계형 시스템에 친숙하다면, 관계형 시스템에서는 데이터 베이스와 테이블, 컬럼 등에 관련된 정보를 시스템 카탈로그라고 불리우는 곳에 저장함을 잘 알것이다. (어떤 시스템에서는 이것을 데이터 사전 (data dictionary) 라고 부른다.) 카탈로그는 사용자에게는 다른 것과 마찬가지로 클래스로 표현되 나, DBMS 는 내부장부를 카탈로그 안에 저장한다. 다른 표준 관계형 시스템과 POSTGRES 가 다른 점은 POSTGRES 는 카탈로그 내부에 좀 더 많은 정보를 저장한다 는 점이다. 저장되는 정보는 테이블과 컬럼에 관련된 정보 뿐만이 아니라, 형 (types), 함수(functions), 접근 방법(access methods) 등등에 관한 정보도 포함된 다. 시스템 카탈로그에 관련된 클래스는 사용자가 변경할 수 있으며, POSTGRES 의 내부적인 작동은 이러한 클래스에 기반한다. 이 의미는 사용자가 POSTGRES 를 확 장할 수 있다는 것이다. 비교를 하자면, 전통적인 데이터베이스 시스템은 DBMS 내 부의 하드코드된 프로시저를 변경하거나, DBMS 공급자가 특별히 제작한 모듈을 적 재함으로써만 확장가능해진다. POSTGRES 는 다른 대부분의 데이터 관리자와는 달리, 사용자가 작성한 코드를 DBMS 내부로 동적 적재(dynamic loading)를 통해서 포함할 수 있다는 점이다. 사용자는 적재시에 새로운 형(type)과 함수가 정의된 오브젝트 코드 파일 (컴파일된 .o파일, 또는 공유 라이브러리) 를 지정할 수 있으며, POSTGRES 는 요청 대로 적재할 것이다. SQL로 작성된 코드는 더욱 쉽게 DBMS 서버에 추가될 수 있다. POSTGRES 의 이러한 수정 능력은 특별히 새로운 응용프로그램의 신속한 원형작성 과 저장구조에 적합하다. 6.2 POSTGRES 형(type) 시스템 POSTGRES 형 시스템은 여러가지 방법으로 무력화 시킬 수 있다. 형(type)은 기본(base)형과 복합(composite)형으로 나눌 수 있다. 기본형은 int4 와 같이, C 와 같은 언어에서 사용되는 것들이다. 기본형은 보통 "이론적인 (abstract) 데이터 형"으로 알려진 것들과 일치한다. POSTGRES 는 사용자가 제공한 방법을 통해 기본형 위에서만 작동할 수 있으며, 기본형의 행동을 사용자가 기술한 확장으로만 이해한다. 복합형은 사용자가 클래스를 만들때 생성된다. 'EMP' 는 복합형의 하나의 예이다. POSTGRES 는 복합형을, 클래스의 모든 인스턴스 들이 저장된 파일 내부의 한곳에만 저장하지만, 사용자는 질의어를 사용하여 복합 형의 속성부분에서 내부를 들여다 볼 수 있다. 아울러 해당 속성에서 (예를 들자면) 인덱스를 정의하는 방법으로 복구를 최적화할 수 있다. 아울러 POSTGRES 의 기본형을 내장(built-in)형과 사용자정의(user-defined)형으로 나눌수 있다. int4 와 같은 내장형은 시스템상에 컴파일된 상태로 포함되어 있다. 사용자정의형은 아래에서 설명하는 방법으로 사용자가 만든 것이다. 6.3 POSTGRES 시스템 카탈로그 이제, 카탈로그의 실제적인 윤곽을 살펴보면서, 기본 확장성 개념에 입문해보자. 이장을 건너뛰는 것은 여러분 마음이지만, 뒷부분에서 여기에 나오는 지식이 꼭 필 요하기 때문에 나중을 위해서라도 이 부분을 표시해두자. 시스템 카탈로그의모든 명칭은 'pg_' 로 시작한다. 아래의 클래스는 사용자에게 유용한 정보이다. (다른 시스템 카탈로그도 많이 있으나 직접 질의에서 사용할 경우는 드물 것이다.) ---------------------------------------------------------------------- 카탈로그 이름 설명 ====================================================================== pg_database 데이터베이스 pg_class 클래스 pg_attribute 클래스 속성 pg_index 두번째(보조) 인덱스 pg_proc 프로시저 (C 와 SQL) pg_type 형 (기본형과 복합형) pg_operator 오퍼레이터 pg_aggregate 집합 및 집합함수 pg_am 엑세스 방법 pg_amop 엑세스 방법 오퍼레이터 pg_amproc 엑세스 방법 제공 함수 pg_opclass 엑세스 방법 오퍼레이터 클래스 ---------------------------------------------------------------------- 레퍼런스 메뉴얼에 이러한 카탈로그와 속성에 대한 좀 더 자세한 설명이 들어있다. 그러나, 그림3은 시스템 카탈로그의 핵심 실체와 이러한 관계를 보여주고 있다. ( 다른 실체를 참조하지 않는 속성은 해당 속성이 프라이머리 키의 일부분이 아닐 경우에는 여기에서 나타나지 않는다.) 이 도표는 실제로 카탈로그의 내용을 보기 전이나 다른 것들과의 상호관계를 살펴보기전에는 다소간 이해하기 어려울 것이다. 이 도표에서 중요한 점은 다음 과 같다. (1) 이후의 여러장에서, 시스템을 확장하는 데 필요한 정보를 보여주는 시스템 카탈로그상에서 다양한 join 질의를 보게 될 것이다. 이 도표를 살펴보면서 좀 더 이해할 수 있도록 이러한 join 질의(보통 세개나 네개의 join)를 조금 만들어보는 것도 좋을 것이다. 질의에서 사용된 속성이 다른 클래스에서는 외부 키의 형태를 이룬다는 것을 알 수 있다. (2) 다른 많은 특징 (클래스, 속성, 함수, 형, 엑세스 방법 등)들도 이 스케마 에서 서로 협력한다. 'create' 명령으로 간단히 이러한 카탈로그의 많은 부분을 수정할 수 있다. [그림 3] POSTGRES 의 핵심 시스템 카탈로그 (3) 타입과 프로시저 (주6)는 이 스케마의 중심이다. 거의 모든 카탈로그는 이러한 클래스의 하나 또는 양쪽 모두에 있는 인스턴스를 참조한다. 예를 들자면, POSTGRES 는 자주 다른 카탈로그의 유일한 인스턴스를 식별하기 위해 형 시그네쳐(함수와 오퍼레이터의)를 사용한다. 주6) 여기서는 다소간의 호환성을 위해 'procedure(프로시저)'와 'function(함수)' 라는 단어를 사용한다. (4) 분명한 의미를 가지는 많은 속성과 관계가 있으나, 그렇지 않은 것(엑세스 방법 과 함께 동작하는 특정한 것) 도 많다. 'pg_am', 'pg_amop', 'pg_amproc', 'pg_operator', 'pg_opclass' 사이의 관계는 이해하기가 매우 까다롭기 때문에, 기본적인 확장에 대해 알아본 뒤에 좀더 심도깊게 (types과 operators 에 대해 자세하게 설명하는 장에서) 알아볼 것이다. #62 한동훈 (ddoch ) [번역] postgres 1.0 메뉴얼 (7) 08/17 15:56 380 line 7. 확장 SQL : 함수 함수를 정의하는 것은 새로운 형(type)을 정의하는 것중 일부분이다. 새로운 형(type)을 정의하지 않고 함수를 정의하는 것은 가능하지만, 그 역은 불가능 하다. 따라서 여기서는 새로운 형(type)을 추가하는 방법을 설명하기에 앞서 새로운 함수를 추가하는 방법부터 먼저 설명할 것이다. 이장에서 나오는 예제들은 funcs.sql 과 C-code/funcs.c 에서 찾을 수 있다. 7.1 질의어 (SQL) 함수 7.1.1 기본형 SQL 함수 가장 간단한 SQL 함수는 매개인자는 없고, int4 와 같은 기본형을 반환하는 것이 아닐까? CREATE FUNCTION one() RETURNS int4 AS 'SELECT 1 as RESULT' LANGUAGE 'sql'; SELECT one() AS answer; answer ------ 1 여기에서 대상 리스트를 RESULT 라는 이름으로 함수를 위해 정의하였으나, 함수를 불러오는 질의에서의 대상 리스트는 함수의 대상 리스트를 무효화한다. 따라서, 그 결과에는 one 대신 answer 이라는 이름의 라벨이 붙는다. 이제 매개인자로 기본형을 가지는 SQL 함수를 정의해보자. 아래의 예에서, 함수내 부에서 매개인자를 참조할 때는 $1, $2 와 같이 사용한다는 점에 주의하라. CREATE FUNCTION add_em(int4, int4) RETURNS int4 AS 'SELECT $1 + $2;' LANGUAGE 'sql'; SELECT add_em(1, 2) AS answer; answer ------ 3 7.1.2 복합형 SQL 함수 함수에서의 매개인자가 복합형 (EMP 처럼)일 경우에는, 원하는 (위에서 $1, $2 라고 했던 것처럼) 인자를 명시만 해서는 안되고 인자의 속성까지 명시해야 한다. 예를 들어, 사원의 급료를 두배로 계산하는 double_salary 함수를 살펴보자. CREATE FUNCTION double_salary(EMP) RETURNS int4 AS 'SELECT $1.salary * 2 AS salary;' LANGUAGE 'sql'; SELECT name, double_salary(EMP) AS dream FROM EMP WHERE EMP.dept = 'toy'; name|dream ----+----- Sam | 2400 $1.salary 문법의 사용에 주의하자. 복합형을 반환하는 함수로 들어가기 전에, 먼저 속성과 관련된 함수식 표기법부터 알 아보자. 이러한 표기방식에는 attribute(class) 와 class.attribute 의 두가지가 있으며 서로 바꾸어 사용할 수 있다. -- -- 이것은 다음의 사용과 동일하다: -- SELECT EMP.name AS youngster FROM EMP WHERE EMP.age < 30 -- SELECT name(EMP) AS youngster FROM EMP WHERE age(EMP) < 30; youngster --------- Sam 결과가 항상 이와 같지는 않다. 이 함수식 표기법은 하나의 인스턴스를 반환하는 함수를 사용할 때 중요하다. 이러한 작업은 함수내의 전체 인스턴스를 속성을 하나씩 끌어모음으로써 할 수 있다. 다음은 하나의 EMP 인스턴스를 반환하는 함수의 예이다. CREATE FUNCTION new_emp() RETURNS EMP AS 'SELECT \'None\'::text AS name, 1000 AS salary, 25 AS age, \'none\'::char16 AS dept;' LANGUAGE 'sql'; 여기서는 각각의 속성을 상수값으로 지정하였으나, 어떠한 계산값이나 표현식도 이러한 상수값을 대체할 수 있다. 이와 같이 함수를 정의하는 것은 일종의 트릭일 것이다. 몇가지 주의해야할 중요 한 사항은 다음과 같다. * 대상 리스트의 순서는 CREATE TABLE 구문에 나타나는 속성의 순서와 정확히 일치 해야 한다. * 표현식을 '::' 를 사용하여 형변환 할 때에는 매우 조심해야 하며, 그렇지 않을 경우에는 다음과 같은 에러가 발생할 것이다. WARN::function declared to return type EMP does not retrieve (EMP.*) * 하나의 인스턴스를 반환하는 함수를 호출할 때, 속성 전체를 회수할 수는 없다. 이경우 인스턴스 중 하나의 속성만을 회수하거나 전체 인스턴스를 또다른 함수 로 넘길 수 있다. SELECT name(new_emp()) AS nobody; nobody ------ None * 함수에서의 반환값에서 속성을 취할 때는 반드시 함수식 표기법을 사용해야 하는 데, 그 이유는 함수호출을 결합해서 사용할 때 파서는 점('.')이 붙은 다른 문법 을 이해하지 못하기 때문이다. SELECT new_emp().name AS nobody; WARN:parser: syntax error at or near "." SQL 질의어에서 어떠한 명령의 조합도 함께 묶을 수 있으며 함수로 정의할 수 있다. SQL 로 작성되는 함수에서 select 질의와 마찬가지로 갱신(insert, update, delete 등) 명령을 포함할 수 있다. 그러나, 마지막 명령은 반드시 select 여야 하며, 함수의 returntype 으로 지정된 어떠한 값을 반환하여야 한다. CREATE FUNCTION clean_EMP () RETURNS int4 AS 'DELETE FROM EMP WHERE EMP.salary <= 0; SELECT 1 AS ignore_this' LANGUAGE'sql'; SELECT clean_EMP(); x - 1 7.2 프로그래밍 언어 함수 7.2.1 기본형 프로그래밍 언어 함수 POSTGRES 는 내부적으로 기본형을 메모리의 파편으로 인식한다. 하나의 형을 넘어 정의한 사용자 정의 함수는 POSTGRES 함수상에서 작동할 수 있는 방법을 정의하는 것이다. POSTGRES 는 함수를 저장하고 디스크에서 읽어올 뿐이며, 데이터 입력. 처리.출력을 위해 사용자 정의함수를 사용할 뿐이다. 기본형은 다음의 세가지 내부적인 형식중 하나를 가질 수 있다. * 값에 의한 전달, 고정길이 * 참조에 의한 전달, 고정길이 * 참조에 의한 전달, 가변길이 값에 의한 형(type)은 사용자의 컴퓨터가 다른 크기의 변수 형태를 제공한다 할지 라도, 그 길이는 1,2,4 바이트만 될 수 있다. POSTGRES 는 그자체로는 값에 의한 전달방식으로 정수형만 넘겨줄 수 있다. 새로운 형(type)을 정의할 때는 모든 아 키텍쳐에서 같은 크기(바이트수로)가 되어야 한다는 점에 주의해야 한다. 예를 들 어, long 형은 위험한데, 그 이유는 int 형이 4바이트인 대부분의 유닉스 머쉰상에 의 어떠한 머쉰에서는 4바이트이고 다른 머쉰에서는 8바이트가 될 수 있기 때문이 다 (대개의 PC 에서는 그렇지 않겠지만). 유닉스 머쉰상에서 int4는 다음과 같다. /* 4-byte integer, passwd by value */ typedef int int4; 그외의 경우에, 고정길이 형은 참조에 의한 전달이 된다. 예를 들어, POSTGRES 의 char16 형은 다음과 같다. /* 16-byte structure, passed by reference */ typedef struct { char data[16]; } char16; char16과 같은 형을 POSTGRES 로 넘겨주거나 받을 때에는 이 형에 대한 포인터만을 사용할 수 있다. 마지막으로, 모든 가변길이 데이터 형은 참조에 의한 전달이어야 한다. 아울러, 모든 가변길이 데이터 형은 정확히 4바이트의 길이를 나타내는 필드로 시작되어야 하며, 해당 데이터 형에 저장될 모든 데이터는 길이표시 필드 바로 다음의 메모리 위치상에 오도록 해야 한다. 길이 필드는 길이 필드 그 자체의 길이를 포함한, 구조체 길이의 합계이다. 'text' 데이터 형을 다음과 같이 정의할 수 있다. typedef struct { int4 length; char data[1]; } text; 사실, data 필드는 가능한 모든 문자열을 저장하기에는 충분하지 않다 -- C 에서도 이러한 충분한 구조체를 선언하는 것은 불가능하다. 가변길이 데이터 형을 처리할 때는, 적절한 양의 메모리를 할당하고 길이 필드를 초기화해야 한다는 점에 유의 해야 한다. 예를 들어, text 구조체에 40바이트를 저장하려 할 경우, 다음과 같은 형태를 띄게 될 것이다. #include "postgres.h" #include "utils/palloc.h" ... char buffer[40]; /* our source data */ ... text *destination = (text *)palloc(VARHDRSZ + 40); destination->length = VARHDRSZ + 40; memmove(destination->data, buffer, 40); ... 지금까지 기본형에서 사용가능한 구조를 모두 살펴보았다. 이제 실제 함수의 예를 조금 살펴보도록 하자. C-code/funcs.c 의 내용은 다음과 같다. #include #include "postgres.h" /* for char16, etc. */ #include "utils/palloc.h" /* for palloc */ int add_one(int arg) { return(arg + 1); } char16 * concat16(char16 *arg1, char16 *arg2) { char16 *new_c16 = (char16 *) palloc(sizeof(char16)); memset((void *) new_c16, 0, sizeof(char16)); (void) strncpy(new_c16, arg1, 16); return (char16 *)(strncat(new_c16, arg2, 16)); } text * copytext(text *t) { /* * VARSIZE is the total size of the struct in bytes. */ text *new_t = (text *) palloc(VARSIZE(t)); memset(new_t, 0, VARSIZE(t)); VARSIZE(new_t) = VARSIZE(t); /* * VARDATA is a pointer to the data region of the struct. */ memcpy((void *) VARDATA(new_t), /* destination */ (void *) VARDATA(t), /* source */ VARSIZE(t)-VARHDRSZ); /* how many bytes */ return (new_t); } OSF/1 시스템 상에서는 다음과 같이 타이핑할 수 있다. CREATE FUNCTION add_one(int4) RETURNS int4 AS '/usr/local/postgres95/tutorial/obj/funcs.so' LANGUAGE 'c'; CREATE FUNCTION concat16(char16, char16) RETURNS char16 AS '/usr/local/postgres95/tutorial/obj/funcs.so' LANGUAGE 'c'; CREATE FUNCTION copytext(text) RETURNS text AS '/usr/local/postgres95/tutorial/obj/funcs.so' LANGUAGE 'c'; 다른 시스템에서는, 그것이 공유 라이브러리라는 것을 나타내기 위해 아마도 파일이름의 끝이 .sl 이 되도록 해야 할 것이다 7.2.2 복합형 프로그래밍 언어 함수 복합형은 C 의 구조체처럼 고정되어 있지는 않다. 복합형의 인스턴스는 널 필드 를 포함할 수 있다. 아울러, 계층적으로 상속된 복합형은 계층적으로 같은 상속을 받은 다른 멤버와는 다른 필드를 가질 수 있다. 따라서, POSTGRES 는 C 로부터 엑세스 하는 복합형 필드를 위해 프로시져 인터페이스를 제공한다. POSTGRES 가 인스턴스의 집합을 처리하는 것처럼, 각각의 인스턴스는 불투명한 TUPLE 형 구조체로 함수에 넘겨질 것이다. 어떠한 질의를 처리하기 위해 함수를 사용하려 한다고 가정해보자. SELECT name, c_overpaid(EMP, 1500) AS overpaid FROM EMP WHERE name = 'Bill' or name = 'Sam'; 위의 질의에 나오는 c_overpaid 는 다음과 같이 정의할 수 있다. #include "postgres.h" /* for char16, etc. */ #include "libpq-fe.h" /* for TUPLE */ bool c_overpaid(TUPLE t, /* the current instance of EMP */ int4 limit) { bool isnull = false; int4 salary; salary = (int4) GetAttributeByName(t, "salary", &isnull); if (isnull) return (false); return (salary > limit); } GetAttributeByName 은 POSTGRES 시스템 함수로서 현재 인스턴스의 속성을 반환한 다. 여기에는 세개의 매개인자가 있는 데, 그각각은 함수로 넘겨진 TUPLE 형 매개인자, 얻기를 바라는 속성의 이름, 해당 속성이 널인지를 나타내는 반환값을 저장하는 매개인자이다. GetAttributeByName 은 아마도 데이터를 정렬할 것이기에 반환값을 원하는 형으로 변환 할 수 있다. 예를 들면, char16 형인 속성 name 이 있다면, GetAttributeByName 호출은 다음과 같을 것이다. char *str; ... str = (char *) GetAttributeByName(t, "name", &isnull) 다음의 질의는 POSTGRES 에게 c_overpaid 함수를 인식시키기 위한 것이다. CREATE FUNCTION c_overpaid(EMP, int4) RETURNS bool AS '/usr/local/postgres95/tutorial/obj/funcs.so' LANGUAGE 'c'; C 함수내부에서부터 새로운 인스턴스를 생성하거나 존재하는 인스턴스를 변경할 수도 있지만, 이 메뉴얼에서 논의하기에는 너무 복잡하다. 7.3 몇가지 주의사항 이제 좀 더 까다로운 프로그래밍 언어 함수를 작성하는 임무로 돌아와보자. 경고하지만 이 내용은 여러분을 프로그래머로 만들기 위한 것이 아니다. 여러분들 은 POSTGRES 로 실제로 사용할 함수를 C 로 작성하려고 하기에 앞서 C (포인터의 사용, malloc 메모리 관리 등을 포함)를 제대로 이해하고 있어야 한다. C 가 아닌 다른 프로그래밍 언어를 사용하여 작성한 함수를 POSTGRES 로 적재할 수 있긴 하지만, 이 작업은 종종 까다롭다. 왜냐하면 포트란이나 파스칼과 같은 다른 언어는 종종 "호출 관습" 이 C 와는 다르기 때문이다. 이점은, 다른 언어는 같은 방법으로 함수사이에 매개인자를 전달하거나 값을 반환할 수 없다는 것이다. 이러한 이유로, 여러분의 프로그래밍 언어 함수는 C 로 작성되었다고 가정한다. C 로 함수를 작성할 때의 기본적인 규칙은 다음과 같다. (1) POSTGRES 에 있어서 대부분의 헤더파일은 /usr/local/postgres95/include 에 설치되어 있어야 한다(그림 2에서 보듯이). cc 명령행에서 -I/usr/local/postgres95/include 를 명시하여 헤더파일을 항상 포함하여야 한다. 가끔, 당신이 찾는 헤더파일이 서버 소스 중에 있을 수도 있다 (우리가 게을러서 설치에 빠뜨린 헤더파일은 여러분들이 직접 include 에 설치할 필요성이 있다). 이러한 경우에 다음 중 하나이상을 추가할 수도 있다. -I/usr/local/postgres95/src/backend -I/usr/local/postgres95/src/backend/include -I/usr/local/postgres95/src/backend/port/ -I/usr/local/postgres95/src/backend/obj (여기에서 은 alpha 나 sparc 와 같은 포트 명칭이다. ) (2) 메모리 할당을 할 때, C 라이브러리의 malloc 와 free 루틴 대신 POSTGRES 의 palloc 와 pfree 루틴을 사용한다. palloc 에 의해 할당된 메모리는 매개 트랜 잭션의 끝부분에서 자동적으로 메모리를 자유롭게 하며, 메모리 유출을 막는다. (3) 해당 구조체는 항상 memset 또는 bzero 를 사용하여 0으로 초기화하는 것이 좋 다. (해쉬 엑세스 메쏘드, 해쉬 결합, 정렬 알고리즘 등과 같은) 여러 루틴은 구조체에 있는 로우(raw) 비트의 작용을 추정한다. 구조체의 필드를 모 두 초기화한다 할지라도, 쓰레기 값을 포함하는, 정렬시에 발생하는 채워넣기 (구조체에서의 홀)바이트가 있을 수 있다. (4) 대개의 내장 POSTGRES 데이터 형은 postgres.h 에 포함되어 선언되어 있으므로, 보통 이 파일을 포함하는 것이 좋다. (5) POSTGRES 에 동적으로 적재할 목적코드를 컴파일하고 적재할 시에는특별한 플래그를 필요로한다. 특정한 운영체제 상에서 이러한 작업을 하는 방법에 대 한 자세한 정보는 부록 A 를 참조하라. #63 한동훈 (ddoch ) [번역] postgres 1.0 메뉴얼 (8) 08/17 17:39 109 line 8. 확장 SQL : 형 (Type) 앞에서 살펴보았지만, POSTGRES 에는 두 종류의 데이터 형이 있다. 기본(base)형 (프로그래밍 언어에 정의되어 있는 형)과 복합(composite)형(인스턴스)가 있다. 여기에 나오는 예제들은 complex.sql 과 complex.c 에 나와있다. 복합 예제는 funcs.sql 에 나와있다. 8.1 사용자 정의 형 8.1.1 사용자 정의 형에 필요한 함수 사용자 정의 형은 반드시 input, output 함수를 가지고 있어야 한다. 이러한 함수 는 형이 (사용자가 입력하고 사용자에게 출력되는)문자열에 어떻게 나타나는 지와 해당 형이 메모리에 어떻게 편재되는지를 검사한다. 입력함수는 널로 끝나는 문자 열을 입력으로 받아들여서 해당 형의 내부적인 표현을 반환한다. 출력함수는 해당 형의 내부적인 표현을 받아들여서 널로 끝나는 문자열을 반환한다. 복합 숫자를 표현하는 complex 데이터 형을 정의해보자. 이 복합형을 메모리에 표 현하기 위해 자연스럽게 다음의 C 구조체를 선택할 것이다. typedef struct Complex { double x; double y; } Complex; (x,y) 형태의 문자열은 외부적인 문자열로 표현된다. 이러한함수는 보통 작성하기가 쉬우며, 특히 출력함수는 더 쉽다. 그러나, 여기에서 기억해야 할 몇가지 사항이 있다. (1) 외부적인 (문자열) 표현을 정의할 때, 최종적으로 입력함수가 해당 표현을 잘 받아들이는 완벽하고 튼튼한 분석기가 되도록 해야 한다는 점을 기억하자! Complex * complex_in(char *str) { double x, y; Complex *result; if (sscanf(str, " ( %1f , %1f )", &x, &y) != 2) { elog(WARN, "complex_in: error in parsing \"%s\"", str); return NULL; } result = (Complex *) palloc(sizeof(Complex)); result->x = x; result->y = y; return (result); } 출력함수는 더욱 간단하게 만들 수 있다. char * complex_out(Complex *complex) { char *result; if (complex == NULL) return(NULL); result = (char *) palloc(60); sprintf(result, "(%g,%g)", complex->x, complex->y); return(result); } (2) 입력, 출력 함수를 만들 때 서로 역으로 만들어 보는 것을 시도해보아야 한다. 만일 이렇게 하지 않을 경우에는, 해당 데이터를 파일에 덤프하거나 (다른 시 스템상의 어떤 다른 데이터베이스로) 거꾸로 읽어들일 때 여러가지 문제가 발 생할 것이다. 특히 부동 소수점을 포함할 때 공통적인 문제로 나타난다. complex 형을 만들려면, 해당 형을 만들기 이전에 complex_in 과 complex_out 의 두가지 사용자 정의 함수를 만들어야 한다. CREATE FUNCTION complex_in(opaque) RETURNS complex AS '/usr/local/postgres95/tutorial/obj/complex.so' LANGUAGE 'c'; CREATE FUNCTION complex_out(opaque) RETURNS opaque AS '/usr/local/postgres95/tutorial/obj/complex.so' LANGUAGE 'c'; CREATE TYPE complex ( internallength = 16, input = complex_in, output = complex_out ); 앞에서도 말했지만, POSTGRES 는 기본형의 배열을 풍족하게 제공한다. 아울러, POSTGRES 는 사용자 정의 형의 배열도 잘 제공한다. 형을 정의할 때, POSTGRES 는 자동적으로 해당 형의 배열을 제공한다. 전통적으로, 배열형의 이름은 사용자 정의 형의 명칭앞에 밑줄 문자 '_' 가 앞에 위치하는 형태가 된다. 복합형은 어떠한 함수도 필요하지 않다. 시스템은 이미 이들 내부를 이해하기 때문 이다. 8.1.2 대형 객체 지금까지 논의한 형은 모두 "소형(small)" 객체이며 8KB (주7) 보다 작은 것들이다. 문서화 시스템이나 비트맵 저장 시스템과 같은 대형 형이 필요하다면, POSTGRES 대형객체 (large object) 인터페이스를 사용할 필요가 있을 것이다. 주7) 8 * 1024 는 8192 바이트이다. POSTGRES 의 tuple 과 페이지 오버헤드는 이 러한 8KB 한계에 적합해야 하기 때문에 실제로 하나의 형은 8192 바이트보다 작게 고려되어야 한다. 이에 적합한 실제 값은 해당 기계의 아키텍쳐에 의존 적이다. #64 한동훈 (ddoch ) [번역] postgres 1.0 메뉴얼 (9,10) 08/17 19:57 112 line 9. 확장 SQL : 연산자 POSTGRES 는 왼쪽, 오른쪽 단일 연산자와 바이너리 연산자를 제공한다. 연산자는 서로 다른 숫자나 형의 매개인자에 과중 적재되거나 재사용될 수 있다. 연산자가 애매한 위치에 있다면 시스템은 올바른 연산자를 결정할 수 없으 며, 에러를 반환한다. 이러한 경우에, 어느 연산자를 사용할 것인지 이해를 돕 기 위해 왼쪽/오른쪽 피연산자를 형변환 할 수 있다. 두개의 complex 멤버를 더하는 연산자를 만드려면 아래와 같이 하면 된다. 먼저 새로운 형에 필요한 함수를 만들어야 한다. 그리고 나서, 해당 연산자를 이들 함 수와 함께 만들면 된다. CREATE FUNCTION complex_add(complex, complex) RETURNS complex AS '$PWD/obj/complex.so' LANGUAGE 'c'; CREATE OPERATOR + ( leftarg = complex, rightarg = complex, procedure = complex_add, commutator = + ); 여기에서 바이너리 오퍼레이터를 만드는 방법을 볼 수 있을 것이다. 단일 오퍼레 이터를 만들려면 leftarg(왼쪽 단일 오퍼레이터) 나 rightarg(오른쪽 단일 오퍼레이 터)중 하나를 생략하면 된다. 시스템에 해당 형에 대한 충분한 정보를 제공한다면, 시스템은 어떠한 오퍼레이터를 사용하는 것이 적당한지 자동적으로 생각해 낼 수 있다. SELECT (a + b) AS c FROM test_complex; c --------------- (5.2,6.05) (133.42,144.95) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 10. 확장 SQL : 전체 (Aggregates) POSTGRES 의 Aggregates 는 상태 변환 함수(state transition functions)라는 관점 으로 표현된다. Aggregate 는 하나의 인스턴스가 처리될 때마다 변경되는 상태 (state)라는 관점으로 정의될 수 있다. 어떤 상태 함수는 인스턴스에서 새로운 상 태를 계산할 때 특정한 값을 찾고(create aggregate 문법에서 sfunc1), 다른 상태 함수는 자신의 내부적인 상태의 자취를 유지만 한다(sfunc2). aggregate 가 sfunc1 만 사용한다면, 각각의 인스턴스에서 속성값상에서 실행되는 함수로 정의할 수 있다. "Sum" 은 이러한 종류의 aggregate 의 예이다. "Sum" 은 처음에는 0의 값을 가지고, 계속 현재의 인스턴스의 값을 합계로 더한다. 잠시뒤에 int4pl 을 사용하여 POSTGRES 가 이러한 덧셈을 수행하도록 할 것이다. CREATE AGGREGATE complex_sum ( sfunc1 = complex_add, basetype = complex, stype1 = complex, initcond1 = '(0,0)' ); SELECT complex_sum(a) FROM test_complex; complex_sum ----------- (34,53.9) sfunc2 만 정의한다면, 각각의 인스턴스에서 속성값과는 독립적으로 수행되는 함수 로 지정할 수 있다. "Count" 는 이러한 aggregate 종류의 대표적인 경우이다. "Count" 는 0에서 시작되고, 각각의 인스턴스마다 합계에 1이 더해지며 인스턴스의 값은 무시된다. 여기서는 POSTGRES 내장 루틴인 int4inc 를 사용한다. 이 루틴은 해당 인자의 값을 하나 증가시킨다. CREATE AGGREGATE my_count (sfunc2 = int4inc, -- add one basetype = int4, stype2 = int4, initcond2 = '0' ); SELECT my_count(*) as emp_count from EMP; emp_count --------- 4 "Average" 는 합계와 횟수, 둘다 계산하는 함수를 필요로 하는 aggregate 의 예이 다. 모든 인스턴스가 처리되고 나면, aggregate 에서 마지막 응답으로 합계를 횟 수로 나눈다. 이전에 사용했던 int4pl 과 int4inc 와 마찬가지로 int4div 는 POSTGRES 의 정수 나눗셈 루틴이며, 합계를 횟수로 나눈 결과를 계산한다. CREATE AGGREGATE my_average (sfunc1 = int4pl, -- sum basetype = int4, stype1 = int4, sfunc2 = int4inc, -- count stype2 = int4, finalfunc = int4div, -- division initcond1 = '0', initcond1 = '0' ); SELECT my_average(salary) as emp_average FROM EMP; emp_average ------------ 1640