Contents

9.1 릴리스 노트

릴리스 노트 정보

본 문서는 CUBRID 9.1(빌드번호 9.1.0.0212)에 관한 정보를 포함한다. CUBRID 9.1은 CUBRID 9.0 Beta에서 발견된 오류 수정 및 기능 개선과 이전 버전들에 반영된 모든 오류 수정 및 기능 개선을 포함한다.

CUBRID 9.0 Beta에 대한 정보는 9.0 릴리스 노트 에서, CUBRID 2008 R4.3에 대한 정보는 http://release.cubrid.org/ko에서 확인할 수 있다.

릴리스 특징

CUBRID 9.1은 CUBRID 9.0 Beta의 안정화 버전 및 업그레이드 버전이다. 9.0 Beta 버전에서 발견된 이슈들을 수정하여 안정화 시켰을 뿐만 아니라 CUBRID 9.1은 질의 수행에 관련된 다양한 기능들을 추가하였으며, 질의 처리 성능이 향상되었고 질의 최적화가 개선되었다. 다국어 관련 기능들을 강화하였으며, 운영 도구를 개선했다.

CUBRID 9.1은 CUBRID 9.0 Beta와 데이터베이스 볼륨이 호환되지 않으므로, CUBRID 9.0 Beta 및 이전 버전 사용자는 반드시 데이터베이스를 마이그레이션해야 한다. 이와 관련하여 업그레이드 절을 참고한다.

SQL 함수 추가 및 인덱스 힌트 확장

  • NTILE, WIDTH_BUCKET, LEAD, LAG 함수를 추가했다.
  • TRUNC, ROUND 함수에 날짜 타입을 인자를 사용할 수 있도록 확장했다.
  • 새로운 인덱스 힌트 지정 구문을 지원한다.
  • Multi UPDATE, DELETE 문에 SQL 힌트를 사용할 수 있도록 확장했다.
  • MERGE 문에 인덱스 힌트를 명시할 수 있도록 확장했다.

성능 및 최적화 개선

  • HA 복제 반영 성능을 크게 개선하였다.
  • 다중 키 범위 최적화를 대폭 개선하였다.
  • ORDER BY 절 최적화 및 GROUP BY 절 최적화를 더욱 개선하였다.
  • 분석 함수 성능을 향상시켰다.
  • INSERT ON DUPLICATE KEY UPDATE 문과 REPLACE 문의 성능을 개선하였다.
  • 중복 키가 많은 인덱스에 대한 탐색 및 삭제 성능을 개선했다.
  • 입력 삭제가 반복될 때 삭제 성능을 개선했다.

다국어 관련 기능 추가 및 안정화

  • 테이블에 대한 콜레이션을 지원한다.
  • SHOW COLLATION 문 및 CHARSET, COLLATION, COERCIBILITY 함수를 추가했다.
  • 확장이 있는 콜레이션에서 액센트에 따라 역순으로 프랑스어를 정렬하는 콜레이션을 지원한다.
  • 9.0 베타 버전의 다국어 관련 제약 사항과 이슈들을 수정, 개선하였다.

Sharding 기능 개선

  • Shard key에 해당하는 shard ID를 확인할 수 있도록 하는 명령을 추가했다.
  • Windows에서 Sharding 기능을 사용할 수 있게 되었다.

운영 도구 개선

  • applyinfo 유틸리티로 복제 로그 반영 상태를 출력할 때 복제 지연 상태를 출력하도록 개선했다.
  • killtran 유틸리티에 각 트랜잭션마다 질의의 수행 상태를 출력하는 기능을 추가했다.
  • killtran 유틸리티에 특정 SQL을 수행하는 트랜잭션을 지정하여 트랜잭션을 제거하는 기능을 추가했다.
  • 질의 수행이 지정한 시간을 초과하면 서버 에러 로그 및 CAS 로그 파일에 질의 실행 정보를 기록하게 하는 기능을 추가했다.

동작 변경

  • CUBRID_LANG 환경 변수가 제거되었고, 데이터베이스 문자셋을 설정하는 CUBRID_CHARSET 환경 변수 및 유틸리티 메시지 및 오류 메시지에 대한 문자셋을 설정하는 CUBRID_MSG_LANG 환경 변수가 추가되었다.
  • cci_execute_array 함수, cci_execute_batch 함수, JDBC의 Statement.executeBatch 메서드, PreparedStatement.executeBatch 메서드 등 배열 내 여러 개의 질의문을 일괄적으로 처리할 때 모든 질의문을 수행한 이후에 커밋했으나 각 질의문을 수행할 때마다 커밋하도록 변경되었다.
  • cci_execute_array 함수, cci_execute_batch 함수 또는 cci_execute_result 함수에서 여러 개의 질의 수행 도중 에러 발생 시 동작 방식이 바뀌었다. 수정 이전에는 중간에 에러가 발생하면 해당 함수가 에러를 반환하고 종료했으나, 수정 이후에는 질의를 끝까지 수행하고 CCI_QUERY_RESULT_* 매크로들을 통해 개별 질의에 대한 에러를 확인할 수 있게 변경되었다.
  • 브로커 파라미터 KEEP_CONNECTION에서 OFF 값 설정이 제거되었다.
  • 브로커 파라미터 SELECT_AUTO_COMMIT 파라미터가 제거되었다.
  • 브로커 파라미터 APPL_SERVER_MAX_SIZE_HARD_LIMIT의 값의 범위가 1과 2,097,151 사이의 값으로 제한되었다.
  • SQL 로그 파일 크기를 지정하는 브로커 파라미터의 기본 설정값이 100MB에서 10MB로 변경되었다.
  • call_stack_dump_activation_list 파라미터의 동작 방식이 변경되었다.

드라이버 호환성

  • 9.1 버전의 JDBC와 CCI 드라이버는 CUBRID 9.0 Beta와 CUBRID 2008 R4.x 버전과 연동된다.

수많은 개선 및 수정

  • 기존 버전에 존재했던 중대한 안정성 이슈들을 다수 수정하였다.
  • 그 외에 안정성, SQL, 분할, HA, Sharding, 유틸리티, 드라이버 등 여러 부분에서 수많은 이슈들을 개선, 수정했다.

보다 자세한 변경 사항은 아래의 내용을 참고하며, 이전 버전 사용자는 동작 변경 절과 신규 주의 사항 절을 반드시 확인하도록 한다.

기능 추가

SQL

WIDTH_BUCKET 함수(CUBRIDSUS-4209)

WIDTH_BUCKET 함수는 범위를 개수로 균등 분할하여 각 버킷마다 순차적으로 번호를 부여해준다. 즉, WIDTH_BUCKET 함수는 equiwidth histogram을 생성한다. 범위는 최소값과 최대값으로 부여하며, 해당 범위를 균등 분할하여 버킷 번호를 순차적으로 1부터 할당한다.

다음은 8명의 고객을 생년월일을 기준으로 '1950-01-01'부터 '1999-12-31'까지의 범위를 5개로 균등 분할하는 예이다. 범위를 벗어나면 0 또는 최대 버킷 번호+1을 리턴한다.

SELECT name, birthdate, WIDTH_BUCKET (birthdate, date'1950-01-01', date'2000-1-1', 5) age_group
FROM t_customer
ORDER BY birthdate;
  name                  birthdate     age_group
===============================================
  'James'               12/28/1948            0
  'Amie'                03/18/1978            4
  'Tom'                 07/28/1980            4
  'Jane'                05/12/1983            5
  'David'               07/28/1986            5
  'Lora'                03/26/1987            5
  'Peter'               10/25/1988            5
  'Ralph'               03/17/1995            6

NTILE 분석 함수(CUBRIDSUS-9688)

NTILE 분석 함수는 값을 균등 분할하여 각 버킷마다 순차적으로 번호를 부여해준다. 즉, NTILE 함수는 equiheight histogram을 생성해준다.

다음은 8명의 고객을 생년월일을 기준으로 5개의 버킷으로 행의 개수를 균등 분할하는 예이다. 1, 2, 3번 버킷에는 2개의 행이, 4,5번 버킷에는 1개의 행이 존재한다.

SELECT name, birthdate, NTILE (5) OVER (ORDER BY birthdate) age_group
FROM t_customer;
  name                  birthdate     age_group
===============================================
  'James'               12/28/1948            1
  'Amie'                03/18/1978            1
  'Tom'                 07/28/1980            2
  'Jane'                05/12/1983            2
  'David'               07/28/1986            3
  'Lora'                03/26/1987            3
  'Peter'               10/25/1988            4
  'Ralph'               03/17/1995            5

LEAD와 LAG 분석 함수(CUBRIDSUS-9414)

한 행 내에서 다음 행과 이전 행의 칼럼 정보를 가져올 수 있는 LEAD, LAG 분석 함수를 추가했다.

다음은 사번 순으로 정렬하여 같은 행에 다음 사번을 같이 출력하는 예이다.

CREATE TABLE t_emp (name VARCHAR (10), empno INTEGER);
INSERT INTO t_emp VALUES
('Amie', 11011), ('Jane', 13077), ('Lora', 12045), ('James', 12006),
('Peter', 14006), ('Tom', 12786), ('Ralph', 23518), ('David', 55);

SELECT name, empno, LEAD (empno, 1) OVER (ORDER BY empno) next_empno
FROM t_emp
ORDER BY 2;
  name                        empno   next_empno
================================================
  'David'                        55        11011
  'Amie'                      11011        12006
  'James'                     12006        12045
  'Lora'                      12045        12786
  'Tom'                       12786        13077
  'Jane'                      13077        14006
  'Peter'                     14006        23518
  'Ralph'                     23518         NULL

다음은 사번 순으로 정렬하여 같은 행에 이전 사번을 같이 출력하는 예이다.

SELECT name, empno, LAG (empno, 1) OVER (ORDER BY empno) prev_empno
FROM t_emp
ORDER BY 2;
  name                        empno   prev_empno
================================================
  'David'                        55         NULL
  'Amie'                      11011           55
  'James'                     12006        11011
  'Lora'                      12045        12006
  'Tom'                       12786        12045
  'Jane'                      13077        12786
  'Peter'                     14006        13077
  'Ralph'                     23518        14006

TRUNC 함수에 DATE, DATETIME, TIMESTAMP 타입을 인자로 사용할 수 있도록 확장(CUBRIDSUS-9413)

TRUNC 함수에 DATE, DATETIME, TIMESTAMP 타입을 입력하면 지정한 단위 미만을 절삭하여 반환하도록 확장했다.

SELECT TRUNC (TO_DATE ('2012-10-26'), 'YYYY') d;
  d
============
 01/01/2012

ROUND 함수에 DATE, DATETIME, TIMESTAMP 타입을 인자로 사용할 수 있도록 확장(CUBRIDSUS-9488)

ROUND 함수에 DATE, DATETIME, TIMESTAMP 타입을 입력하면 지정한 단위 미만을 반올림(rounding)하도록 확장했다.

SELECT ROUND (datetime'2012-10-21 10:20:30', 'yyyy') d;
  d
============
 01/01/2013

새로운 인덱스 힌트 지정 구문 지원(CUBRIDSUS-6675)

기존의 USING INDEX 절 이외에 USE INDEX, FORCE INDEX, IGNORE INDEX 절과 같은 새로운 인덱스 힌트 지정 구문을 지원한다.

SELECT * FROM tbl USE INDEX (idx1), IGNORE INDEX (idx2) WHERE col1 < 4;

또한, IGNORE INDEX 힌트와 같은 기능을 하는 "USING INDEX index_name(-)" 구문을 지원한다.

SELECT * FROM tbl  WHERE col1 < 4 USING INDEX idx1(-);

UPDATE JOIN, DELETE JOIN 문에 SQL 힌트 지정할 수 있도록 확장(CUBRIDSUS-9491)

UPDATE JOIN, DELETE JOIN 문에 대해 ORDERED, USE_DESC_IDX, NO_COVERING_INDEX, NO_DESC_IDX, USE_NL, USE_IDX, USE_MERGE, NO_MULTI_RANGE_OPT, RECOMPILE과 같은 SQL 힌트를 사용할 수 있도록 개선했다.

MERGE 문에 인덱스 힌트 지원(CUBRIDSUS-10134)

MERGE 문에 USE_UPDATE_IDX, USE_INSERT_IDX 인덱스 힌트를 지원한다. USE_UPDATE_IDX 힌트는 UPDATE 절을 수행할 때 ON 절과 UPDATE 절의 WHERE 절에 적용되며, USE_INSERT_IDX 힌트는 INSERT 절을 수행할 때 ON 절에 적용된다.

MERGE /*+ USE_UPDATE_IDX(i_s_ij) USE_INSERT_IDX(i_t_ij, i_t_i) */
INTO target t USING source s ON t.i=s.i
WHEN MATCHED THEN UPDATE SET t.j=s.j WHERE s.i <> 1
WHEN NOT MATCHED THEN INSERT VALUES(i,j);

INSERT 문의 VALUES와 SET 절에서 이전에 지정된 칼럼을 참조할 수 있도록 확장(CUBRIDSUS-3112)

INSERT 문의 VALUES와 SET 절에서 이전에 지정된 칼럼을 참조할 수 있도록 수정했다. 예를 들어, b = a + 1와 같은 할당 표현식 평가 시에 앞쪽에서 지정된 a 칼럼의 값을 참조할 수 있다.

CREATE TABLE tbl (a INT, b INT);
INSERT INTO tbl SET a = 0, b = a + 1;
INSERT INTO tbl VALUES (0, a + 1);

위의 예에서 수정 이전 버전은 b의 값을 평가할 수 없으나, 수정 이후에는 a의 값(0)을 참조하여 b의 값을 1로 평가한다.

할당 표현식에 대한 평가는 왼쪽에서 오른쪽으로 수행된다. 칼럼 값이 정해지지 않았으면 기본값을 할당하고, 기본값이 없으면 NULL을 할당한다.

다국어

SHOW COLLATION 문 및 CHARSET, COLLATION, COERCIBILITY 함수 지원(CUBRIDSUS-9404)

콜레이션 정보를 출력하는 SHOW COLLATION 문을 추가했다. 또한 각각 지정한 문자열의 문자셋, 콜레이션, 콜레이션 변환도를 반환하는 CHARSET 함수, COLLATION 함수, COERCIBILITY 함수를 추가했다.

테이블에 대한 콜레이션 지원(CUBRIDSUS-9403)

9.0 베타 버전에서는 컬럼에 대한 콜레이션만을 지정할 수 있었으나, 9.1 버전부터 테이블에 대한 콜레이션을 지정할 수 있다.

CREATE TABLE address_book (id INTEGER, name STRING, address1 STRING, address2 STRING) COLLATE utf8_en_cs;

데이터베이스 콜레이션을 시스템 콜레이션에 맞게 변경하는 synccolldb 유틸리티 제공(CUBRIDSUS-9495)

데이터베이스 콜레이션(시스템 카탈로그 테이블에 정의된 콜레이션)을 시스템 콜레이션($CUBRID/conf/cubrid_locales.txt에 정의된 콜레이션)에 맞게 변경하는 유틸리티를 제공한다.

% cubrid synccolldb testdb

이와 함께, 로캘 라이브러리를 생성하는 스크립트(Linux에서는 make_locale.sh, Windows에서는 make_locale.bat) 실행 이후 기존에 생성된 데이터베이스의 콜레이션과 로캘 라이브러리의 콜레이션을 동기화하도록 cubrid synccolldb 유틸리티 실행을 요구하는 메시지를 출력하도록 수정했다.

To check compatibility and synchronize your existing databases, run:
    cubrid synccolldb <database-name>

cubrid synccolldb 유틸리티는 시스템 카탈로그 테이블에 정의된 콜레이션을 변경시킬 뿐 일반 테이블의 콜레이션과 데이터의 문자셋을 변경하는 것은 아니다.

역순 액센트에 따라 정렬하는 콜레이션 지원(CUBRIDSUS-9407)

역순 액센트에 따라 캐나다 프랑스어를 정렬하는 확장 콜레이션(utf8_fr_exp_ab)을 지원한다. 역순 액센트에 따른 캐나다 프랑스어 정렬(Canadian French sorting by backward accents)이란 문자열 뒤에 액센트가 오는 순서를 기준으로 정렬하는 것을 의미하며, 가중치가 문자열의 끝에서부터 확인된다.

Normal Accent Ordering : cote < coté < côte < côté
Backward Accent Ordering : cote < côte < coté < côté

Sharding

Shard key로 해당 shard ID 값을 얻는 'cubrid shard getid' 명령 추가(CUBRIDSUS-9547)

Shard key로 해당 shard id를 얻는 명령을 추가했다.

다음은 shard1이라는 shard proxy에서 shard key 1에 대한 shard ID 정보를 출력하는 명령이다.

% cubrid shard getid -b shard1 1

-f 옵션을 통해 shard id에 대한 전체 정보를 출력할 수 있다.

% cubrid shard getid -b shard1 -f 1

Windows 버전에서 SHARD 기능 지원(CUBRISUS-9549)

Windows 버전에서 SHARD 기능을 지원한다. SHARD 기능을 이용하기 위해서는 9.1 버전의 드라이버를 사용해야한다.

드라이버

[JDBC][CCI] 로드 밸런싱 기능 추가(CUBRIDSUS-8675)

CCI, JDBC의 연결 URL에 altHosts를 포함하는 경우 응용 프로그램이 메인 호스트와 altHosts에 지정한 호스트들에 임의의 순서로 연결되게 하는 기능을 추가했다. 아래의 예와 같이 연결 URL의 loadBalance의 값을 true로 설정하는 경우 해당 기능이 동작된다.

jdbc:cubrid:host1:port1:demodb:::?altHosts=host2:port2,host3:port3&loadBalance=true

[CCI] cci_close_query_result() 함수 추가(CUBRIDSUS-9269)

resultset과 statement를 각각 종료(close)하는 메서드를 제공하는 JDBC 드라이버와 달리, CCI 드라이버는 이 둘을 모두 종료하는 cci_close_req_handle 함수만 제공했으나, resultset을 종료하는 cci_close_query_result 함수를 추가했다. 새로운 함수를 호출하지 않으면 statement를 종료할 때까지 resultset의 메모리를 유지하므로 메모리 사용량이 증가하는 현상이 발생할 수 있다.

수정 이후 버전에서도 cci_close_query_result 함수 호출 없이 cci_close_req_handle 함수를 호출하면 이전 버전과 마찬가지로 resultset과 statement를 모두 종료한다.

설정

check_peer_alive 시스템 파라미터(CUBRIDSUS-9308)

데이터베이스 서버 프로세스(cub_server)와 이에 접속하는 클라이언트 프로세스가 정상 동작하는지 서로 확인하는 과정의 수행 여부를 설정할 수 있도록 check_peer_alive 시스템 파라미터를 추가했다. 클라이언트 프로세스에는 브로커 응용 서버(cub_cas) 프로세스, 복제 로그 반영 프로세스(copylogdb), 복제 로그 복사 프로세스(applylogdb), CSQL 인터프리터(csql) 등이 있다.

서버 프로세스와 클라이언트 프로세스는 접속이 이루어진 후 네트워크를 통해 데이터를 기다리는 중 오랫동안(예: 5초 이상) 응답을 받지 못하면 설정에 따라 상대방이 정상 동작하는지 확인하는 과정을 거친다. 서로 확인하는 과정에서 정상 동작하지 않는다고 판단되면 연결된 접속을 강제 종료한다.

ECHO(7) 포트가 방화벽(firewall) 설정으로 막혀있으면 서버 프로세스 또는 클라이언트 프로세스가 각각 서로의 상태를 확인할 때 상대방 프로세스가 종료된 것으로 오인할 수 있으므로, 이 파라미터를 none으로 설정하여 이 문제를 회피해야 한다.

ENABLE_MONITOR_HANG 브로커 파라미터(CUBRIDSUS-7558)

일정 비율 이상의 CAS가 멈춘(hang) 것으로 판단되면 해당 브로커로의 접속을 차단하는 기능을 추가했다. 이 기능은 ENABLE_MONITOR_HANG 파라미터를 ON으로 설정할 때 동작한다.

브로커 프로세스는 CAS의 멈춤(hang)이 1분 이상 지속되는 경우 CAS를 멈춘(hang) 상태로 판단하고, 해당 CAS의 개수에 따라 해당 브로커 프로세스가 비정상으로 판단되면 정상화되기 전까지 해당 브로커로 접속을 시도하는 응용 프로그램을 차단하여, 접속 URL에 설정한 대체 호스트(altHosts)로의 접속을 유도한다.

운영 도구

복제 지연 정보를 출력하도록 개선(CUBRIDSUS-9525)

HA 환경에서 cubrid applyinfo 명령으로 트랜잭션 로그 복사와 트랜잭션 로그 반영 정보 출력 시 복제 지연 정보를 출력하도록 개선했다. 다음은 복제 지연 정보를 출력하는 예이다.

% cubrid applyinfo -L /home/cubrid/DB/testdb_nodeA -r nodeA -a -i 3 testdb

...

*** Delay in Copying Active Log ***
Delayed log page count         : 4
Estimated Delay                : 0 second(s)

*** Delay in Applying Copied Log ***
Delayed log page count         : 1459
Estimated Delay                : 22 second(s)

tranlist 유틸리티 추가(CUBRIDSUS-9601)

데이터베이스의 트랜잭션 정보를 출력하는 cubrid tranlist 유틸리티를 추가했다. DBA 또는 DBA 그룹에 속한 사용자만 사용할 수 있다.

% cubrid tranlist -s testdb

Tran index         User name      Host name      Process id          Program name
-------------------------------------------------------------------------------------
   1(ACTIVE)         PUBLIC        myhost            1822           broker1_cub_cas_1
   2(ACTIVE)            dba        myhost            1823           broker1_cub_cas_2
   3(COMMITTED)         dba        myhost            1824           broker1_cub_cas_3
-------------------------------------------------------------------------------------

killtran 유틸리티에 질의 수행 상태를 출력하는 -q 옵션 추가(CUBRIDSUS-9588)

cubrid killtran 유틸리티에 트랜잭션의 질의 수행 상태를 출력하는 -q(--query-exec-info) 옵션을 추가했다.

% cubrid killtran -q testdb

Tran index  Process id  Program name   Query time   Tran time  Wait for lock holder        SQL ID  SQL Text
--------------------------------------------------------------------------------------------------------------------------------
  1(ACTIVE)      22982   b1_cub_cas_1        0.00       0.00                    -1                 *** empty ***
  2(ACTIVE)      22983   b1_cub_cas_2        1.80       1.80                     1  5377225ebc75a  update [ta] [ta] set [a]=5 wh
--------------------------------------------------------------------------------------------------------------------------------

질의 수행 상태에는 다음 정보를 포함한다.

  • Tran index: 트랜잭션 인덱스
  • Process id: 클라이언트 프로세스 ID
  • Program name: 클라이언트 프로그램 이름
  • Query time: 수행중인 질의의 총 수행 시간(단위: 초)
  • Tran time: 현재 트랜잭션의 총 수행 시간(단위: 초)
  • Wait for lock holder: 현재 트랜잭션이 잠금(lock) 대기중이면 해당 잠금을 소유하고 있는 트랜잭션의 리스트
  • SQL ID: SQL Text에 대한 ID
  • SQL Text: 수행중인 질의문(최대 30자)

killtran 유틸리티에 특정 SQL을 수행 중인 트랜잭션을 제거할 수 있는 옵션 추가(CUBRIDSUS-9653)

cubrid killtran 유틸리티에 SQL ID를 통해 특정 트랜잭션을 제거하는 --kill-sql-id 옵션을 추가했다.

% cubrid killtran --query-exec-info testdb

Tran index  Process id  Program name             Query time   Tran time  Wait for lock holder     SQL ID      SQL Text
--------------------------------------------------------------------------------------------------------------------------------------------
  1(ACTIVE)    26650    query_editor_cub_cas_1        0.00         0.00                    -1  *** empty ***
  2(ACTIVE)    26652    query_editor_cub_cas_3        0.00         0.00                    -1  *** empty ***
  3(ACTIVE)    26651    query_editor_cub_cas_2        0.00         0.00                    -1  *** empty ***
  4(ACTIVE)    26653    query_editor_cub_cas_4        1.80         1.80               2, 1, 3  cdcb58552e320  update [ta] [ta] set [ta].[a]=
--------------------------------------------------------------------------------------------------------------------------------------------

SQL_ID: cdcb58552e320
Tran index : 4
update [ta] [ta] set [ta].[a]= ?:1  where ([ta].[a]> ?:0 )

% cubrid killtran --kill-sql-id=cdcb58552e320 -f testdb

killtran 유틸리티에 여러 트랜잭션을 한꺼번에 종료할 수 있도록 -i 옵션 확장(CUBRIDSUS-9601)

cubrid killtran 유틸리티의 -i 옵션에 강제 종료하고자 하는 트랜잭션 ID들을 쉼표로 구분하여 입력할 수 있도록 확장하였다.

% cubrid killtran -i 1,3,8 testdb

지정한 시간을 초과하는 질의문과 질의 실행 계획 정보를 로그에 기록하게 하는 기능(CUBRIDSUS-6987)

시스템 파라미터 sql_trace_slow_msecs에 의해 지정한 시간을 초과하는 질의문의 질의 실행 계획 정보를 로그에 기록하게 하는 기능을 추가했다. 시스템 파라미터 sql_trace_execution_plan의 값이 yes이면 해당 SQL 문과 함께 질의 실행 계획, cubrid statdump 정보를 각각 서버 에러 로그 파일과 브로커 응용 서버(CAS) SQL 로그 파일에 기록하며, cubrid plandump 유틸리티를 실행하면 해당 SQL 문과 질의 실행 계획을 출력한다.

단, error_log_level 파라미터를 NOTIFICATION으로 지정한 경우에만 서버 에러 로그 파일에 해당 정보를 기록한다.

브로커 및 샤드의 실행중인 파라미터 정보를 확인하는 명령 추가(CUBRIDSUS-7771)

브로커의 실행 중인 파라미터 정보를 확인하는 "cubrid broker info", "cubrid shard info" 명령을 추가했다.

브로커 로그 변환 및 브로커 로그 실행 유틸리티 확장(CUBRIDSUS-8804)

브로커 로그 변환 유틸리티인 cubrid broker_log_converter에 질의문 앞에 질의 ID 커멘트를 출력하는 -i 옵션을 추가했다. 또한, cubrid broker_log_converter 유틸리티에 의해 변환된 출력 파일을 가지고 질의를 재수행하는 명령인 cubrid broker_log_runner 유틸리티에 질의 당 statdump 정보를 출력하는 -s, 자동 커밋 모드로 질의를 실행하게 하는 -a 옵션을 추가했다.

동작 변경

다국어

콜레이션 변환도 변경(CUBRIDSUS-10057)

높은 변환도가 낮은 변환도의 콜레이션으로 변환되는 정도를 나타내는 콜레이션 변환도(coercibility level)가 다음 표와 같이 변경되었다. 특히, 바이너리 콜레이션은 호스트 변수와 문자열 상수에 대한 LIKE 질의 시 결과가 서로 불일치되는 일이 없도록 변경되었다.

CREATE TABLE tbl (s STRING COLLATE utf8_bin);
INSERT INTO tbl VALUES ('bbb');
SET NAMES utf8 COLLATE utf8_gen_ci;

-- 아래 질의는 정상적으로 1건을 출력한다.
SELECT * FROM t WHERE s LIKE '_B_';

-- 아래 질의는 9.0 베타 버전에서 0건을 출력하였으나, 9.1에서는 정상적으로 1건을 출력한다.
PREPARE st from 'SELECT * FROM tbl WHERE s LIKE ?';
EXECUTE st USING '_B_';
콜레이션 변환도 표현식의 인자(피연산자)
0 COLLATE 수정자를 지닌 피연산자
1 칼럼이 바이너리가 아닌(non-binary) 콜레이션을 가진 경우
2 칼럼이 ISO-8859-1 문자셋을 가진 경우를 제외하고 바이너리 콜레이션을 가진 경우
3 칼럼이 바이너리 콜레이션과 ISO-8859-1 문자셋(iso88591_bin)을 가진 경우
4 SELECT 값, 표현식이 바이너리가 아닌 콜레이션을 가진 경우
5 SELECT 값, 표현식이 ISO-8859-1 문자셋을 가진 경우를 제외하고 바이너리 콜레이션을 가진 경우
6 SELECT 값, 표현식이 바이너리 콜레이션과 ISO-8859-1 문자셋(iso88591_bin)을 가진 경우
7 특수 함수들 (USER(), DATABASE(), SCHEMA(), VERSION())
8 상수 문자열이 바이너리가 아닌(non-binary) 콜레이션을 가진 경우
9 상수 문자열이 ISO-8859-1 문자셋을 가진 경우를 제외하고 바이너리 콜레이션을 가진 경우
10 상수 문자열이 바이너리 콜레이션과 ISO-8859-1 문자셋(iso88591_bin)을 가진 경우
11 호스트 변수, 사용자 정의 변수

SQL 함수에서 입력 인자가 어느 한 쪽으로 콜레이션 변환이 되지 않으면 함수가 수행되지 않도록 수정(CUBRIDSUS-9920)

IF, CASE, DECODE, FIELD 함수 등에 두 개 이상의 인자가 주어진 경우에, 어느 한 쪽으로 변환이 가능한 콜레이션이 주어진 경우에만 함수 수행이 가능하도록 변경하였다.

입력 인자의 콜레이션이 바이너리인 경우는 호환이 가능하다. 아래 예와 같이 utf8_bin 문자열과 iso88591_bin 문자열이 입력되면 utf8_bin 문자열은 iso88591_bin 문자셋으로 변환된다.

SELECT IF (1, _utf8'a', _iso88591'b') AS `if`, CHARSET (IF (1, _utf8'a', _iso88591'b')) AS `charset`;
   if                   charset
============================================
  'a'                   'iso88591'

입력 인자의 콜레이션이 바이너리가 아닌 경우는 어느 한 쪽으로 변환 가능하지 않으므로 오류가 발생된다.

SELECT * FROM t1
WHERE IF (id % 2, _utf8'a' COLLATE utf8_en_cs, _utf8'b' COLLATE utf8_en_ci) = CONCAT (a, '');
ERROR: before '  = CONCAT(a, ''); '
'if ' requires arguments with compatible collations.

바이너리가 아닌 콜레이션 문자열로 해시 분할을 허용하지 않도록 수정(CUBRIDSUS-10156)

바이너리가 아닌(non-binary) 콜레이션 문자열을 사용하여 테이블을 해시 분할(hash partitioning)할 수 없도록 수정했다.

SET NAMES utf8 COLLATE utf8_de_exp_ai_ci;

-- 9.1 버전에서는 아래와 같은 테이블 생성을 허용하지 않는다.
CREATE TABLE t2 (code VARCHAR(10)) COLLATE utf8_de_exp_ai_ci PARTITION BY HASH (code) PARTITIONS 4;
INSERT INTO t2(code) VALUES ('AE');
INSERT INTO t2(code) VALUES ('ae');
INSERT INTO t2(code) VALUES ('Ä');
INSERT INTO t2(code) VALUES ('ä');

-- 9.0 베타 버전에서 아래 질의 수행 시 'ä'와 'Ä' 두 개의 행을 출력해야 하나 4개의 행을 출력하는 문제가 존재한다.
SELECT * FROM t2 WHERE code='ä';

드라이버

[JDBC][CCI] 자동 커밋 모드에서 배열/배치 실행 함수가 각 질의문을 수행할 때마다 커밋하도록 수정(CUBRIDSUS-6148)

자동 커밋 모드에서 cci_execute_array 함수와 cci_execute_batch 함수, 그리고 JDBC의 Statement.executeBatch 메서드, PreparedStatement.executeBatch 메서드 등이 배열 내 여러 개의 질의문을 일괄적으로 처리할 때 모든 질의문을 수행한 이후에 커밋했으나 각 질의문을 수행할 때마다 커밋하도록 수정했다.

[JDBC] PreparedStatement.setBoolean 메서드 변경(CUBRIDSUS-9205)

JDBC에서 PreparedStatement 객체에 대해 setBoolean() 메서드로 값을 바인딩할 때 BIT 타입의 값만 허용했었으나, BIT 타입의 값은 제외하되 SMALLINT, INTEGER, BIGINT, NUMERIC, FLOAT, DOUBLE, MONETARY 등 모든 숫자 타입 또는 CHAR, VARCHAR 등 모든 문자 타입의 값을 바인딩할 수 있도록 수정했다.

[CCI] 배열/배치 실행 함수에 대한 에러 처리 방식 수정(CUBRIDSUS-9364)

여러 개의 질의를 한 번에 수행할 때 2008 R3.0부터 2008 R4.1 버전까지는 cci_execute_array 함수, cci_execute_batch 함수 또는 cci_execute_result 함수에 의한 질의 수행 결과들 중 하나만 에러가 발생해도 해당 질의의 에러 코드를 반환했으나, 2008 R4.3 버전 및 9.1 버전부터는 전체 질의 개수를 반환하고 CCI_QUERY_RESULT_* 매크로들을 통해 개별 질의에 대한 에러를 확인할 수 있도록 수정했다.

이와 관련하여 전체 질의 결과에서 실패한 특정 질의의 에러 번호를 확인할 수 있도록 CCI_QUERY_RESULT_ERR_NO 매크로를, 실패한 위치가 CAS인지 DBMS인지 알 수 있도록 CCI_QUERY_RESULT_RESULT 매크로의 반환 값에 에러 인식자(CAS 에러 -1, DBMS 에러 -2)를 추가했다.

관련된 CCI_QUERY_RESULT_* 매크로들은 다음과 같다.

  • CCI_QUERY_RESULT_RESULT
  • CCI_QUERY_RESULT_ERR_NO
  • CCI_QUERY_RESULT_ERR_MSG
  • CCI_QUERY_RESULT_STMT_TYPE
  • CCI_QUERY_RESULT_OID

[CCI] cci_property_set 함수와 cci_connect_with_url 함수의 DB 사용자와 암호 설정에 대한 동작 방식 변경(CUBRIDSUS-9393)

cci_property_set 함수와 cci_connect_with_url 함수의 DB 사용자와 암호 설정 시 동작 방식을 통일했다. 수정 이후 다음과 같이 동작한다.

  • 인자와 URL에 둘 다 값이 지정되면 인자의 값이 우선한다.
  • 둘 중 하나가 NULL이면 NULL이 아닌 값이 사용된다.
  • 둘 다 NULL이면 NULL 값으로 사용된다.
  • DB 사용자 인자 값이 NULL이면 "public", 암호 인자 값이 NULL이면 NULL로 설정된다.
  • 암호 인자 값이 NULL이면 URL의 설정을 따른다.

수정 이전 버전에서 cci_property_set 함수로 DATASOURCE에 대한 DB 사용자와 암호 설정 시 DB 사용자 인자는 반드시 설정해야 되며, 암호 인자를 설정하지 않으면 NULL로 인식했다. 또한, 암호 인자가 NULL이면 URL의 암호를 사용했다.

수정 이전 버전에서 cci_connect_with_url 함수에 DB 사용자와 암호 설정 시 DB 사용자 인자가 NULL이면 "public"으로 지정되었으며, 암호 인자가 NULL이면 URL의 암호를 사용했다.

기본 설정 변경

CUBRID_LANG 환경 변수 제거 및 CUBRID_CHARSET, CUBRID_MSG_LANG 환경 변수 추가(CUBRIDSUS-9719)(CUBRIDSUS-9468)

CUBRID_LANG 환경 변수를 제거하고, 데이터베이스 문자셋을 설정하는 CUBRID_CHARSET 환경 변수와 오류 메시지를 비롯한 각종 메시지의 문자셋을 설정하는 CUBRID_MSG_LANG 환경 변수를 추가했다. CUBRID_CHARSET 환경 변수는 반드시 설정되어야 하며, CUBRID_MSG_LANG 환경 변수는 생략되면 CUBRID_CHARSET 환경 변수의 설정을 따른다.

시스템 파라미터 sort_buffer_size의 최대 크기를 2G로 제한(CUBRIDSUS-9582)

시스템 파라미터인 sort_buffer_size의 최대 크기를 2G로 제한했다. 수정 이전 버전에서 sort_buffer_size의 크기를 2G보다 크게 설정하고, 인덱스 생성과 같은 정렬이 필요한 작업에서 2G보다 큰 sort_buffer를 사용하게 되면 해당 작업이 비정상 종료되었다.

call_stack_dump_activation_list 파라미터의 사용 방식 변경 (CUBRIDSUS-9836)

cubrid.conf의 call_stack_dump_activation_list 파라미터 지정에 따른 동작 방식이 변경되었다.

  • call_stack_dump_activation_list의 값을 지정하면 기본적으로 설정되던 오류 번호들이 있었으나 지정한 값에 대해서만 오류 번호가 설정되도록 수정했다.
  • call_stack_dump_activation_list의 값으로 DEFAULT 키워드를 지정할 수 있게 수정했다. DEFAULT 키워드는 "-2, -7, -13, -14, -17, -19 , -21, -22, -45, -46, -48, -50, -51, -52, -76, -78, -79, -81, -90, -96, -97, -313, -314, -407, -414, -415, -416, -417, -583, -603, -836, -859, -890, -891, -976, -1040, -1075"으로 대체된다.

call_stack_dump_activation_list의 값을 지정하지 않으면 기존처럼 "-2, -7, -13, -14, -17, -19 , -21, -22, -45, -46, -48, -50, -51, -52, -76, -78, -79, -81, -90, -96, -97, -313, -314, -407, -414, -415, -416, -417, -583, -603, -836, -859, -890, -891, -976, -1040, -1075"이 기본으로 설정된다.

브로커 파라미터 KEEP_CONNECTION에서 OFF 옵션 제거(CUBRIDSUS-5316)

브로커 파라미터 KEEP_CONNECTION에서 OFF 옵션을 제거했다. 2008 R4.x 이하 버전에서 해당 파라미터의 값을 OFF로 설정하면 사용자 정의 변수, LAST_INSERT_ID, ROW_COUNT, PREPARE 문이 정상 수행되지 않는다.

브로커 파라미터 SELECT_AUTO_COMMIT 제거(CUBRIDSUS-9326)

브로커 파라미터 SELECT_AUTO_COMMIT은 더 이상 불필요하므로 제거되었다.

APPL_SERVER_MAX_SIZE_HARD_LIMIT 브로커 파라미터 변경(CUBRIDSUS-10260)

브로커 파라미터 APPL_SERVER_MAX_SIZE_HARD_LIMIT의 값의 범위를 1과 2,097,151 사이의 값으로 제한하고 이를 벗어나는 경우 브로커 구동을 하지 못하도록 수정했다. 이와 함께 broker_changer를 이용해서 APPL_SERVER_MAX_SIZE_HARD_LIMIT의 값을 APPL_SERVER_MAX_SIZE보다 작게 변경하면 경고 메시지를 출력하도록 수정했다.

SQL 로그 파일 크기를 지정하는 브로커 파라미터의 기본 설정값을 100MB에서 10MB로 줄임(CUBRIDSUS-9944)

cubrid_broker.conf의 SQL_LOG_MAX_SIZE의 기본 설정값을 100MB에서 10MB로 줄였다. 기존 버전 사용자가 새 버전으로 업그레이드 한 이후에도 기존과 동일한 양의 SQL 로그를 남기고 싶다면 SQL_LOG_MAX_SIZE의 값을 100,000(단위: KB)으로 설정해야 한다.

HA

HA 환경에서 노드가 to-be-active 상태에서도 SELECT 문을 처리할 수 있도록 수정(CUBRIDSUS-8896)

HA 환경에서 노드가 to-be-active 상태에서도 SELECT 문을 처리할 수 있도록 수정했다.

기타

"cubrid broker status" 명령 변경(CUBRIDSUS-9602)

cubrid broker status 명령을 통해 브로커의 상태를 출력할 때 아래와 같이 몇 가지 사항이 추가 또는 변경되었다.

  • 브로커의 SERVICE 파라미터 값을 ON으로 설정하면 구동 중인 브로커의 상태만 출력하게 되었다.

    % cubrid broker status SERVICE=ON
  • -b 옵션으로 브로커 상태 출력 시

    • 브로커 이름은 최대 20자까지만 출력하고, 이를 초과하는 경우 이름 뒤에 ...을 출력한다.
    • REQ 항목은 더 이상 출력하지 않는다.
    • QPS, TPS 항목 출력 시 UINT64 최대 값까지 출력한다. 수정 이전에는 해당 항목이 음수로 출력되는 경우가 존재했다.
    • 브로커 응용 서버(CAS) 별 응용 프로그램 연결 개수의 합을 출력하는 #CONNECT가 추가되었다.
    • 질의 종류 별 수행 회수를 출력하는 SELECT, INSERT, UPDATE, DELETE, OTHERS 항목을 추가하게 되었다. 단, -f 옵션이 있는 경우는 해당 항목들이 출력되지 않는다.
    • 고유 키 위반 오류 회수를 출력하는 UNIQUE-ERR-Q 항목이 추가되었다.
  • -b 옵션 없이 브로커 상태 출력 시

    • STATUS 항목 출력 시 "CLIENT WAIT", "CLOSE WAIT"가 각각 "CLIENT_WAIT", "CLOSE_WAIT"로 출력되도록 변경되었다.
    • 브로커 설정 정보가 출력에서 제외되었다.
  • -l 옵션 사용 시 상태가 "CLOSE_WAIT"인 CAS의 정보는 출력에서 제외되었다.

개선 및 오류 수정

성능 및 최적화

HA 복제 성능 개선(CUBRIDSUS-8114)

HA 환경에서 복제 반영 성능이 대폭 개선되었다. 마스터 노드에서의 변경은 슬레이브 노드에 실시간으로 반영된다. 대량의 YCSB 벤치마크 워크로드를 주었을 때 복제 지연 시간을 측정한 결과는 다음과 같다.

Version Delay Time (sec)
CUBRID 9.0 Beta 2238.73
CUBRID 9.1 1.18

INSERT와 DELETE 반복 수행 시 DELETE 성능 개선(CUBRIDSUS-5222)

INSERT와 DELETE 반복 수행 시 DELETE 수행 시간이 점점 증가했으나 INSERT와 DELETE 반복 수행 이후에도 초기 DELETE와 비슷한 수행 시간을 유지하도록 개선했다.

빈번하게 테이블을 TRUNCATE하거나 인덱스를 재생성한 이후의 테이블 접근 성능 개선(CUBRIDSUS-6501)

빈번하게 테이블을 TRUNCATE하거나 인덱스를 재생성한 이후에 해당 테이블에 대한 접근 성능이 저하되는 문제를 개선했다.

INSERT ON DUPLICATE KEY UPDATE, REPLACE 문의 성능 개선(CUBRIDSUS-8337)

유일성을 위반한 레코드를 찾기 위해서 내부적으로 SELECT 문을 실행하던 기존 방식 대신 직접 인덱스를 검색하는 방법으로 수정하여 성능을 높였다. 또한, INSERT ON DUPLICATE KEY UPDATE 문을 서버에서 실행할 때 UPDATE 문을 실행하던 방식 대신 직접 수정하도록 하여 성능을 개선했다.

분석 함수 성능 개선(CUBRIDSUS-8487)

분석 함수의 성능을 개선하였다.

  • 질의에 명시된 분석 함수들이 같은 윈도우를 공유하는 경우에 대한 성능 향상
  • 많은 그룹으로 구성되는 데이터에 대한 분석 함수 처리 성능 향상
  • 일부분이 정렬된 데이터에 대한 분석 함수 처리 성능 향상
-- Q1: 2배 향상
SELECT *
FROM (SELECT ROWNUM AS rn,
             AVG (c1) OVER (PARTITION BY p1) a1,
             AVG (c1) OVER (PARTITION BY p1) a2
      FROM t) x
WHERE x.rn > 999999;

-- Q2: 2.45배 향상
SELECT *
FROM (SELECT ROWNUM AS rn,
             AVG (c1) OVER (PARTITION BY p1 ORDER BY o1) a1,
             AVG (c1) OVER (PARTITION BY p1 ORDER BY o1) a2
      FROM t) x
WHERE x.rn > 999999;

-- Q3: 5.6배 향상
SELECT *
FROM (SELECT ROWNUM AS rn,
             AVG (c1) OVER (PARTITION BY p1 ORDER BY o1) a1,
             AVG (c1) OVER (PARTITION BY p1 ORDER BY o1) a2,
             AVG (c1) OVER (PARTITION BY p1 ORDER BY o1) a3
      FROM t) x
WHERE x.rn > 999999;

-- Q4: 약 15% 향상
SELECT *
FROM (SELECT ROWNUM AS rn,
             AVG (c1) OVER (PARTITION BY p1) a1
      FROM t) x
WHERE x.rn > 999999;

-- Q5: 약 25% 향상
SELECT *
FROM (SELECT ROWNUM AS rn,
             AVG (c1) OVER (PARTITION BY p1 ORDER BY o1) a1
      FROM t) x
WHERE x.rn > 999999;

다중 키 범위 최적화 개선(CUBRIDSUS-10278)(CUBRIDSUS-6091)

다중 키 범위 최적화(multi-key range optimization)가 대폭 개선되었다.

  • ORDER BY 칼럼이 2개 이상이라도, orderby_num()에 의해 범위가 주어져도 중간 값의 정렬을 진행하면서 결과를 수집하는 다중 키 범위 최적화가 가능하도록 개선했다.

    SELECT *
    FROM tbl
    WHERE a IN (1, 2, 3)
    USING INDEX idx
    ORDER BY col1 DESC, col2 DESC
    LIMIT 2;
    
    SELECT *
    FROM tbl
    WHERE a IN (1,3)
    ORDER BY b, c DESC
    FOR orderby_num() BETWEEN 5 AND 10;
    
  • 일부 JOIN 질의에서도 다중 키 범위 최적화가 가능해졌다.

    SELECT *
    FROM tbl1 t JOIN tbl2 s
    ON s.b = t.b
    WHERE t.a in (1,3) AND t.b = 1
    ORDER BY t.c DESC, d
    LIMIT 10;
    
  • 다중 키 범위 최적화를 질의 실행 계획 생성 단계에서 수행하도록 변경하여 질의 플랜을 통해서 볼 수 있다. 다중 키 범위 최적화 적용 여부는 LIMIT 절 또는 orderby_num()을 통해서 정의되는 최종 결과 크기에 따라서 결정된다. 예를 들어, 파라미터를 통해서 설정된 크기보다 큰 최종 결과를 얻고자 하는 경우에는 다중 키 범위 최적화 실행 계획은 적용되지 않는다.

ORDER BY 절의 칼럼을 타입 변환해도 결과 순서에 영향이 없으면 ORDER BY 절 최적화를 적용하도록 개선(CUBRIDSUS-7418)

ORDER BY 절의 칼럼을 타입 변환해도 타입 변환 이전과 이후의 결과 순서가 동일한 경우, 정렬 작업을 수행하지 않고 인덱스에 의해 정렬된 값의 순서대로 가져오는 ORDER BY 절 최적화(skip order by)를 적용하도록 개선했다.

CREATE TABLE t (a datetime);
CREATE INDEX i ON t (a);

SELECT * FROM t
WHERE a > '0000-00-00 00:00:00'
ORDER BY cast (a AS DATE);

LIMIT 절을 포함한 GROUP BY 질의의 최적화 개선(CUBRIDSUS-6400)

LIMIT 절을 포함한 GROUP BY 질의에 GROUP BY 생략 최적화가 적용될 때, LIMIT 절의 결과 갯수에 도달하면 곧바로 스캔을 종료하도록 개선했다.

CREATE TABLE t (i INTEGER, j INTEGER);
CREATE INDEX idx ON t (i);

SELECT i, j
FROM t
WHERE i > 0
GROUP BY i
LIMIT 5;

LIMIT 절 질의 최적화 개선(CUBRIDSUS-7661)

LIMIT N 처리 과정 중에 N+1번째 레코드까지 탐색한 후 질의 수행을 종료하지 않고 N번째 레코드를 탐색한 직후에 곧바로 질의 수행을 종료하도록 개선하였다.

SELECT * FROM t1 WHERE a > 0 AND b = 1 LIMIT 3;

브로커 응용 서버(CAS)를 최대 접속 개수까지 구동하는데 소요되는 시간 개선(CUBRIDSUS-9067)

브로커를 구동하면 처음에는 브로커 파라미터 MIN_NUM_APPL_SERVER 값만큼 CAS가 구동되어 있으며, 해당 CAS와 접속하는 응용 프로그램의 개수가 늘어나면서 최대 MAX_NUM_APPL_SERVER 값까지 CAS가 구동된다. 9.1에서는 MAX_NUM_APPL_SERVER까지 많은 수의 CAS가 구동되는데 소요되는 시간을 개선했다.

예를 들어 MIN_NUM_APPL_SERVER이 100이고 MAX_NUM_APPL_SERVER가 400일 때, 접속을 400개까지 늘리면 브로커가 101번째 접속부터 CAS를 400개까지 하나씩 늘어나는데 기존에는 30초가 소요되었으나 수정 이후 3초로 줄어들었다.

리소스

cubrid addvoldb 유틸리티에 디스크 출력량을 제한하는 옵션 추가(CUBRIDSUS-9521)

데이터베이스 볼륨 추가로 인한 시스템 운영 영향을 줄이기 위해 cubrid addvoldb 유틸리티에 디스크 출력량을 제한하는 옵션을 추가했다. --max_writesize-in-sec 옵션을 통해 초당 쓸 수 있는 최대 크기를 지정할 수 있다.

% cubrid addvoldb -C --db-volume-size=2G --max-writesize-in-sec=1M testdb

오버플로우 레코드에 대한 정렬 과정에서 임시 볼륨 사용 효율성 개선(CUBRIDSUS-9772)

인덱스 생성 또는 질의 처리 과정 중에 정렬이 필요할 때 오버플로우 레코드가 포함된 경우에 임시 볼륨 사용의 효율성을 높이도록 개선했다. 재사용이 가능한 공간을 최대한 활용하고 필요한 경우에만 임시 볼륨을 확장하도록 하였다.

주기적으로 샤드 상태 정보를 출력하는 명령에 존재했던 메모리 누수 수정(CUBRIDSUS-10393)

주기적으로 샤드 상태 정보를 출력하는 "cubrid shard status -c -s 1" 명령에 존재했던 메모리 누수(leak)를 수정했다.

질의 결과 정렬 시 필요한 메모리 사용 공간을 보다 정확히 예측하도록 개선(CUBRIDSUS-1339)

질의 결과 정렬 시 필요한 메모리 사용 공간을 보다 정확히 예측하여 디스크를 사용해야 하는 외부 정렬(external sorting)의 가능성을 줄이도록 개선했다.

자동으로 볼륨이 증가될 때 한 번에 여러 개의 볼륨이 생성되는 문제(CUBRIDSUS-10295)

여러 클라이언트가 자동 볼륨 확장을 동시에 요구했을 때 한 번에 여러 개의 볼륨이 추가되는 문제를 수정했다.

안정성

잠금 관리자의 내부 문제로 인해 DB 서버 프로세스의 동작이 멈추는(hang) 현상(CUBRIDSUS-10329)(CUBRIDSUS-10009)

잠금 관리자의 문제로 인해서 잠금 획득 과정에서 서버 프로세스가 더 이상 진행하지 못하고 멈출 수 있는 문제점과 잠금 대기 과정에서의 내부 오류로 인해서 잠금을 잘못 대기하여 결국 서버가 진행하지 못하는 문제점들을 수정했다.

교착 상태 감지시 발생 가능한 메모리 누수와 서버가 비정상 종료될 수 있는 문제(CUBRIDSUS-10378)

교착 상태 감지시 특정 상황에서 발생할 수 있는 메모리 누수 문제와 서버가 비정상 종료될 수 있는 문제를 수정했다.

체크포인트 이후에도 보관 로그가 정리되지 않는 현상(CUBRIDSUS-9848)

복구 시간 단축을 위해 데이터를 DB 볼륨에 갱신(flush)하는 체크포인트 수행 이후에도 보관 로그가 정리되지 않는 현상을 수정했다. 데이터의 갱신이 빈번한 상황에서 체크포인트가 수행되면 이 현상이 발생할 가능성이 높다. 수정 이전 버전에서는 해당 현상 발생 시 체크포인트 발생 시점이 갱신되지 않아 보관 로그를 유지해야 했으나, 수정 이후 체크포인트 발생 시점 이전의 보관 로그는 정리될 수 있도록 수정했다.

독립 모드에서 새로운 페이지 할당 도중에 체크포인트가 발생하면 오류가 발생할 수 있는 문제(CUBRIDSUS-10444)

독립(Stand Alone) 모드에서 데이터가 입력되는 등으로 인해 새로운 페이지가 할당되는 도중에 체크포인트가 발생하면 "Skip invalid page in checkpoint." 오류가 발생할 수 있는 문제를 수정했다.

CAS가 CLIENT WAIT인 상태에서 동작을 멈출 수 있는 문제(CUBRIDSUS-10238)

CAS가 특정 시점에 시그널로 인해 종료되거나 비정상 종료되면 그 이후로 해당 번호의 CAS 또는 브로커 프로세스가 정상적으로 동작하지 못하고 무한히 대기할 수 있는 문제를 수정했다.

CAS에서 DB 서버 에러 수신 도중 네트워크 소켓 에러가 발생하면 CAS가 비정상 종료하는 현상(CUBRIDSUS-10401)

CAS에서 DB 서버 에러를 수신하는 도중에 네트워크 소켓 에러가 발생하는 경우 CAS가 비정상 종료하는 현상을 수정했다. 수정 이전 버전에서 이러한 현상이 발생할 수 있는 예로, 샤드 환경에서 shard CAS 프로세스의 개수를 설정하는 cubrid_shard.conf의 MAX_NUM_APPL_SERVER 값이 서버가 허용하는 최대 접속 개수를 설정하는 cubrid.conf의 max_clients 값보다 크도록 설정한 상태에서 "cubrid shard start"를 수행하면 SHARD CAS가 비정상 종료하는 현상이 발생한다.

SQL 함수와 연산자

분석 함수의 PARTITION BY 절에 표현식을 지정하면 오류 발생하는 문제 수정(CUBRIDSUS-9579)

분석 함수의 PARTITION BY 절에 표현식을 지정하면 오류가 발생하는 문제를 수정했다.

SELECT v.a, ROW_NUMBER() over(PARTITION BY 1 + 0) r
FROM (VALUES (1), (2), (3)) v (a);

수정 이전 9.0 베타 버전에서는 아래의 오류가 발생한다.

Semantic: System error (generate order_by) in ..\..\src\parser\xasl_generation.c (line: 5466)
select [v].[a], row_number() over (partition by 1+0) from (values (1),(2),(3)) [v] ([a]);

분석 함수의 OVER 절 뒤에 함께 사용되는 ORDER BY 절 및 PARTITION BY 절에 명시되는 표현식에 따른 동작 방식은 다음과 같다.

  • ORDER BY 상수 (예: 1): 상수는 SELECT 리스트의 칼럼 위치를 지정한다.
  • ORDER BY 상수 표현식 (예: 1+0): 상수 표현식은 무시되어 정렬/분할(ordering/partitioning)에 사용되지 않는다.
  • ORDER BY 상수가 아닌 표현식(예: i, sin(i+1)): 표현식은 정렬/분할(ordering/partitioning)에 사용된다.

STR_TO_DATE 함수가 밀리초를 항상 0으로 리턴하는 문제 수정(CUBRIDSUS-9553)

STR_TO_DATE 함수가 밀리초를 항상 0으로 리턴하는 문제를 수정했다.

SELECT STR_TO_DATE ('2012-10-31 23:49:29.123', '%Y-%m-%d %H:%i:%s.%f');

BLOB_FROM_FILE, CLOB_FROM_FILE 함수 수행 시 오류가 발생하는 문제 수정(CUBRIDSUS-7596)

BLOB_FROM_FILE, CLOB_FROM_FILE 함수 수행 시 "Semantic: Cannot coerce blob to type unknown data type."과 같은 오류가 발생하는 문제를 수정했다.

BIGINT 타입에 TIME 타입의 값을 더할 때 오버플로우 발생시 오류를 반환하도록 수정(CUBRIDSUS-3735)

BIGINT 타입에 TIME 타입의 값을 더할 때 오버플로우 발생시에 잘못된 결과를 출력했으나, 오류를 출력하도록 수정했다.

SELECT CAST (9223372036854775807 as bigint) + TIME'11:59:59 pm';

SUM, AVG 함수의 호스트 변수 인자에 double 타입으로 변환 가능한 문자열을 입력하는 경우 오류 발생 현상(CUBRIDSUS-8789)

SUM, AVG 함수의 호스트 변수 인자로 double 타입으로 변환 가능한 문자열을 입력하는 경우 "ERROR: Invalid data type referenced." 오류를 출력하는 현상을 수정했다.

CREATE TABLE tbl (a INTEGER);
INSERT INTO tbl VALUES (1),(2);

PREPARE STMT FROM 'SELECT AVG (?) FROM tbl';
EXECUTE STMT USING '1.1';

GROUP BY 절을 포함한 질의문에서 분석 함수를 사용하면 오류가 발생하는 문제(CUBRIDSUS-7270)

GROUP BY 절을 포함한 질의문에서 분석 함수를 사용할 수 있도록 수정했다.

SELECT a, ROW_NUMBER() OVER (ORDER BY a) FROM tbl GROUP BY a;
-- 수정 이전 버전에서는 다음의 오류가 발생했다.
ERROR:  before '  from tbl group by a; '
Nested or invalid use of aggregate function.

FROM 절을 생략한 질의문에서 SQL 함수의 입력 인자로 부질의가 지정되면 오류가 발생하는 현상(CUBRIDSUS-9949)

FROM 절을 생략한 질의문에서 SQL 함수의 입력 인자로 부질의가 지정되면 "ERROR: syntax is ambiguous" 오류가 발생하는 현상을 수정했다.

SELECT INET_NTOA ((SELECT 3232235530));

SQL 함수나 연산자에 NULL이 주어지면 NULL을 반환하도록 수정(CUBRIDSUS-10324)

NULL을 특수하게 처리하는 연산자(예를 들어, IS NULL 등)과 SQL 함수(예를 들어, NVL 등) 외에는 피연산자나 인자로 NULL이 주어지면 결과로 항상 NULL을 반환하도록 수정했다.

SELECT POW ('a', NULL);
-- 수정 이전 버전에서 위의 질의를 수행하면 아래와 같은 오류가 발생하지만, 9.1 버전부터는 NULL을 반환한다.

ERROR: before ' , null); '
Cannot coerce 'a' to type double.

SPACE 함수에 대해 함수 인덱스를 생성할 수 없도록 수정(CUBRIDSUS-10419)

SPACE 함수는 인덱스 스캔 입장에서 무의미한 일련의 공백 문자를 반환하므로 SPACE 함수에 대한 함수 인덱스 생성을 허용하지 않도록 수정했다.

CREATE INDEX i_tbl_col ON tbl (SPACE (col1));
-- 수정 이후 위의 질의를 수행하면 아래 오류 메시지를 출력한다.
'space ' function cannot be used for function based index.

TO_CHAR 함수의 인자가 문자열 타입인 경우 함수 기반 인덱스를 허용하지 않도록 제한(CUBRIDSUS-8977)

TO_CHAR 함수의 첫번째 인자가 문자열 타입인 경우에 주어진 인자가 함수 결과로 그대로 반환된다. 이와 같은 경우에 함수 기반 인덱스를 생성할 수 없도록 제한했다.

IN 연산자에 ENUM 타입 칼럼과 문자열이 피연산자로 주어지면 서버 프로세스가 비정상 종료되는 문제(CUBRIDSUS-10586)

IN 연산자의 피연산자로 ENUM 타입 칼럼과 집합이 아닌 단순 문자열이 주어지면 오류를 반환하지 않고 서버 프로세스가 비정상 종료하는 문제를 수정했다. IN 연산자의 RHS 피연산자는 집합이나 부질의가 주어져야 하므로, 이 경우에는 문자열을 괄호로 묶어 집합 타입을 지정해야 한다.

CREATE TABLE t1 (fruit ENUM ('apple', 'orange', 'peach', 'banana', 'strawberry'));
INSERT INTO t1 VALUES ('orange');

-- 아래 질의를 수행하면 9.0 베타 버전의 서버 프로세스가 비정상 종료된다.
SELECT * FROM t1 WHERE fruit IN 'apple';

-- 정상적인 질의는 다음과 같다.
SELECT * FROM t1 WHERE fruit IN ('apple');

SQL

다중 왼쪽 조인 질의에 WHERE 절 조건이 있으면 잘못된 질의 결과를 출력하는 문제 수정(CUBRIDSUS-8867)

아래의 예와 같이 왼쪽 조인(left outer join)이 세 번 이상 중첩된 질의에 WHERE 절 조건이 있으면 잘못된 질의 결과를 출력하는 문제를 수정했다.

SELECT *
FROM tblA LEFT OUTER JOIN tblB ON tblA.pkey = tblB.pkey
          LEFT OUTER JOIN tblC ON tblB.p2key = tblC.p2key
          LEFT OUTER JOIN tblD ON tblC.p3key = tblD.p3key
WHERE tblD.p3key = 1;

데이터베이스 이름을 변경한 후 LOB 타입의 연산 수행에 실패하는 문제 수정(CUBRIDSUS-8905)

데이터베이스 이름 변경 과정에서 BLOB/CLOB 타입에 대한 디렉터리 정보가 설정되지 않아, CHAR_TO_BLOB 함수와 같은 LOB 타입 연산 수행에 실패하는 문제를 수정했다.

% cubrid createdb --db-volume-size=20m testdb
% cubrid renamedb testdb testdb2
% cubrid server start testdb2

% csql -u dba testdb2

csql> CREATE TABLE tbl(b BLOB);
csql> INSERT INTO tbl VALUES(CHAR_TO_BLOB('1'));

ERROR: before ' )); '
External storage is not initialized because the path is not specified in "databases.txt".

네트워크 장애나 HA 절체 또는 데이터베이스 서버의 재시작 이후 LAST_INSERT_ID와 같이 세션 데이터를 사용하는 작업 요청이 정상 처리되지 못하는 문제 수정(CUBRIDSUS-7549)(CUBRIDSUS-7669)

HA 절체(failover) 또는 데이터베이스 서버가 재시작되면 서로 다른 응용 클라이언트들이 같은 세션 ID를 공유하는 경우가 발생할 수 있었다. 이 경우 세션을 공유하는 응용 클라이언트 중 하나가 종료하면 다른 응용 클라이언트에서 세션 데이터에 의해 관리되는 사용자 정의 변수, PREPARE 문, LAST_INSERT_ID, ROW_COUNT 등의 요청이 정상 처리되지 못했다.

다중 컬럼 인덱스에 DESC 컬럼이 존재하고 OR 조건이 있을 때 조건에 따라 질의 결과가 잘못되는 문제(CUBRIDSUS-9314)

다중 컬럼 인덱스에 DESC 컬럼이 존재하고 인덱스 전체 키가 아닌 부분 키에 대한 OR 조건들이 주어지면, 질의 결과가 잘못되는 문제를 수정했다.

CREATE TABLE foo(col1 INTEGER, col2 INTEGER, col3 INTEGER);
CREATE INDEX idx_foo ON foo(col1, col2 DESC, col3);
INSERT INTO foo VALUES(1,10,100);
INSERT INTO foo VALUES (1,11,100);
PREPARE s FROM 'SELECT col1,col2 FROM foo WHERE col1=? AND ((col2=? AND col3<?) OR col2>?);';
EXECUTE s USING 1, 10, 100, 10;

자동 커밋 모드에서 다중 질의를 한 번에 수행하면 자동 커밋되지 않는 문제(CUBRIDSUS-7606)

자동 커밋 모드에서, 예를 들어 "CREATE TABLE a(col INTEGER); INSERT INTO a VALUES (1);"와 같이 한 번에 여러 개의 질의를 수행하면 자동 커밋되지 않는 문제를 수정했다.

ORDER BY 절을 포함한 뷰를 SELECT할 때 서버가 비정상 종료하는 현상(CUBRIDSUS-9331)

ORDER BY 절을 포함한 뷰를 SELECT할 때 SELECT 리스트에 *을 사용하는 경우를 제외하고는 서버가 비정상 종료하는 현상을 수정했다.

CREATE VIEW au AS
SELECT
    tbla.a_id AS a_id,
    tbla.u_id AS u_id,
    tbla.a_date AS a_date,
    tblu.u_name AS u_name,
FROM
    tbla LEFT JOIN tblu ON tbla.u_id = tblu.u_id
ORDER BY tbla.a_date ASC;

SELECT u_name FROM au;

테이블과 같은 이름을 가지는 뷰를 생성하는 오류(CUBRIDSUS-3091)

테이블과 같은 이름을 가지는 뷰 생성을 허용하던 오류를 수정했다.

CREATE TABLE t1 (a INTEGER, b INTEGER);
CREATE VIEW t1 AS SELECT * FROM t1;
ERROR: Class t1 already exists.

뷰 생성 시 SELECT 리스트에 명시되지 않은 칼럼을 ORDER BY 절에서 참조하면 뷰 생성하지 못하는 문제(CUBRIDSUS-9345)

뷰를 생성하는 질의문에서 SELECT 리스트에 명시되지 않은 칼럼(hidden column)을 ORDER BY 절에서 참조하면 뷰 생성에 실패하는 문제를 수정했다.

CREATE TABLE foo (i INTEGER, j INTEGER);
CREATE VIEW v AS SELECT i FROM foo ORDER BY j;

ORDER BY 절을 포함한 뷰에 대해서 DISTINCT 질의 수행 시 잘못된 결과를 출력하거나 서버가 비정상 종료되는 문제(CUBRIDSUS-9880)

ORDER BY 절을 포함한 뷰에 대해서 DISTINCT 질의 수행 시 잘못된 결과를 출력하거나 서버가 비정상 종료되는 문제를 수정했다.

CREATE TABLE t (s CHAR(10), i INTEGER);
INSERT INTO t VALUES ('xxxx', 1);
INSERT INTO t VALUES ('yyyy', 2);

CREATE VIEW v AS SELECT s s_v, i i_v FROM t ORDER BY s;

SELECT DISTINCT t1.i_v FROM v t1, v t2;

뷰 생성에 사용된 테이블의 이름을 변경한 후에 뷰에 대한 질의 수행 시 변경 이전의 테이블로 동작하는 문제(CUBRIDSUS-8536)

뷰 생성에 사용된 테이블의 이름을 변경한 후에 뷰에 대한 질의를 수행하면 변경 이전의 테이블로 동작하는 문제를 수정했다.

CREATE TABLE foo (a INTEGER PRIMARY KEY, b VARCHAR (20));
INSERT INTO foo VALUES (1, 'foo');

CREATE TABLE bar (a INTEGER PRIMARY KEY, b VARCHAR (20));
INSERT INTO bar VALUES (1, 'bar');
CREATE VIEW v1 (a INTEGER, b VARCHAR (20)) AS SELECT * FROM foo;

-- foo를 foo_old, bar를 foo로 이름을 변경한다.
RENAME foo AS foo_old;
RENAME bar AS foo;

-- 수정 이전 버전에서는 Q1의 결과로 'bar', Q2의 결과로 'foo'를 출력하며, 수정 이후 버전에서는 둘다 'bar'를 출력한다.
SELECT b FROM foo; -- Q1
SELECT b FROM v1;  -- Q2

자기 자신을 참조하는 뷰가 생성되는 문제(CUBRIDSUS-3090)

자기 자신을 참조하는 뷰 생성이 불가능하도록 수정했다. 이전 버전에서는 이와 같은 뷰가 생성되고, 해당 뷰에 대한 질의 시에 오류가 반환되었다.

CREATE VIEW v2 AS SELECT * FROM t1;
-- 수정 이후에는 아래의 질의 수행을 허용하지 않는다.
CREATE OR REPLACE VIEW v2 AS SELECT * FROM v2;

LIMIT 절을 포함한 뷰에 대해 INSERT 수행 시 응용 프로그램이 비정상 종료하는 현상(CUBRIDSUS-9940)

CREATE TABLE t (s VARCHAR);
CREATE VIEW tv AS SELECT s FROM t ORDER BY s LIMIT 2;

INSERT INTO tv VALUES ('a');

WITH CHECK OPTION 절을 포함한 뷰에 대해 MERGE 문 수행 시 조건 위배를 검출하지 못하는 문제(CUBRIDSUS-10219)

9.0 베타 버전에서는 아래와 같은 MERGE 문 수행 중에 WITH CHECK OPTION 조건을 위배하는 것을 검출하지 못하고 질의를 수행하는 문제가 있었다.

CREATE TABLE t1 (a INTEGER, b INTEGER);
INSERT INTO t1 VALUES (1, 500);

CREATE TABLE t2 (a INTEGER, b INTEGER);
INSERT INTO t2 VALUES (1, 400);
INSERT INTO t2 VALUES (2, 200);

CREATE VIEW v AS SELECT * FROM t1 WHERE b < 300 WITH CHECK OPTION;

MERGE INTO v USING t2 ON (t2.a = v.a)
WHEN NOT MATCHED THEN INSERT VALUES (t2.a, t2.b);

VALUES 절을 이용하여 생성한 뷰에 대한 SELECT 질의가 오류를 발생시키는 문제(CUBRIDSUS-9982)

CREATE VIEW vw as VALUES (1 AS col1, 'first' AS col2);
SELECT * FROM vw;
-- 9.0 Beta 버전에서는 다음 오류가 발생했다.
ERROR: There are more attributes in class vw than columns in the query specification.

WITH CHECK OPTION 절을 포함하는 뷰에 대해 MERGE 문 수행 시 실패하는 문제(CUBRIDSUS-9174)

WITH CHECK OPTION 절을 포함한 뷰에 대해 MERGE 문 수행 시 오류가 발생되는 문제를 수정했다.

CREATE TABLE t1 (a INTEGER, b INTEGER);
INSERT INTO t1 VALUES (1, 100);
INSERT INTO t1 VALUES (2, 200);

CREATE TABLE t2 (a INTEGER, b INTEGER);
INSERT INTO t2 VALUES (1, 99);
INSERT INTO t2 VALUES (2, 999);

CREATE VIEW v as SELECT * FROM t1 WHERE b < 150 WITH CHECK OPTION;

MERGE INTO v USING t2 ON (t2.a = v.a)
WHEN MATCHED THEN UPDATE SET v.b = t2.b;
-- 위의 질의 수행이 성공해야 하나 수정 이전 버전에서는 아래의 오류 메시지가 출력되었다.
ERROR: Check option exception on view v.

MERGE 문의 대상 테이블의 레코드가 여러 번 수정될 수 있는 잘못된 MERGE 문을 허용하는 문제 수정(CUBRIDSUS-7489)

MERGE 문의 대상 테이블에서 UPDATE 대상이 되는 레코드를 잘못 지정한 경우에도 오류를 반환하지 않고 해당 레코드를 여러 번 반복해서 UPDATE하는 문제를 수정했다. 전체 MERGE 문장 수행 과정 중에 각 레코드가 한번만 수정될 수 있도록 질의가 주어져야 한다.

CREATE TABLE t1 (a INTEGER, b INTEGER);
INSERT INTO t1 VALUES (1, 100);

CREATE TABLE t2 (a INTEGER, b INTEGER);
INSERT INTO t2 VALUES (1, 200);
INSERT INTO t2 VALUES (1, 300);

-- 수정 이후 아래 질의 수행 시 오류를 반환한다.
MERGE INTO t1 USING t2 ON (t1.a = t2.a)
WHEN MATCHED THEN UPDATE SET t1.b = t2.b;

MERGE 문이 오동작하는 문제(CUBRIDSUS-9158)

MERGE 문에서 원본 테이블을 참조하는 부질의를 대상 테이블로 사용할 때 오동작하는 현상을 수정했다.

MERGE INTO t1 USING (SELECT * FROM t1 WHERE b < 3) t2 ON (t1.a = t2.a)
WHEN MATCHED THEN UPDATE SET t1.b = 1000 DELETE WHERE t1.a > 1;

또한 MERGE 문에서 분할 테이블을 UPDATE한 이후 해당 데이터가 DELETE되지 않는 현상을 수정했다.

MERGE INTO t2 USING t1 ON (t1.id1 = t2.id2)
WHEN MATCHED THEN UPDATE SET t2.col1 = 'updated', t2.col2 = t1.col1
DELETE WHERE t2.col1 = 'updated';

원본과 대상 테이블이 같으면 MERGE 문을 허용하지 않는 문제(CUBRIDSUS-10207)

9.0 베타 버전에서는 아래와 같이 원본과 대상 테이블이 같은 경우에 "Cannot affect the source table in a MERGE statement." 오류를 반환하였다.

MERGE INTO tbl t USING tbl s ON (t.a = s.a)
WHEN MATCHED THEN UPDATE SET t.b = 'updated';

UPDATE JOIN 수행 시 영향을 받는 레코드 개수가 잘못 출력되는 현상(CUBRIDSUS-7185)

UPDATE JOIN 질의가 한 레코드를 여러 번 UPDATE하고, 이로 인해서 영향을 받는 레코드(affected rows) 수가 잘못 출력되는 현상을 수정했다.

CREATE TABLE t1 (a INTEGER);
INSERT INTO t1 VALUES (1), (1), (1), (1);

CREATE TABLE t2 (b INTEGER);
INSERT INTO t2 VALUES (1), (1), (1), (1);

UPDATE t1 m1, t2 m2 SET m1.a = 100, m2.b = 100 WHERE m1.a = m2.b;
-- 수정 이후 8 rows가 정상 출력된다. 9.0 베타 버전에서는 32 rows가 출력되었다.
8 rows affected.

서로 연관이 없는 다중 테이블 DELETE 질의 성능 개선(CUBRIDSUS-8144)

서로 연관이 없는 다중 테이블 DELETE 질의 수행 시 불필요한 JOIN 연산을 수행하지 않도록 하여 성능을 개선했다.

DELETE m1, m2, m3, m4, m5, m6, m7, m8, m9, m10
FROM m1, m2, m3, m4, m5, m6, m7, m8, m9, m10;

OUTER 조인 및 explicit INNER 조인의 ON 절에 ROWNUM, INST_NUM 조건을 명시할 수 없도록 수정(CUBRIDSUS-10366)

OUTER 조인 및 explicit INNER 조인의 ON 절에 ROWNUM, INST_NUM 조건을 명시할 수 없도록 수정했다. 질의의 WHERE 절에 ROWNUM, INST_NUM 조건을 명시하는 것은 무방하다.

DELETE t1, t2 FROM t1 LEFT OUTER JOIN t2 ON t1.b = t2.b AND ROWNUM < 100;
-- 9.0 베타 버전에서는 다음과 같은 오류가 발생되었다.
ERROR: System error (generate inst_num or orderby_num) in ../../src/parser/xasl_generation.c (line: 6889)

-- 9.1 버전부터는 다음과 같은 오류가 반환된다.
ERROR: before ' ; '
INST_NUM()/ROWNUM expression not allowed in join condition.

자식 테이블의 기본 키를 참조하는 외래 키에 설정한 "ON DELETE CASCADE" 속성이 동작하지 않는 오류(CUBRIDSUS-3493)

특정 테이블로부터 상속받은 자식 테이블의 기본 키를 참조하는 외래 키에 "ON DELETE CASCADE" 속성이 있음에도 불구하고 해당 자식 테이블에 대해 DELETE를 수행해도 이를 참조하는 테이블의 레코드가 삭제되지 않는 오류를 수정했다.

CREATE TABLE pk_super10 (id INTEGER PRIMARY KEY);
CREATE TABLE pk20 UNDER pk_super10 (A INTEGER);
CREATE TABLE fk20 (id INTEGER);
ALTER TABLE fk20 ADD CONSTRAINT FOREIGN KEY (id) REFERENCES pk20 (id) ON DELETE CASCADE;

INSERT INTO pk20 VALUES (1,1), (2,2), (3,3);
INSERT INTO fk20 VALUES (1), (1), (2);

DELETE FROM pk20 WHERE a = 1;
SELECT COUNT(*) FROM fk20;  -- 수정 이전에는 DELETE CASCADE가 동작하지 않아 3건, 수정 이후 정상 동작하여 1건

부질의에 사용되는 ORDER BY 절의 칼럼이 부질의의 SELECT 리스트에 없는 경우 잘못된 결과를 출력하는 문제(CUBRIDSUS-8931)

부질의(subquery)에 사용되는 ORDER BY 절의 칼럼이 부질의의 SELECT 리스트에 명시되지 않은 경우에 잘못된 결과를 출력하거나 오류를 출력(9.0 Beta만 해당)하는 문제를 수정했다.

SELECT a FROM foo WHERE a IN (SELECT a FROM foo WHERE b = 'AAA' ORDER BY b, c);

NUMERIC 타입 컬럼에 호스트 변수를 이용하여 INSERT 수행 시 실패하는 문제(CUBRIDSUS-9500)

NUMERIC 타입 컬럼에 대해 호스트변수를 이용하여 INSERT를 수행할 때, 사용자가 입력한 값이 NUMERIC의 기본 precision(15), scale(0)으로 변경되어 입력되는 문제를 수정했다.

CREATE TABLE tb2 (a NUMERIC (4,4));

PREPARE STMT FROM 'INSERT INTO tb2 VALUES (?)';
EXECUTE STMT USING 0.1;

SELECT a FROM tb2;
    a
==========
    0.0
EXECUTE STMT USING 0.5;
ERROR: A domain conflict exists on attribute "a".

계층 질의문에서 CONNECT BY 절에 LEVEL 의사 칼럼의 최대값 조건과 NOCYCLE이 지정된 경우에 잘못된 질의 결과를 출력하는 문제(CUBRIDSUS-9581)

계층 질의문에서 CONNECT BY 절에 LEVEL 의사 칼럼의 최대값 조건과 NOCYCLE이 지정된 경우에 잘못된 질의 결과를 출력하는 문제를 수정했다.

SELECT LEVEL FROM db_root CONNECT BY NOCYCLE LEVEL <= 5;
    level
=============
    1
    2
    3
    4
    5

트리거 실행 구문에서 현재의 날짜/시간을 입력하면 0이 입력되는 문제(CUBRIDSUS-9596)

트리거 실행 구문에서 SYSDATE, SYSTIME, SYSTIMESTAMP, SYSDATETIME를 통해서 날짜/시간을 입력하면 0(zero datetime)이 입력되는 문제를 수정했다.

CREATE TABLE testtbl (field1 INTEGER);
CREATE TABLE resulttbl (ts TIMESTAMP);

CREATE TRIGGER batchtestresult AFTER INSERT ON testtbl
EXECUTE AFTER INSERT INTO resulttbl VALUES (SYSTIMESTAMP);

INSERT INTO testtbl VALUES(1);

SELECT * FROM resulttbl;
  ts
===============================
  12:00:00 AM 00/00/0000

AUTO_INCREMENT 칼럼이 있는 테이블을 RENAME할 수 없는 문제(CUBRIDSUS-9691)

AUTO_INCREMENT 속성을 가지는 칼럼을 포함한 테이블의 이름을 변경할 때 오류가 발생되는 문제를 수정했다.

INSERT ON DUPLICATE KEY UPDATE 문에서 SELECT 문의 칼럼을 참조할 때 오류 수정(CUBRIDSUS-8337)

아래의 예와 같이 ON DUPLICATE KEY UPDATE 절에서 SELECT 문의 칼럼을 참조할 때 오류가 발생하는 문제를 수정했다.

INSERT INTO t1 (field_1, field_2, field_3)
SELECT t2.field_a, t2.field_b, t2.field_c FROM t2 ON DUPLICATE KEY UPDATE t1.field_3 = t2.field_c;
ERROR: t2.field_c is not defined.

ORDER BY 절 뒤에 질의문이 이어질 경우 문법 오류가 발생하는 문제(CUBRIDSUS-6920)

ORDERY BY 절이 질의문의 가장 뒤에 위치하는 것으로 다루어져 "SELECT ~ ORDER BY ~ UNION SELECT ~ "처럼 ORDER BY 절 뒤에 문장이 이어지는 경우 문법 오류로 처리하는 문제를 수정했다.

SELECT * FROM tbl1 ORDER BY a UNION SELECT * FROM tbl2 ORDER BY b;

참고로 수정 이전 버전에서는 아래와 같이 각각의 SELECT 문을 괄호로 묶어줘야만 한다.

(SELECT * FROM tbl1 ORDER BY a) UNION (SELECT * FROM tbl2 ORDER BY b);

NOT NULL 제약 조건을 가진 ENUM 타입 칼럼에 대한 인덱스 전체 검색 시에 정렬 안되는 문제(CUBRIDSUS-10841)

NOT NULL 제약 조건을 가지는 ENUM 타입 컬럼에 대해서 인덱스 전체 검색(index full scan) 시에 정렬이 되지 않는 문제를 수정했다.

CREATE TABLE t1 (e ENUM('a', 'b', 'c', 'd', 'e') NOT NULL);
CREATE INDEX idx_t1 ON t1 (e);
INSERT INTO t1 VALUES (3), (1), (2), (5), (4);

SELECT * FROM t1 ORDER BY 1;

click counter 질의로 인한 교착 상태 발생 후에 질의 결과 잘못되는 문제(CUBRIDSUS-5009)

두 개 이상의 응용 프로그램이 동시에 INCR/DECR 함수를 수행할 때 교착 상태가 발생한 후에 질의 결과가 잘못되는 문제를 수정했다.

T1 T2
-- autocommit off -- autocommit off
CREATE TABLE t1(a INT PRIMARY KEY);  
INSERT INTO t1 VALUES (1),(4),(7);  
COMMIT;  
INSERT INTO t1 VALUES (3);  
  DELETE FROM t1 WHERE a=4;
SELECT INCR(a) FROM t1 WHERE a=3; -- BLOCKED  
  SELECT INCR(a) FROM t1 WHERE a=1; -- BLOCKED
  -- a deadlock is detected
0 rows selected.  
SELECT INCR(a) FROM t1 WHERE a=3;  
0 rows selected.  
-- the same as above  

자동 커밋 OFF인 상태에서 테이블 생성 후 고유 키 위반 오류 이후 INSERT 문 재수행 시 -96 오류가 발생하는 현상(CUBRIDSUS-10239)

자동 커밋 OFF인 상태에서 테이블 생성 후 INSERT 문 수행 도중 고유 키 위반 오류가 발생한 이후, INSERT 문을 재수행하면 -96번 오류가 발생하는 현상을 수정했다.

% csql testdb --no-auto-commit
CREATE TABLE tbl(col1 INTEGER UNIQUE);
INSERT INTO tbl SELECT 500 + ROWNUM FROM db_class a, db_class b;
INSERT INTO tbl SELECT ROWNUM FROM db_class a, db_class b;
ERROR: Operation would have caused one or more unique constraint violations. INDEX u_t_i(B+tree: 0|139|540) ON CLASS t(CLASS_OID: 0|486|2). key: 501(OID: 0|551|358).
INSERT INTO tbl SELECT 500 + ROWNUM FROM db_class a, db_class b;
ERROR: Media recovery may be needed on volume "/home1/cubrid1/CUBRID/databases/testdb/testdb".

DELETE, UPDATE 범위 질의에서 키 잠금 오류로 인한 고유 키 위반 오류 발생 현상(CUBRIDSUS-9382)

여러 개의 응용 프로그램이 동시에 DELETE, UPDATE의 범위 질의를 수행할 때 키 잠금 오류로 인해 고유 키 위반 오류가 발생하는 현상을 수정했다.

중복되는 키가 많아지면서 인덱스 노드의 분할 오류로 인해 INSERT 문 수행에 실패하는 문제(CUBRIDSUS-9829)

중복되는 키가 많아 중복되는 레코드들의 주소 목록이 커진 상태에서, 인덱스의 리프 노드(leaf node)를 분할하며 위치할 노드를 잘못 선택하여 INSERT 문 수행에 실패하는 현상을 수정하였다.

단일 컬럼 인덱스의 key 크기가 데이터베이스 페이지 크기의 1/4보다 큰 경우 인덱스 생성이 실패하는 문제(CUBRIDSUS-10570)

단일 컬럼 인덱스의 key 크기가 데이터베이스 페이지 크기의 1/4보다 큰 경우에 해당 인덱스를 생성할 수 없는 문제를 수정했다.

CREATE TABLE tbl (col1 VARCHAR (10), col2 CHAR (4096));
INSERT INTO tbl VALUES ('1007', '100001');
INSERT INTO tbl VALUES ('1009', '100001');

-- 수정 이전 버전에서 아래와 같은 인덱스를 생성할 수 없는 문제가 존재했다.
CREATE INDEX tbl_idx2 ON tbl (col2);
ERROR: Schema manager internal corruption detected.

논리 표현식을 괄호 없이 사용할 수 있도록 확장(CUBRIDSUS-7392)

논리 표현식(logical expression)을 괄호 없이 사용할 수 있도록 수정했다.

-- 수정 이전 버전에서는 아래 질의의 논리 표현식에서 반드시 괄호를 명시해야 했다.
SELECT * FROM t1 ORDER BY (code > 10);
SELECT SUM((code>10)) FROM t1;

OR 연산자의 피연산자로 항상 거짓인 조건들이 주어졌을 때 질의 결과가 잘못되는 문제(CUBRIDSUS-10475)

CREATE TABLE tab0 (col1 INTEGER);
INSERT INTO tab0 VALUES (514);
INSERT INTO tab0 VALUES (698);

-- 아래 질의는 0건을 출력해야 하나 수정 이전 버전에서 2건을 출력하는 오류가 존재한다.
SELECT * FROM tab0 WHERE (col1 BETWEEN 9 AND 2) OR (col1 BETWEEN 5 AND 4);

문장 집합 연산자를 포함한 CREATE 문으로 생성된 테이블을 조회할 때 NULL로 조회되는 문제(CUBRIDSUS-10105)

문장 집합 연산자(UNION, DIFFERENCE, INTERSECT)를 포함한 CREATE 문으로 생성된 테이블을 조회할 때 데이터가 무조건 NULL로 조회되는 문제를 수정했다.

CREATE TABLE t1 AS SELECT '1' a UNION SELECT '2' a;

-- 수정 이전 버전에서는 다음과 같이 잘못된 결과가 출력되었다.
SELECT * FROM t1;
  a
======================
  NULL
  NULL

Windows에서 "0x"로 시작하는 16진수 숫자를 나타내는 문자열을 부동 소수로 변환하지 못하는 문제(CUBRIDSUS-10384)

SELECT CAST ('0x1111' AS float);
VALUES (1), ('123'), ('0x75');
-- 수정 이전 버전에서 위의 질의들을 수행하면 아래의 오류 메시지를 출력했다.
ERROR: Cannot coerce value of domain "character" to domain "float".

질의 계획만 보도록 설정했음에도 불구하고 SELECT 문을 제외한 나머지 질의문들이 실행되는 문제(CUBRIDSUS-9771)(CUBRIDSUS-10352)

질의 최적화 수준을 질의 계획만 보도록 설정했음에도 불구하고 SELECT문을 제외한 INSERT, UPDATE, DELETE, REPLACE, TRIGGER, SERIAL 문 등이 실행되는 문제가 9.0 베타 버전에 존재했으나 실행이 되지 않게 수정했다. 이전 버전에서는 일부 SQL에 대해서는 비정상 종료되는 문제가 존재했다. SELECT 문을 제외한 나머지 질의문은 질의 계획이 출력되지 않는다.

SET OPTIMIZATION LEVEL 514;
REPLACE INTO tbl (col1, col2, col3) VALUES (1, 2, 3);

다국어

COLLATE 수정자가 표현식에 대해 적용될 수 있도록 수정(CUBRIDSUS-9401)

COLLATE 수정자가 표현식에 대해 적용될 수 있도록 수정했다. 다음 예에서 첫 번째 질의와 두 번째 질의는 같은 결과를 반환한다.

SELECT * FROM t WHERE (col > 'a') COLLATE utf8_en_ci;
SELECT * FROM t WHERE col COLLATE utf8_en_ci > 'a' COLLATE utf8_en_ci;

ENUM 타입에 대해 COLLATE 수정자 지원(CUBRIDSUS-8700)(CUBRIDSUS-9943)

ENUM 타입에 대해 COLLATE 수정자를 사용할 수 있다.

SET NAMES utf8 COLLATE utf8_en_ci;

-- 수정 이후 아래 문장들은 정상 수행된다.
CREATE TABLE tbl (a ENUM ('A','B') COLLATE utf8_en_ci);
INSERT INTO tbl VALUES ('a');

ENUM 칼럼은 기본적으로 ENUM 도메인에 해당하는 인덱스 값으로 숫자 타입으로 인식되는데, ENUM 타입 칼럼에 COLLATE 수정자를 사용하는 경우에는 VARCHAR 타입으로 인식한다. ALTER TABLE MODIFY 문을 이용하여 ENUM 타입 칼럼을 다른 문자셋으로 바꿀 수는 없다.

FIND_IN_SET, POSITION, REPLACE, INSTR, LOCATE, SUBSTRING_INDEX 함수가 콜레이션을 고려하도록 수정(CUBRIDSUS-6319)(CUBRIDSUS-8393)

FIND_IN_SET, POSITION, REPLACE, INSTR, LOCATE, SUBSTRING_INDEX 함수가 콜레이션을 고려하도록 수정했다.

SELECT FIND_IN_SET ('b', 'a,B,c' COLLATE 'iso88591_en_ci') r;
        r
=============
        2
SELECT POSITION ('a' IN 'A') r0, POSITION ('a' IN 'A' COLLATE 'utf8_en_ci') r1;
    r0           r1
==========================
    0            1

대소문자 구분없는 콜레이션에 대한 LIKE 검색이 대소문자를 구분하지 않도록 수정(CUBRIDSUS-8391)

대소문자 구분없는 콜레이션에 대한 LIKE 검색이 대소문자를 구분하는 문제를 수정했다.

CREATE TABLE t (v STRING COLLATE utf8_en_ci);
INSERT INTO t VALUES ('I'), ('i');

-- 수정 이전 버전에서 'I'가 질의 결과에서 제외되었지만, 9.1부터는 'I'와 'i' 모두 출력된다.
SELECT * FROM t WHERE v LIKE '%i%';

콜레이션을 가지는 칼럼에 대한 인덱스 생성 변경(CUBRIDSUS-7737)

콜레이션을 가지는 칼럼에 대한 인덱스 생성 시에 해당 콜레이션을 고려하도록 수정했다.

9.0 베타 버전에서 iso88591_bin, utf8_bin, euckr_bin, iso88591_en_cs, utf8_en_cs, utf8_ko_cs 이외의 콜레이션을 가지는 칼럼에 대해서 생성된 인덱스는 재생성해야 한다.

CREATE TABLE tbl (id INTEGER, s STRING COLLATE utf8_en_ci);
CREATE INDEX ix1 ON tbl (s DESC);

또한 확장있는 콜레이션을 가지는 칼럼에 대한 인덱스 생성 시에 키 구분자(separator)로 9.0 베타 버전과 같이 문자열 전체를 사용하지 않고 최소한의 prefix를 사용하도록 개선했다.

참고로 확장있는 콜레이션을 가지는 칼럼에 대해 prefix 인덱스를 생성할 수 없다.

CREATE TABLE t1 (s1 VARCHAR(200) COLLATE utf8_ja_exp);
CREATE INDEX i ON t1 (s1(5));
ERROR: before ' ; '
Prefix index is not allowed on attribute 's1' (has collation with expansions).

유니코드 정규화가 수행되지 않는 문제(CUBRDISUS-8685)

유니코드 정규화(normalization)를 수행하도록 설정했는데도 정규화가 수행되지 않는 문제를 수정했다.

9.0 베타 버전에서 사용했던 LDML 파일의 정규화 관련 태그는 더 이상 사용되지 않으며, 다음과 같은 두 개의 시스템 파라미터가 사용된다.

  • unicode_input_normalization: 데이터를 저장할 때에 유니코드 결합(composition) 수행 여부를 지정한다.
  • unicode_output_normalization: 데이터를 읽을 때에 유니코드 분해(decomposition) 수행 여부를 지정한다.

서로 호환되지 않는 콜레이션을 가지는 칼럼 조합 간에 외래 키 제약조건을 설정할 수 없도록 수정(CUBRIDSUS-8742)

서로 호환되지 않는 콜레이션을 가지는 칼럼 조합 간에 외래 키 제약조건을 설정할 수 없도록 수정했다.

CREATE TABLE dim (s STRING COLLATE utf8_en_ci PRIMARY KEY);
CREATE TABLE fact (s STRING COLLATE utf8_en_cs PRIMARY KEY);

-- 수정 이후 아래 질의를 수행하면 오류를 출력한다.
ALTER TABLE fact ADD CONSTRAINT FOREIGN KEY(s) REFERENCES dim(s);

존재하지 않는 문자셋의 콜레이션으로 변환하면 비정상 종료되는 문제(CUBRIDSUS-10158)

사용할 수 없는 문자셋의 콜레이션으로 문자열을 변환하려고 하면, csql, cub_cas 프로세스 등이 비정상 종료되는 문제를 수정했다. 아래 예에서 test 데이터베이스는 프랑스어 문자셋만 사용할 수 있다.

% echo fr_FR > $CUBRID/conf/cubrid_locales.txt
% make_locale.sh -t64
% cubrid createdb test
% csql -u dba test -S

하지만 사용할 수 없는 독일어 콜레이션으로 문자열을 변환하려고 했고, 이 경우에 9.0 베타 버전은 비정상 종료되었다.

SET NAMES utf8;

CREATE TABLE t (i INTEGER, s STRING COLLATE utf8_fr_exp_ab);
INSERT INTO t VALUES (1,'cote '), (2,'coté'), (3,'côte '), (4,'côté');

SELECT * FROM t ORDER BY CAST (s AS STRING COLLATE utf8_de_exp);

CHR 함수가 기본 시스템 문자셋만 사용하는 문제(CUBRIDSUS-8934)

CHR 함수가 기본 시스템 문자셋 이외에 현재 지정된 클라이언트의 문자셋을 사용할 수 있도록 확장했다.

SET NAMES utf8;
SELECT CHR (14909886) c;
   c
======================
  'ま'
SELECT CHR (15041963 USING utf8) c;
   c
======================
  '八'

CHR 함수에 COLLATE 수정자를 사용할 수 있도록 확장(CUBRIDSUS-9939)

CHR 함수가 COLLATE 수정자를 사용할 수 있도록 확장했다.

SELECT * FROM tbl WHERE CHR (65) COLLATE utf8_bin > 'a';

CLOB_TO_CHAR 함수의 인자에 변환될 문자열의 문자셋을 지정할 수 있도록 확장(CUBRIDSUS-9467)

CLOB_TO_CHAR 함수를 통해서 변환될 문자열의 문자셋을 지정할 수 있도록 확장하였다.

SELECT CLOB_TO_CHAR (contents USING utf8) FROM documents;

로캘 라이브러리 생성 시 LDML 파일의 속성 값 설정 오류를 검증하도록 수정(CUBRIDSUS-10000)

make_locale 도구(Linux 확장자는 .sh, Windows 확장자는 .bat)를 사용하여 로캘 라이브러리 생성 시 입력으로 주어진 LDML(Locale Data Markup Language) 파일의 속성 값 설정 오류를 검증하여 오류 발견 시 적절한 메시지를 출력하도록 수정했다. 속성 값을 잘못 설정하는 예는 다음과 같다.

  • 같은 콜레이션 타입을 중복해서 설정하는 경우
  • 콜레이션 ID로 설정할 수 있는 범위(0~255)를 벗어나는 경우

또한, 속성 값에 대해 대소문자를 구분하지 않도록 수정했다.

SQL 함수 결과 값에 대해 COLLATE 수정자가 정상 적용되지 않는 문제(CUBRIDSUS-10043)

SQL 함수 결과 값에 대해 COLLATE 수정자가 정상 적용되지 않아 잘못된 결과를 출력하는 문제를 수정했다.

CREATE TABLE tbl (col1 CHAR(10) COLLATE utf8_gen_ci, col2 CHAR(10) COLLATE utf8_gen_ai_ci);
INSERT INTO tbl VALUES ('bbb', '%Bb_%');

-- 수정 이전 버전에서 아래의 질의를 수행하면 1건을 출력하나, 수정 이후 버전에서는 COLLATE 수정자가 정상 적용되어 0건을 출력한다.
SELECT col1, TRIM (REPLACE (col1,'b','B')), TRIM (col2)
FROM tbl
WHERE TRIM (REPLACE (col1,'b','B')) COLLATE utf8_gen LIKE TRIM (col2) COLLATE utf8_gen;

EUC-KR 문자셋 DB에서 고정 길이 문자열에 대한 LIKE 질의 결과가 잘못되는 문제(CUBRIDSUS-9199)

EUC-KR 문자셋 DB에서 고정 길이 문자열에 대한 LIKE 질의 처리시에 ASCII space와 EUC-KR 문자셋의 공백 문자(A1 A1)를 모두 감안하도록 하도록 수정했다.

CREATE TABLE t (col CHAR(10));
INSERT INTO t VALUES ('ab');

-- 수정 이전 버전에서 LIKE 검색되지 않는 문제가 있었다.
SELECT * FROM t WHERE col LIKE '_b';

euckr_bin 콜레이션의 일부 문자 정렬이 잘못되는 현상(CUBRIDSUS-10493)

euckr_bin 콜레이션의 일부 문자 정렬이 잘못되는 현상을 수정했다. EUC-KR 문자셋의 공백 문자(A1 A1)는 ASCII 공백 문자와 동일하게 가장 작은 값으로 간주된다.

EUC 문자셋의 CHAR 타입에 공백 문자로 인해 타입 변환하지 못하는 문제(CUBRIDSUS-10555)

CAST, TO_DATE, TO_TIME, TO_TIMESTAMP, TO_DATETIME, STR_TO_DATE, TO_NUMBER 함수에서 고정 길이 문자열에 포함되는 EUC 공백 문자(A1 A1)를 처리하도록 수정했다.

시스템 문자셋과 클라이언트의 문자셋이 다른 경우에 뷰, 함수 인덱스, 필터링된 인덱스, 트리거에 대한 질의 수행 시 오류 발생되는 문제(CUBRIDSUS-10561)

시스템 문자셋과 클라이언트의 문자셋이 다른 경우에 뷰, 함수 인덱스, 필터링된 인덱스, 트리거에 대한 질의 수행 시 오류가 발생되는 문제를 수정했다. 이 문제는 클라이언트의 문자셋을 SET NAMES 문으로 시스템의 문자셋과 다르게 변경한 후 질의를 수행하는 경우에 발생될 수 있다.

일반적으로 질의문을 파싱(parsing)할 때는 현재 클라이언트의 문자셋을 활용하는데, 이미 저장된 질의문 또는 조건식을 파싱해야 하는 뷰, 함수 인덱스, 필터링된 인덱스, 트리거 등에 포함된 상수 문자열은 특별히 문자셋이 지정되어 있지 않은 경우에는 시스템 문자셋을 이용해야 정상적으로 파싱할 수 있다.

-- 시스템 문자셋이 ko_KR.utf8으로 지정된 경우에

SET NAMES euckr;

-- 9.0 베타 버전에서 아래 질의 수행 시 오류가 발생되었다.
SELECT * FROM db_class;

SHOW TABLES 문장도 위와 같은 구문 분석 오류를 발생시켰었지만, 9.1 버전에서 수정되었다.

-- 시스템 문자셋이 ko_KR.euck로 지정된 경우에

SET NAMES utf8;

-- 9.0 베타 버전에서 아래 질의 수행 시 오류가 발생되었다.
SHOW TABLES;

REVERSE 함수, BETWEEN 조건, 계층 연산자의 콜레이션 지원(CUBRIDSUS-10423)

REVERSE 함수와 BETWEEN 조건이 콜레이션을 감안하도록 수정하였다.

SET NAMES utf8;
SELECT LOCATE ('0', REVERSE ('22'));

PRIOR, CONNECT_BY_ROOT 계층 연산자에 COLLATE 수정자를 적용할 수 있도록 확장했다.

CREATE TABLE tbl (
  id VARCHAR COLLATE utf8_en_cs,
  parentid VARCHAR COLLATE utf8_en_ci,
  msg VARCHAR (32)
);

INSERT INTO tbl VALUES ('a', NULL, 'A');
INSERT INTO tbl VALUES ('b', NULL, 'B');
INSERT INTO tbl VALUES ('c', 'A', 'AA');
INSERT INTO tbl VALUES ('d', 'a', 'AB');
INSERT INTO tbl VALUES ('e', 'b', 'BA');
INSERT INTO tbl VALUES ('f', 'b', 'BB');
INSERT INTO tbl VALUES ('g', 'f', 'BBA');
INSERT INTO tbl VALUES ('h', 'g', 'CBA');

SELECT *
FROM tbl
CONNECT BY (PRIOR id) COLLATE utf8_en_cs = parentid
ORDER BY id;

SELECT id, parentid, msg, CONNECT_BY_ROOT id
FROM tbl
WHERE (CONNECT_BY_ROOT id) COLLATE utf8_en_ci < 'D'
START WITH parentid IS NULL
CONNECT BY PRIOR id = parentid
ORDER BY id;

Ubuntu Linux에서 make_locale.sh 스크립트 실행이 안 되는 문제(CUBRIDSUS-10647)

dash 쉘에서 make_locale.sh 실행이 안 되는 문제를 수정했다.

ISO-8859-1 문자셋에서 확장 ASCII 코드에 대한 대소문자 변환이 안 되는 문제(CUBRIDSUS-10624)

ISO-8859-1 문자셋에서 확장 ASCII 코드(C0 - FE 영역)에 대해 대소문자 변환이 정상적으로 처리되지 못하는 문제를 수정했다. 이로 인해서 확장 ASCII 영역에 속하는 문자를 포함하는 사용자 식별자를 사용하는데 아래와 같은 문제점이 존재했다.

  • 사용자 이름, 그룹 이름이 대문자로 변환되지 못하는 문제
  • CREATE, ALTER와 같은 일반적인 스키마 작업을 할 수 없는 문제
  • 문자열 변환과 같은 문자열 처리가 정상적으로 이뤄지지 못하는 문제

두 개의 인자를 가지는 표현식에 대한 콜레이션 결정 방식 오류(CUBRIDSUS-10560)

두 개의 인자를 가지는 표현식에 대한 콜레이션 결정 방식의 오류를 수정했다.

SET NAMES utf8;

CREATE TABLE t (s1 STRING COLLATE utf8_bin, s2 STRING COLLATE iso88591_bin);
INSERT INTO t VALUES ('a', 'b');

-- 9.0 베타 버전에서 아래 질의 수행 시 실패
SELECT s1 || s2 FROM t;

허용 한계를 초과하여 PREPARE 문을 수행할 때 발생하는 오류 메시지를 잘못 출력하는 문제(CUBRIDSUS-8998)

하나의 응용 프로그램에 허용되는 최대 개수(20개)를 초과하여 PREPARE 문을 수행할 때 "ERROR: Too many prepared statements." 오류 메시지를 출력해야 하나, "ERROR: No error message available."로 잘못 출력하는 문제를 수정했다.

CLOB_FROM_FILE과 BLOB_FROM_FILE 함수에 잘못된 경로의 파일이 주어지면 부정확한 오류 메시지를 출력하는 문제(CUBRIDSUS-10320)

CLOB_FROM_FILE과 BLOB_FROM_FILE 함수에 잘못된 경로의 파일이 입력되면 "해당 경로가 유효하지 않다"는 오류 메시지를 출력하도록 수정했다.

SELECT CLOB_FROM_FILE ('file:/home/cubrid/databases/lob/ces_722/image_t.00001357286783349177_590');
-- 2008 R4.3 이하 버전에서는 다음 오류를 출력했다.
ERROR: Cannot coerce clob to type unknown data type.

-- 9.0 Beta에서는 다음 오류를 출력했다.
Attempted to create string with illegal length - 1545942208

FORMAT 함수의 인자가 숫자가 아닌 경우 부적절한 오류를 출력하는 현상(CUBRIDSUS-10426)

FORMAT 함수의 인자가 숫자가 아닌 경우 부적절한 오류를 출력하는 문제를 수정했다.

SELECT  FORMAT ('nan', 2);

-- 수정 이전 버전에서 위의 질의를 실행하면 아래 오류를 출력했다.
ERROR: No error message available.
SELECT  FORMAT (CAST('nan' as double), 2);

-- 수정 이전 버전에서 위의 질의를 실행하면 아래 오류를 출력했다.
ERROR: Execute: Query execution failure #1326.

분할

특정 분할을 명시하도록 PARTITION 절 지원(CUBRIDSUS-9492)(CUBRIDSUS-9935)

특정 분할(partition)을 지정할 때 분할 테이블 이름을 명시하지 않고 분할 이름만 명시하여 지정할 수 있도록 PARTITION 절을 지원한다. PARTITION 절은 분할 테이블 이름 뒤에 명시할 수 있으며, SELECT 문 뿐만 아니라 분할을 사용할 수 있는 모든 SQL에 사용할 수 있다.

-- 기존 지원 형태
SELECT * FROM athlete2__p__event2;

-- 아래 질의는 기존에 사용하던 위의 문장과 같다.
SELECT * FROM athlete2 PARTITION (event2);

INSERT 문 등에 PARTITION 절을 명시했을 때 지정된 파티션이 정의와 다를 경우에는 오류가 반환된다.

CREATE TABLE t (i INTEGER)
PARTITION BY RANGE(i) (
  PARTITION p0 VALUES LESS THAN (10),
  PARTITION p1 VALUES LESS THAN (100)
);

-- success
INSERT INTO t PARTITION (p0) VALUES (2);

-- error -1108
INSERT INTO t PARTITION (p0) VALUES (20);

WHERE 절을 가지는 질의에 대해 특정 분할을 직접 참조하면 분할 프루닝 과정을 수행하지 않게 되는 성능상의 (작은) 이점이 있으며, 또한 일반적으로 분할 테이블에는 적용되지 못하는 INDEX JOIN, ORDER BY 및 GROUP BY 생략 최적화, 다중 키 범위 최적화, INDEX SKIP SCAN 등의 질의 처리 기법이 사용될 수 있다.

분할 테이블에 대해 click counter (INCR, DECR 함수) 지원(CUBRIDSUS-9157)

분할 테이블에 대해 click counter (INCR, DECR 함수) 사용이 가능하도록 수정했다. 기존에는 INCR, DECR 함수가 정상적으로 동작하지 않아 값이 증가되거나 감소되지 않았었다.

분할 테이블에 대해 INSERT ON DUPLICATE KEY UPDATE, REPLACE 문 지원(CUBRIDSUS-8337)

분할 테이블에 대해 INSERT ON DUPLICATE KEY UPDATE, REPLACE 문을 사용할 수 있도록 수정했다.

범위 분할 테이블의 질의 조건이 "칼럼 > 최대값"일 때 분할 프루닝되지 않는 문제(CUBRIDSUS-7792)

범위 분할 테이블의 질의 조건이 "칼럼 > 최대값"으로 주어지면 분할 프루닝(partition pruning)되지 못하고 전체 분할 테이블을 검색하는 문제를 수정하여, 곧바로 결과 없음을 반환하도록 했다.

CREATE TABLE t (i INTEGER) PARTITION BY RANGE (i) (PARTITION p0 VALUES LESS THAN (21));

SELECT * FROM t WHERE i >= 21;

-- 수정 이후 아래의 조건은 위의 조건과 같이 취급하여 분할 프루닝이 수행된다.
SELECT * FROM t WHERE i > 20;

분할 테이블에서 분할을 제거하면 데이터가 존재함에도 불구하고 COUNT(*) 값으로 0을 출력하는 현상(CUBRIDSUS-9338)

분할 테이블에 여러 건의 INSERT, UPDATE 또는 DELETE를 수행한 이후에 분할을 제거하면 데이터가 존재함에도 불구하고 COUNT(*) 값으로 0을 출력하는 현상을 수정했다.

CREATE TABLE TBL (i INTEGER PRIMARY KEY)
PARTITION BY RANGE (i) (
  PARTITION p0 VALUES LESS THAN (20),
  PARTITION p1 VALUES LESS THAN (40),
  PARTITION p2 VALUES LESS THAN MAXVALUE
);
INSERT INTO tbl SELECT ROWNUM FROM db_class;

ALTER TABLE tbl REMOVE PARTITIONING;

SELECT COUNT (*) FROM tbl;

수정 이전 버전에서 해당 분할 테이블이 있는 데이터베이스는 cubrid checkdb 명령을 수행하면 데이터 불일치로 나타나며, cubrid checkdb -r 명령을 수행해도 데이터가 회복되지 않는 현상이 발생한다.

% cubrid checkdb testdb

Some inconsistencies were detected in your database.
Please consult error_log_file /home/CUBRID/log/testdb_checkdb.err for additional information.

특정 분할을 대상으로 하는 뷰가 updatable하지 못한 문제(CUBRIDSUS-10264)

특정 분할을 대상으로 하는 뷰가 updatable하지 못한 문제를 수정했다.

CREATE TABLE tbl (col1 INTEGER, col2 INTEGER)
PARTITION BY RANGE (col1) (
  PARTITION p0 VALUES LESS THAN (5),
  PARTITION p1 VALUES LESS THAN (10)
);

CREATE VIEW v1 AS SELECT * FROM tbl PARTITION (p0);
INSERT INTO v1 VALUES (1, 1);
ERROR: Not allowed access to partition: 's1__p__p0'

분할 테이블에서 분할 키 값이 칼럼과 다른 문자셋을 가지면 데이터가 정상적으로 분할되지 않는 문제(CUBRIDSUS-9904)

다음 예와 같이 분할 테이블에서 분할 키 값이 칼럼과 다른 문자셋을 가지면 데이터가 정상적으로 분할되지 않는 문제가 존재했으나, 칼럼과 다른 문자셋을 가진 분할 키를 허용하지 않도록 수정했다.

CREATE TABLE t (c CHAR(50) COLLATE utf8_bin)
PARTITION BY LIST(c) (
  PARTITION p0 VALUES IN (_utf8'x'),
  PARTITION p1 VALUES IN (_iso88591'y')
);

뷰를 통해 분할 테이블을 업데이트할 때 에러 발생해도 영향받는 레코드 수를 잘못 출력하는 현상(CUBRIDSUS-9011)

뷰를 통해 분할 테이블을 업데이트할 때 에러가 발생했음에도 불구하고 UPDATE 문의 영향받은 레코드(affected rows) 수를 잘못 반환되는 문제를 수정했다.

CREATE TABLE t (i INTEGER) PARTITION BY RANGE (i) (PARTITION p0 VALUES LESS THAN(3));
INSERT INTO t VALUES (1), (2);
CREATE VIEW v as SELECT * FROM t;
UPDATE v SET i = i + 1;
-- incorrect affected rows
2 rows affected.
ERROR: Appropriate partition does not exist.

HA

HA 환경에서 노드 상태가 변경되는 경우에 대한 로그 정보 추가(CUBRIDSUS-9748)

HA 환경에서 노드 상태가 변경되는 경우 다음 로그 정보를 추가하도록 수정했다. 이 정보는 error_log_level 시스템 파라미터의 값이 error 이하인 경우에 에러 로그 파일에 기록된다.

  • cub_master 프로세스의 로그 정보는 $CUBRID/log/<hostname>_master.err 파일에 저장되며 다음의 내용이 기록된다.

    HA generic: Send changemode request to the server. (state:1[active], args:[cub_server demodb ], pid:25728).
    HA generic: Receive changemode response from the server. (state:1[active], args:[cub_server demodb ], pid:25728).
  • cub_server 프로세스의 로그 정보는 $CUBRID/log/server/<db_name>_<date>_<time>.err 파일에 저장되며 다음의 내용이 기록된다.

    Server HA mode is changed from 'to-be-active' to 'active'.

슬레이브 노드를 maintenance 모드로 변경하면 마스터 노드의 복제 로그 반영 프로세스가 재시작을 반복하는 문제(CUBRIDSUS-9380)

HA 환경에서 슬레이브 노드를 maintenance 모드로 변경하면 마스터 노드의 복제 로그 반영 프로세스가 반복적으로 재시작하는 문제를 수정했다.

다중 칼럼으로 구성된 기본 키에 DESC 방향이 포함된 경우 데이터가 복제되지 않는 문제(CUBRIDSUS-9774)

CREATE TABLE t (a INTEGER, b INTEGER, c INTEGER, PRIMARY KEY (a, b DESC, c));
INSERT INTO t VALUES (1, 1, 1);

복제 재구축 스크립트 개선(CUBRIDSUS-10327)

ha_make_slavedb.sh 스크립트 내에 설정된 $repl_log_home 디렉터리가 존재하지 않을 경우 이를 생성하도록 수정했다. 또한, $CUBRID_DATABASES 와 $repl_log_home이 서로 다르게 생성된 경우 스크립트 수행 도중 예전에 슬레이브 노드로부터 복사해 온 마스터 노드의 복제 로그가 삭제되지 않는 문제를 수정했다.

databases.txt에 설정한 호스트 이름이 여러 개인 경우 뒤의 호스트 이름을 제대로 인식하지 못할 수 있는 문제(CUBRIDSUS-10344)

HA 환경에서 databases.txt에 설정한 호스트 이름이 여러 개이고 뒤의 호스트 이름이 앞의 호스트 이름을 포함하는 문자열인 경우 뒤의 호스트 이름을 제대로 인식하지 못하는 문제를 수정했다. 예를 들어 수정 이전 버전에서 호스트 이름 리스트가 "node:node1"으로 설정되면 node1을 제대로 인식하지 못하게 되어, "node"가 슬레이브 노드이고 "node1"이 마스터 노드가 되는 경우 RW 브로커 응용 서버(CAS)는 "node1"을 인식하지 못하면서 이에 접속하지 못하게 된다.

ALTER TABLE ... CHANGE COLUMN 문이 슬레이브 노드에 반영되지 않는 문제(CUBRIDSUS-9649)

ALTER TABLE ... CHANGE COLUMN 문이 슬레이브 노드에 반영되지 않는 문제를 수정했다.

ALTER TABLE t1 CHANGE i2 i0 INTEGER FIRST;

응용 프로그램에서 처음 DB에 접속했던 사용자의 소유로 슬레이브 노드에 스키마가 복제되는 현상(CUBRIDSUS-6511)

응용 프로그램에서 처음 DB에 접속했던 사용자의 소유로 슬레이브 노드에 스키마가 복제되는 현상으로, 예를 들어 user1 계정으로 DB에 접속했다가 종료한 후 다시 user2 계정으로 접속하여 테이블을 생성하면 슬레이브 노드에는 처음에 접속했던 user1 소유로 테이블이 생성되었다. 이 문제는 브로커 응용 서버(CAS)를 재시작하지 않는 한 지속되었으나, 이를 수정했다.

기본 키가 없는 테이블에 대한 TRUNCATE 문은 슬레이브 노드로 복제되지 않도록 수정(CUBRIDSUS-6502)

기본 키가 없는 테이블은 복제 대상이 아니므로 해당 테이블에 대한 TRUNCATE 문 수행이 복제되지 않도록 하여 슬레이브 노드의 복제 반영이 지연되는 현상을 수정했다.

자동 커밋 모드가 OFF일 때 AUTO_INCREMENT 칼럼이 있는 테이블에 INSERT를 수행하면 해당 시리얼에 복제 불일치 발생(CUBRIDSUS-9045)

자동 커밋 모드가 OFF일 때 AUTO_INCREMENT 칼럼이 있는 테이블에 INSERT를 수행하면 해당 AUTO_INCREMENT를 관리하는 시리얼에 복제 불일치가 발생하는 현상을 수정했다. AUTO_INCREMENT는 db_serial 시스템 카탈로그 테이블에서 시리얼 값으로 관리된다.

Sharding

질의문에 두 개 이상의 shard 힌트가 서로 다른 shard를 가리키는 경우 오류 처리하도록 수정(CUBRIDSUS-9395)

질의문에 두 개 이상의 shard 힌트가 서로 다른 shard를 가리키는 경우 기존에는 첫번째 힌트의 shard를 사용했으나, 모두 같은 shard가 아니면 오류 처리하도록 수정했다.

SELECT *
FROM student
WHERE (id = /*+ shard_key */ 250) OR (id = /*+ shard_key */ 22);

독립된 트랜잭션으로 다수의 SHARD에 대한 SELECT가 실패하는 문제(CUBRIDSUS-9529)

SHARD 환경에서 각각 독립된 트랜잭션으로 처음에 한 SHARD에 SELECT를 수행하고 난 후, 다른 SHARD에 SELECT를 시도하면 실패하는 문제를 수정했다.

SHARD의 메타 정보를 출력하는 명령 수행 시 해당 명령이 비정상 종료되는 문제(CUBRIDSUS-10375)

shard.conf의 MAX_NUM_PROXY 파라미터 값을 2 이상으로 설정하여 다수의 shard proxy를 실행한 상태에서 "cubrid shard status -m"으로 CUBRID SHARD의 메타 정보를 출력하는 명령을 실행하면 해당 명령이 비정상 종료되는 문제를 수정했다.

shard.conf의 기본 설정에 포함된 PROXY_LOG_FILE을 PROXY_LOG_DIR로 바로 잡음(CUBRIDSUS-10381)

기본으로 설치되는 shard.conf 파일에 포함되어 있던 잘못된 PROXY_LOG_FILE 파라미터 설정을 PROXY_LOG_DIR로 바로 잡았다.

바인딩 배열의 shard 키 값이 서로 다른 shard에 존재하면 오류 처리하도록 수정(CUBRIDSUS-9826)

Shard 환경에서 JDBC의 PreparedStatement.executeBatch(), CCI의 cci_execute_array()와 같이 여러 개의 값을 바인딩하여 질의를 일괄 처리하는 함수에서 바인딩하는 배열의 shard 키 값이 서로 다른 shard에 존재하면 해당 함수의 실행을 오류 처리하도록 수정했다.

prepare 요청이 많아지면서 응답이 오지 않는 현상(CUBRIDSUS-10041)

Shard 환경에서 동시에 동일한 질의에 대한 prepare 요청이 많아지면서 그 중 하나가 질의 타임아웃 또는 PROXY_TIMEOUT 시간 내에 처리하지 못하게 되는 경우, 처리 대기중이던 나머지 prepare 요청들도 함께 응답을 받지 못하는 문제를 수정했다.

shard proxy에서 연결 URL의 rcTime 값을 설정해도 원래의 연결로 복귀하는 동작이 정상 수행되지 않는 문제(CUBRIDSUS-10823)

shard proxy가 절체되는 경우 연결 URL에 rcTime이 설정되어 있으면 rcTime이 지난 이후 원래의 연결로 복귀하는 시도를 해야 하나, 이 동작이 정상 수행되지 않는 문제를 수정했다.

CUBRID SHARD proxy에서 인증 실패 시 적절한 에러 메시지를 출력하도록 수정(CUBRIDSUS-8839)

CUBRID SHARD proxy에서 인증 실패 시에도 에러 메시지를 출력하지 않았으나, 다음의 예와 같이 적절한 에러 메시지를 출력하도록 수정했다.

Authorization error.(Address is rejected)

드라이버

[JDBC][CCI] 질의 타임아웃 시간 계산 방식 개선(CUBRIDSUS-9585)

응용 프로그램 단에서 사용한 시간을 제외한 나머지 시간을 서버에 전달하여 응용 프로그램이 요구하는 질의 타임아웃 기간이 만료되면 질의 수행이 중단되도록 수정했다.

[JDBC][CCI] 질의 타임아웃을 설정하면 fetch 도중에 질의 타임아웃이 발생하면서 실패하는 현상(CUBRIDSUS-9043)

브로커 파라미터 MAX_QUERY_TIMEOUT, JDBC의 setQueryTimeout 메서드, 연결 URL의 queryTimeout 속성으로 질의 타임아웃을 설정하면 fetch 도중에 질의 타임아웃이 발생하면서 실패하는 현상이 있었으나, 질의 execute 시간에만 타임아웃 발생이 가능하게 하고 fetch 도중에는 타임아웃이 발생하지 않도록 수정했다.

또한, cci_execute_batch 함수와 cci_execute_array 함수에서는 질의 타임 아웃이 동작하지 않도록 수정했다.

[JDBC][CCI] 배열/배치 실행 함수에서 질의를 실행하는 도중 교착 상태가 발생하면 나머지 질의를 수행하지 않도록 수정(CUBRIDSUS-9692)

JDBC의 PreparedStatement.executeBatch 메서드 또는 CCI의 cci_execute_array, cci_execute_batch와 같은 배열/배치 실행 함수에서 각각의 질의문을 실행하는 도중 교착 상태(deadlock)가 발생했음에도 불구하고 나머지 질의를 계속 수행했었지만, 교착 상태가 발생하면 나머지 질의 수행을 중단하도록 수정했다. 그 외에 일반적인 오류가 발생하는 경우에는 나머지 질의를 계속 수행한다.

[JDBC][CCI] SHOW EXEC STATISTICS ALL 문장 끝에 세미콜론(;)이 없으면 오류 발생되는 문제(CUBRIDSUS-7430)

응용 프로그램에서 SHOW EXEC STATISTICS ALL 구문을 수행할 때 문장 끝에 세미콜론(;)이 포함되어 있지 않으면 실패하는 현상을 수정했다. 수정 이전 버전에서도 CUBRID 매니저, 쿼리 브라우저 및 CSQL 등은 이와 같은 문제가 발생하지 않았고, JDBC 및 CCI 응용 프로그램만 이와 같은 문제가 존재했다.

[CCI] CCI_U_TYPE_ENUM 타입 추가(CUBRIDSUS-10236)

ENUM 타입 컬럼에 대한 CCI의 데이터베이스 타입(u_type)인 CCI_U_TYPE_ENUM을 추가했다.

CCI_U_TYPE_ENUM은 CCI_A_TYPE_STR을 통해 값을 조회하거나 전달할 수 있다.

cci_bind_param (req, 1, CCI_A_TYPE_STR, (char *) buffer, CCI_U_TYPE_ENUM, CCI_BIND_PTR);
cci_get_data (req, 1, CCI_A_TYPE_STR, &buffer, &ind);

[JDBC][CCI] ENUM 칼럼의 타입으로 "VARCHAR" 대신 "ENUM"을 반환하도록 수정(CUBRIDSUS-10236)

ENUM 칼럼의 타입으로 "VARCHAR" 대신 "ENUM"이 반환되도록 수정했다.

  • JDBC DatabaseMetaData를 통한 타입 이름 조회

    DatabaseMetaData dbmd = conn.getMetaData();
    rs = dbmd.getColumns(null, null, "tbl", null);
    while (rs.next()) {
     String type = rs.getString("type_name");
     System.out.println("Column type is:" + type);
    }
    
  • CCI의 cci_schema_info와 cci_get_result_info 함수를 통한 타입 형식 조회

    res_col_info = cci_get_result_info (req, &stmt_type, &col_count);
    
    for (i = 1; i <= col_count; i++)
      {
        printf ("resultset metadata - column type: %d\n",
                 CCI_GET_RESULT_INFO_TYPE (res_col_info, i));
      }
    

[JDBC] 예외 발생 시 메시지에 다양한 정보를 출력하도록 수정(CUBRIDSUS-9611)

JDBC에서 예외 발생 시 메시지에 브로커 응용 서버(CAS) ID, CAS PID, SESSION ID, 연결 URL을 출력하도록 수정했다.

[JDBC] executeBatch 메서드가 실행에 실패하는 현상(CUBRIDSUS-9496)

JDBC의 executeBatch 메서드 실행 시 "Cannot communicate with the broker or received invalid packet" 오류 메시지와 함께 실패하는 현상을 수정했다.

[JDBC] 하나의 실행 함수로 다수의 질의 수행 도중 질의 계획 실패 등으로 인해 질의가 재시도되는 경우 일부 DML이 반복 수행되는 현상(CUBRIDSUS-8472)

하나의 실행 함수로 여러 개의 질의 수행 도중 질의 계획 실패 등으로 질의가 첫번째 질의부터 재시도되는 경우, 앞서 수행되었던 일부 DML이 롤백되지 않아 반복 수행되는 문제를 수정했다.

-- 아래의 MULTI_STMT는 하나의 작업으로 간주한다.
String MULTI_STMT = "INSERT INTO T1 VALUES (1, 1); INSERT INTO T1 VALUES (2, 2); UPDATE T2 SET A = 0";
PreparedStatement p = c.prepareStatement(MULTI_STMT);
boolean retval = p.execute();

[JDBC] 자동 커밋 모드에서 커서 타입이 TYPE_FORWARD_ONLY인 업데이트 가능한 결과 셋에 대해 updateRow()를 수행하면 예외 처리되는 문제(CUBRIDSUS-9313)

자동 커밋 모드에서 커서 타입이 TYPE_FORWARD_ONLY인 업데이트 가능한 결과 셋(resultSet)에 대해 updateRow()를 수행하면 "Internal server error"로 예외 처리되는 문제를 수정했다. 수정 이전 버전에서는 커서 타입이 TYPE_SCROLL_SENSITIVE인 경우에만 결과 셋의 업데이트가 가능했으나, 수정 이후 모든 커서 타입(TYPE_FORWARD_ONLY, TYPE_SCROLL_INSENSITIVE, TYPE_SCROLL_SENSITIVE)에 대해 결과 셋의 업데이트가 가능하게 되었다.

conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
...
rs.updateNull("col2");
rs.updateRow();

[JDBC] 연결 URL에서 connectTimeout을 설정해도 altHosts로 재연결을 시도하지 않는 문제(CUBRIDSUS-10240)

JDBC에서 연결 URL에 connectTimeout을 설정해도 connectTimeout이 발생되었을 때 altHosts로의 재연결을 시도하지 않고 오류가 발생하는 문제를 수정했다.

[JDBC] 응용 프로그램에서 Statement를 닫지 않았음에도 불구하고 PreparedStatement.clearParameter() 메서드 호출 시 예외 발생(CUBRIDSUS-10274)

JDBC 응용 프로그램에서 사용자가 DB 연결을 종료하지 않았고 Statement를 닫지 않았음에도 불구하고 PreparedStatement.clearParameter() 메서드를 호출하면 'Connection or Statement might be closed' 예외가 발생하는 문제를 수정했다.

[CCI] 같은 SQL을 두 번 prepare 했을 때 statement pool에서 statement가 제거되지 않는 문제(CUBRIDSUS-9397)

한 DB 연결에서 같은 SQL로 두 번 prepare 했을 때 두 번째 statement를 닫으면 사용 중인 statement pool에서 해당 statement가 제거되지 않는 문제를 수정했다.

[CCI] T_CCI_ERROR 구조체 포인터를 사용하는 함수에 포인터 값으로 NULL을 입력하면 응용 프로그램이 비정상 종료하는 현상(CUBRIDSUS-9435)

CCI 응용 프로그램에서 cci_datasource_release 등 T_CCI_ERROR 구조체 포인터를 사용하는 함수에 포인터 값으로 NULL을 입력하면 응용 프로그램이 비정상 종료하는 현상을 수정했다.

[CCI] 비동기 모드로 SELECT 질의 수행 이후 fetch가 완료되면 CAS_NO_MORE_DATA 오류가 발생하는 문제(CUBRIDSUS-7170)

비동기 모드로 SELECT 질의 수행 이후 fetch가 완료되면 CCI_NO_MORE_DATA 오류 대신 CAS_NO_MORE_DATA 오류가 발생하는 문제를 수정했다.

res = cci_execute (req, CCI_EXEC_ASYNC, 0, &error);

[CCI] Windows CCI 응용 프로그램이 연결 대상 DB 서버와 접속할 수 없을 때 무한 대기하는 현상(CUBRIDSUS-9361)

연결하고자 하는 데이터베이스 서버가 존재하지 않는 경우와 같이 서버에 접속할 수 없을 때 Windows CCI 응용 프로그램이 무한대기하는 문제를 수정했다.

[CCI] 질의를 다중 처리하는 함수들에서 질의 결과를 전달받을 인자에 NULL이 입력되면 응용 프로그램이 비정상 종료되는 문제(CUBRIDSUS-9600)

cci_execute_batch, cci_execute_array, cci_execute_result 함수들의 질의 결과를 전달받을 인자에 NULL이 입력되면 "invalid argument"라는 오류 메시지를 출력하도록 수정했다.

[CCI] cci_is_holable 함수 추가(CUBRIDSUS-8803)

해당 request handle의 holdable cursor 여부를 반환하는 cci_is_holdable 함수를 추가했다.

holdable = cci_is_holdable (req_handle);

[CCI] DATASOURCE에서 사용한 연결을 닫은 후 연결 핸들을 그대로 다시 사용하는 경우 응용 프로그램이 비정상적으로 동작하는 문제(CUBRIDSUS-9586)

datasource를 사용하는 CCI 응용 프로그램에서 사용한 연결을 닫은 후 연결 핸들을 그대로 다시 사용하면 응용 프로그램이 비정상적으로 동작했으나 오류를 출력하도록 수정했다.

con_1 = cci_datasource_borrow (ds, &error);
cci_prepare_and_execute (con_1, query, 1, &exec_retval, &error);
ret = cci_datasource_release (ds, con_1, &error);

ret = cci_prepare_and_execute (con_1, query, 1, &exec_retval, &error); /* invalid access */

[CCI] pool_prepared_statement=off 상태에서 DATASOURCE 해제 후 cci_execute()를 호출하면 비정상 종료되는 문제(CUBRIDSUS-10847)

pool_prepared_statement=off 상태에서 DATASOURCE를 해제한 후에 이후 닫힌 핸들로 cci_execute() 함수를 호출하면 비정상 종료되는 문제를 수정했다.

[CCI] prepared statement를 실행하는 도중 -20004번 오류가 발생하는 문제(CUBRIDSUS-10840)

자동 커밋 모드가 ON인 상태로 cci_execute()를 실행하는 도중 CAS_ER_STMT_POOLING 오류가 발생하면 드라이버가 prepare를 내부적으로 재시도하는데 이와 동시에 CAS가 재시작되면 -20004 오류(CCI_ER_COMMUNICATION)가 발생하는 문제를 수정했다.

[CCI] cci_execute 함수를 통해 다중 질의문 수행 시 두번째로 해당 함수를 호출하면 오류가 발생하는 문제(CUBRIDSUS-10424)

cci_execute 함수를 통해 다중 질의문 수행 시 다중 질의문 중 첫번째와 마지막의 질의 유형이 다른 경우, 예를 들어 첫번째가 UPDATE 문이고 마지막이 SELECT 문인 경우에 두번째로 해당 함수를 호출하면 "Invalid cursor position" 오류가 발생하는 문제를 수정했다.

static char *MULTI_STMT = "UPDATE T1 SET B = A; SELECT A FROM T1 WHERE A = ?;";

result = cci_execute (request, CCI_EXEC_QUERY_ALL, 0, error); /* 1st */

result = cci_execute (request, CCI_EXEC_QUERY_ALL, 0, error); /* 2nd */

[CCI] Windows에서 cci_set_allocator 함수가 동작하지 않도록 수정(CUBRIDSUS-10669)

Windows에서는 cci_set_allocator 함수를 사용해도 메모리 할당 및 해제 함수가 변경되지 않도록 수정했다.

[CCI] 정적 라이브러리를 사용하면 링크 오류가 발생하는 문제(CUBRIDSUS-10743)

CCI 정적 라이브러리를 사용하여 C 코드를 컴파일하면 링크 오류가 발생하는 문제를 수정했다.

[PHP] 웹 페이지 로딩을 중단했음에도 불구하고 서버 단에서는 수행 중이던 질의가 중단되지 않는 문제(CUBRIDSUS-5855)

PHP 응용 웹사이트에서 페이지 로딩을 중단했음에도 서버 단에서는 수행 중이던 질의가 중단되지 않는 문제를 수정했다. 수정 이전 버전에서 사용자가 장시간의 질의 수행을 요구하는 웹 페이지에 대해 로딩 중단을 반복하면 웹 서버 단에서 해제해도 되는 연결 리소스가 늘어나는 현상이 발생한다.

유틸리티

CSQL에서 결과 출력 시 칼럼의 길이를 제한하는 기능 추가(CUBRIDSUS-9643)

CSQL에서 결과 출력 시 칼럼의 길이를 제한하는 기능을 추가했다.

  • ;STring-width는 문자열과 비트 타입의 칼럼에 대해 출력 길이를 제한하는 CSQL 세션 명령어이다. 명령행 옵션(--string-width)도 제공한다.
  • ;COLumn-width는 타입의 구분 없이 모든 칼럼의 출력 길이를 제한하는 CSQL 세션 명령어이다.

CSQL에 ;line-output 세션 명령 추가(CUBRIDSUS-9537)

CSQL의 명령행 옵션(--line-output)에 해당하는 ;line-output CSQL 세션 명령을 추가했다.

csql> ;line-output on
csql> ;line-output off

CSQL에서 SQL 실행 시간을 기본으로 출력하도록 변경(CUBRIDSUS-9537)

CSQL에서 SQL 수행 시 수행 시간을 기본으로 출력하도록 변경했다. 수행 시간 출력 여부는 ;time CSQL 세션 명령을 통해 변경할 수 있다.

서버의 최대 접속 개수를 초과해도 CSQL에서 --sysadm으로 추가 접속이 가능해짐(CUBRIDSUS-9478)

시스템 파라미터 max_clients 값에 의해 설정된 서버의 최대 접속 개수를 초과하더라도 CSQL에서 시스템 관리자 모드(--sysadm)로 단 하나의 추가 접속이 가능하도록 수정했다.

% csql -u dba --sysadm testdb

Windows에서 CSQL의 ;historylist와 ;historyread 명령 수행 시 지원하지 않는다는 오류를 출력하도록 수정(CUBRIDSUS-10190)

Windows 버전은 ;historylist와 ;historyread 세션 명령어를 지원하지 않기 때문에, 해당 세션 명령이 입력되면 오류 메시지를 출력한다.

로컬 호스트 DB에 접속한 CSQL에서 ;database 실행 시 호스트 이름을 출력하도록 변경(CUBRIDSUS-5243)

로컬 호스트 DB에 접속한 CSQL에서 ;database 실행 시 "localhost"가 아닌 호스트 이름을 출력하도록 변경했다.

csql> ;database
testdb@cubridhost

CSQL에서 주석 내에 작은 따옴표가 포함되어 있을 때 주석 처리가 제대로 되지 못하는 문제(CUBRIDSUS-8999)

다음과 같은 경우에 주석 처리가 정확히 되지 않아 세션 명령어가 수행되지 않는 문제를 수정했다.

csql> -- it's a line comment.
csql> ;exit

유니코드 분해된 문자를 식별자로 가지는 스키마 객체를 CSQL에서 조회할 수 없는 문제(CUBRIDSUS-9923)

테이블 이름이나 트리거 이름 등에 유니코드 분해(decomposition)된 문자가 포함되어 있을 때, CSQL의 ;SCHEMA, ;TRIGGER 세션 명령어로 해당 스키마 객체를 조회할 수 없는 문제를 수정했다.

CSQL 세션 명령어인 ";read" 수행 시 파일 이름 뒤에 공백 문자가 오면 수행에 실패하는 문제(CUBRIDSUS-10357)

아래 명령 수행 시 test.txt 뒤에 공백 문자가 오면 발생되는 오류를 수정했다.

csql> ;read test.txt
ERROR: Too many file names have been entered.

Windows 버전의 CSQL로 긴 질의문 수행 시 비정상 종료되는 문제(CUBRIDSUS-9315)

스택(stack) 오버플로우를 회피하기 위해, Windows 버전의 CSQL의 스택 메모리 크기를 1M에서 8M로 변경하였다.

자바 저장 프로시저를 포함하는 뷰를 언로드한 스키마 파일로 로드할 수 없는 문제(CUBRIDSUS-1520)

자바 저장 프로시저를 포함하는 뷰를 unloaddb 유틸리티로 언로드한 스키마 파일로 loaddb 유틸리티로 로드할 수 없는 문제를 수정했다.

loaddb에 특정 에러를 무시하도록 설정한 경우 제약 조건을 위배하는 데이터가 입력되는 현상(CUBRIDSUS-7650)

loaddb 유틸리티에 --error-control-file=FILE 옵션을 지정하여 특정 에러를 무시하도록 설정한 경우에 제약 조건을 위배하는 데이터가 입력되는 문제를 수정했다. 예를 들어 NULL 에러를 무시하도록 -205를 설정했는데, 기본 키 칼럼에 NULL 데이터가 입력되는 현상이 존재했다. 에러가 발생하면 해당 데이터는 입력하지 않도록 수정했다.

loaddb 수행 시 오류 발생된 행 번호를 잘못 출력하는 문제(CUBRIDSUS-7894)

loaddb 유틸리티가 데이터 로딩 중에 오류가 발생된 행 번호를 잘못 출력할 수 있는 문제를 수정했다.

스키마 파일에 백슬래시('\')로 끝나는 문자열이 포함되어 있으면 loaddb가 실패하거나 잘못된 값으로 로딩되는 현상(CUBRIDSUS-9109)

loaddb 유틸리티가 스키마 파일에 백슬래시('\')로 끝나는 문자열이 포함되어 있으면 정상적으로 로딩되지 못하는 문제를 수정했다.

ALTER TABLE [t] ADD ATTRIBUTE
[dir] character varying(200) DEFAULT 'C:\Databases\',
...;

역순의 PREFIX 인덱스를 잘못 언로드하는 문제(CUBRIDSUS-9966)

역순 prefix 인덱스를 아래 예와 같이 잘못 언로드하여 해당 인덱스를 로딩할 때 오류가 발생되는 문제를 수정했다.

CREATE TABLE t (a VARCHAR (200));
CREATE INDEX i ON t (a (2) DESC);
% cubrid unloaddb -S testdb
% cat testdb_indexes
CREATE INDEX [i] ON [t1] ([a] DESC (2));

db_collation 시스템 카탈로그 뷰의 데이터가 언로드되는 문제(CUBRIDSUS-10350)

9.0 베타 버전의 데이터베이스를 언로드할 때 db_collation 시스템 카탈로그 뷰에 대해 데이터를 언로드하는 문제를 수정했다.

9.0 Beta 버전에서 9.1 버전으로 데이터를 마이그레이션할 때 unloaddb/loaddb 유틸리티를 사용하면 시스템 카탈로그 뷰에 대한 데이터 로딩을 시도하면서 오류가 발생할 수 있으므로, 언로드된 파일에서 db_collation 부분을 제거하거나 unloaddb/loaddb 유틸리티 대신 migrate_90beta_to_91 유틸리티를 사용할 것을 권장한다.

Windows 버전의 backupdb 유틸리티가 잘못된 입력에 대해 내부 에러를 출력하는 문제(CUBRIDSUS-10634)

Windows 버전의 cubrid backupdb 유틸리티의 -D 옵션에 존재하지 않는 디렉터리를 입력하면 "pthread_cond_destroy" 오류가 발생하는 현상을 수정했다.

checkdb 유틸리티 수행을 인터럽트하지 못하는 문제(CUBRIDSUS-7452)

cubrid checkdb 유틸리티의 인덱스 검사 작업을 인터럽트하여 중단시키지 못하는 문제를 수정했다.

killtran 유틸리티를 통해 종료된 트랜잭션의 질의문이 오류를 반환하지 않는 문제(CUBRIDSUS-10133)

질의를 수행중인 트랜잭션을 killtran으로 종료하면 해당 트랜잭션에서 수행중인 질의문의 결과로 아무런 오류가 반환되지 않았으나, "Has been interrupted" 오류를 반환하도록 수정했다.

plandump 유틸리티 또는 슬로우 쿼리 로그 출력 시 질의 원문이 포함되도록 수정(CUBRIDSUS-9593)

cubrid plandump 유틸리티를 통해 질의 계획 대상이 되는 질의를 출력하거나 서버 에러 로그 혹은 브로커 로그에 슬로우 쿼리(slow query)를 출력할 때 기존에는 재작성된(rewritten) 질의문을 출력했으나, 사용자가 입력한 질의 원문도 포함하도록 수정했다.

dumplocale 유틸리티가 로캘 설정이 잘못되어 있을 때 오류를 출력하도록 수정(CUBRIDSUS-10306)

cubrid dumplocale 유틸리티 수행 시 로캘 라이브러리에 존재하지 않는 로캘이 cubrid_locales.txt에 지정되어 있으면 오류를 출력하도록 수정했다.

SQL 로그 상에 바인딩되는 문자열 값에 ')'이 포함되어 있으면 broker_log_top 유틸리티가 비정상 종료되는 문제(CUBRIDSUS-9245)

SQL 로그 상에 바인딩되는 문자열 값에 ')'이 포함되어 있으면 broker_log_top 유틸리티가 비정상 종료되는 문제를 수정했다.

SQL 로그 파일 형식이 잘못된 경우 broker_log_top 유틸리티가 비정상 종료하는 문제(CUBRIDSUS-10072)

SQL 로그 파일 형식이 잘못되어 있는 경우에 broker_log_top, shard_broker_log_top 유틸리티가 비정상 종료되는 문제를 수정했다.

Windows 버전의 broker_log_top 유틸리티가 UNIX 파일 형식의 SQL 로그 파일을 분석하지 못하는 문제(CUBRIDSUS-10139)

Windows 버전의 broker_log_top 유틸리티가 UNIX 파일 형식의 SQL 로그 파일을 입력으로 받아 정상적으로 분석하지 못하는 문제를 수정했다.

백업 수행 시 체크포인트 작업이 진행 중이면 백업을 중단할 수 없는 문제(CUBRIDSUS-9337)

백업을 수행할 때 체크포인트(checkpoint) 작업이 진행 중이면, 백업 작업에 대해서 인터럽트(Ctrl+C)를 해도 중단되지 않는 문제를 수정했다.

데이터베이스 종료 과정 중 타임아웃 발생시 진행 중인 체크포인트를 중단하여 정상적으로 서버가 종료되도록 수정(CUBRIDSUS-6867)

cubrid server stop 명령으로 데이터베이스 종료를 수행하는 시간이 1분 이상 걸리면 데이터베이스를 강제 종료하게 되어 있다. 종료 과정 중에 체크포인트 작업이 오래 걸리는 경우에도 데이터베이스 서버를 강제 종료함으로 인해서 이후 데이터베이스 재시작 시 복구 시간이 오래 걸릴 수 있었으나, 셧다운 과정 중에 정해진 기간이 만료되면 진행 중인 체크포인트 작업을 중단하고 서버를 정상적으로 종료하도록 수정했다.

브로커 상태 정보 출력 시 client wait CAS 개수가 전체 CAS 개수보다 크게 출력되는 현상(CUBRIDSUS-10235)

cubrid broker status -f 명령으로 브로커 상태 정보를 출력할 때, CAS 개수가 최소 개수보다 늘었다가 줄어들었으면 CLIENT WAIT 상태의 CAS 개수가 전체 CAS 개수보다 더 크게 출력되는 현상을 수정했다.

Windows 버전의 createdb 유틸리티 수행을 중단시키는 경우 비정상 종료되는 문제(CUBRIDSUS-9332)

Windows 버전의 cubrid createdb 유틸리티 수행을 인터럽트로 중단시키면 비정상 종료되는 문제를 수정했다.

shard_broker_changer 유틸리티를 통해 파라미터 값을 변경할 때 잘못된 값으로 설정되는 문제(CUBRIDSUS-9956)

SQL_LOG, SLOW_LOG, PROXY_LOG 등의 파라미터 값을 shard_broker_changer 유틸리티를 통해 변경할 때 잘못된 값으로 설정되는 문제를 수정했다.

cubrid broker status 명령의 -s 옵션이 주어진 경우 ERR-Q 항목 값을 잘못 출력하는 문제(CUBRIDSUS-10391)

cubrid broker status 명령의 -s 옵션이 주어진 경우 ERR-Q 항목에 초당 오류 질의 개수를 출력했으나, 옵션으로 주어진 N 초 동안의 오류 질의 개수를 출력하도록 수정했다.

Windows 버전 CSQL이 ;append 세션 명령에 파일 인자가 누락되었을 때 잘못된 오류 메시지를 출력하는 문제(CUBRIDSUS-10191)

Windows 버전 CSQL이 ;append 세션 명령에 파일 이름 인자가 누락되었을 때 오류 메시지로 "ERROR: A file name is required."를 출력하도록 수정했다. 수정 이전 버전에서는 "ERROR: Permission denied" 또는 "ERROR: Too many file names have been entered."를 출력했다.

createdb 유틸리티가 데이터베이스 생성 시 요구되는 디스크 공간 크기를 출력하도록 수정(CUBRIDSUS-6623)

createdb 유틸리티가 데이터베이스 생성 시 요구되는 디스크 공간 크기를 출력하도록 했다.

Creating database with 512.0M size. The total amount of disk space needed is 1.5G.

디스크 공간이 부족한 경우에는 추가로 다음과 같은 오류 메시지가 출력된다.

Couldn't create database.
Unable to create volumes for database "testdb". Please refer "/home/CUBRID/log/testdb_createdb.err" for additional information.

DB 생성 시 범위를 벗어난 볼륨 크기를 입력하면 출력하는 오류 메시지 개선(CUBRIDSUS-9761)

DB 생성 시 허용 범위를 벗어난 볼륨 크기를 입력 단위 없이 입력하면 Byte(B) 단위로 입력되었다는 것을 오류 메시지에 포함하여 출력하도록 수정했다.

% cubrid createdb testdb --db-volume-size=1121
Couldn't create database.
The given 'db_volume_size', 1121B is out of range. Choose a size between 20.0M and 20.0G.

설정, 빌드 및 설치

정의되지 않은 시스템 파라미터를 cubrid.conf에 명시하면 클라이언트 및 서버 구동 시 비정상 종료하는 문제(CUBRIDSUS-9765)

9.0 베타 버전에서 cubrid.conf에 존재하지 않는 시스템 파라미터를 설정하면, 클라이언트와 서버 구동시에 비정상 종료되는 문제를 수정했다.

일부 시스템 파라미터를 시스템 운영 중에 변경할 수 있도록 수정(CUBRIDSUS-7625)

다음의 시스템 파라미터들은 시스템 운영 도중 변경할 수 있도록 수정했다.

  • index_scan_oid_buffer_size
  • sort_buffer_size
  • temp_file_memory_size_in_pages
  • unfill_factor
  • volume_extension_path
  • lock_escalation
  • checkpoint_every_npages
  • async_commit
  • access_ip_control
  • access_ip_control_file
  • index_unfill_factor

또한, CSQL에서 ;get 세션 명령으로 시스템 파라미터 값을 구할 때 발생하는 다음 현상들을 수정했다.

  • ;get access_ip_control_file을 수행하면 CSQL이 비정상 종료
  • ;get unfill_factor을 수행하면 잘못된 결과를 출력
  • 정의되지 않은 시스템 파라미터에 대해 ;get 명령을 수행하여 실패한 후에는 정상적인 시스템 파라미터도 ;get 세션 명령으로 조회할 수 없는 문제

CUBRID 소스 파일에서 CCI 드라이버만 빌드하는 옵션 추가 및 CCI 소스 패키지 배포(CUBRIDSUS-8247)

CUBRID 소스 파일에서 CCI 드라이버만 빌드할 수 있도록 configure 스크립트에 --with-cci-only 옵션을 추가했다. 또한, CCI 드라이버만 빌드할 수 있는 소스 패키지를 별도로 배포한다.

브로커 파라미터 SQL_LOG의 값이 NOTICE로 설정되어 있어도 SQL 로그에 정상 수행된 질의가 가끔 출력되는 현상(CUBRIDSUS-10286)

cubrid_broker.conf의 SQL_LOG 값이 NOTICE로 설정되어 있어도 정상 수행된 질의가 가끔 출력되는 현상이 발생할 수 있는데, 이러한 가능성을 줄이도록 수정했다.

Windows에서 브로커 파라미터의 경로 구분자로 '/'도 쓸 수 있도록 수정(CUBRIDSUS-9318)

Windows에서 브로커 파라미터의 경로 구분자로 '/'를 쓸 수 있게 수정했다.

D:/dir/dir/file

Windows에서 ACCESS_CONTROL_FILE 파일 내용 중 "드라이브명:"이 잘못 인식되는 문제(CUBRIDSUS-9318)

ACCESS_CONTROL_FILE 파일 내용을 "db_name:db_user_id:IP_file" 포맷으로 기록할 때 IP_file 경로가 "드라이브명:경로파일명"과 같이 기록될 경우, 드라이브명 뒤의 ":"을 값의 구분자로 오인하여 파일을 제대로 인식하지 못하는 문제를 수정했다.

Windows에서 브로커 파라미터 값이 잘못되었음에도 불구하고 브로커 구동 시 정상 구동되었다는 메시지가 출력되는 문제(CUBRIDSUS-9992)

Windows에서 브로커 파라미터 값이 잘못되었으면 브로커를 구동할 수 없다는 오류 메시지가 정상 출력되도록 수정했다.

Windows에서 CUBRID 엔진 설치 중 Java 설치 여부에 따른 알림 메시지 수정(CUBRIDSUS-9917)

Windows에서 CUBRID 엔진 설치 중 Java 1.6 이상 버전이 설치되지 않았으면 CUBRID Manager를 사용할 수 없다는 메시지를 출력했으나, 이 메시지는 CUBRID 엔진과는 무관한 메시지이므로 이 메시지 대신 자바 저장 프로시저를 사용할 수 없다는 메시지를 출력하도록 수정했다.

기타

Warning을 에러 로그에 출력하도록 설정하면 잘못된 warning 메시지를 출력하는 현상(CUBRIDSUS-9458)

Warning을 에러 로그에 출력하도록 설정하면 정상적인 INSERT/UPDATE/DELETE를 수행함에도 불구하고 잘못된 warning 메시지를 출력되는 문제를 수정했다.

일부 에러 메시지에서 32비트 int 범위를 넘는 64비트 int 값을 잘못 출력하는 문제(CUBRIDSUS-8379)

일부 에러 메시지에서 32비트 int 범위를 넘는 64비트 int 값을 잘못 출력하는 문제를 수정했다.

데이터베이스 접속 요청에 대한 notification 메시지를 한번만 기록하도록 수정(CUBRIDSUS-9885)

데이터베이스 서버에 대한 접속 요청 시에 접속 요청에 대한 처리 시작과 끝을 나타내는 각각의 notification 메시지를 출력하던 것을 하나의 notification 메시지만 출력하도록 수정했다.

응용 클라이언트의 접속 정보는 에러 로그에서 제거하고 접속 로그에 기록하도록 수정(CUBRIDSUS-5962)

응용 클라이언트의 접속 정보가 에러 로그에 너무 많이 기록되어 실제 에러를 파악하기 어려운 문제를 해결하기 위해, 응용 클라이언트의 접속 정보를 에러 로그 대신 접속 로그에 기록하도록 수정했다.

인터럽트 발생 시 인터럽트 에러 외에 다른 에러가 반환되는 문제(CUBRIDSUS-9450)

인터럽트가 발생했을 때 인터럽트 에러 외에 다른 에러가 반환될 수 있는 문제를 수정했다.

여러 클라이언트가 동일한 테이블에 대한 UPDATE 수행 시 -495번 오류가 발생할 수 있는 문제(CUBRIDSUS-10651)

여러 클라이언트가 동시에 같은 테이블에 대해 UPDATE를 수행하고 질의 타임아웃이 자주 발생하는 상황에서, 몇 가지 원인으로 인해 -495번 오류("Execute: Query execution failure #8560")가 발생하는 문제를 수정했다.

하지만 부하가 집중되어 특정 서버 스레드가 UPDATE를 위한 페이지 접근에 여러 번 실패하게 되면 수정 이전 버전에서는 -495번 오류가 발생했는데, 수정 이후 -2번 오류("Internal system failure: no more specific information is available.")가 발생한다. 이런 상황은 동일한 페이지에 대한 UPDATE 요청이 집중되는 상황에서 발생할 수 있는 문제로 사용자는 실패한 질의를 다시 시도해야 한다.

자동 커밋 모드에서 내부 에러 발생 시에 커서가 닫히는 문제(CUBRIDSUS-10840)

자동 커밋 모드에서 내부적으로 -20004번 에러(CAS_ER_STMT_POOLING) 발생 시에 자동 롤백되어 유지되고 있던 커서가 모두 닫히는 문제를 수정했다.

메모리 사용량 초과로 브로커 응용 서버(CAS)가 재시작될 때 메모리 사용량을 CAS 로그에 출력하도록 수정(CUBRIDSUS-10181)

브로커 응용 서버(CAS)가 메모리 사용량 최대값인 cubrid_broker.conf의 APPL_SERVER_MAX_SIZE 초과로 인해 재시작할 때 해당 프로세스의 메모리 사용량을 CAS 로그에 출력하도록 수정했다.

01/10 18:43:42.217 (0) CAS MEMORY USAGE (101M) HAS EXCEEDED MAX SIZE (101M)

브로커 및 데이터베이스 서버의 에러 로그를 임의로 삭제하면 재생성되지 않는 문제(CUBRIDSUS-8351)

브로커 및 데이터베이스 서버의 에러 로그 파일을 임의로 삭제하더라도 재생성되도록 수정했다.

브로커 이름이 길면 응용 프로그램에서 브로커 접속시 브로커가 비정상 종료되는 문제(CUBRIDSUS-9392)

브로커 이름의 길이가 32자 이상이면 응용 프로그램에서 브로커에 접속 시 브로커가 비정상 종료되었으나, 브로커 이름의 길이를 63자까지만 허용하고 또한 브로커 이름이 이보다 길면 브로커를 구동할 수 없도록 수정했다.

Windows에서 서비스가 정상 종료되지 않는 경우에도 정상 종료된 것으로 메시지를 잘못 출력하는 문제(CUBRIDSUS-10143)

Windows에서 "cubrid service stop" 명령을 수행하면 cubrid.conf의 services에 등록된 프로세스들이 모두 정상 종료되지 않았음에도 "++ cubrid service stop: success" 라는 메시지를 출력하는 문제를 수정했다.

Windows에서 서버가 구동된 상태에서 서버 시작을 실행하면 잘못된 메시지가 출력되는 현상(CUBRIDSUS-10216)

Windows에서 서버가 구동된 상태에서 또 다시 서버를 구동하려고 하면 "cubrid server start: success" 메시지가 출력되었으나, "cubrid server is already running" 메시지가 출력되도록 수정했다.

Windows 버전 브로커를 통해 서버에 접속할때 cub_master가 구동되어 있지 않으면 잘못된 에러가 발생하는 문제(CUBRIDSUS-10739)

응용프로그램이 Windows 버전 브로커를 통해 서버에 접속하는 경우 cub_master 프로세스가 구동되어 있지 않으면 잘못된 에러가 발생하고 CAS가 무한 루프를 반복하는 문제를 수정했다.

수정 이전 버전에서 Windows의 경우 아래의 오류 번호를 반환한다. * 첫번째 접속 시도 시 -21112 (An IOException was caught during reading the inputstream) 반환 * 두번째 접속 시도 시 -21013 (Cannot connect to a broker)

수정 전후의 Linux와 수정 이후의 Windows의 경우 아래의 오류 번호를 반환한다. * 첫번째, 두번째 접속 시도 시 모두 -353 (Failed to connect to database server, 'basic', on the following host(s): localhost) 반환

Windows 서비스 프로세스인 CUBRIDService에 설명 추가(CUBRIDSUS-8917)

CUBRID의 Windows 서비스 프로세스인 CUBRIDService에 다음 설명(description)을 추가했다. 이 설명은 Windows의 "제어판 > 시스템 및 보안 > 관리 도구 > 서비스 > CUBRIDService"에서 확인할 수 있다.

Service to execute master,broker,database server and manager server processes for CUBRID.
Service start/stop menu is equal to the command of "cubrid service start/stop".
If you setup "startup type" of this service to "Disabled", you can't use "cubrid service" command.

CUBRID Manager를 통해 DB 사용자를 편집하지 못하는 현상(CUBRIDSUS-9971)

9.0 Beta 버전에서 CUBRID Manager를 통해 DB 사용자의 비밀번호 또는 그룹 변경과 같은 편집 기능을 수행하지 못하는 문제를 수정했다.

9.0 버전부터 STRCMP는 대소문자를 구분하여 문자열을 비교

9.0 이전 버전까지는 STRCMP가 대소문자를 구분하지 않고 문자열을 비교했으나, 9.0 버전부터는 대소문자를 구분하여 문자열을 비교한다. 대소문자를 구분하지 않게 동작하려면 문자열에 대소문자를 구분하지 않는 콜레이션(예: utf8_en_ci)을 지정한다.

-- In previous version of 9.0 STRCMP works case-insensitively
SELECT STRCMP ('ABC','abc');
0

-- From 9.0 version, STRCMP distinguish the uppercase and the lowercase when the collation is case-sensitive.
export CUBRID_CHARSET=en_US.iso88591

SELECT STRCMP ('ABC','abc');
-1

-- If the collation is case-insensitive, it distinguish the uppercase and the lowercase.
export CUBRID_CHARSET=en_US.iso88591

SELECT STRCMP ('ABC' COLLATE utf8_en_ci ,'abc' COLLATE utf8_en_ci);
0

주의 사항

신규 주의 사항

9.1 버전과 9.0 베타 버전 사이에 DB 볼륨 호환 안 됨(CUBRIDSUS-10147)

9.1 버전과 9.0 베타 버전 사이에 DB 볼륨이 호환되지 않게 됨에 따라 CUBRID 9.0 Beta를 9.1로 업그레이드하는 사용자는 CUBRID 9.1 설치 이후 기존의 DB 볼륨을 9.1용으로 반드시 변환해야 한다. 볼륨 마이그레이션을 위해서 9.1 버전에 제공되는 migrate_90beta_to_91 유틸리티를 제공한다.

% migrate_90beta_to_91 <db_name>

보다 자세한 사항은 업그레이드를 참고한다.

9.1 버전과 9.0 Beta 이전 버전 간에 DB 볼륨이 호환되지 않음(CUBRIDSUS-5238)

9.0 Beta 이전 버전과 DB 볼륨이 호환되지 않으므로 cubrid unloaddb/loaddb를 이용하여 데이터를 마이그레이션해야 한다. 보다 자세한 사항은 업그레이드를 참고한다.

Note

9.0 Beta 버전 및 그 이전 버전 사용자는 데이터를 마이그레이션하는 것과 함께 드라이버, 브로커, DB 서버 모두를 반드시 업그레이드해야 한다.

CUBRID_LANG 환경 변수 대신에 CUBRID_CHARSET 및 CUBRID_MSG_LANG 환경 변수로 변경

9.1 버전부터 CUBRID_LANG 환경 변수는 더 이상 사용되지 않으며, 데이터베이스를 생성하거나 구동할 때 CUBRID_CHARSET 환경 변수를 통해 어떤 문자셋을 사용할 지 결정하므로 CUBRID_CHARSET 환경 변수를 반드시 설정해야 한다. 유틸리티 메시지 및 오류 메시지를 출력할 때는 CUBRID_MSG_LANG 환경 변수를 사용하며 생략되면 CUBRID_CHARSET 환경 변수 설정을 따른다.

CCI 응용 프로그램에서 여러 개의 질의를 한 번에 수행한 결과의 배열에 대한 에러 처리 방식 수정(CUBRIDSUS-9364)

CCI 응용에서 여러 개의 질의를 한 번에 수행할 때 2008 R3.0부터 2008 R4.1 버전까지는 cci_execute_array 함수, cci_execute_batch 함수 또는 cci_execute_result 함수에 의한 질의 수행 결과들 중 하나만 에러가 발생해도 해당 질의의 에러 코드를 반환했으나, 2008 R4.3 버전 및 9.1 버전부터는 전체 질의 개수를 반환하고 CCI_QUERY_RESULT_* 매크로들을 통해 개별 질의에 대한 에러를 확인할 수 있도록 수정했다.

수정 이전 버전에서는 에러가 발생한 경우에도 배열 내 각각의 질의들의 성공 실패 여부를 알 수 없으므로, 이를 판단해야 한다.

...
char *query = "INSERT INTO test_data (id, ndata, cdata, sdata, ldata) VALUES (?, ?, 'A', 'ABCD', 1234)";
...
req = cci_prepare (con, query, 0, &cci_error);
...
error = cci_bind_param_array_size (req, 3);
...
error = cci_bind_param_array (req, 1, CCI_A_TYPE_INT, co_ex, null_ind, CCI_U_TYPE_INT);
...
n_executed = cci_execute_array (req, &result, &cci_error);

if (n_executed < 0)
  {
    printf ("execute error: %d, %s\n", cci_error.err_code, cci_error.err_msg);

    for (i = 1; i <= 3; i++)
      {
        printf ("query %d\n", i);
        printf ("result count = %d\n", CCI_QUERY_RESULT_RESULT (result, i));
        printf ("error message = %s\n", CCI_QUERY_RESULT_ERR_MSG (result, i));
        printf ("statement type = %d\n", CCI_QUERY_RESULT_STMT_TYPE (result, i));
      }
  }
...

수정 이후 버전에서는 에러가 발생하면 전체 질의가 실패한 것이며, 에러가 발생하지 않은 경우에 대해 배열 내 각 질의들의 성공 실패 여부를 판단한다.

...
char *query = "INSERT INTO test_data (id, ndata, cdata, sdata, ldata) VALUES (?, ?, 'A', 'ABCD', 1234)";
...
req = cci_prepare (con, query, 0, &cci_error);
...
error = cci_bind_param_array_size (req, 3);
...
error = cci_bind_param_array (req, 1, CCI_A_TYPE_INT, co_ex, null_ind, CCI_U_TYPE_INT);
...
n_executed = cci_execute_array (req, &result, &cci_error);
if (n_executed < 0)
  {
    printf ("execute error: %d, %s\n", cci_error.err_code, cci_error.err_msg);
  }
else
  {
    for (i = 1; i <= 3; i++)
      {
        printf ("query %d\n", i);
        printf ("result count = %d\n", CCI_QUERY_RESULT_RESULT (result, i));
        printf ("error message = %s\n", CCI_QUERY_RESULT_ERR_MSG (result, i));
        printf ("statement type = %d\n", CCI_QUERY_RESULT_STMT_TYPE (result, i));
      }
  }
...

javax.sql.XAConnection 인터페이스에서 HOLD_CURSORS_OVER_COMMIT 미지원(CUBRIDSUS-10800)

CUBRID는 현재 javax.sql.XAConnection 인터페이스에서 ResultSet.HOLD_CURSORS_OVER_COMMIT을 지원하지 않는다.

기존 주의 사항

2008 R4.1 버전부터 CCI_DEFAULT_AUTOCOMMIT 의 기본값이 ON으로 바뀜(CUBRIDSUS-5879)

2008 R4.1 버전부터 CCI 인터페이스로 개발된 응용 프로그램의 자동 커밋 모드에 영향을 주는 브로커 파라미터인 CCI_DEFAULT_AUTOCOMMIT의 기본값이 ON으로 변경되었다. 따라서 CCI 및 CCI로 개발된 인터페이스(PHP, ODBC, OLE DB 등) 사용자는 응용 프로그램의 자동 커밋 모드가 이에 적합한지 살펴보아야 한다.

2008 R4.0 버전부터 페이지 단위의 옵션 및 파라미터가 볼륨 크기 단위로 바뀜(CUBRIDSUS-5136)

cubrid createdb 유틸리티의 DB 볼륨 크기 및 로그 볼륨 크기를 지정할 때 페이지 단위를 사용하는 옵션들(-p, -l, -s)은 제거될 예정이므로, 2008 R4.0 Beta 이후 새로 추가된 옵션들(--db-volume-size, --log-volume-size, --db-page-size, --log-page-size)을 사용한다.

cubrid addvoldb 유틸리티의 DB 볼륨 크기를 지정하는 경우에도 페이지 단위를 사용하지 않고 2008 R4.0 Beta 이후 새로 추가된 옵션(--db-volume-size)을 사용한다. 페이지 단위의 시스템 파라미터들은 추후 제거될 예정이므로 바이트 단위의 새로운 시스템 파라미터를 사용할 것을 권장한다. 관련 시스템 파라미터들에 대한 내용은 아래를 참고한다.

2008 R4.0 Beta 이전 사용자는 DB 볼륨 크기 설정 시 주의(CUBRIDSUS-4222)

2008 R4.0 Beta 버전부터 DB 생성 시 데이터 페이지 및 로그 페이지의 크기 기본값이 4KB에서 16KB로 변경되었으므로, DB 볼륨을 페이지 개수로 지정하여 생성하는 경우 볼륨의 바이트 크기가 기대와 다를 수 있음에 주의한다. 아무런 옵션도 주지 않을 경우 이전 버전에서는 4KB의 페이지 크기로 100MB의 DB 볼륨을 생성했으나, 2008 R4.0 버전부터는 16KB의 페이지 크기로 512MB의 DB 볼륨을 생성하게 된다.

그리고, DB 볼륨의 생성 가능한 최소 크기를 20MB로 제한했으므로 이보다 작은 크기의 DB 볼륨은 생성할 수 없다.

2008 R4.0 이전 버전의 일부 시스템 파라미터들의 기본값 변경(CUBRIDSUS-4095)

2008 R4.0부터 다음 시스템 파라미터들의 기본값이 변경되었다.

DB 서버가 허용하는 동시 연결 개수를 설정하는 max_clients의 기본값, 인덱스 페이지 생성 시 향후 업데이트를 대비하여 확보하는 여유 공간 비율을 설정하는 index_unfill_factor의 기본값이 변경되었으며, 바이트 단위 시스템 파라미터의 기본값이 기존 페이지 단위 시스템 파라미터의 기본값보다 커져서 별도의 설정을 하지 않는 경우 더 많은 메모리를 사용하게 되었다.

기존 시스템 파라미터 추가된 시스템 파라미터 기존 기본값 변경된 기본값 (단위: 바이트)
max_clients 없음 50 100
index_unfill_factor 없음 0.2 0.05
data_buffer_pages data_buffer_size 100M(페이지 크기=4K) 512M
log_buffer_pages log_buffer_size 200K(페이지 크기=4K) 4M
sort_buffer_pages sort_buffer_size 64K(페이지 크기=4K) 2M
index_scan_oid_buffer_pages index_scan_oid_buffer_size 16K(페이지 크기=4K) 64K

또한, cubrid createdb로 DB 생성 시 데이터 페이지 크기와 로그 페이지 크기의 최소값이 1K에서 4K로 변경되었다.

시스템 파라미터를 잘못 설정하면 DB 서비스, 유틸리티 및 응응 프로그램이 구동되지 않음(CUBRIDSUS-5375)

cubrid.conf 또는 cubrid_ha.conf에 정의되지 않은 시스템 파라미터를 설정하거나, 페이지 단위의 시스템 파라미터와 바이트 단위의 시스템 파라미터가 동시에 사용되거나, 시스템 파라미터 값이 허용 범위를 벗어나면 이와 관련된 DB 서비스, 유틸리티 및 응응 프로그램이 구동되지 않는다.

CUBRID 32bit 버전에서 data_buffer_size에 2G를 초과하는 값을 설정하면 DB 구동에 실패함(CUBRIDSUS-5349)

CUBRID 32bit 버전에서 data_buffer_size가 2G를 초과하는 값으로 설정되는 경우 DB 구동에 실패한다. 32bit 버전에서는 OS의 한계로 인해 설정값이 2G를 초과할 수 없음에 주의한다.

Windows Vista 이상 버전에서 CUBRID 유틸리티를 사용한 서비스 제어 시 권장 사항(CUBRIDSUS-4186)

Windows Vista 이상 버전에서 cubrid 유틸리티를 사용하여 서비스를 제어하려면 명령 프롬프트 창을 관리자 권한으로 구동한 후 사용하는 것을 권장한다.

명령 프롬프트 창을 관리자 권한으로 구동하지 않고 cubrid 유틸리티를 사용하는 경우 UAC(User Account Control) 대화 상자를 통하여 관리자 권한으로 수행될 수 있으나 수행 결과 메시지를 확인할 수 없다.

Windows Vista 이상 버전에서 명령 프롬프트 창을 관리자 권한으로 구동하는 방법은 다음과 같다.

  • [시작> 모든 프로그램> 보조 프로그램> 명령 프롬프트]에서 마우스 오른쪽 버튼을 클릭한다.
  • [관리자 권한으로 실행(A)]을 선택하면 권한 상승을 확인하는 대화 상자가 활성화되고, "예"를 클릭하여 관리자 권한으로 구동한다.

CUBRID 소스 빌드 후 실행 시, 매니저 서버 프로세스 관련 오류 발생(CUBRIDSUS-3553)

사용자가 직접 빌드하여 설치하는 경우, CUBRID와 CUBRID 매니저를 각각 빌드하여 설치해야 한다. 만약, CUBRID 소스만 checkout하여 빌드 후 cubrid service start 또는 cubrid manager start를 실행하면, cubrid manager server is not installed라는 오류가 발생한다.

2008 R3.0 이하 버전에서 사용하던 GLO 클래스 지원 중단(CUBRIDSUS-3826)

CUBRID 2008 R3.0 이하 버전은 glo (Generalized Large Object) 클래스를 사용하여 Large Object를 처리했으나, CUBRID 2008 R3.1 이상 버전 glo 클래스를 제거하고 BLOB, CLOB 타입(이하 LOB)을 지원한다. LOB 데이터 타입에 대한 자세한 내용은 BLOB/CLOB 데이터 타입 절을 참고하면 된다.

기존의 glo 클래스 사용자는 다음과 같이 작업할 것을 권장한다.

  • GLO 데이터를 파일로 저장한 후 어플리케이션 및 DB 스키마에서 GLO를 사용하지 않도록 수정한다.
  • unloaddb, loaddb 유틸리티를 이용하여 DB 마이그레이션을 한다.
  • 변경한 어플리케이션에 맞게 파일을 LOB 데이터로 로딩하는 작업을 수행하도록 한다.
  • 수정한 어플리케이션이 정상 동작하는지 확인한다.

참고로, cubrid loaddb 유틸리티는 GLO 클래스를 상속받거나 GLO 클래스 타입을 가진 테이블을 로딩하려는 경우 " Error occurred during schema loading " 오류 메시지와 함께 데이터 로딩을 중지한다.

GLO 클래스의 지원 중단에 따라 각 인터페이스 별로 삭제한 함수는 다음과 같다.

인터페이스 삭제한 함수
CCI

cci_glo_append_data

cci_glo_compress_data

cci_glo_data_size

cci_glo_delete_data

cci_glo_destroy_data

cci_glo_insert_data

cci_glo_load

cci_glo_new

cci_glo_read_data

cci_glo_save

cci_glo_truncate_data

cci_glo_write_data

JDBC

CUBRIDConnection.getNewGLO

CUBRIDOID.loadGLO

CUBRIDOID.saveGLO

PHP

cubrid_new_glo

cubrid_save_to_glo

cubrid_load_from_glo

cubrid_send_glo

마스터 프로세스와 서버 프로세스 간 프로토콜 변경 및 두 개 버전을 동시에 운영하는 경우 포트 설정 필요(CUBRIDSUS-3564)

마스터 프로세스(cub_master)와 서버 프로세스(cub_server) 간 통신 프로토콜 변경으로 인해 CUBRID 2008 R3.0 이상 버전의 마스터 프로세스는 하위 버전의 서버 프로세스와 통신할 수 없고, 하위 버전의 마스터 프로세스도 2008 R3.0 이상 버전의 서버 프로세스와 통신할 수 없다. 따라서, 이미 하위 버전이 설치되어 있는 환경에서 새 버전을 추가 설치하여, 두 개 버전의 CUBRID를 동시에 운영하는 경우 각각 서로 다른 포트를 사용하도록 cubrid.conf의 cubrid_port_id 시스템 파라미터를 수정해야 한다.

JDBC에서 연결 정보를 URL 스트링으로 입력하는 경우 물음표를 반드시 명시(CUBRIDSUS-3217)

JDBC에서 URL 스트링으로 연결 정보를 입력하는 경우 이전 버전에서는 물음표(?)를 입력하지 않더라도 속성(PROPERTY) 정보가 적용되었으나, CUBRID 2008 R3.0부터는 문법에 따라 반드시 물음표를 명시해야 하고 이를 생략할 경우 에러를 출력한다. 또한, 연결 정보 중 USERNAME과 PASSWORD가 없더라도 반드시 콜론( : )을 명시해야 한다.

URL=jdbc:CUBRID:127.0.0.1:31000:db1:::altHosts=127.0.0.2:31000,127.0.0.3:31000 –에러 처리
URL=jdbc:CUBRID:127.0.0.1:31000:db1:::?altHosts=127.0.0.2:31000,127.0.0.3:31000 –정상 처리

DB 이름에 @를 포함할 수 없음(CUBRIDSUS-2828)

DB 이름에 @이 포함되는 경우 호스트 이름이 명시된 것으로 해석될 수 있으므로 이를 방지하기 위하여 cubrid createdb, cubrid renamedb, cubrid copydb 유틸리티 실행 시 DB 이름에 @를 포함할 수 없도록 수정했다.