다국어 개요

문자 데이터

콜레이션을 적용할 수 있는 데이터의 타입은 VARCHAR, CHAR, ENUM 타입이다.

문자셋(charset, codeset)은 어떤 타입에 대해 문자가 저장되는 방식 또는 일련의 바이트가 하나의 문자를 구성하는 방식을 제어한다. CUBRID는 UTF-8, ISO-8859-1, EUC-KR 문자셋을 지원하며, UTF-8에 대해 코드포인트 10FFFF(4 바이트까지 인코딩됨)까지만 지원한다. 예를 들어, 문자 “Ç”는 코드셋 ISO-8859-1에서 1 바이트(C7)으로 인코딩되지만, UTF-8에서는 2 바이트(C3 88)로 인코딩된다. 반면, EUC-KR에서 이 문자는 사용할 수 없다.

콜레이션은 문자를 비교하는 방법을 결정한다. 사용자는 흔히 콜레이션을 통해 대소문자를 구분하지 않거나 구분한다. 예를 들어 “ABC”와 “abc”는 대소문자 구분 무시(case insensitive) 콜레이션에서는 동일한 반면, 대소문자 구분(case sensitive) 콜레이션에서는 동일하지 않다. 또한 콜레이션에 따라 비교 결과가 “ABC” > “abc”가 되거나 “ABC” < “abc”가 될 수 있다.

콜레이션은 대소문자 비교 이상의 것을 의미한다. 콜레이션은 두 문자열 간에 관계를 결정하여 LIKE와 같은 문자열 매칭에 사용되거나 인덱스 스캔에서 영역을 계산하는데 사용된다.

CUBRID에서 콜레이션은 문자셋을 포함한다. 예를 들어, “utf8_en_ci”과 “iso88591_en_ci”은 대소문자를 구분하지 않는 비교이지만 다른 문자셋에서 동작한다. ASCII 범위에서 비교 결과는 비슷하지만 UTF-8 인코딩은 가변적인 바이트 수에 따라 동작해야 하기 때문에 “utf8_en_ci” 콜레이션에서 비교 수행 속도가 더 느리다.

  • “‘a’ COLLATE iso88591_en_ci”는 “_iso88591’a’ COLLATE iso88591_en_ci”를 나타낸다.
  • “‘a’ COLLATE utf8_en_ci”는 “_utf8’a’ COLLATE utf8_en_ci”를 나타낸다.

모든 문자 데이터 타입은 자릿수(precision)를 지원한다. 고정 길이 문자(CHAR)는 특별히 다루어져야 한다. CHAR 타입의 값은 자릿수를 채워서 저장된다. 예를 들어 “abc”를 CHAR(5) 칼럼에 저장하면, “abc “(2 개의 공백 문자가 패딩됨)를 저장하게 된다. 공백 문자(ASCII 32, Unicode 0020)는 대부분 문자에서 사용하는 패딩 문자이다. 하지만 EUC-KR 문자셋에서 패딩 문자는 두 개 바이트(A1 A1)로 저장된 하나의 문자로 구성된다.

관련 용어

  • 문자셋(character set): 기호를 인코딩(어떤 기호에 특정 번호를 부여)한 집합

  • 콜레이션(collation): 문자셋에서 문자를 비교하기 위한, 데이터 정렬을 위한 규칙의 집합

  • 로캘(locale): 사용자의 언어 및 국가에 따라 숫자 형식, 캘린더(월의 이름, 요일의 이름), 날짜/시간 형식, 콜레이션 등을 정의하는 인자들의 집합. 로캘은 언어에 대한 지역화(localization)를 정의한다. 로캘의 문자셋은 월의 이름 및 다른 데이터가 어떻게 인코딩되는지를 나타낸다. 로캘은 최소한 하나의 언어 식별자와 영역 식별자로 구성되어 있으며 language[_territory][.codeset]으로 표현한다. (예를 들어 UTF-8 인코딩을 쓰는 오스트레일리아 영어는 en_AU.utf8로 표기한다.)

  • 유니코드 정규화(Unicode normalization): 모양이 같은 여러 문자들이 있을 경우 기준에 따라 이를 하나로 통합하는 것. CUBRID는 입력 시에는 NFC(Normalization Form C) 형식(분해된 코드포인트에서 결합된 코드포인트로 변환)을 사용하고, 출력 시에는 NFD(Normalization Form D) 형식(결합된 코드포인트에서 분해된 코드포인트로 변환)을 사용한다. 하지만, CUBRID는 예외적으로 규범적 등가(canonical equivalence) 규칙을 적용하지 않는다.

    예를 들어, 일반적인 NFC 규칙에 따르면 규범적 등가 규칙을 적용하여 코드포인트 212A(캘빈 기호 K)는 코드포인트 4B(ASCII 코드 대문자 K)로 변환된다. CUBRID는 규범적 등가 규칙에 의한 변환을 수행하지 않도록 하여 정규화 알고리즘을 더 간단하고 빠르게 하였고, 따라서 역변환도 수행하지 않는다.

  • 규범적 등가(canonical equivalence): 시각적으로 구별이 불가능하고 텍스트 비교상 정확히 동일한 의미를 가지는 문자. 한 예로 ‘A’에 옹스트롬(Angstrom) 기호가 있는 ‘Å’가 있는데, ‘Å’(유니코드 U+212B)와 라틴어 ‘A’(유니코드 U+00C5)는 모양이 같고 코드포인트가 다르지만 분해된 결과는 ‘A’와 U+030A로 같으므로 규범적 등가이다.

  • 호환성 등가(compatibility equivalence): 동일한 문자나 문자 시퀀스의 대체 표현 문자. 예로는 숫자 ‘2’(유니코드 U+0032)와 위 첨자 ‘²’(유니코드 U+00B2)가 있는데, ‘²’ 는 숫자 ‘2’의 다른 형태이긴 하지만 시각적으로 구별되고 의미도 다르기 때문에 규범적 등가에 해당되지 않는다. ‘2²’를 NFC로 정규화하면 규범적 등가를 사용하기 때문에 ‘2²’가 유지되지만, NFKC 방식에서는 ‘²’가 호환성 등가인 ‘2’로 분해된 후 결합되어 ‘22’로 바뀔 수 있다. CUBRID의 유니코드 정규화에서는 호환성 등가 규칙도 적용하지 않는다.

유니코드 정규화에 대한 설명은 유니코드 정규화 를 참고하며, 보다 자세한 내용은 http://unicode.org/reports/tr15/를 참고한다.

유니코드 정규화 관련 시스템 파라미터에서 기본으로 설정되는 값은 unicode_input_normalization=no이고 unicode_output_normalization=no이다. 이 파라미터에 대한 보다 자세한 설명은 구문/타입 관련 파라미터 를 참고한다.

로캘 속성

로캘은 다음과 같은 속성들로 정의된다.

  • 문자셋(코드셋): 여러 바이트를 하나의 문자로 해석하는 방법을 정의한다. 유니코드에서는 여러 개의 바이트가 하나의 코드포인트(codepoint)를 구성하는 것으로 해석된다.
  • 콜레이션(collation): LDML(UNICODE Locale Data Markup Language) 파일의 로캘 데이터에 여러 콜레이션을 지정할 수 있는데, 이 중에 마지막으로 명시된 것이 기본(default) 콜레이션으로 사용된다.
  • 알파벳(대소문자 규칙): 하나의 로캘 데이터는 테이블 이름, 칼럼 이름과 같은 식별자용과 사용자 데이터용으로 최대 두 종류의 알파벳을 가질 수 있다.
  • 캘린더: 요일 이름, 월의 이름, 오전/오후(AM/PM) 표시
  • 숫자 표기: 자릿수 구분 기호
  • 텍스트 변환 데이터: CSQL 콘솔 변환용. 선택 사항
  • 유니코드 정규화 데이터: 모양이 같은 여러 문자들이 있을 경우 이를 기준에 따라 하나의 값으로 통합하는 정규화를 수행하여 변환된 데이터. 정규화 이후에는 로캘이 달라도 모양이 같은 문자는 같은 코드값을 가지며, 각 로캘은 이 정규화 기능을 활성화 또는 비활성화할 수 있다.

Note

일반적으로 한 로캘은 다양한 문자셋을 지원하지만, CUBRID 로캘은 영어와 한국어에 한해서만 ISO와 UTF-8 문자셋을 둘 다 지원한다. 그 외의 LDML 파일을 이용한 모든 사용자 정의 로캘은 UTF-8 문자셋만 지원한다.

콜레이션 속성

콜레이션(collation)은 문자열의 비교 및 정렬 규칙의 집합으로, CUBRID에서 콜레이션은 다음과 같은 속성(property)을 갖는다.

  • 세기(strength): 기본 비교 항목들(문자들)이 어떻게 다른지 나타내는 측정 기준이다. 이것은 선택도(selectivity)에 영향을 준다. LDML 파일에서 콜레이션의 세기는 네 가지 수준(level)으로 설정할 수 있다. 예를 들어, 대소문자 구분이 없는 콜레이션은 level = “secondary” (2) 또는 “primary” (1)로 설정해야 한다.
  • 확장(expansion)축약(contraction) 지원 여부

각각의 칼럼이 콜레이션을 가질 수 있기 때문에, LOWER(), UPPER() 함수 등을 적용할 때 해당 콜레이션의 기본 언어에서 정의한 로캘의 대소문자 구분 규칙(casing rule)이 사용된다.

콜레이션 속성에 따라 일부 콜레이션에서 다음과 같은 특정 CUBRID 최적화가 동작하지 않을 수 있다.

  • LIKE 구문 재작성: 같은 가중치(weight)에 여러 개의 다른 문자를 매핑하는 콜레이션, 예를 들어 대소문자 구분이 없는 콜레이션에서는 LIKE 구문이 재작성되지 않는다.
  • 커버링 인덱스 스캔: 같은 가중치에 여러 개의 다른 문자를 매핑하는 콜레이션에서는 커버링 인덱스 스캔이 동작하지 않는다(커버링 인덱스 참고).

이에 관한 보다 자세한 설명은 콜레이션 설정으로 인한 영향 을 참고하면 된다.

콜레이션 명명 규칙

콜레이션 이름은 다음 규칙을 따른다.

<charset>_<lang specific>_<desc1>_<desc2>_...
  • <charset>: 문자셋 이름. iso88591, utf8, euckr이 있다.
  • <lang specific>: 지역/언어를 나타내며, en, de, es, fr, it, ja, km, ko, tr, vi, zh, ro가 있다. 특정 언어를 나타내지 않을 때는 “gen”으로 일반적인 정렬 규칙을 의미한다.
  • <desc1>_<desc2>_…: 대부분 LDML 콜레이션에만 적용되며 각각 다음의 의미를 갖는다.
    • ci: 대소문자 구분 안 함. LDML 파일에서 다음을 설정하면 적용된다: strength=”secondary” caseLevel=”off” caseFirst=”off”
    • cs: 대소문자 구분. 기본적으로 모든 콜레이션은 대소문자를 구분한다. LDML 파일에서 다음을 설정하면 적용된다: strength=”tertiary”
    • bin: 정렬 순서가 코드포인트의 순서와 똑같음. 메모리의 바이트 순서를 비교하면 거의 같은 결과가 나오는데, 공백 문자와 EUC의 더블 바이트 패딩 문자는 “bin” 콜레이션에서 항상 0으로 정렬된다. LDML 파일에는 bin 콜레이션을 설정하는 방법이 없는데(bin 콜레이션은 이미 내장되어 있음), LDML 파일에서 다음을 설정하면 비슷하게 적용된다: strength=”quaternary” 또는 strength=”identical”
    • ai: 악센트 구분 안 함. 예를 들어, ‘Á’는 ‘A’와 같은 순서이다. 이는 또한 대소문자를 구분하지 않는다. LDML 파일에서 (strength=”primary”)를 설정하면 적용된다.
    • uca: UCA(Unicode Collation Algorithm) 기반 콜레이션을 의미함. 내장된 변형 콜레이션과 구별하기 위해서만 사용된다. 즉, 모든 LDML 콜레이션은 UCA를 기반으로 하지만 짧은 이름을 유지하기 위해 “_uca”가 생략되며, 예외적으로 ‘utf8_ko_cs_uca’, ‘utf8_tr_cs_uca’ 이 두 개의 콜레이션만 내장된 ‘utf8_ko_cs’, ‘utf8_tr_cs’ 콜레이션과 구별하기 위해 사용된다.
    • exp: 다른 콜레이션들이 문자 단위로 비교하는 것에 반해, 확장 은 전체 단어 매칭/비교 알고리즘을 사용한다. 이 콜레이션은 좀더 복잡한 알고리즘을 사용하므로 훨씬 느릴 수 있지만, 알파벳 정렬에 유용할 수 있다. LDML 파일에 다음이 명시되어야 한다: CUBRIDExpansions=”use”
    • ab: 역순 액센트(accent backwards). 특히 캐나다 프랑스어에만 적용되는데, UCA 2단계(액센트 가중치를 저장)는 문자열의 끝에서부터 시작 방향으로 비교된다. 이 콜레이션 설정은 오직 확장 이 활성화되는 경우에만 사용될 수 있다. “ab” 설정은 다음 정렬을 허용한다.
      • 일반적인 액센트 순서: cote < coté < côte < côté
      • 역방향 액센트 순서: cote < côte < coté < côté
    • cbm: 축약 영역 매칭(contraction boundary match). 확장축약 이 있는 콜레이션의 특별한 콜레이션이며, 매칭되는 문자열에서 축약 이 발견될 때 동작하는 방법을 설정한다. 콜레이션의 축약 을 “ch”로 정의했다고 가정하자. 그러면 일반적으로 “bac”라는 패턴은 문자열 “bachxxx”와는 매칭되지 않는다. 그러나 콜레이션이 “축약을 시작하는 문자 매칭”을 허용하도록 설정되면, 앞서 말한 문자열들은 매칭된다. 이러한 식으로 동작하는 콜레이션은 ‘utf8_ja_exp_cbm’ 밖에 없는데, 일본어 정렬은 무수히 많은 축약 을 요구한다.

콜레이션 이름은 동적으로 생성되지 않는다. LDML에 정의되어 있으며, 콜레이션 설정을 반영해야 한다.

콜레이션 이름은 콜레이션의 내부적인 ID에 영향을 준다. CUBRID는 256 개의 콜레이션을 허용하며, 각 식별자들은 다음과 같이 등록된다.

  • 0 - 31: 내장된(built-in) 콜레이션(이름과 식별자가 제품에 포함됨)
  • 32 - 46: 언어 부분에 “gen”을 가지는 LDML 콜레이션
  • 47 - 255: 나머지 LDML 콜레이션

CUBRID가 제공하는 모든 로캘을 데이터베이스에 포함하고 싶다면, 먼저 $CUBRID/conf 디렉터리의 cubrid_locales.all.txt 파일을 cubrid_locales.txt 파일로 복사한다. 그리고, make_locale 스크립트(확장자가 Linux는 .sh, Windows는 .bat)를 실행하면 된다. make_locale 스크립트에 대한 자세한 설명은 2단계: 로캘 컴파일하기를 참고하면 된다.

기존의 데이터베이스에 새로 추가한 로캘 정보를 포함하고 싶다면 cubrid synccolldb <dbname>을 실행한다. 이에 대한 자세한 설명은 데이터베이스 콜레이션을 시스템 콜레이션에 동기화를 참고하면 된다.

LDML 파일로 정의된 로캘을 모두 포함하는 경우 CUBRID는 다음의 콜레이션을 가진다.

CUBRID 콜레이션

콜레이션 대소문자 구분을 위한 로캘 문자 범위
iso88591_bin en_US - 영어 ASCII + ISO88591 (C0-FE, except D7, F7)
iso88591_en_cs en_US - 영어 ASCII + ISO88591 (C0-FE, except D7, F7)
iso88591_en_ci en_US - 영어 ASCII + ISO88591 (C0-FE, except D7, F7)
utf8_bin en_US - 영어 ASCII
euckr_bin ko_KR - 한국어, en_US - 영어와 같음 ASCII
utf8_en_cs en_US - 영어 ASCII
utf8_en_ci en_US - 영어 ASCII
utf8_tr_cs tr_TR - 터키어 터키어 알파벳
utf8_ko_cs ko_KR - 한국어, en_US - 영어와 같음 ASCII
utf8_gen de_DE - 독일어, 독일어 규칙에 맞게 대소문자를 커스터마이징한 유니코드 0000-FFFF 범위의 모든 유니코드 코드포인트
utf8_gen_ai_ci de_DE - 독일어, 독일어 규칙에 맞게 대소문자를 커스터마이징한 유니코드 0000-FFFF 범위의 모든 유니코드 코드포인트
utf8_gen_ci de_DE - 독일어, 독일어 규칙에 맞게 대소문자를 커스터마이징한 유니코드 0000-FFFF 범위의 모든 유니코드 코드포인트
utf8_de_exp_ai_ci de_DE - 독일어, 독일어 규칙에 맞게 대소문자를 커스터마이징한 유니코드 0000-FFFF 범위의 모든 유니코드 코드포인트
utf8_de_exp de_DE - 독일어, 독일어 규칙에 맞게 대소문자를 커스터마이징한 유니코드 0000-FFFF 범위의 모든 유니코드 코드포인트
utf8_ro_cs ro_RO - 루마니아어, 일반적인 유니코드 대소문자 규칙과 동일 0000-FFFF 범위의 모든 유니코드 코드포인트
utf8_es_cs es_ES - 스페인어, 일반적인 유니코드 대소문자 규칙과 동일 0000-FFFF 범위의 모든 유니코드 코드포인트
utf8_fr_exp_ab fr_FR - 프랑스어, 일반적인 유니코드 대소문자 규칙과 동일 0000-FFFF 범위의 모든 유니코드 코드포인트
utf8_ja_exp ja_JP - 일본어, 일반적인 유니코드 대소문자 규칙과 동일 0000-FFFF 범위의 모든 유니코드 코드포인트
utf8_ja_exp_cbm ja_JP - 일본어, 일반적인 유니코드 대소문자 규칙과 동일 0000-FFFF 범위의 모든 유니코드 코드포인트
utf8_km_exp km_KH - 캄보디아어, 일반적인 유니코드 대소문자 규칙과 동일 0000-FFFF 범위의 모든 유니코드 코드포인트
utf8_ko_cs_uca ko_KR - 한국어, 일반적인 유니코드 대소문자 규칙과 동일 0000-FFFF 범위의 모든 유니코드 코드포인트
utf8_tr_cs_uca tr_TR - 터키어, 터키어 규칙에 맞게 대소문자를 커스터마이징한 유니코드 0000-FFFF 범위의 모든 유니코드 코드포인트
utf8_vi_cs vi_VN - 베트남어, 일반적인 유니코드 대소문자 규칙과 동일 0000-FFFF 범위의 모든 유니코드 코드포인트
binary none (invariant to casing operations) any byte value (null-terminator는 0)

터키어의 대소문자 규칙은 i,I,ı,İ 에 대해 대소문자를 바꾼다. 독일어 대소문자 규칙은 ß에 대해 대소문자를 바꾼다.

위에서 iso88591_bin, iso88591_en_cs, iso88591_en_ci, utf8_bin, euckr_bin, utf8_en_cs, utf8_en_ci, utf8_tr_cs, utf8_ko_cs와 같은 9개의 콜레이션은 CUBRID에 기본적으로 내장되어 있다.

한 개 이상의 로케일 파일(.ldml)에 콜레이션이 포함되어 있는 경우 대소문자 구분을 위한 로케일(콜레이션의 기본 로케일)이 첫 번째로 포함되는 로케일이다. 로딩 순서는 $CUBRID/conf/cubrid_locales.txt의 로케일 순서와 같다. 콜레이션 utf8_gen, utf8_gen_ci, utf8_gen_ai_ci에 대한 위의 로케일 대소문자는 cubrid_locales.txt의 기본 순서(알파벳 순서)를 따르므로 모든 일반 LDML 콜레이션의 기본 로케일은 de_DE(독일어)가 된다.

로캘 저장 위치

CUBRID는 로캘 설정을 위해 여러 디렉터리와 파일들을 사용한다.

  • $CUBRID/conf/cubrid_locales.txt 파일: 사용할 로캘 리스트를 포함하는 초기 설정 파일
  • $CUBRID/conf/cubrid_locales.all.txt 파일: cubrid_locales.txt 와 같은 구조를 갖는 초기 설정 파일의 템플릿. 사용자가 직접 정의하지 않아도 되는 CUBRID가 현재 지원하는 CUBRID 로캘 버전의 전체 리스트를 포함한다.
  • $CUBRID/locales/data 디렉터리: 로캘 데이터를 생성하는데 필요한 파일들을 포함한다.
  • $CUBRID/locales/loclib 디렉터리: 로캘 데이터를 포함하는 공유 라이브러리 생성을 위한 C 언어로 작성된 locale_lib_common.h 헤더 파일과 빌드를 위한 makefile을 포함한다.
  • $CUBRID/locales/data/ducet.txt 파일: 코드포인트, 축약과 확장 등과 같은 기본적인 범용 콜레이션 정보와 이들의 가중치 값을 표현하는 파일로, 이 정보들은 유니코드 컨소시엄에 의해 제정된 표준을 따른다. 자세한 사항은 http://unicode.org/reports/tr10/#Default_Unicode_Collation_Element_Table 을 참고한다.
  • $CUBRID/locales/data/unicodedata.txt 파일: 대소문자 구별, 분해, 정규화 등 각각의 유니코드 코드 포인트를 포함하는 파일로, CUBRID는 대소문자 구분 규칙을 결정하기 위해 이 파일을 사용한다. 더 많은 정보는 http://www.ksu.ru/eng/departments/ktk/test/perl/lib/unicode/UCDFF301.html 을 참고한다.
  • $CUBRID/locales/data/ldml 디렉터리: common_collations.xml 파일과 cubrid_<locale_name>.xml 형식의 이름을 지니는 XML 파일들을 포함한다. common_collations.xml 파일은 모든 로캘에서 공유되는 콜레이션 정보를 표현하며, 각각의 cubrid_<locale_name>.xml 파일은 해당 언어에 대한 로캘 정보를 표현한다.
  • $CUBRID/locales/data/codepages 디렉터리: 한 바이트 코드 페이지들을 위한 코드 페이지 콘솔 변환용 파일들(8859-1.txt, 8859-15.txt, 8859-9.txt)과 멀티바이트 코드 페이지를 위한 코드 페이지 콘솔 변환용 파일들(CP1258.txt, CP923.txt, CP936.txt, CP949.txt)을 포함한다.
  • $CUBRID/bin/make_locale.sh 파일 또는 %CUBRID%\bin\make_locale.bat 파일(Windows): 로캘 데이터를 표현하는 공유 라이브러리를 생성하기 위해 사용되는 스크립트 파일이다.
  • $CUBRID/lib 디렉터리: 로캘 데이터를 표현하는 공유 라이브러리 파일이 저장된다.

로캘 설정

특정 언어의 문자셋과 콜레이션을 사용하려면 해당 문자셋은 새로 생성할 데이터베이스와 반드시 일치해야 한다. CUBRID가 지원하는 문자셋은 ISO-8859-1, EUC-KR, UTF-8이며, 데이터베이스를 생성할 때 사용하게 될 문자셋은 데이터베이스 생성 시 지정된다.

예를 들어, 데이터베이스를 생성 시 로캘을 ko_KR.utf8로 지정했으면 테이블 및 칼럼 생성, 콜레이션 변경 등에서 utf8_ja_exp과 같이 “utf8_”로 시작하는 콜레이션을 모두 사용할 수 있으나, ko_KR.euckr로 설정하면 다른 문자셋과 관련된 콜레이션을 모두 사용할 수 없게 된다. (CUBRID 콜레이션 참고)

다음은 로캘을 en_US.utf8로 설정하여 데이터베이스를 생성한 후, 콜레이션 utf8_ja_exp를 사용한 예이다.

  1. cd $CUBRID/conf

  2. cp cubrid_locales.all.txt cubrid_locales.txt

  3. make_locale.sh -t64 # 64 bit locale library creation

  4. cubrid createdb testdb en_US.utf8

  5. cubrid server start testdb

  6. csql -u dba testdb

  7. csql에서 아래 질의 수행

    SET NAMES utf8;
    CREATE TABLE t1 (i1 INT , s1 VARCHAR(20) COLLATE utf8_ja_exp, a INT, b VARCHAR(20) COLLATE utf8_ja_exp);
    INSERT INTO t1 VALUES (1, 'いイ基盤',1,'いイ 繭');
    

보다 자세한 설명은 아래를 참고한다.

1단계: 로캘 선택

사용하려는 로캘을 $CUBRID/conf/cubrid_locales.txt 에 지정한다. 모두 선택하거나 부분만 선택할 수 있다.

CUBRID가 현재 지원하는 로캘은 en_US, de_DE, es_ES, fr_FR, it_IT, ja_JP, km_KH, ko_KR, tr_TR, vi_VN, zh_CN, ro_RO이며, 이 목록은 $CUBRID/conf/cubrid_locales.all.txt에 작성되어 있다.

각 로캘 이름 및 언어, 사용 국가는 다음 표와 같다.

로캘 이름 언어 - 사용 국가
en_US 영어 - 미국
de_DE 독일어 - 독일
es_ES 스페인어 - 스페인
fr_FR 프랑스어 - 프랑스
it_IT 이태리어 - 이탈리아
ja_JP 일본어 - 일본
km_KH 크메르어 - 캄보디아
ko_KR 한국어 - 대한민국
tr_TR 터키어 - 터키
vi_VN 베트남어 - 베트남
zh_CN 중국어 - 중국
ro_RO 루마니아어 - 루마니아

Note

지원하는 로캘들을 위한 LDML 파일들은 cubrid_<locale_name>.xml 파일로 명명되며, $CUBRID/locales/data/ldml 폴더에 저장된다. 지원하려는 로캘에 해당하는 LDML 파일이 $CUBRID/locales/data/ldml 디렉터리에 존재해야 한다. cubrid_locales.txt에 로캘이 지정되지 않거나 cubrid_<locale_name>.xml 파일이 존재하지 않으면 해당 로캘을 사용할 수 없다.

로캘 라이브러리들은 $CUBRID/conf/cubrid_locales.txt 설정 파일에 의해 생성되는데, 이 파일은 원하는 로캘들의 언어 코드들을 포함하고 있다. 사용자가 정의하는 모든 로캘들은 UTF-8 문자셋으로만 생성된다. 또한 이 파일을 통해서 각 로캘 LDML 파일에 대한 파일 경로와 라이브러리들을 선택적으로 설정할 수 있다.

<lang_name>  <LDML file>                                        <lib file>
ko_KR        /home/CUBRID/locales/data/ldml/cubrid_ko_KR.xml    /home/CUBRID/lib/libcubrid_ko_KR.so

기본적으로 LDML 파일은 $CUBRID/locales/data/ldml 디렉터리에, 로캘 라이브러리들은 $CUBRID/lib 디렉터리에 존재한다. 이와 같이 LDML 파일과 로캘 라이브러리가 기본 위치에 존재한다면 <lang_name>만 작성해도 된다. LDML을 위한 파일 이름 형식은 cubrid_<lang_name>.ldml이다.

라이브러리에 대한 파일 이름 형식은 Linux에서는 libcubrid_<lang_name>.so, Windows에서는 libcubrid_<lang_name>.dll이다.

2단계: 로캘 컴파일하기

1단계에서 설명한 요구사항들이 충족되었다면 로캘 데이터를 컴파일할 수 있다.

CUBRID에 내장된 로캘을 사용한다면 사용자 로캘 라이브러리를 컴파일하지 않고 사용할 수 있으므로 2단계를 생략할 수 있으나, 내장된 로캘과 라이브러리 로캘에는 차이가 있다. 이와 관련하여 내장된 로캘과 라이브러리 로캘을 참고한다.

로캘 데이터를 컴파일하려면 make_locale 스크립트(파일의 확장자는 Linux에선 .sh, Windows에선 .bat)를 사용한다. 이 스크립트는 $CUBRID/bin 디렉터리에 위치하며, 이 경로가 $PATH 환경 변수에 포함되어야 한다. 여기서 $CUBRID, $PATH 는 Linux의 환경 변수이며, Windows에서는 %CUBRID%, %PATH%이다.

Note

make_locale 스크립트를 Windows에서 실행하려면, Visual C++ 2005, 2008 또는 2010 중 하나가 설치되어 있어야 한다.

사용법은 make_locale.sh -h 명령(Windows는 make_locale /h)을 실행하면 출력되며, 사용 구문은 다음과 같다.

make_locale.sh [options] [locale]

options ::= [-t 32 | 64 ] [-m debug | release]
locale ::= [de_DE | es_ES | fr_FR | it_IT | ja_JP | km_KH | ko_KR | tr_TR | vi_VN | zh_CN |ro_RO]
  • options
    • -t: 32비트 또는 64비트 중 하나를 선택한다(기본값: 64).
    • -m: release 또는 debug 중 하나를 선택한다. 일반적인 사용을 위해서는 release를 선택한다(기본값: release). debug 모드는 로캘 라이브러리를 직접 작성하려는 개발자를 위해 제공한다.
  • locale: 빌드할 라이브러리의 로캘 이름. locale 이 주어지지 않으면, 설정한 모든 로캘의 데이터를 포함하도록 빌드된다. 이 경우 $CUBRID/lib 디렉터리에 libcubrid_all_locales.so (Windows의 경우 .dll)라는 이름으로 라이브러리 파일이 저장된다.

여러 로캘에 대해서 사용자 정의 로캘 공유 라이브러리를 만들려면 다음 두 가지 방법 중 하나를 사용할 수 있다.

  • 모든 로캘을 포함하는 하나의 라이브러리 생성: 다음과 같이 로캘을 명시하지 않고 실행한다.

    make_locale.sh -t64                        # Build and pack all locales (64/release)
    
  • 하나의 로캘만을 포함하는 라이브러리를 여러 개 반복하여 생성: 다음과 같이 하나의 언어를 지정한다.

    make_locale.sh -t 64 -m release ko_KR
    

이와 같은 두 가지 방법 중에서 첫 번째 방법을 사용하는 것을 권장한다. 공유 라이브러리를 생성하면 로캘들 간에 공유될 수 있는 데이터들이 중복되지 않기 때문에 메모리 사용량을 줄일 수 있다. 첫 번째 방식으로 지원하는 모든 로캘을 포함하도록 생성하면 약 15MB 정도 크기의 라이브러리가 생성되며, 두 번째 방식으로 생성할 경우에는 언어에 따라서 1MB에서 5MB 이상의 크기의 라이브러리가 생성된다. 또한 첫 번째 방식에서는 두 번째 방식을 사용했을 때에 서버 재시작 시점 등에 발생되는 런타임 오버헤드가 없기 때문에 런타임에도 유리하다.

Warning

제약 사항 및 규칙

  • 일단 로캘 라이브러리가 생성된 후에는 $CUBRID/conf/cubrid_locales.txt 파일을 변경하면 안 된다. 다시 말해서, 이 파일에서 명시된 언어들의 순서를 포함하여 어떤 내용도 변경해서는 안 된다. 로캘이 컴파일되고 나면, 일반 콜레이션(generic collation)은 cubrid_locales.txt에 존재하는 첫번째 로캘을 기본 로캘로 사용한다. 따라서 순서를 바꾸면 해당 콜레이션(utf8_gen_*)에 대한 대소문자 변환 결과가 달라질 수 있다.
  • $CUBRID/locales/data/*.txt 파일들은 변경되어서는 안 된다.

Note

make_locale.sh(.bat) 스크립트 수행 절차

make_locale.sh(.bat) 스크립트는 다음과 같은 작업을 수행한다.

  1. $CUBRID/locales/data/ducet.txt, $CUBRID/locales/data/unicodedata.txt, $CUBRID/locales/data/codepages/*.txt 와 같이 이미 설치된 공통 파일과 해당 언어의 .ldml 파일을 읽는다.
  2. 원본(raw) 데이터를 처리한 후 $CUBRID/locales/loclib/locale.c 임시 파일에 로캘 데이터를 포함하는 C 상수 값과 배열을 작성한다.
  3. .so (.dll) 파일을 빌드하기 위해 임시 파일인 locale.c 파일이 플랫폼 컴파일러에 전달된다. 이 단계는 장비가 C/C++ 컴파일러 및 링커를 가지고 있다고 가정한다. 현재 Windows 버전에서는 MS Visual Studio가, Linux 버전에서는 gcc 컴파일러가 사용된다.
  4. 임시 파일이 삭제된다.

3단계: 특정 로캘을 사용하기 위해 CUBRID 설정하기

DB 생성 시 로캘 지정을 통해 오직 하나의 로캘을 기본 로캘로 지정할 수 있다.

기본 로캘을 지정하여 기본 캘린더가 정의되지만, intl_date_lang 시스템 파라미터를 설정하면 기본 로캘 설정보다 우선 적용된다.

  • 로캘의 값은 <locale_name>[.utf8 | .iso88591]과 같이 설정한다. (예: tr_TR.utf8, en_US.iso88591, ko_KR.utf8)
  • intl_date_lang 시스템 파라미터의 값은 <locale_name>과 같이 설정한다. <locale_name>으로 사용할 수 있는 값은 1단계: 로캘 선택을 참고한다.

Note

월, 요일, 오전/오후 표기 및 숫자 형식 설정

날짜/시간을 입출력하는 함수에서 각 로캘 이름에 따라 입출력하는 월, 요일, 오전/오후 표기 방법을 intl_date_lang 시스템 파라미터로 설정할 수 있다.

또한 문자열을 숫자로 또는 숫자를 문자열로 변환하는 함수에서 각 로캘에 따라 입출력하는 숫자의 문자열 형식은 intl_number_lang 시스템 파라미터로 설정할 수 있다.

내장된 로캘과 라이브러리 로캘

CUBRID에 내장된 로캘에 대해서는 사용자 로캘 라이브러리를 컴파일하지 않고 사용할 수 있으므로 2단계를 생략할 수 있으나, 내장된 로캘과 라이브러리 로캘에는 다음과 같은 차이가 있다.

  • 내장된(built-in) 로캘(과 콜레이션)은 유니코드 데이터를 인식하지 못한다. 예를 들어, 내장된 로캘은 (Á, á) 간 대소문자 변환이 불가능하다. 반면 LDML 로캘(컴파일된 로캘)은 유니코드 코드포인트에 대한 데이터를 65535개까지 지원한다.
  • 내장된 콜레이션은 ASCII 범위만 다루거나, utf8_tr_cs의 경우 ASCII와 터키어(turkish) 알파벳 글자만 다룬다. 따라서 내장된 UTF-8 로캘은 유니코드와 호환되지 않는 반면, LDML 로캘(컴파일된 로캘)은 유니코드와 호환된다.

DB 생성 시 설정할 수 있는 내장 로캘은 다음과 같다.

  • en_US.iso88591
  • en_US.utf8
  • ko_KR.utf8
  • ko_KR.euckr
  • ko_KR.iso88591: 월, 요일 표시 방법은 로마자 표기를 따른다(romanized).
  • tr_TR.utf8
  • tr_TR.iso88591: 월, 요일 표시 방법은 로마자 표기를 따른다(romanized).

DB를 생성하면서 로캘 값 지정 시 문자셋(charset)이 명시되지 않으면 위 순서에서 앞에 있는 로캘의 문자셋으로 결정된다. 예를 들어, 로캘 값이 ko_KR로 설정되면(예: cubrid createdb testdb ko_KR) 위의 목록에서 ko_KR 중 가장 먼저 나타나는 로캘인 ko_KR.utf8을 지정한 것과 같다. 위의 내장된 로캘을 제외한 나머지 언어의 로캘은 뒤에 반드시 .utf8 을 붙여야 한다. 예를 들어, 독일어의 경우 로캘 값을 de_DE.utf8로 지정한다.

ko_KR.iso88591과 tr_TR.iso88591에서 월과 요일을 나타낼 때에는 로마자 표기를 따른다. 예를 들어, 한국어 “일요일”(영어로 Sunday)의 로마자 표기는 “Iryoil”이다. 이것은 ISO-8859-1 문자만 제공하기 위해서 요구되는 사항이다. 이에 관한 자세한 설명은 ISO-8859-1 문자셋에서 한국어와 터키어의 월, 요일를 참고하면 된다.

ISO-8859-1 문자셋에서 한국어와 터키어의 월, 요일

문자셋이 UTF-8인 한국어나 터키어 또는 문자셋이 EUC-KR인 한국어에서 월, 요일, 오전/오후 표시는 각 국가에 맞게 인코딩된다. 그러나, ISO-8859-1 문자셋에서 한국어와 터키어의 월, 요일, 오전/오후 표시를 원래의 인코딩으로 사용하면 복잡한 표현식이 사용되는 경우 서버 프로세스에서 예기치 않은 행동이 발생할 수 있기 때문에, 로마자 표기(romanized)로 출력한다. CUBRID의 기본 문자셋은 ISO-8859-1이며, 한국어와 터키어의 경우 이 문자셋을 사용할 수 있다. 한국어와 터키어에서 각 요일, 월, 오전/오후는 로마자로 다음과 같이 출력한다.

요일의 표기

긴/짧은 표기 한국어 긴/짧은 로마자 표기 터키어 긴/짧은 표기
Sunday / Sun Iryoil / Il Pazar / Pz
Monday / Mon Woryoil / Wol Pazartesi / Pt
Tuesday / Tue Hwayoil / Hwa Sali / Sa
Wednesday / Wed Suyoil / Su Carsamba / Ca
Thursday / Thu Mogyoil / Mok Persembe / Pe
Friday / Fri Geumyoil / Geum Cuma / Cu
Saturday / Sat Toyoil / To Cumartesi / Ct

월의 표기

긴 / 짧은 표기 한국어 긴/짧은 로마자 표기 (구분 없음) 터키어 긴 / 짧은 표기
January / Jan 1wol Ocak / Ock
February / Feb 2wol Subat / Sbt
March / Mar 3wol Mart / Mrt
April / Apr 4wol Nisan / Nsn
May / May 5wol Mayis / Mys
June / Jun 6wol Haziran / Hzr
July / Jul 7wol Temmuz / Tmz
August / Aug 8wol Agustos / Ags
September / Sep 9wol Eylul / Eyl
October / Oct 10wol Ekim / Ekm
November / Nov 11wol Kasim / Ksm
December / Dec 12wol Aralik / Arl

오전/오후의 표기

오전/오후 표기 한국어 로마자 표기 터키어 표기
AM ojeon AM
PM ohu PM

4단계: 선택한 로캘 설정으로 데이터베이스 생성하기

cubrid createdb <db_name> <locale_name.charset>을 실행하면, 해당 언어와 문자셋을 사용하는 데이터베이스가 생성된다. 일단 데이터베이스가 생성되면 해당 데이터베이스에 부여된 로캘 설정은 바꿀 수 없다.

문자셋과 로캘 이름은 db_root라는 시스템 카탈로그 테이블에 저장되며, 생성 시점의 설정과 다른 설정을 사용하여 데이터베이스를 구동할 수 없다.

5단계(선택 사항): 로캘 파일의 수동 검증

로캘 라이브러리의 내용들을 dumplocale 유틸리티를 이용해서 사람이 읽을 수 있는 형태로 출력할 수 있다. 사용법은 cubrid dumplocale -h로 출력할 수 있다.

cubrid dumplocale [options] [language-string]

options ::= -i|--input-file <shared_lib>
            -d|--calendar
            -n|--numeric
            {-a |--alphabet=}{l|lower|u|upper|both}
            -c|--codepoint-order
            -w|--weight-order
            {-s|--start-value} <starting_codepoint>
            {-e|--end-value} <ending_codepoint>
            -k
            -z

language-string ::= de_DE | es_ES | fr_FR | it_IT | ja_JP | km_KH | ko_KR | tr_TR | vi_VN | zh_CN | ro_RO
  • dumplocale: 로캘 라이브러리에 설정된 내용을 텍스트로 출력하는 명령이다.
  • language-string: de_DE, es_ES, fr_FR, it_IT, ja_JP, km_KH, ko_KR, tr_TR, vi_VN, zh_CN, ro_RO 중 하나의 값. 로캘 공유 라이브러리를 덤프할 로캘 언어를 지정한다. language-string이 생략되면 cubrid_locales.txt 파일에 명시된 모든 언어가 주어진다.

다음은 cubrid dumplocale에 대한 [options]이다.

-i, --input-file=FILE

로캘 공유 라이브러리 파일 이름을 지정하며, 경로를 포함한다.

-d, --calendar

캘린더와 날짜/시간 정보를 추가로 덤프한다.

-n, --numeric

숫자 정보를 덤프한다.

-a, --alphabet=l | lower | u | upper | both

알파벳과 대소문자 구분 정보를 덤프한다.

--identifier-alphabet=l | lower | u | upper

식별자에 대한 알파벳과 대소문자 구분 정보를 추가로 덤프한다.

-c, --codepoint-order

코드포인트 값을 기반으로 정렬한 콜레이션 정보를 추가로 덤프한다. 출력되는 정보는 cp, char, weight, next-cp, char, weight이다.

-w, --weight-order

가중치 값을 기반으로 정렬한 콜레이션 정보를 추가로 덤프한다. 출력되는 정보는 weight, cp, char이다.

-s, --start-value=CODEPOINT

덤프 범위의 시작을 지정한다. -a , –identifier-alphabet , -c, -w 옵션들에 대한 시작 코드포인트이며, 기본값은 0이다.

-e, --end-value=CODEPOINT

덤프 범위의 끝을 지정한다. -a, –identifier-alphabet, -c, -w 옵션들에 대한 끝 코드포인트이며, 기본값은 로캘 공유 라이브러리에서 읽은 최대값이다.

-k, --console-conversion

콘솔 변환 데이터를 추가로 덤프한다.

-z, --normalization

정규화 데이터를 추가로 덤프한다.

다음은 캘린더 정보, 숫자 표기 정보, 알파벳 및 대소문자 정보, 식별자에 대한 알파벳 및 대소문자 정보, 코드포인트 순서에 기반한 콜레이션의 정렬, 가중치에 기반한 콜레이션의 정렬, 데이터를 정규화하여 ko_KR 로캘의 내용을 ko_KR_dump.txt라는 파일에 덤프하는 예이다.

% cubrid dumplocale -d -n -a both -c -w -z ko_KR > ko_KR_dump.txt

여러 개의 옵션을 설정하면 출력되는 내용이 매우 많을 수 있으므로, 파일로 리다이렉션하여 저장할 것을 권장한다.

6단계: CUBRID 관련 프로세스 시작

모든 CUBRID 관련 프로세스는 같은 환경 설정을 통해 구동되어야 한다. CUBRID 서버, 브로커, CAS, CSQL 등은 같은 버전의 로캘 바이너리 파일을 사용해야 한다. CUBRID HA 구성 시에도 마찬가지이다. 예를 들어, CUBRID HA 구성에서 마스터 서버, 슬레이브 서버와 레플리카 서버 등은 환경 설정이 모두 같아야 한다.

서버 프로세스와 CAS 프로세스에 의해 사용되는 로캘의 호환성 여부를 시스템이 자동으로 검사하지 않기 때문에, 두 프로세스 간에 LDML 파일들이 똑같다는 것을 보장해야 한다.

로캘 라이브러리 로딩은 CUBRID 구동의 첫 단계로서, 구동 시에 데이터베이스 구조를 초기화하기 위해 로캘 정보를 요구하는 서버, CAS, CSQL, createdb, copydb, unloaddb, loaddb 프로세스 등은 구동 시점에 로캘 라이브러리를 로딩한다.

로캘 라이브러리 로딩 절차는 다음과 같다.

  • 라이브러리 경로가 제공되지 않으면 $CUBRID/lib/libcubrid_<lang_name>.so 파일의 로딩을 시도한다. 이 파일이 발견되지 않으면 하나의 파일 $CUBRID/lib/libcubrid_all_locales.so에서 모든 로캘이 발견된다고 간주한다.
  • 로캘 라이브러리가 발견되지 않거나 라이브러리를 로딩하는 동안 오류가 발생하면 CUBRID 프로세스 구동이 종료된다.
  • 데이터베이스와 로캘 라이브러리 간 콜레이션 정보가 다르면 CUBRID 프로세스가 구동되지 않는다. 기존 데이터베이스에 로캘 라이브러리의 변경된 콜레이션을 포함하려면, 먼저 cubrid synccolldb 명령을 수행하여 데이터베이스 콜레이션을 로캘 라이브러리에 맞게 동기화한다. 다음으로, 스키마와 데이터를 원하는 콜레이션에 맞게 기존 데이터베이스에 업데이트해야 한다. 자세한 내용은 데이터베이스 콜레이션을 시스템 콜레이션에 동기화를 참고한다.

데이터베이스 콜레이션을 시스템 콜레이션에 동기화

CUBRID가 정상적으로 동작하기 위해서는 시스템 콜레이션과 데이터베이스 콜레이션이 같아야 한다. 시스템 로캘은 내장된 로캘과 cubrid_locales.txt 파일을 통해(로캘 설정 참고) 생성한 라이브러리 로캘을 포함한 로캘을 의미하며, 시스템 로캘은 시스템 콜레이션 정보를 포함한다. 데이터베이스 콜레이션 정보는 _db_collation 시스템 카탈로그 테이블에 저장된다.

cubrid synccolldb 유틸리티는 데이터베이스 콜레이션이 시스템 콜레이션과 일치하는지 확인하고, 다를 경우 데이터베이스 콜레이션을 시스템 콜레이션에 동기화하는 유틸리티이다. 하지만, 이 유틸리티는 데이터베이스 서버에 저장된 데이터 자체를 변환하지 않음을 인지해야 한다.

이 유틸리티는 시스템 로캘이 변경된 이후 기존의 데이터베이스 콜레이션 정보를 변경해야 할 때 사용할 수 있다. 단, 사용자가 직접 수동으로 진행해야 하는 작업들이 있다.

동기화하기 전에 다음과 같은 작업을 수행한다. cubrid synccolldb -c 명령을 수행하여 생성되는 cubrid_synccolldb_<database_name>.sql 파일을 CSQL을 통해 실행하면 된다.

  • ALTER TABLE MODIFY 문을 사용하여 콜레이션을 수정한다.
  • 콜레이션을 포함하는 뷰, 인덱스, 트리거, 분할(partition) 등을 모두 제거한다.

cubrid synccolldb를 가지고 동기화를 수행한다. 그리고 아래 작업을 수행한다.

  • 뷰, 인덱스, 트리거, 분할 등을 재생성한다.
  • 새로운 콜레이션에 맞게 응용 프로그램의 질의문들을 업데이트한다.

이 유틸리티는 데이터베이스를 정지한 상태에서 수행해야 한다.

synccolldb 구문은 다음과 같다.

cubrid synccolldb [options] database_name
  • cubrid: CUBRID 서비스 및 데이터베이스 관리를 위한 통합 유틸리티이다.
  • synccolldb: 데이터베이스 콜레이션을 시스템 콜레이션(로캘 라이브러리의 내용과 $CUBRID/conf/cubrid_locales.txt 파일을 따름)으로 동기화하는 명령이다.
  • database_name: 콜레이션 정보가 로캘 라이브러리의 콜레이션에 맞게 동기화될 데이터베이스의 이름이다.

[options]를 생략하면 시스템과 데이터베이스 간 콜레이션 차이를 출력하고, 동기화하기 전에 삭제되어야 할 객체 질의문을 포함하는 cubrid_synccolldb_<database_name>.sql 파일을 생성한다.

다음은 cubrid synccolldb에서 사용하는 [options]이다.

-c, --check-only

데이터베이스의 콜레이션과 시스템의 콜레이션을 확인하여 불일치하는 콜레이션 정보를 출력한다.

-f, --force-only

데이터베이스에 있는 콜레이션 정보를 시스템에서 설정한 콜레이션과 동일하게 업데이트할 때 업데이트 여부를 질문하지 않는다.

다음의 예는 시스템 콜레이션과 데이터베이스의 콜레이션이 서로 다를 때 어떻게 동작하는지를 보여준다.

먼저 ko_KR 로캘에 대한 로캘 라이브러리를 생성한다.

$ echo ko_KR > $CUBRID/conf/cubrid_locales.txt
$ make_locale.sh -t 64

다음으로 데이터베이스를 생성한다.

$ cubrid createdb --db-volume-size=20M --log-volume-size=20M xdb en_US

스키마를 생성한다. 이때, 각 테이블에 원하는 콜레이션을 지정한다.

$ csql -S -u dba xdb -i in.sql
CREATE TABLE dept (depname STRING PRIMARY KEY) COLLATE utf8_ko_cs_uca;
CREATE TABLE emp (eid INT PRIMARY KEY, depname STRING, address STRING) COLLATE utf8_ko_cs_uca;
ALTER TABLE emp ADD CONSTRAINT FOREIGN KEY (depname) REFERENCES dept(depname);

시스템의 로캘 설정을 변경한다. cubrid_locales.txt에 아무런 값도 설정하지 않으면 데이터베이스에는 내장된 로캘만 존재하는 것으로 간주한다.

$ echo "" > $CUBRID/conf/cubrid_locales.txt

cubrid synccolldb -c 명령을 수행하여 시스템과 데이터베이스 간 콜레이션 차이를 확인한다.

$ cubrid synccolldb -c xdb

----------------------------------------
----------------------------------------
Collation 'utf8_ko_cs_uca' (Id: 133) not found in database or changed in new system configuration.
----------------------------------------
----------------------------------------
Collation 'utf8_gen_ci' (Id: 44) not found in database or changed in new system configuration.
----------------------------------------
----------------------------------------
Collation 'utf8_gen_ai_ci' (Id: 37) not found in database or changed in new system configuration.
----------------------------------------
----------------------------------------
Collation 'utf8_gen' (Id: 32) not found in database or changed in new system configuration.
----------------------------------------
----------------------------------------
There are 4 collations in database which are not configured or are changed compared to system collations.
Synchronization of system collation into database is required.
Run 'cubrid synccolldb -f xdb'

인덱스가 존재한다면 먼저 인덱스를 제거한 후 각 테이블의 콜레이션을 변환하고, 이후 인덱스 생성을 직접 수행해야 한다. 인덱스를 제거하고 테이블의 콜레이션을 변환하는 과정은 synccolldb에서 생성된 cubrid_synccolldb_xdb.sql 파일로 수행할 수 있다. 다음 예에서는 외래 키가 재생성해야 될 인덱스에 해당한다.

$ cat cubrid_synccolldb_xdb.sql

ALTER TABLE [dept] COLLATE utf8_bin;
ALTER TABLE [emp] COLLATE utf8_bin;
ALTER TABLE [emp] DROP FOREIGN KEY [fk_emp_depname];
ALTER TABLE [dept] MODIFY [depname] VARCHAR(1073741823) COLLATE utf8_bin;
ALTER TABLE [emp] MODIFY [address] VARCHAR(1073741823) COLLATE utf8_bin;
ALTER TABLE [emp] MODIFY [depname] VARCHAR(1073741823) COLLATE utf8_bin;

$ csql -S -u dba -i cubrid_synccolldb_xdb.sql xdb

시스템 콜레이션을 데이터베이스에 동기화하기 전에 위의 cubrid_synccolldb_xdb.sql 스크립트 파일을 실행하여 예전의 콜레이션들을 삭제해야 한다.

cubrid synccolldb 명령을 수행한다. 옵션을 생략하면 해당 명령을 수행할 것인지를 확인하는 메시지가 나타나며, -f 옵션을 주면 확인 과정 없이 데이터베이스와 시스템 간 콜레이션 동기화를 수행한다.

$ cubrid synccolldb xdb
Updating system collations may cause corruption of database. Continue (y/n) ?
Contents of '_db_collation' system table was updated with new system collations.

DROP된 외래 키를 다시 생성한다.

$ csql -S -u dba xdb

ALTER TABLE emp ADD CONSTRAINT FOREIGN KEY fk_emp_depname(depname) REFERENCES dept(depname);

Note

CUBRID에서 콜레이션은 CUBRID 서버에 의해 숫자 ID로 인식되며, ID의 범위는 0부터 255까지이다. LDML 파일은 공유 라이브러리로 컴파일되는데, 콜레이션 ID와 콜레이션(이름, 속성)의 매핑 정보를 제공한다.

  • 시스템 콜레이션은 CUBRID 서버와 CAS 모듈에 의해 로캘 라이브러리로부터 로딩되는 콜레이션이다.
  • 데이터베이스 콜레이션은 _db_collation 시스템 테이블에 저장되는 콜레이션이다.

콜레이션 설정

콜레이션(collation)이란 문자열 비교 및 정렬 규칙의 집합이다. 콜레이션의 전형적인 예는 알파벳 순서의 정렬(alphabetization)이다.

테이블 생성 시에 칼럼의 문자셋과 콜레이션이 명시되지 않으면, 칼럼은 테이블의 문자셋과 콜레이션을 따른다. 문자셋과 콜레이션 설정은 기본적으로 클라이언트의 설정을 따른다. 표현식 결과가 문자열 데이터이면 표현식의 피연산자를 감안한 콜레이션 추론 과정을 통하여 문자셋과 콜레이션을 결정한다.

Note

CUBRID는 유럽과 아시아 언어를 포함한 여러 가지 언어들의 콜레이션을 지원한다. 이러한 언어들은 다른 알파벳들을 사용할 뿐만 아니라, 특정 언어들은 일부 문자셋에 대해 확장(expansion) 또는 축약(contraction) 정의를 필요로 한다. 이러한 사항들의 대부분은 The Unicode Consortium에 의해 유니코드 표준(2012년 현재 버전 6.1.0)으로 제정되어 있으며, 대부분의 언어가 요구하는 모든 문자 정보는 DUCET 파일(http://www.unicode.org/Public/UCA/latest/allkeys.txt)에 저장되어 있다.

이러한 DUCET에 표현된 대부분의 코드포인트는 0~FFFF 내의 범위에 포함되지만, 이 범위를 넘는 코드포인트도 존재한다. 하지만 CUBRID는 0~FFFF 내의 코드포인트만 사용하고, 나머지들은 무시한다(하위 부분만 사용하도록 설정할 수도 있다).

DUCET에 있는 각각의 코드포인트는 하나 또는 그 이상의 콜레이션 원소(element)를 가지고 있다. 하나의 콜레이션 원소는 네 개 숫자 값의 집합으로, 문자 비교의 네 가지 수준(level)을 가중치(weight)로 표현한다. 각각의 가중치 값은 0~FFFF의 범위를 가진다.

DUCET에서 한 문자는 하나의 라인으로 다음과 같이 표현된다.

< codepoint_or_multiple_codepoints >  ; [.W1.W2.W3.W4][....].... # < readable text explanation of the symbol/character >

한국어 문자 기역은 다음과 같이 표현된다.

1100  ; [.313B.0020.0002.1100] # HANGUL CHOSEONG KIYEOK

위의 예에서 1100은 코드포인트, [.313B.0020.0002.1100]은 하나의 콜레이션 원소이며, 313B는 Level 1, 0020은 Level 2, 0002는 Level 3, 1100은 Level 4의 가중치이다.

언어의 기능적 속성으로 정의되는 확장 지원은 하나의 결합 문자를 그것을 만드는 한 쌍의 문자들로 해석하도록 지원한다는 것을 의미한다. 예를 들어, 한 문자 ‘æ’ 을 두 개의 문자 ‘ae’와 같은 문자로 해석한다. DUCET에서 확장은 하나의 코드포인트나 축약에 대해 하나 이상의 콜레이션 원소들로 표현된다. 확장이 있는 콜레이션을 다루는 것은 두 개의 문자열을 비교할 때 콜레이션의 세기/수준까지 여러 번 비교하는 비용을 감수해야 하기 때문에, CUBRID는 기본적으로는 확장을 지원하지 않도록 설정되어 있다.

칼럼의 문자셋과 콜레이션

칼럼의 문자셋과 콜레이션은 문자열 데이터 타입(VARCHAR, CHAR)과 ENUM 타입에 적용된다. 기본적으로 모든 문자열 데이터 타입은 데이터베이스의 기본 문자셋과 콜레이션을 따르는데, 이를 변경하여 지정할 수 있는 방법을 제공한다.

문자셋

문자셋은 문자열 리터럴이나 따옴표 없는 식별자(identifier)로 명시될 수 있으며, 지원하는 문자셋은 다음과 같다.

  • ISO-8859-1
  • UTF-8 (문자당 최대 4 바이트 길이, 즉 0~0x10FFFF 범위 내의 코드포인트를 지원)
  • EUC-KR (이 문자셋은 하위 호환을 위해서 존재할 뿐 사용을 권장하지 않는다.)

Note

CUBRID 9.0 미만 버전까지는 ISO-8859-1 문자셋이 설정되면 EUC-KR 문자들을 사용할 수 있도록 지원했지만, 이후 버전부터는 이를 지원하지 않는다. EUC-KR 문자들은 오직 EUC-KR 문자셋에서만 사용될 수 있다.

문자열 검사

기본적으로 모든 입력 데이터는 DB 생성 시 설정한 문자로 간주한다. 하지만 SET NAMES 문이나 문자셋 소개자(또는 COLLATE 문자열 수정자)가 DB 생성 시 설정한 로캘보다 우선한다(문자열 리터럴의 문자셋과 콜레이션 참고).

서버 문자셋이 UTF-8인데 UTF-8 바이트 순서(byte sequence)에 맞지 않는 데이터와 같이 무효한 데이터에 대해 문자열을 검사하지 않으면 정의되지 않은 동작을 보이거나 심지어 서버가 비정상 종료(crash)될 수 있다. 기본적으로는 문자열을 검사하지 않도록 설정되어 있다. 문자열을 검사하려면 intl_check_input_string 시스템 파라미터의 값을 yes로 설정한다(기본값: no). 하지만 유효한 데이터만 입력된다고 보장할 수 있다면, 문자열 검사는 하지 않는 것이 성능상 더 유리하다. intl_check_input_string 시스템 파라미터의 값이 yes인 경우, UTF-8과 EUC-KR 문자셋에 대해서만 유효한 데이터 인코딩인지 검사한다. ISO-8859-1 문자셋은 한 바이트 인코딩이므로 모든 바이트 값이 유효하기 때문에 검사하지 않는다.

문자셋 변환

콜레이션/문자셋 수정자(COLLATE / CHARSET) 또는 콜레이션 추론 과정에 의해서 문자셋 변환이 일어날 수 있는데, 이러한 문자셋 변환은 비가역적(irreversible)이다. 일반적으로, 문자셋 변환은 문자 트랜스코딩(transcoding)이다(어떤 문자셋에 있는 문자를 표현하는 바이트 값이 대상 문자셋에서 같은 문자를 나타내지만 다른 바이트 값으로 대체된다).

어떤 변환이든, 손실이 발생할 수 있다. 원본 문자셋에 있는 문자를 대상 문자셋으로 인코딩할 수 없으면 ‘?’ 문자로 대체된다. 바이너리 문자셋을 다른 문자셋으로 변환할 때도 마찬가지이다. 가장 많은 문자를 지원하는 문자셋은 UTF-8이며 유니코드를 인코딩하므로 모든 문자가 인코딩될 수 있다. 그러나 ISO-8859-1에서 UTF-8로 변환하면 일부 “손실”이 발생할 수 도 있다. 예를 들어 80-A0 범위의 바이트 값은 ISO-8859-1 문자에서 유효한 값은 아니지만 문자열에 나타날 수도 있다. 이 문자들을 UTF-8로 변환하면 ‘?’로 대체된다.

한 문자에서 다른 문자로 변환되는 규칙은 다음과 같다.

Source \ Destination Binary ISO-8859-1 UTF-8 EUC-KR
Binary 변환 없음 변환 없음 변환 없음. 문자당 유효성 검증. 유효하지 않은 문자 ‘?’로 대체 변환 없음. 문자당 유효성 검증. 유효하지 않은 문자 ‘?’로 대체
ISO-8859-1 변환 없음 변환 없음 바이트 변환. 바이트 크기가 증가됨. 사용 가능한 문자 손실은 없음. 바이트 변환. 바이트 크기가 증가됨. 사용 가능한 문자 손실은 없음.
UTF-8 변환 없음. 바이트 크기는 변화 없음. 문자 길이는 증가함. 바이트 재해석. 바이트 크기가 감소될 수 있음. 문자 손실이 예상됨. 변환 없음 바이트 변환. 바이트 크기가 감소될 수 있음. 문자 손실이 예상됨.
EUC-KR 변환 없음. 바이트 크기는 변화 없음. 문자 길이는 증가함. 바이트 변환. 바이트 크기가 감소될 수 있음. 문자 손실이 예상됨. 바이트 변환. 바이트 크기가 증가될 수 있음. 사용 가능한 문자 손실은 없음. 변환 없음

Note

CUBRID 9.x 이전 버전은 바이너리 문자셋을 지원하지 않았으며, 대신 ISO-8859-1 문자셋이 기본 바이너리 문자셋 기능을 했다. UTF-8 및 EUC-KR 문자셋에서 ISO-8859-1로 변환하는 경우 문자 변환이 아니라 원본의 콘텐츠(바이트)를 재해석하여 변환을 수행한다.

콜레이션

콜레이션은 문자열 리터럴이나 따옴표 없는 식별자로 명시될 수 있다.

다음은 내장된(built-in) 콜레이션에 대한 db_collation 시스템 카탈로그 뷰의 질의(SELECT * FROM db_collation WHERE is_builtin=’Yes’) 결과이다.

coll_id  coll_name        charset_name    is_builtin  has_expansions  contractions  uca_strength
================================================================================================
0        'iso88591_bin'   'iso88591'     'Yes'        'No'            0             'Not applicable'
1        'utf8_bin'       'utf8'         'Yes'        'No'            0             'Not applicable'
2        'iso88591_en_cs' 'iso88591'     'Yes'        'No'            0             'Not applicable'
3        'iso88591_en_ci' 'iso88591'     'Yes'        'No'            0             'Not applicable'
4        'utf8_en_cs'     'utf8'         'Yes'        'No'            0             'Not applicable'
5        'utf8_en_ci'     'utf8'         'Yes'        'No'            0             'Not applicable'
6        'utf8_tr_cs'     'utf8'         'Yes'        'No'            0             'Not applicable'
7        'utf8_ko_cs'     'utf8'         'Yes'        'No'            0             'Not applicable'
8        'euckr_bin'      'euckr'        'Yes'        'No'            0             'Not applicable'
9        'binary'         'binary'       'Yes'        'No'            0             'Not applicable'

내장된 콜레이션은 사용자 로캘 라이브러리의 추가 없이 사용 가능하며, 각 콜레이션은 관련 문자셋을 가지고 있기 때문에 문자셋과 콜레이션이 호환되도록 지정해야 한다.

COLLATE 수정자가 CHARSET 수정자 없이 명시되면, 콜레이션의 기본 문자셋이 설정된다. CHARSET 수정자가 COLLATE 수정자 없이 명시되면, 기본(default) 콜레이션이 설정된다.

문자셋들에 대한 기본 콜레이션은 바이너리 콜레이션으로, 문자셋 및 이에 대응되는 바이너리 콜레이션은 다음과 같다.

  • ISO-8859-1: iso88591_bin
  • UTF-8: utf8_bin
  • EUC-KR: euckr_bin
  • Binary: binary

Binary는 콜레이션과 관련 문자셋의 이름이다.

서로 다른 콜레이션(과 문자셋)을 가진 표현식 인자(피연산자)를 가질 때 어떤 콜레이션을 사용할지 결정하는 방법에 대해서는 콜레이션이 서로 다를 때 결정 방식 을 참고한다.

CHARSET과 COLLATE 수정자

기본 데이터베이스 콜레이션과 문자셋을 따르지 않고 콜레이션과 문자셋을 변경하여 지정할 수 있는 문자열 타입에 대한 수정자를 제공한다.

  • CHARACTER_SET (또는 CHARSET) 수정자는 칼럼의 문자셋을 바꾼다.
  • COLLATE 수정자는 칼럼의 콜레이션을 바꾼다.
<data_type> ::= <column_type> [<charset_modifier_clause>] [<collation_modifier_clause>]

<charset_modifier_clause> ::= {CHARACTER_SET | CHARSET} {<char_string_literal> | <identifier> }

<collation_modifier_clause> ::= COLLATE {<char_string_literal> | <identifier> }

다음은 VARCHAR 타입 칼럼의 문자셋을 UTF-8로 설정하는 예이다.

CREATE TABLE t1 (s1 VARCHAR (100) CHARSET utf8);

다음은 칼럼 s1의 이름을 c1으로 바꾸고, 해당 타입을 콜레이션이 utf8_en_cs인 CHAR(10) 으로 바꾸는 예이다. 문자셋은 해당 콜레이션에 대한 기본 문자셋인 UTF-8으로 지정된다.

ALTER TABLE t1 CHANGE s1 c1 CHAR(10) COLLATE utf8_en_cs;

다음은 c1 칼럼의 값을 콜레이션 iso88591_en_ci인 VARCHAR(5) 타입으로 바꿔 출력한다. 정렬 연산 또한 첫번째로 선택된 칼럼의 타입에 대한 콜레이션 iso88591_en_ci을 사용하여 수행된다.

SELECT CAST (c1 as VARCHAR(5) COLLATE 'iso88591_en_ci') FROM t1 ORDER BY 1;

다음은 위와 유사한 질의(같은 정렬)이지만, 출력되는 칼럼 결과가 원래의 값이다.

SELECT c1 FROM t1 ORDER BY CAST (c1 as VARCHAR(5) COLLATE iso88591_en_ci);

콜레이션이 서로 다를 때 결정 방식

CREATE TABLE t (
    s1 STRING COLLATE utf8_en_cs,
    s2 STRING COLLATE utf8_tr_cs
);

-- insert values into both columns

SELECT s1, s2 FROM t WHERE s1 > s2;
ERROR: '>' requires arguments with compatible collations.

위의 예에서 칼럼 s1과 s2 는 다른 콜레이션을 가지고 있고, s1과 s2 를 비교한다는 것은 테이블 t에 있는 레코드끼리 어떤 칼럼의 값이 “더 큰지” 결정할 수 있는 문자열을 비교한다는 것을 의미한다. 콜레이션 utf8_en_cs와 utf8_tr_cs는 서로 비교할 수 없으므로 이 경우에는 에러를 출력할 것이다.

표현식의 타입 결정 방법의 원칙이 콜레이션 결정 방법에도 마찬가지로 적용된다.

  1. 표현식의 모든 인자들을 고려하여 공통 콜레이션과 문자셋을 결정한다.
  2. 1.에서 결정된 공통 콜레이션(또는 문자셋)과 다른 인자들을 변환한다.
  3. 콜레이션을 변경하기 위해서 CAST() 연산자가 사용될 수 있다.

비교 표현식의 결과 콜레이션을 결정하기 위해 “콜레이션 변환도(collation coercibility)”를 사용한다. 이는 자신의 콜레이션이 얼마나 쉽게 상대 인자의 콜레이션으로 변환되기 쉬운가를 표현한 것으로, 표현식의 두 피연산자를 비교할 때 콜레이션 변환도가 크다는 것은 상대 인자의 콜레이션으로 쉽게 변환된다는 것을 의미한다. 즉, 높은 변환도를 지닌 인자는 더 낮은 변환도를 지닌 인자의 콜레이션으로 변환될 수 있다.

표현식의 인자들이 서로 다른 콜레이션을 가지면, 이들에 대한 공통 콜레이션은 각 인자들의 콜레이션과 변환도에 기반하여 결정된다.

  1. 높은 변환도를 가진 인자는 더 낮은 변환도를 가진 인자의 콜레이션으로 변환된다.
  2. 인자들의 콜레이션이 서로 다르고 변환도가 같은 경우에는 표현식의 콜레이션을 결정할 수 없고 에러가 리턴된다. 단, 콜레이션 변환도 11(호스트 변수, 사용자 정의 변수)이고 동일한 문자셋인 두 피연산자를 비교하는 경우 둘 중 하나가 바이너리 콜레이션(utf8_bin, iso88591_bin, euckr_bin)이면 바이너리가 아닌(non-binary) 콜레이션으로 변환된다. 세션 변수와(또는) 호스트 변수의 비교를 참고한다.

표현식 인자들의 변환도는 다음의 표와 같다.

콜레이션 변환도 표현식의 인자(피연사자)
-1 호스트 변수만을 가지는 표현식으로, 실행단계 이전에는 콜레이션 변환도를 결정할 수 없는 경우.
0 COLLATE 수정자를 가진 피연산자
1 Columns 이 바이너리가 아닌 (non-binary) 콜레이션을 가진 경우
2 Columns 이 바이너리 콜레이션과 ISO-8859-1 문자셋(iso88591_bin)을 가진 경우
3 Columns 이 ISO-8859-1 문자셋을 가진 경우를 제외하고 바이너리 콜레이션을 가진 경우
4 SELECT 값, 표현식이 바이너리가 아닌 콜레이션을 가진 경우
5 SELECT 값, 표현식이 바이너리 콜레이션과 ISO-8859-1 문자셋(iso88591_bin)을 가진 경우
6 SELECT 값, 표현식이 ISO-8859-1 문자셋을 가진 경우를 제외하고 바이너리 콜레이션을 가진 경우
7 특수 함수들 (SYSTEM_USER(), DATABASE(), SCHEMA(), VERSION())
8 상수 문자열이 바이너리가 아닌(non-binary) 콜레이션을 가진 경우
9 상수 문자열이 바이너리 콜레이션과 ISO-8859-1 문자셋(iso88591_bin)을 가진 경우
10 상수 문자열이 ISO-8859-1 문자셋을 가진 경우를 제외하고 바이너리 콜레이션을 가진 경우
11 호스트 변수, 사용자 정의 변수

Note

9.x 버전에서는 바이너리 콜레이션을 지원하지 않았으며, 대신 iso85891_bin 콜레이션이 기본 바이너리 콜레이션 기능을 했다. 버전 10.0부터는 iso88591_bin이 포함된 컬럼의 변환도(coercibility)가 2에서 3으로 강등되었고, iso88591_bin이 포함된 표현식에서는 5에서 6으로, iso88591_bin이 포함된 상수에서는 9에서 10으로 강등되었다.

호스트 변수만을 인자로 가지는 표현식(예: 아래의 UPPER(?))에 대해서는 실행 단계에서 콜레이션 변환도를 결정할 수 있다. 즉, 파싱 단계에서는 이러한 표현식의 콜레이션 변환도를 결정할 수 없으므로 COERCIBILITY 함수는 -1을 반환한다.

SET NAMES utf8
PREPARE st FROM 'SELECT COLLATION(UPPER(?)) col1, COERCIBILITY(UPPER(?)) col2';
EXECUTE st USING 'a', 'a';
  col1                         col2
===================================
  'utf8_bin'                     -1

모든 인자의 변환도가 11이고 콜레이션이 서로 다른 표현식에서는 실행중에 공통 콜레이션이 확인된다(이것은 유추를 위한 변환도 값 기반 규칙의 예외 사항이며 오류를 유발할 것이다.)

PREPARE st1 FROM 'SELECT INSERT(?,2,2,?)';
EXECUTE st1 USING _utf8'abcd', _binary'ef';
 insert( ?:0 , 2, 2,  ?:1 )
======================
 'aefd'

콜레이션이 서로 다른 두 개의 인자가 하나의 콜레이션으로 변환되는 경우를 살펴보면 다음과 같다.

  • 원하는 콜레이션을 지정하여 변환

    앞의 예제에서 실행에 실패한 SELECT 문은 다음 질의문처럼 한 칼럼에 CAST 연산자로 콜레이션을 지정하여 두 피연산자를 같은 콜레이션을 갖도록 하면 성공적으로 수행된다.

    SELECT s1, s2 FROM t WHERE s1 > CAST (s2 AS STRING COLLATE utf8_en_cs);
    

    또한, s2를 바이너리 콜레이션으로 CAST 하면, s1의 콜레이션으로 변환도 (6)은 s1의 변환도 (1)보다 높다.

    SELECT s1, s2 FROM t WHERE s1 > CAST (s2 AS STRING COLLATE utf8_bin);
    

    다음과 같은 질의문에서 두 번째 피연산자 “CAST (s2 AS STRING COLLATE utf8_tr_cs)”는 서브 표현식이고, 서브 표현식은 칼럼(s1)보다 더 높은 변환도를 가지기 때문에, “CAST (s2 AS STRING COLLATE utf8_tr_cs)”는 s1의 콜레이션으로 변환된다.

    SELECT s1, s2 FROM t WHERE s1 > CAST (s2 AS STRING COLLATE utf8_tr_cs);
    

    어떤 표현식이든 표현식은 칼럼보다 높은 변환도를 갖는다.

    SELECT s1, s2 FROM t WHERE s1 > CONCAT (s2, '');
    
  • 상수와 칼럼의 콜레이션 변환

    다음의 경우 칼럼 s1의 콜레이션을 사용하여 비교가 수행된다.

    SELECT s1, s2 FROM t WHERE s1 > 'abc';
    
  • 칼럼이 Bin 콜레이션으로 생성되는 경우

    CREATE TABLE t (
        s1 STRING COLLATE utf8_en_cs,
        s2 STRING COLLATE utf8_bin
    );
    SELECT s1, s2 FROM t WHERE s1 > s2;
    

    위 경우 s2 칼럼의 변환도는 6( Bin 콜레이션)으로, s1 칼럼의 콜레이션으로 “완전히 변환 가능”하여 utf8_en_cs 콜레이션이 사용된다.

    CREATE TABLE t (
        s1 STRING COLLATE utf8_en_cs,
        s2 STRING COLLATE iso88591_bin
    );
    SELECT s1, s2 FROM t WHERE s1 > s2;
    

    위 경우에도 마찬가지로 콜레이션으로 utf8_en_cs가 사용되는데, s2 칼럼이 ISO 문자셋이므로 UTF-8로 변환하는 오버헤드가 발생한다는 차이가 있다.

    다음 질의문에서 문자셋 변환은 발생하지 않고 s2 칼럼의 UTF-8의 바이트 데이터는 간단하게 ISO-8859-1 문자셋으로 재해석되며, iso88591_en_cs 콜레이션을 사용하여 문자 비교만 수행된다.

    CREATE TABLE t (
        s1 STRING COLLATE iso88591_en_cs,
        s2 STRING COLLATE utf8_bin
    );
    SELECT s1, s2 FROM t WHERE s1 > s2;
    
  • 서브 표현식과 칼럼의 콜레이션 변환

    CREATE TABLE t (
        s1 STRING COLLATE utf8_en_cs,
        s2 STRING COLLATE utf8_tr_cs
    );
    SELECT s1, s2 FROM t WHERE s1 > s2 + 'abc';
    

    위 경우 두 번째 피연산자는 표현식이기 때문에 s1의 콜레이션이 사용된다.

    다음 예제는 서로 다른 콜레이션을 지닌 s2와 s3에 대해 ‘+’ 연산을 수행하려고 하기 때문에 에러가 발생한다.

    CREATE TABLE t (
        s1 STRING COLLATE utf8_en_cs,
        s2 STRING COLLATE utf8_tr_cs,
        s3 STRING COLLATE utf8_en_ci
    );
    
    SELECT s1, s2 FROM t WHERE s1 > s2 + s3;
    
    ERROR: '+' requires arguments with compatible collations.
    

    다음 예제에서는 s2와 s3가 같은 콜레이션이므로 ‘+’ 표현식이 utf8_tr_cs이 되고, s1은 칼럼이므로 표현식보다 낮은 변환도를 갖기 때문에 비교 연산은 utf8_en_cs 콜레이션을 사용해서 수행된다.

    CREATE TABLE t (
        s1 STRING COLLATE utf8_en_cs,
        s2 STRING COLLATE utf8_tr_cs,
        s3 STRING COLLATE utf8_tr_cs
    );
    
    SELECT s1, s2 FROM t WHERE s1 > s2 + s3;
    
  • 숫자, 날짜 타입 상수의 콜레이션 변환

    연산 과정에서 문자열로 변환 가능한 숫자 또는 날짜 타입 상수는 항상 상대 문자열의 콜레이션으로 변환될 수 있다.

  • 세션 변수와(또는) 호스트 변수의 콜레이션 변환

    콜레이션 변환도가 11(세션 변수, 호스트 변수)이고 문자셋이 동일한 피연산자끼리 비교하는 경우 바이너리가 아닌(non-bin) 콜레이션으로 변환된다.

    SET NAMES utf8;
    SET @v1='a';
    PREPARE stmt FROM 'SELECT COERCIBILITY(?), COERCIBILITY(@v1), COLLATION(?), COLLATION(@v1), ? = @v1';
    SET NAMES utf8 COLLATE utf8_en_ci;
    EXECUTE stmt USING 'A', 'A', 'A';
    

    @v1과 ‘A’를 비교하면 @v1은 바이너리가 아닌 콜레이션인 utf8_en_ci로 변환되어 @v1과 ‘A’가 서로 동일하게 되므로, 아래처럼 “? = @v1”의 결과는 1이 된다.

       coercibility( ?:0 )   coercibility(@v1)   collation( ?:1 )      collation(@v1)          ?:2 =@v1
    ===================================================================================================
                        11                  11  'utf8_en_ci'          'utf8_bin'                      1
    
    SET NAMES utf8 COLLATE utf8_en_cs;
    EXECUTE stmt USING 'A', 'A', 'A';
    

    @v1과 ‘A’를 비교하면 @v1은 바이너리가 아닌 콜레이션인 utf8_en_cs로 변환되어 @v1과 ‘A’가 서로 다르게 되므로, 아래처럼 “? = @v1”의 결과는 0이 된다.

       coercibility( ?:0 )   coercibility(@v1)   collation( ?:1 )      collation(@v1)          ?:2 =@v1
    ===================================================================================================
                        11                  11  'utf8_en_cs'          'utf8_bin'                      0
    

    그러나, 아래와 같이 @v1과 ‘A’의 콜레이션이 둘 다 바이너리가 아닌 콜레이션이고 두 콜레이션이 서로 다르면 에러가 발생한다.

    DEALLOCATE PREPARE stmt;
    SET NAMES utf8 COLLATE utf8_en_ci;
    SET @v1='a';
    PREPARE stmt FROM 'SELECT COERCIBILITY(?), COERCIBILITY(@v1), COLLATION(?), COLLATION(@v1), ? = @v1';
    SET NAMES utf8 COLLATE utf8_en_cs;
    EXECUTE stmt USING 'A', 'A', 'A';
    
    ERROR: Context requires compatible collations.
    

ENUM 타입 칼럼의 문자셋과 콜레이션

ENUM 타입 칼럼의 문자셋과 콜레이션은 DB 생성 시 지정한 로캘을 따른다.

예를 들어, en_US.iso88591로 DB를 생성하여 다음 테이블을 생성한다.

CREATE TABLE tbl (e ENUM (_utf8'a', _utf8'b'));

위에서 생성된 테이블의 칼럼 ‘e’는 그 원소의 문자셋이 UTF8로 정의되어 있더라도 ISO88591 문자셋, iso88591_bin 콜레이션을 가진다. 문자열 원소는 칼럼이 생성될 때 UTF8 문자셋에서 ISO88591 문자셋으로 변환된다. 사용자가 다른 문자셋이나 콜레이션을 적용하고 싶으면 테이블의 칼럼에 대해 이를 명시해야 한다.

아래는 테이블의 칼럼에 대해 콜레이션을 명시하는 예이다.

CREATE TABLE t (e ENUM (_utf8'a', _utf8'b') COLLATE utf8_bin);
CREATE TABLE t (e ENUM (_utf8'a', _utf8'b')) COLLATE utf8_bin;

테이블의 문자셋과 콜레이션

테이블 생성 구문에 문자셋과 콜레이션을 지정할 수 있다.

CREATE TABLE table_name (<column_list>) [CHARSET charset_name] [COLLATE collation_name]

칼럼의 문자셋과 콜레이션이 생략되면, 테이블의 문자셋과 콜레이션이 사용된다. 테이블의 문자셋과 콜레이션이 생략되면, 시스템의 문자셋과 콜레이션이 사용된다.

다음은 테이블에 콜레이션을 지정하는 예이다.

CREATE TABLE tbl (
    i1 INTEGER,
    s STRING
) CHARSET utf8 COLLATE utf8_en_cs;

칼럼의 문자셋이 지정되어 있고 테이블의 콜레이션이 지정되는 경우, 해당 칼럼의 콜레이션은 칼럼의 문자셋에 대한 기본 콜레이션(<collation_name>_bin)이 지정된다.

CREATE TABLE tbl (col STRING CHARSET utf8) COLLATE utf8_en_ci;

위의 질의문에서 칼럼 col의 콜레이션은 칼럼에 대한 문자셋의 기본 콜레이션인 utf8_bin이 된다.

csql> ;sc tbl

 <Class Name>

  tbl                  COLLATE utf8_en_ci

 <Attributes>

  col                  CHARACTER VARYING(1073741823) COLLATE utf8_bin

문자열 리터럴의 문자셋과 콜레이션

문자열 리터럴(string literal)의 문자셋과 콜레이션은 다음과 같은 우선 순위에 따라 정해진다.

  1. 문자셋 소개자 또는 문자열의 COLLATE 수정자
  2. SET NAMES 문으로 명시한 문자셋과 콜레이션
  3. 시스템 문자셋과 콜레이션(DB 생성 시 지정한 로캘에 의한 기본 콜레이션)

SET NAMES 문

SET NAMES 문은 기본 클라이언트 문자셋과 콜레이션 값을 변경하여, 이를 실행한 클라이언트에서 이후에 실행하는 모든 문장은 지정한 문자셋과 콜레이션을 가지게 된다. 구문은 다음과 같다.

SET NAMES [charset_name] [COLLATE collation_name]
  • charset_name: 유효한 문자셋 이름은 iso88591, utf8,euckr 그리고 binary이다.
  • collation_name: 콜레이션 지정은 생략할 수 있으며, 모든 가능한 콜레이션이 설정될 수 있다. 콜레이션과 문자셋은 호환되어야 하며, 그렇지 않으면 오류가 발생한다. 사용 가능한 콜레이션 이름은 db_collation 카탈로그 뷰를 검색하여 확인할 수 있다. (칼럼의 문자셋과 콜레이션 참고)

SET NAMES 문으로 콜레이션을 지정하는 것은 시스템 파라미터 intl_collation을 지정하는 것과 같다. 따라서, 다음 두 문장은 같은 동작을 수행한다.

SET NAMES utf8;
SET SYSTEM PARAMETERS 'intl_collation=utf8_bin';

다음은 기본 문자셋과 콜레이션을 가진 문자열 상수를 생성한다.

SELECT 'a';

다음은 utf8 문자셋과 utf8_bin 콜레이션을 가진 문자열 상수를 생성한다. 참고로 기본 콜레이션은 해당 문자셋의 바이너리 콜레이션이다.

SET NAMES utf8;
SELECT 'a';

문자셋 소개자

상수 문자열 앞에는 문자셋 소개자(introducer)가 올 수 있고, 뒤에는 COLLATE 수정자(modifier)가 올 수 있는데, 문자셋 소개자는 언더바(_)로 시작하는 문자셋 이름으로 상수 문자열 앞에 올 수 있다. 문자열에 대해 문자셋 소개자와 COLLATE 수정자를 지정하는 구문은 다음과 같다.

[charset_introducer]'constant-string' [COLLATE collation_name]
  • charset_introducer: 언더바(_)를 앞에 붙인 문자셋 이름으로 생략할 수 있다. _utf8, _iso88591, _euckr, _binary 중 하나를 입력할 수 있다.
  • constant-string: 상수 문자열 값이다.
  • collation_name: 시스템에서 사용 가능한 콜레이션 이름으로 생략할 수 있다.

상수 문자열의 기본 문자셋과 콜레이션은 현재의 데이터베이스 연결을 기준으로 정해지며, 가장 마지막에 수행한 SET NAMES 문 또는 기본값으로 설정된다. 문자셋 소개자 또는 COLLATE 수정자를 생략했을 때는 다음과 같이 동작한다.

  • 문자셋 소개자를 지정하고 COLLATE 수정자를 생략할 때,
    • 문자셋 소개자가 클라이언트 문자셋(SET NAMES로 지정)과 동일하면 클라이언트 콜레이션이 적용된다.
    • 문자셋 소개자가 클라이언트 문자셋과 동일하지 않으면 문자셋 소개자와 동일한 바이너리 콜레이션(euckr_bin, iso88591_bin, utf8_bin 중 하나)이 적용된다.
  • 문자셋 소개자를 생략하고 COLLATE 수정자를 지정하면, 문자셋은 콜레이션에 따라 적용된다.

다음은 문자셋 소개자와 COLLATE 수정자를 지정하는 예제이다.

SELECT 'cubrid';
SELECT _utf8'cubrid';
SELECT _utf8'cubrid' COLLATE utf8_en_cs;

다음 예에서는 utf8 문자셋과 utf8_en_cs 콜레이션을 가지는 문자열 상수를 생성한다. SELECT 문의 COLLATE 수정자가 SET NAMES 문에서 지정한 콜레이션을 오버라이드한다.

SET NAMES utf8 COLLATE utf8_en_ci;
SELECT 'a' COLLATE utf8_en_cs;

표현식의 문자셋과 콜레이션

표현식 결과의 문자셋과 콜레이션은 표현식의 인자들로부터 추론된다. 콜레이션 추론 과정은 콜레이션 변환도(coercibility)에 기반하며 이에 관한 자세한 내용은 콜레이션이 서로 다를 때 결정 방식을 참고한다.

모든 문자열 매칭 함수(LIKE, REPLACE, INSTR, POSITION, LOCATE, SUBSTRING_INDEX, FIND_IN_SET 등)와 비교 연산자들(<, >, = 등)에서 콜레이션이 고려된다.

시스템 데이터의 문자셋과 콜레이션

시스템 문자셋은 DB 생성 시 지정한 로캘에 의해 정해진다. 시스템의 콜레이션은 항상 시스템 문자셋의 바이너리 콜레이션(<charset>_bin)이다. CUBRID는 iso88591, euckr, utf8 이렇게 3개의 문자셋을 지원하며, 이에 따른 iso88591_bin, euckr_bin, utf8_bin 이렇게 3개의 시스템 콜레이션을 지원한다.

DB 생성 시 지정한 로캘의 영향

DB 생성 시 지정한 로캘은 다음에 영향을 끼친다.

  • 식별자(identifier)와 대소문자 규칙에서 지원되는 문자(이를 “알파벳”이라고 지칭함)
  • 날짜-문자열 변환 함수들에 대한 기본 로캘
  • 숫자-문자열 변환 함수들에 대한 기본 로캘
  • CSQL에서 콘솔 변환

식별자의 대소문자 구분

CUBRID에서 식별자는 대소문자 구분을 하지 않는다. 테이블 칼럼, 사용자 정의 변수, 트리거, 저장 프로시저들의 이름은 소문자로, 사용자 이름 및 그룹 이름은 대문자로 저장된다.

ISO-8859-1은 255 개의 문자만을 포함하므로 전체 문자들이 대소문자 변환의 대상이 되며, EUC-KR 문자셋에서는 ASCII 호환 문자들만이 대소문자 변환의 대상이 된다. ISO-8859-1과 EUC-KR 문자셋은 내장된(built-in) 데이터이다.

UTF-8 문자셋에 해당하는 로캘은 내장된 로캘(en_US.utf8, tr_TR.utf8, ko_KR.utf8)과 LDML 로캘의 두 종류가 있다.

내장된 로캘은 특정 문자(en_US.utf8과 ko_KR.utf8에서는 ASCII 문자, tr_TR.utf8에서는 ASCII 문자와 터키어의 글리프(glyphs) [1])만 구현한 것이다. 즉, 최대 4 바이트까지 인코딩된 모든 UTF-8 문자는 식별자로 받아들여지기는 하지만, 이 중 대부분의 문자들은 일반적인 유니코드 문자로 처리되어 대소문자 변환이 이뤄지지 않는다는 것을 뜻한다. 예를 들어, 테이블 이름에서 È(유니코드 코드포인트 00C8)는 허용되지만, 그것을 포함하는 식별자는 소문자 “è”로 변환되어 표현되지 않는다.

CREATE TABLE ÈABC;

따라서, 위의 질의 수행 시 테이블 이름은 _db_class 시스템 테이블에 “Èabc”라는 이름으로 저장된다.

LDML 로캘(내장된 로캘은 LDML 로캘에 의해 오버라이드됨)은 지원하는 유니코드 문자셋을 코드포인트 FFFF까지 확장하므로 식별자에 대해 확장된 알파벳의 대소문자 변환이 가능하다. 예를 들어, DB 생성 시 지정한 로캘이 es_ES.utf8이고 해당 로캘 라이브러리가 로딩되면, 위의 CREATE TABLE 문은 “èabc”라는 이름을 가진 테이블을 생성한다.

앞서 설명한 바와 같이 대소문자 규칙과 지원되는 문자들로 “알파벳”(LDML 파일에 “alphabet” 태그로 정의됨)이 구성되며, tr_TR과 de_DE와 같은 일부 로캘들은 특별한 대소문자 규칙을 가진다. 터키어에서 lower (‘I’) = ‘ı’(점없는 소문자 i)이고, upper (‘i’) = ‘İ’(점있는 대문자 I)이다. 독일어에서 upper (‘ß’) = ‘SS’(두 개의 대문자 S)이다.

이런 특수한 규칙을 갖는 로캘들은 식별자가 대문자 또는 소문자로 변환 저장되면서 발생할 수 있는 문제를 피하기 위해 시스템 데이터(식별자)를 위한 “알파벳”과 사용자 데이터를 위한 “알파벳” 두 개를 가진다. 즉, 사용자 데이터에 적용되는 “알파벳”은 위에서 설명한 특별한 규칙을 포함하는 반면, 시스템 데이터(식별자)를 위한 “알파벳”은 특별한 규칙을 포함하지 않는다. 예를 들어 터키어에서 그룹 이름 “public”에 대해 사용자 데이터에 적용되는 “알파벳”을 적용하면 “PUBLİC”이 되어 결국 의도했던 “PUBLIC”과는 다른 값이 되는 문제가 발생한다.

또한, 시스템 데이터를 위한 “알파벳”은 서로 다른 로캘을 가진 데이터베이스 간에 호환성 제공을 위해서도 필요하다. 이로 인해 서로 다른 로캘 사이에 데이터베이스의 스키마와 데이터를 언로드-로드하는 것이 가능해진다.

문자열 리터럴의 입출력

문자열 리터럴 데이터는 CUBRID에 다양한 방법으로 입력된다.

  • C API interface (CCI)
  • 언어 의존적인 인터페이스. JDBC, Perl 드라이버 등
  • CSQL - 콘솔 또는 파일로부터 입력

드라이버를 통해 문자 데이터를 받을 때, CUBRID는 이 문자들의 문자셋을 인지할 수 없다. 문자열 리터럴(따옴표로 감싼 문자)에 해당하는 모든 텍스트 데이터는 있는 그대로(raw data) 다루어진다. 문자셋 메타 정보는 응용 클라이언트에 의해 제공되어야 한다. 클라이언트는 SET NAMES 문이나 문자셋 소개자 를 통해 문자셋 정보를 제공할 수 있다.

CSQL을 위한 텍스트 변환

CSQL 콘솔 인터페이스에서는 텍스트 변환 동작이 일어날 수 있다. 대부분의 로캘들에는 콘솔에서 ASCII 문자가 아닌 문자를 쉽게 쓸 수 있도록 해주는 문자셋이 별도로 존재한다. 예를 들어 로캘 tr_TR.utf8에 대한 LDML 파일에는 다음 라인이 포함되어 있다.

<consoleconversion type="ISO88599" windows_codepage="28599" linux_charset="iso88599,ISO_8859-9,ISO8859-9,ISO-8859-9" />

사용자가 이와 같이 콘솔의 문자셋을 설정하면(예: Windows에서 chcp 28599, Linux에서 export LANG=tr_TR.iso88599), 모든 입력이 ISO-8859-9 문자셋으로 인코딩된다고 가정하고 모든 데이터를 UTF-8로 변환한다. 또한 결과를 출력할 때는 반대로 UTF-8을 ISO-8859-9로 변환한다. Linux에서는 이러한 변환을 피하기 위해 UTF-8 콘솔(예: export LANG=tr_TR.utf8)을 직접 사용할 것을 권장한다.

LDML 로캘 파일에서 이 XML 태그 설정은 반드시 요구되지는 않으며 선택 사항이다. 예를 들어, 로캘 km_KH.utf8은 관련 코드 페이지가 없다.

프랑스어 설정 및 프랑스어 문자 입력을 위한 설정 예

프랑스어 설정을 하려면 먼저 cubrid_locales.txt 파일에 fr_FR을 설정하고, 로캘을 컴파일(로캘 설정 참고)한 후 DB 생성 시 로캘을 fr_FR.utf8을 설정해야 한다.

Linux에서는 다음과 같이 설정한다.

  • 콘솔이 UTF-8을 입력받을 수 있도록 LANG=fr_FR.utf8 또는 en_US.utf8로 설정한다. 이 설정은 프랑스어 문자 뿐만 아니라 모든 UTF-8 문자를 입력받을 수 있게 한다.
  • 또는 콘솔이 ISO-8859-15를 입력받을 수 있도록 LANG=fr_FR.iso885915로 설정하고, LDML 파일의 <consoleconversion> 태그에서 linux_charset=”iso885915”로 설정한다. 이와 같이 설정하면 ISO-8859-15 문자만을 입력받아 CSQL에 의해 UTF-8로 변환될 것이다.

Windows에서는 다음과 같이 설정한다.

  • Windows 코드페이지를 28605로 변환한다(명령 프롬프트에서 chcp 28605). LDML <consoleconversion> 태그에서 set windows_codepage=”28605”로 설정한다. 코드페이지 28605는 ISO-8859-15 문자셋에 해당한다.

루마니아어 설정 및 루마니아어 문자 입력을 위한 설정 예

루마니아어 설정을 하려면 먼저 cubrid_locales.txt 파일에 ro_RO를 설정하고, 로캘을 컴파일(로캘 설정 참고)한 후 DB 생성 시 로캘을 ro_RO.utf8을 설정해야 한다.

Linux에서는 다음과 같이 설정한다.

  • 콘솔이 UTF-8을 입력받을 수 있도록 LANG=ro_RO.utf8 또는 en_US.utf8로 설정한다. 이 설정은 루마니아어 문자 뿐만 아니라 모든 UTF-8 문자를 입력받을 수 있게 한다.
  • 또는 콘솔이 ISO-8859-2를 입력받을 수 있도록 LANG=ro_RO.iso88592로 설정한다. LDML 파일의 <consoleconversion> 태그에서 linux_charset=”iso88592”로 설정한다. 이와 같이 설정하면 ISO-8859-2 문자만을 입력받아 CSQL에 의해 UTF-8로 변환될 것이다.

Windows에서는 다음과 같이 설정한다.

  • Windows 코드페이지를 1250으로 변환한다(명령 프롬프트에서 chcp 1250). LDML <consoleconversion> 태그에서 set windows_codepage=”1250”로 설정한다. 코드페이지 1250은 ISO-8859-2 문자셋에 해당하며, 루마니아어를 포함하는, 중유럽과 동유럽 언어들 일부에 특화된 문자셋이다. 코드페이지 1250 외의 문자는 제대로 출력되지 않음에 유의한다.

    루마니아 알파벳에 존재하는 특수 문자(예: 문자 아래에 세딜라(cedilla)가 있는 “S”와 “T”)를 사용하기 위해서는 Windows의 “제어판”을 통해 루마니아어(레거시)로 키보드 설정을 변경해야 한다.

  • ISO8859-2는 코드페이지 1250에 없는 문자를 일부 포함하고 있으므로, ISO8859-2의 모든 문자를 CSQL로 입력하거나 출력할 수는 없다.

입력 시 콘솔 변환 프로세스는 SQL 문장을 포함한 모든 입력에 대해 변환이 필요한 문자 데이터들을 변환한다. 결과 출력과 에러 메시지 출력 시에 CSQL은 모든 텍스트를 변환하지 않고 변환이 필요한 문자들만 변환한다. 예를 들어, 숫자 텍스트들은 모두 ASCII 문자이므로 이를 출력할 때는 콘솔 변환 작업이 발생하지 않는다.

유니코드 정규화

글리프(glyph [1] , 문자 기호)는 유니코드 문자를 사용해서 다양한 방법으로 사용된다. 대부분 분해(decomposed)된 형태와 결합(composed form)된 형태로 사용된다. 예를 들어, 글리프 ‘Ä’는 단일 코드포인트 00C4로 결합된 형태로 쓰이는데, UTF-8에서 “C3 84”와 같이 2 바이트로 표현된다. 완전히 분해된 형태에서 2 개의 코드 포인트 0041(‘A’)과 0308(COMBINING DIAERESIS)로 쓰여지며, UTF-8에서 “41 CC 88”과 같이 3 바이트로 표현된다. 대부분의 텍스트 편집기는 두 가지 형식을 모두 다룰 수 있어서, 두 가지 형식의 인코딩은 같은 글리프 ‘Ä’로 나타날 것이다. 내부적으로 CUBRID는 “완전히 결합된” 텍스트만을 처리할 수 있다.

“완전히 분해된” 텍스트로 작업하는 클라이언트에 대해 CUBRID는 “완전히 결합된” 텍스트로 변환하고 돌려줄 때는 “완전히 분해된” 텍스트로 변환하도록 설정될 수 있다. 정규화는 로캘에 대한 기능이 아니며, 따라서 로캘에 의존하지 않는다.

시스템 파라미터 unicode_input_normalization 는 결합 여부를 설정하며, 시스템 파라미터 unicode_output_normalization는 분해 여부를 설정한다. 보다 자세한 내용은 unicode_input_normalization을 참고한다.

응용 클라이언트가 분해된 유니코드만을 다룰 수 있는 경우에는 unicode_input_normalizationunicode_output_normalization을 모두 yes로 설정하는 경우를 사용해야 하고, 분해된 형태와 결합된 형태를 모두 다룰 수 있는 경우에는 unicode_input_normalization = yes와 unicode_output_normalization = no 로 설정하여 사용할 수 있다.

콜레이션의 축약과 확장

콜레이션의 구축을 위해 축약(contraction)과 확장(expansion)을 지원하며, 축약과 확장은 UTF-8 문자셋 콜레이션에서만 가능하다. 이러한 축약과 확장은 LDML 파일의 콜레이션 설정에서 정의할 수 있는데, 이들의 사용은 로캘 데이터(공유 라이브러리)의 크기와 서버의 성능 모두에 영향을 준다.

축약

축약은 둘 또는 그 이상의 코드포인트로 이루어진 일련의 문자들을 하나의 문자로 간주하여 정렬할 수 있도록 해주는 일련의 시퀀스들로 구성된다. 예를 들어, 전통적인 스페인어 정렬 순서에서 “ch”는 하나의 문자로 간주된다. “ch”로 시작하는 모든 단어들은 “c”로 시작하는 모든 단어들 뒤에 정렬되지만, “d”로 시작하는 단어보다 앞에 위치한다. 축약의 다른 예는 체코어의 “ch”인데 “h” 뒤에 정렬되며, 크로아티아어와 세르비아어의 라틴 문자에서 “lj”와 “nj”는 각각 “l”과 “n” 뒤에 정렬된다. 축약에 대한 추가 정보는 http://userguide.icu-project.org/collation/concepts를 참고한다. http://www.unicode.org/Public/UCA/latest/allkeys.txt의 DUCET에도 축약에 대해 일부가 정의되어 있다.

확장이 있는 콜레이션과 확장이 없는 콜레이션 모두에 대해 축약을 지원한다. 콜레이션을 정의하는 <setting> 태그에서 DUCETContractions=”ignore/use”TailoringContractions=”ignore/use” 두 개의 LDML 파라미터를 통해서 설정할 수 있다. DUCETContractions 파라미터는 DUCET 파일에 있는 축약을 콜레이션에 로딩할 것인지를 결정하며, TailoringContractions 파라미터는 LDML 파일의 규칙에 의해 정의된 축약을 사용할 것인지를 결정한다.

확장

확장은 하나의 콜레이션 원소보다 많은 원소들을 가진 코드포인트(문자)들을 참조한다. 확장을 사용하면 아래에 서술된 바와 같이 콜레이션의 동작이 근본적으로 변경된다. LDML 파일의 CUBRIDExpansions=”use” 파라미터 설정을 통해 확장을 사용할 수 있다.

확장이 없는 콜레이션

확장이 없는 콜레이션에서 각 코드포인트는 개별적으로 처리된다. 콜레이션의 세기에 기반하여 문자들이 완전히 정렬될 수도 있고 그렇지 않을 수도 있다. 콜레이션 알고리즘은 각 수준들의 집합의 가중치를 비교하여 해당 코드포인트의 가중치를 나타내는 하나의 값을 생성하며, 이를 기반으로 코드포인트들을 정렬한다. 확장이 없는 콜레이션에서 두 문자열 비교는 이와 같이 계산된 가중치로 각각의 코드포인트를 차례로 비교하게 된다.

확장이 있는 콜레이션

확장이 있는 콜레이션에서 일부 결합 문자(코드포인트)들은 다른 문자들로 구성된 순서 있는 리스트(ordered list)로 해석된다. 예를 들어, ‘æ’는 ‘ae’, ‘ä’는 ‘ae’ 또는 ‘aa’와 같이 해석된다. DUCET에서 ‘æ’의 콜레이션 원소 리스트는 ‘a’와 ‘e’의 순서로 두 콜레이션 원소 리스트들을 연결(concatenation)한 것이 된다. 코드포인트에 대해 특정한 순서를 부여하는 것은 불가능하며, 각 문자(코드포인트)들의 새로운 가중치를 계산하는 것도 불가능하다.

확장이 있는 콜레이션에서 문자열 비교는 두 개의 코드포인트/축약에 대해 콜레이션 원소들을 연결(concatenation)한 후에, 각 단계별로 두 리스트의 가중치를 비교하는 것이다.

예제 1

다음의 예제는 콜레이션 설정에 따라 문자열 비교가 다른 결과를 가져올 수 있다는 것을 보여준다.

다음의 DUCET 파일 일부는 아래 예에서 사용할 코드포인트들이다.

0041  ; [.15A3.0020.0008.0041] # LATIN CAPITAL LETTER A
0052  ; [.1770.0020.0008.0052] # LATIN CAPITAL LETTER R
0061  ; [.15A3.0020.0002.0061] # LATIN SMALL LETTER A
0072  ; [.1770.0020.0002.0072] # LATIN SMALL LETTER R
00C4  ; [.15A3.0020.0008.0041][.0000.0047.0002.0308] # LATIN CAPITAL LETTER A WITH DIAERESIS;
00E4  ; [.15A3.0020.0002.0061][.0000.0047.0002.0308] # LATIN SMALL LETTER A WITH DIAERESIS;

콜레이션을 위해 세 가지 설정 타입으로 표현된다.

  • 첫 번째 세기(primary strength), 대소문자 구분 없음 (단계 1)
  • 두 번째 세기(secondary strength), 대소문자 구분 없음 (단계 1, 2)
  • 세 번째 세기(tertiary strength), 대문자 우선 (단계 1, 2, 3)

지금부터 확장이 있는 콜레이션과 확장이 없는 콜레이션을 가지고 문자열 ‘’Ar’’과 ‘’Är’’의 정렬을 살펴볼 것이다.

확장이 없는 콜레이션

확장이 없을 때 각 코드포인트는 하나의 가중치 값을 부여받는다. A, Ä, R과 해당 소문자 코드포인트에 대한 가중치를 위에서 언급된 알고리즘을 기반으로 한 이 문자들에 대한 코드포인트의 순서는 다음과 같다.

  • 첫 번째 세기: A = Ä < R = r
  • 두 번째 세기: A < Ä < R = r
  • 세 번째 세기: A < Ä < R < r

각 코드포인트에 대해 계산된 가중치가 있기 때문에 문자열들의 정렬 순서는 쉽게 결정된다.

  • 첫 번째 세기: “Ar” = “Är”
  • 두 번째 세기: “Ar” < “Är”
  • 세 번째 세기: “Ar” < “Är”

확장이 있는 콜레이션

확장이 있는 콜레이션이면 정렬 순서가 바뀐다. DUCET에 기반한 콜레이션 원소들의 연결된 리스트들은 다음과 같다.

Ar      [.15A3.0020.0008.0041][.1770.0020.0002.0072]
Är      [.15A3.0020.0008.0041][.0000.0047.0002.0308][.1770.0020.0002.0072]

수준 1의 첫 번째 과정에서 가중치 0x15A3과 0x15A3이 비교된다. 두 번째 과정에서 가중치 0x0000은 비교가 생략되고, 0x1770과 0x1770이 비교된다. 여기까지 문자열이 동일하므로 수준 2 가중치로 계속 비교하게 되는데, 첫 번째 과정에서 0x0020을 0x0020과 비교하고 두 번째 과정에서 0x0020을 0x0047과 비교하여 “Ar” < “Är”이라는 결과를 생성한다. 이 예제를 통해 확장이 있는 콜레이션을 사용할 때 어떻게 문자열 비교가 수행되는지 살펴보았다.

이제 콜레이션 설정을 독일어 콜레이션으로 변경하여 같은 문자열에 대해 다른 순서로 정렬되는 과정을 살펴보자. 독일어에서 “Ä”는 문자 그룹 “AE”로 해석된다. 이 예에 해당하는 코드포인트와 콜레이션 원소들은 다음과 같다.

0041  ; [.15A3.0020.0008.0041] # LATIN CAPITAL LETTER A
0045  ; [.15FF.0020.0008.0045] # LATIN CAPITAL LETTER E
0072  ; [.1770.0020.0002.0072] # LATIN SMALL LETTER R
00C4  ; [.15A3.0020.0008.0041][.15FF.0020.0008.0045] # LATIN CAPITAL LETTER A WITH DIAERESIS; EXPANSION

문자열 “Ar”과 “Är”을 비교할 때 확장이 있는 콜레이션을 사용하면, 두 문자열에 있는 문자들의 콜레이션 원소 리스트를 결합한 후 비교하는 과정이 포함된다.

Ar [.15A3.0020.0008.0041][.1770.0020.0002.0072]
Är [.15A3.0020.0008.0041][.15FF.0020.0008.0045][.1770.0020.0002.0072]

첫 번째 과정에서 수준 1의 가중치 0x15A3과 0x15A3를 비교한다. 그리고 나서 0x1770과 0x15FF를 비교하여 “Ar” > “Är”이라는 결과가 나오는데, 이는 앞의 예제와는 전혀 다른 결과이다.

예제 2

캐나다 프랑스어의 확장이 있는 콜레이션(utf8_fr_exp_ab)에서는 액센트 문자를 뒤쪽에서 앞쪽 방향으로 비교하여 정렬한다.

  • 일반적인 액센트 순서: cote < coté < côte < côté
  • 역순 액센트 순서: cote < côte < coté < côté

문자셋과 콜레이션을 필요로 하는 연산

문자셋

문자셋 정보는 문자열 데이터를 사용하는 연산자와 함수들에게 필요한 정보이다. 하지만 예외적으로, OCTET_LENGTH() 함수와 BIT_LENGTH() 함수는 바이트와 비트 값을 반환하기 위해 문자셋 정보가 불필요하다. 그러나, 다른 문자셋으로 저장된 같은 글리프(glyph, 문자 기호)에 대해 이 함수들을 수행하면 다른 값을 반환한다.

CREATE TABLE t (s_iso STRING CHARSET iso88591, s_utf8 STRING CHARSET utf8);
SET NAMES iso88591;
INSERT INTO t VALUES ('È','È');

-- the first returns 1, while the second does 2
SELECT OCTET_LENGTH(s_iso), OCTET_LENGTH(s_utf8) FROM t;

위의 예는 콘솔(또는 응용 클라이언트)에서 iso88591 문자셋으로 질의를 입력해야 한다.

콜레이션

콜레이션은 STRCMP(), POSITION(), LIKE 조건, <, =, > 등 두 문자열 간의 비교 또는 매칭을 수반하는 연산자와 함수에서 필요하다. 또한 ORDER BY, GROUP BY 및 집계 함수(MIN(), MAX(), GROUP_CONCAT()) 등에서도 콜레이션이 필요하다.

콜레이션은 또한 UPPER(), LOWER() 함수에서도 고려되는데, 다음과 같이 동작한다.

  • 각 콜레이션은 부모에 해당하는 기본 로캘이 있다.
  • UPPER와 LOWER 함수는 콜레이션의 기본 로캘을 사용하여 수행된다.

대부분의 콜레이션에서 기본 로캘은 명확하다(콜레이션 이름에 포함됨).

  • utf8_tr_cs → tr_TR.utf8
  • iso88591_en_ci → en_US (ISO-8859-1 문자셋)

바이너리 콜레이션은 다음의 기본 로캘을 가지고 있다.

  • iso88591_bin → en_US (ISO-8859-1 문자셋)
  • utf8_bin (en_US.utf8 - 내장된 로캘 - ASCII 문자만 다룬다)
  • euckr_bin (ko_KR.euckr - 내장된 로캘 - ASCII 문자만 다룬다)

LDML에서 정의한 일반적인(generic) 콜레이션들이 있는데, 이 콜레이션들은 $CUBRID/conf/cubrid_locales.txt 파일에서 먼저 나타나는 로캘을 기본 로캘로 가진다. 최초 설치 시 가장 처음에 나타나는 로캘은 de_DE(독일어)이므로, de_DE가 일반적인 콜레이션의 기본 로캘이 된다.

문자셋 변환

CUBRID가 지원하는 3 가지 문자셋에 대한 변환 규칙은 다음과 같다.

  • 일반적인 규칙은 문자 트랜스코딩((바이트의 표현이 대상 문자셋으로 표현됨)이 발생하는 것이다 - VARCHAR 문자 데이터에서 문자의 길이(precision)는 유지되는 반면, 바이트 크기는 바뀔 수 있다. 고정 길이 칼럼의 문자셋을 바꿀 때(ALTER..CHANGE), 바이트 크기는 항상 바뀐다. (크기 = 길이 x 문자셋에서 문자 하나가 차지하는 바이트 크기)
  • 예외 규칙은 utf8과 euckr에서 iso88591로 변환하는 것인데, 길이는 유지되지만 데이터는 잘릴 수 있다.

다음은 DB 생성 시 지정한 로캘이 en_US(.iso88591)인 데이터베이스에서 utf8로 문자셋을 변환할 때 데이터가 잘리는 예이다.

SET NAMES utf8;
CREATE TABLE t1(col1 CHAR(1));
INSERT INTO t1 VALUES ('Ç');

위의 질의를 수행하면 ‘Ç’는 2바이트 문자인데 col1 칼럼의 크기는 1바이트이므로 col1의 데이터가 잘리게 된다. 데이터베이스의 문자셋은 iso88591인데 입력 데이터의 문자셋은 utf8이며, 이는 utf8을 iso88591로 변환한다.

콜레이션 설정으로 인한 영향

LIKE 조건 최적화

LIKE 조건은 문자열 데이터 간의 패턴을 비교하여 문자열이 패턴과 매칭되면 TRUE 를 리턴한다. 확장이 없는 콜레이션을 사용할 때에는 각 코드포인트는 가중치를 나타내는 하나의 정수 값을 갖는데, 이 가중치 값은 콜레이션 설정(세기, 대소문자 구분 등)에 기반하여 계산된다.

문자들은 항상 하나의 개체(entity)로 간주될 수 있기 때문에, LIKE 조건을 사용한 패턴으로 문자열을 매칭하려는 시도는 문자열이 어떤 범위 내에서 발견될 수 있는지 확인하는 것과 같다고 볼 수 있다. 예를 들어, “s LIKE ‘abc%’”는 칼럼 s의 값은 문자열 “abc”로 시작해야 한다는 것을 의미하므로, “s LIKE ‘abc%’”와 같은 절을 수행하기 위해 먼저 칼럼 s의 문자열에 대한 제한 범위로 구문을 재작성한다. 확장이 없는 콜레이션에서 이는 s가 “abc”보다 크거나 같지만 후속 문자열보다 작다는 의미이다. 예를 들어, 영어의 알파벳 기준으로 ‘abc’의 후속 문자열은 ‘abd’이므로 아래와 같이 변환할 수 있다.

s LIKE 'abc%' → s ≥ 'abc' AND s < 'abd' (if using strictly the English alphabet)

이와 같이 LIKE 조건의 패턴은 간단한 비교 조건으로 대체될 수 있는데, 확장이 있는 콜레이션의 경우는 다르게 동작한다.

확장이 있는 콜레이션을 사용할 때 문자열을 비교하는 것은 각 코드포인트나 확장에 대해 각 수준(level)별로 콜레이션 원소의 결합된 리스트들을 비교하는 것을 뜻한다. 확장이 있는 콜레이션에서 문자열 비교에 대한 자세한 내용은 확장 을 참고하면 된다.

확장이 있는 콜레이션에 대해서 위의 예와 같이 LIKE 조건을 일반 비교 조건으로 변환하면 비교가 잘못될 수 있다. 정확한 질의 결과를 보장하기 위하여 확장이 있는 콜레이션의 경우에는 LIKE 조건 재작성 방법이 아래의 예와 같이 다르게 동작한다. 즉, 범위 조건으로 변경하고 확장 있는 콜레이션에서 잘못 추가될 수 있는 데이터들을 배제시키기 위해 주어진 LIKE 조건이 필터로 추가된다.

s LIKE 'abc%' → s ≥ 'abc' AND s < 'abd' and s LIKE 'abc%' (if using strictly the English alphabet)

커버링 인덱스

커버링 인덱스 스캔은 실제 레코드를 액세스하지 않고 인덱스에 있는 값만을 사용해서 질의를 처리하는 질의 최적화 기법으로, 이에 대한 자세한 내용은 커버링 인덱스 를 참고한다.

대소문자 구분이 없는 콜레이션에서 ‘abc’와 ‘ABC’ 두 개의 문자열을 인덱스에 저장한다고 가정할 때 인덱스의 키 값으로 이 중 하나만이 저장된다. 이와 같이 하나의 콜레이션에서 서로 다른 두 개 이상의 문자열이 하나의 키 값을 가지게 되면, 정확한 질의 결과를 만들어낼 수 없게 된다. 결국 수준 4(quaternary) 보다 작은 세기(strength)의 모든 UTF-8 콜레이션에서 커버링 인덱스에 의한 질의 최적화는 적용되지 않는다.

이러한 세기 수준은 LDML에서 콜레이션 정의를 위한 <strength> 태그의 strength=”tertiary/quaternary”에 의해 제어될 수 있다. 확장이 있는 콜레이션의 세기 값을 최대 값으로 설정하는 것은 주의 깊게 고려되어야 하는데, 네 번째 세기 수준은 공유 라이브러리 크기와 메모리 요구량이 커질 뿐만 아니라 문자열 비교 시간을 증가시키기 때문이다.

콜레이션과 관련된 자세한 내용은 콜레이션 설정을 참고한다.

각 콜레이션에 대한 기능 요약

콜레이션 LIKE 문을 범위로 재작성 이후 조건 유지 커버링 인덱스 허용
iso88591_bin No Yes
iso88591_en_cs No Yes
iso88591_en_ci Yes No
utf8_bin No Yes
euckr_bin No Yes
utf8_en_cs No Yes
utf8_en_ci Yes No
utf8_tr_cs No Yes
utf8_ko_cs No Yes
utf8_gen No Yes
utf8_gen_ai_ci Yes No
utf8_gen_ci Yes No
utf8_de_exp_ai_ci Yes No
utf8_de_exp Yes No
utf8_ro_cs No Yes
utf8_es_cs No Yes
utf8_fr_exp_ab Yes No
utf8_ja_exp Yes No
utf8_ja_exp_cbm Yes No
utf8_km_exp Yes No
utf8_ko_cs_uca No Yes
utf8_tr_cs_uca No Yes
utf8_vi_cs No Yes
binary No Yes

콜레이션 정보 보기

콜레이션 정보를 보려면 CHARSET(), COLLATION()COERCIBILITY() 정보 함수를 사용한다.

데이터베이스 콜레이션 정보는 db_collation 시스템 뷰 또는 SHOW COLLATION을 통해 확인할 수 있다.

JDBC에서 i18n 문자 사용

CUBRID JDBC는 문자열 및 CUBRIDBinaryString 객체를 사용하여 서버에서 수신된 문자열 타입 값을 저장한다. 문자열 객체는 각 문자를 저장하기 위해 내부적으로 UTF-16을 사용하며, 바이너리 문자셋을 제외한 모든 문자열을 저장하는 데 사용된다. CUBRIDBinaryString은 바이트 배열을 사용하며 바이너리 문자셋의 문자열 값을 저장하는 데 사용된다. 서버에서 수신된 각 문자열 값의 데이터 버퍼에는 서버에서 수신된 값의 문자셋이 포함된다. 이 문자셋은 컬럼의 문자셋, 표현식 결과의 문자셋, 시스템 문자셋(문자셋이 표현되지 않은 경우) 중 하나이다

Note

이전 버전에서는 JDBC 문자열 객체를 인스턴스화하는 데 연결URL의 문자셋이 사용되었다.

UTF-8 문자셋을 갖는 컬럼 한 개와 바이너리 문자셋을 갖는 다른 컬럼이 포함된 테이블 생성:

CREATE TABLE t1(col1 VARCHAR(10) CHARSET utf8, col2 VARCHAR(10) CHARSET binary);

한 레코드 입력 (두번째 컬럼은 랜덤 값):

Connection conn = getConn(null);
PreparedStatement st = conn.prepareStatement("insert into t1 values( ?, ? )");
byte[] b = new byte[]{(byte)161, (byte)224};
CUBRIDBinaryString cbs = new CUBRIDBinaryString(b);
String utf8_str = new String("abc");
st.setObject(1, utf8_str);
st.setObject(2, cbs);
st.executeUpdate();

테이블 질의 및 내용 표시(바이너리 문자열의 경우 hex dump, 다른 문자셋의 경우 문자열 값 표시):

ResultSet rs = null;
Statement stmt = null;
rs = stmt.executeQuery("select col1, col2 from t1;");
ResultSetMetaData rsmd = null;
rsmd = rs.getMetaData();
int numberofColumn = rsmd.getColumnCount();
while (rs.next()) {
        for (int j = 1; j <= numberofColumn; j++) {
                String columnTypeName = rsmd.getColumnTypeName(j);
                int columnType = rsmd.getColumnType(j);
                if (((CUBRIDResultSetMetaData) rsmd).getColumnCharset(j).equals("BINARY")) {
                        // database string with binary charset
                        Object res;
                        byte[] byte_array = ((CUBRIDBinaryString) res).getBytes();
                        res = rs.getObject(j);
                        System.out.println(res.toString());
                } else {
                        // database string with any other charset
                        String res;
                        res = rs.getString(j);
                        System.out.print(res);
                }
        }
}

타임존 설정

타임존은 시스템 파라미터를 통해 설정할 수 있는데, 세션에서 설정하는 timezone 파라미터와 데이터베이스 서버에서 설정하는 server_timezone 파라미터가 있다. 타임존 파라미터에 대한 설명은 타임존 파라미터를 참고한다.

timezone 파라미터는 세션에 대한 파라미터이다. 세션 단위로 별개의 설정을 유지할 수 있다.

SET SYSTEM PARAMETERS 'timezone=Asia/Seoul';

이 값을 설정하지 않은 경우 server_timezone 파라미터의 설정을 따른다.

server_timezone 파라미터는 데이터베이스 서버에 대한 파라미터이다.

SET SYSTEM PARAMETERS 'server_timezone=Asia/Seoul';

이 값을 설정하지 않은 경우 OS의 설정을 따른다.

타임존을 사용하려면 타임존 타입을 사용해야 하는데, 이와 관련하여 타임존이 있는 날짜/시간 데이터 타입을 참고한다.

타임존을 지역 이름으로 설정하는 경우 별도의 타임존 라이브러리를 필요로 하는데, 큐브리드 설치 시 제공하는 라이브러리가 아닌 업데이트된 타임존 정보를 가진 라이브러리를 사용하려면, 타임존 정보를 변경한 후 직접 라이브러리를 컴파일해야 한다.

다음은 최신의 타임존 정보를 IANA(http://www.iana.org/time-zones)로부터 받아와 타임존 라이브러리를 컴파일하는 예이다.

보다 자세한 설명은 다음 설명을 참고한다.

타임존 라이브러리 컴파일

지역 이름으로 타임존을 명시하여 사용하려면 타임존 라이브러리가 필요한데, 큐브리드 설치 시 기본으로 제공된다. 그런데, 타임존 지역 정보를 최신 정보로 업데이트하려면 IANA(http://www.iana.org/time-zones)에서 최신 코드를 받아와 타임존 라이브러리를 컴파일해야 한다.

다음은 타임존 라이브러리를 최신 정보로 업데이트하기 위한 절차이다.

먼저 구동 중인 큐브리드 서비스를 종료한 후, OS에 따라 다음 절차를 수행한다.

윈도우즈

  1. http://www.iana.org/time-zones 에서 최신의 타임존 데이터를 내려받는다.

    “Latest version”의 “Time Zone Data”에 링크된 파일을 받는다.

  2. %CUBRID%/timezones/tzdata 디렉터리 이하에 압축 파일을 푼다.

  3. %CUBRID%/bin/make_tz.bat 를 실행한다.

    %CUBRID%/lib 이하에 libcubrid_timezones.dll 이 생성된다.

    make_tz.bat
    

Note

make_locale 스크립트를 Windows에서 실행하려면, Visual C++ 2005, 2008 또는 2010 중 하나가 설치되어 있어야 한다.

리눅스

  1. http://www.iana.org/time-zones 에서 최신의 타임존 데이터를 내려 받는다.

    “Latest version”’의 “Time Zone Data”에 링크된 파일을 다운로드 한다.

  2. 압축된 파일을 $CUBRID/timezones/tzdata directory에 푼다.

  3. make_tz.sh 를 실행한다.

    $CUBRID/lib 디렉터리에 libcubrid_timezones.so 파일이 생성된다.

    make_tz.sh
    

타임존 라이브러리 및 데이터베이스 호환성

CUBRID에서 빌드된 타임존 라이브러리에는 타임존 데이터의 MD5 체크섬이 포함된다. 이 해시는 해당 라이브러리에서 생성된 모든 데이터베이스의 db_root 시스템 테이블의 timezone_checksum 컬럼에 저장된다. 타임존 라이브러리가 변경되고(새로운 타임존 데이터로 다시 컴파일됨) 체크섬이 변경되면 기존 데이터베이스로 CUBRID 서버와 그 밖의 모든 CUBRID 도구를 시작할 수 없다. 이러한 호환성 문제를 방지하는 방법 중 하나는 make_tz 도구의 extend 인자를 사용하는 것이다. extend 옵션을 사용하면 데이터베이스의 timezone_checksum 값도 새로운 타임존 라이브러리의 새로운 MD5 체크섬으로 변경된다. IANA 사이트에서 다른 타임존 라이브러리 버전을 사용하려는 경우 extend 기능을 사용해야 한다. 이 기능이 수행하는 두 가지 작업은 다음과 같다.

  • 이전 타임존 데이터와 새 타임존 데이터를 병합하여 새 라이브러리를 생성한다. 데이터베이스 테이블에 있는 데이터와의 역호환성을 위해, 병합 후에도 새 타임존 데이터베이스에 존재하지 않는 모든 타임존 지역을 유지한다.
  • 새 타임존 라이브러리가 생성되었을 때 역호환성을 유지할 수 없는 경우 테이블에서 타임존 데이터를 갱신한다. 오프셋 규칙 또는 서머타임 규칙이 변경될 때 이러한 상황이 발생할 수 있다.

extend 옵션과 함께 make_tz**를 실행하면 데이터베이스 디렉터리 파일(**databases.txt)에 있는 모든 데이터베이스가 MD5 체크섬과 함께 갱신된다. 다음과 같은 예외적인 상황이 있다.

  • 여러 사용자가 동일한 CUBRID 설치를 공유하는데, 그 중 한 명이 extend를 수행하는 경우가 있다. extend를 수행한 사용자에게 다른 사용자들의 데이터베이스가 포함된 파일에 액세스할 수 있는 권한이 없는 경우 다른 사용자들의 데이터베이스는 갱신되지 않는다. 그 후, 데이터베이스가 갱신되지 않은 다른 사용자가 자신의 데이터베이스에서 extend를 수행하려고 시도하면 라이브러리의 체크섬이 자신의 데이터베이스에 있는 체크섬과 다르기 때문에 작업에 실패한다.
  • CUBRID_DATABASES 환경 변수 값이 다른 사용자의 경우 databases.txt 파일이 다르다. 이 경우 현재로서는 한 번에 모든 데이터베이스를 갱신하는 것이 불가능하다.

해결책은 두 가지가 있다.

  • 각 사용자에게 자신의 데이터베이스가 포함된 폴더에 액세스할 수 있는 권한을 부여하고, CUBRID_DATABASES 변수의 값을 동일하게 만든다.
  • 이것이 불가능한 경우 각 사용자에 대해 다음을 수행할 수 있다.
    • 현재 타임존 라이브러리 및 databases.txt 파일 백업
    • databases.txt 파일에서 현재 사용자의 데이터베이스를 제외한 모든 데이터베이스 삭제
    • extend 실행
    • databases.txt 파일 및 타임존 라이브러리 복구

단 마지막 사용자의 경우 최종 단계에서 databases.txt 파일만 복구하고 타임존 라이브러리 복구는 하지 않는다.

리눅스의 경우:

make_tz.sh -g extend

윈도우즈의 경우:

make_tz.bat /extend

JDBC에서 타임존 데이터 타입 사용

JDBC CUBRID 드라이버는 타임존 정보에 대해 완전하게 CUBRID 서버에 의존한다. 자바와 CUBRID가 타임존에 대해 동일한 정보의 기본 소스가 사용되더라도 지역명과 타임존 정보가 호환되지 않는다고 간주된다.

타임존이 있는 모든 CUBRID 데이터 타입은 CUBRIDTimestamptz 자바 객체에 매핑된다.

JDBC를 사용하여 타임존이 있는 값 삽입:

String datetime = "2000-01-01 01:02:03.123";
String timezone = "Europe/Kiev";
CUBRIDTimestamptz dt_tz = CUBRIDTimestamptz.valueOf(datetime, false, timezone);
PreparedStatement  pstmt = conn.prepareStatement("insert into t values(?)");
pstmt.setObject(1, ts);
pstmt.executeUpdate();

JDBC를 사용하여 타임존이 있는 값 검색:

String sql = "select * from tz";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
CUBRIDTimestamptz object1 = (CUBRIDTimestamptz) rs.getObject(1);
System.out.println("object: " + object1.toString());

CUBRID JDBC는 내부적으로 CUBRIDTimestamptz 객체의 날짜/시간 부분을 1970년 1월 1일 이후 경과한 시간(밀리초)(Unix epoch)이 보관되는 ‘long’ 값(날짜 객체를 통해 상속)에 저장한다. CUBRIDTimestamptz 객체는 로컬 타임존을 사용하는 타임스탬프 객체와는 달리 UTC 시간 참조에서 내부 인코딩을 수행하기 때문에, 자바 로컬 타임존과 동일한 타임존으로 생성되어도 보관하는 내부 epoch 값은 다르다. Unix epoch를 제공하려면 getUnixTime() 메서드를 사용하면 된다.

String datetime = "2000-01-01 01:02:03.123";
String timezone = "Asia/Seoul";
CUBRIDTimestamptz dt_tz = CUBRIDTimestamptz.valueOf(datetime, false, timezone);
System.out.println("dt_tz.getTime: " + dt_tz.getTime());
System.out.println("dt_tz.getUnixTime: " + dt_tz.getUnixTime ());

다국어 설정을 위한 고려 사항

데이터베이스 설계자는 데이터베이스 구조를 설계할 때 문자 데이터의 속성을 고려해야 한다. 다음은 문자 데이터 설정 시에 알아야 할 사항들을 요약한 것이다.

로캘

  • 기본적으로 DB 생성 시 로캘을 en_US를 사용하면 가장 좋은 성능을 낸다. 영어만 사용한다면 로캘을 en_US로 지정하는 것이 가장 좋다.
  • UTF-8 로캘의 사용은 CHAR 타입에 대해 추가적인 저장 공간을 필요로 한다. 고정 길이 문자 타입(CHAR)의 경우 4배까지 늘어나며, EUC-KR의 경우 3배까지 늘어난다.
  • 사용자 문자열 리터럴이 시스템과 다른 문자셋과 콜레이션을 가진다면, 질의문은 문자셋과 콜레이션을 설정하기 위해 더 길어질 것이다.
  • ASCII 문자가 아닌 문자를 사용자 식별자로 사용하려면 .utf8 로캘을 사용한다.
  • UTF-8 문자셋이 설정되면, 시스템 로캘보다는 LDML 로캘을 사용하는 것이 좋다. LDML 로캘은 식별자에 포함된 유니코드 문자의 대소문자 변환을 보장한다.
  • 로캘 설정은 문자열 변환 함수에도 영향을 준다. 가장 빈번하게 변환이 이루어지는 로캘을 선택하는 것이 좋다.
  • 로캘 설정 시 문자열 상수, 사용자 테이블 칼럼의 문자셋과 콜레이션에 대해 고민하지 않아도 된다. 질의문에서 CAST() 연산자를 사용하여 런타임에 바꿀 수 있으며, “ALTER … CHANGE” 문을 통해 영구히 바꿀 수 있다. 단, 콜레이션 간에 변환은 같은 문자셋끼리만 가능하다.

CHAR와 VARCHAR

  • 일반적으로 데이터의 크기 변화가 심할 때는 VARCHAR를 사용한다.
  • CHAR 타입은 고정 길이 타입이므로, 영문만 저장하는 경우에도 UTF-8은 4 bytes의 저장 공간을, EUC-KR은 3 bytes의 저장 공간을 필요로 한다.
  • 칼럼의 자릿수(precision)는 문자(글리프, 문자 기호)의 개수이다.
  • 자릿수를 정한 이후에, 대부분의 사용 시나리오에 따라 문자셋과 콜레이션이 설정되어야 한다.

문자셋 선택

  • 텍스트가 ASCII가 아닌 문자를 포함하고 있더라도 응용 프로그램이 문자 개수 세기, 문자열 치환 등의 문자열 조작이 필요한 경우에 utf8이나 euckr 문자셋을 사용한다.
  • CHAR 타입의 저장 공간을 고려해야 한다.
  • CHAR와 VARCHAR 타입에서 INSERT/UPDATE 시 오버헤드가 있다. 각 행에서 문자열의 문자 개수(precision)를 세는 것은 ISO가 아닌 문자셋에서 더 많은 수행 시간을 필요로 한다.
  • 질의문 내의 표현식의 문자셋은 CAST() 연산자를 사용하여 변환할 수 있다.

콜레이션 선택

  • 콜레이션에 의존하는 연산(문자열 검색, 정렬, 비교, 대소문자 구분)을 수행하지 않는 경우 해당 문자셋의 bin 콜레이션이나 바이너리 콜레이션을 선택한다.
  • 표현식의 원래 문자셋과 새로운 콜레이션 사이에서 문자셋이 변경되지 않는다면 콜레이션은 CAST() 연산자, COLLATE 수정자를 사용하여 쉽게 오버라이드할 수 있다.
  • 콜레이션은 문자열의 대소문자 구분 규칙을 제어한다.
  • 확장이 있는 콜레이션은 더 느리지만 더 유연하며 전체 단어 정렬을 수행한다.

정규화

  • 응용 클라이언트가 CUBRID에 분해된 형태의 텍스트 데이터를 보낸다면, unicode_input_normalization = yes로 설정하여 CUBRID가 재구성하여 결합된 형태로 다룰 수 있도록 한다.
  • 응용 클라이언트가 분해된 형태만 다룰 수 있다면, unicode_output_normalization = yes로 설정하여 CUBRID가 항상 분해된 형식으로 텍스트 데이터를 보내도록 한다.
  • 응용 클라이언트가 모든 형식을 알고 있다면, unicode_output_normalization = no인 상태로 둔다.

CAST vs COLLATE

  • CAST() 연산자는 COLLATE 수정자보다 더 많은 실행 비용이 든다 (문자셋 변환이 발생하면 더 많은 비용이 든다).
  • COLLATE 수정자는 질의 실행 과정에서 실행 연산이 추가되지 않기 때문에, COLLATE 수정자를 사용하는 것이 CAST() 연산자를 사용하는 것보다 실행 속도가 더 빠르다.
  • COLLATE 수정자는 문자셋이 바뀌지 않을 때만 사용될 수 있다.

주의 사항

  • 호스트 변수의 지연 바인딩이 있는 경우에 질의 실행 계획 출력 시에 콜레이션이 출력되지 않는다.
  • 기본 다국어 영역인 0000~FFFF 범위의 유니코드 코드포인트만 정규화된다.
  • 숫자 구분자로 특정 문자(예를 들어, 공백 문자)를 사용할 수 없다. 일부 로캘에서는 공백 문자를 숫자 구분자로 활용하기도 하는데, 이는 허용되지 않는다.

Note

  • 9.2 이하 버전에서 사용자 정의 변수는 시스템 콜레이션과 다른 콜레이션으로 설정할 수 없다. 예를 들어, 시스템 콜레이션이 iso88591일 때 “SET @v1=’a’ COLLATE utf8_en_cs;”과 같은 구문을 사용할 수 없다.
  • 9.3 이상 버전에서는 위의 제약이 더 이상 존재하지 않는다.

로캘과 콜레이션 추가 안내서

대부분의 새로운 로캘 또는 콜레이션은 사용자가 LDML 파일을 새로 추가 또는 변경해서 추가될 수 있다. CUBRID에서 사용되는 LDML 파일 포맷은 Unicode Locale Data Markup Language(http://www.unicode.org/reports/tr35/)에서 비롯되었다. CUBRID에만 명시되는 태그와 속성은 이름에 “cubrid”를 포함하고 있기 때문에 쉽게 구별할 수 있다.

새로운 로캘을 추가하는 가장 좋은 방법은 기존의 LDML 파일을 복사해서 원하는 결과가 나올 때까지 설정을 바꾸는 것이다. 파일 이름은 “cubrid_<language>.xml”과 같이 주어져야 하며 $CUBRID/locales/data/ldml 디렉터리에 위치한다. <language> 부분은 IETF 포맷(http://en.wikipedia.org/wiki/BCP_47)에 있는 ASCII 문자열(보통 5개 문자)이어야 한다. LDML 파일을 생성한 이후, <language> 부분이 CUBRID 설정 파일인 $CUBRID/conf/cubrid_locales.txt 에 추가되어야 한다. 이 파일에 기록된 언어의 순서가 로캘 라이브러리를 생성(컴파일)하고 구동 시 로캘을 읽는 순서임에 유의한다.

make_locale 스크립트는 새로 추가되는 로캘을 컴파일하고 그 데이터를 CUBRID 로캘 라이브러리($CUBRID/lib/ )에 추가하는데 사용된다.

LDML 파일은 UTF-8로 인코딩되며, 같은 LDML 파일에는 하나의 로캘 정보만 기록할 수 있다.

LDML 파일에 새로운 로캘을 추가하려면 다음이 요구된다.

  • 캘린더 정보를 명시한다(CUBRID 날짜 포맷, 월 및 요일 이름의 다양한 포맷, 오전/오후에 대한 이름). CUBRID는 캘린더 정보를 명시하기 위해 그레고리력만 지원한다(일반적인 LDML은 CUBRID가 지원하지 않는 다른 캘린더 타입을 지원한다).
  • 숫자 설정을 명시한다(자릿수 구분 기호)
  • 알파벳을 제공한다(대소문자에 대한 규칙의 집합)
    • 옵션으로, 일부 콜레이션이 추가될 수 있다.
    • 또한 옵션으로, Windows CSQL 응용에 대한 콘솔 변환 규칙이 정의될 수 있다.

LDML 캘린더 정보

  • 첫 번째 부분은 DATE, DATETIME, TIME, TIMESTAMP, DATETIME WITH TIME ZONETIMESTAMP WITH TIME ZONE 데이터와 문자열 간의 타입변환을 위한 기본 CUBRID 형식으로 이루어진다. 이 형식은 TO_DATE(), TO_TIME(), TO_DATETIME(), TO_TIMESTAMP(), TO_CHAR(), TO_DATETIME_TZ(), TO_TIMESTAMP_TZ() 함수에서 사용된다. 허용되는 형식 요소는 데이터 타입에 따라 다르며 TO_CHAR() 함수(Date/Time Format 1)에서 사용된다. 이 형식의 문자열에는 ASCII 문자만 허용된다. DATETIME 형식은 30바이트(문자), DATETIMETIMESTAMP 형식은 48자, DATETIME WITH TIME ZONETIMESTAMP WITH TIME ZONE 은 70자까지 허용된다.
  • <months>는 긴 형식과 축약된 형식 둘 다에 대한 월 이름이 필요하다. 허용되는 크기는 축약된 형식에 대해 15자(또는 60 바이트)이고 긴 형식에 대해 25자(또는 100바이트)이다.
  • <days>는 긴 형식과 축약된 형식 둘 다에 대한 요일 이름이 필요하다. 허용되는 크기는 축약된 형식에 대해 10자(또는 40 바이트)이고 긴 형식에 대해 15자(또는 60 바이트)이다.
    • <dayperiods> 서브 트리는 오전/오후 형식의 변형(타입 속성에 따라 달라짐)에 대한 문자열을 정의한다. 허용되는 크기는 10자(또는 40바이트)이다.

월과 요일 이름은 긴 포맷과 축약된 포맷 둘 다 카멜 표기 형식(Camel case case format, 첫 문자는 대문자, 나머지 문자는 소문자)으로 명시되어야 한다. CUBRID는 최대로 허용된 크기를 바이트 단위로 검사한다. 문자의 크기는 UTF-8 문자의 최대 크기에 해당하는 4바이트로만 계산되므로, 100개의 ASCII 문자로만 구성된 월 이름을 설정하는 것이 가능하다(25자 제한은 월 이름의 각 문자가 4바이트로 인코딩된 UTF-8 문자인 경우이다).

LDML 숫자 정보

  • <symbols> 태그는 정수와 소수 분할 기호 문자와 자릿수 구분 기호 문자를 정의한다. CUBRID는 이 기호들에 대해 ASCII 기호만을 기대하며, 공백 문자는 허용하지 않는다. CUBRID는 3개의 숫자를 그룹지어 자릿수를 구분한다.

LDML 알파벳

LDML 알파벳은 로캘의 알파벳에 대한 대소문자 규칙을 정의한다. ‘CUBRIDAlphabetMode’ 속성은 문자에 대한 데이터의 기본 원본(primary source)을 정의한다. 일반적으로 이 속성은 “UNICODEDATAFILE”로 지정되어야 하는데, 이 값은 CUBRID가 유니코드 데이터 파일($CUBRID/locales/data/unicodedata.txt) 을 사용한다는 의미이다.

이 파일은 수정되어서는 안 되며, 특정 문자에 대한 변경은 LDML 파일에서 이루어져야 한다. 이러한 값이 설정되어 있는 경우, 코드포인트 65535까지의 모든 유니코드 문자가 대소문자 정보를 가지고 로딩된다. ‘CUBRIDAlphabetMode’에 대해 허용된 다른 값은 “ASCII”로, ASCII 문자만이 소문자, 대문자 또는 대소문자 구분을 하지 않는 문자열 비교 함수에서 사용될 수 있다.

“ASCII”는 CUBRID가 모든 UTF-8 (4바이트) 인코딩 문자를 지원하는 기능에 영향을 주는 것이 아니라, 특정 문자가 대소문자를 구분하는 기능에 포함되지 않도록 제한할 뿐이다.

대소문자 구분 규칙은 선택적이며 문자 정보(UNICODEDATAFILE 또는 ASCII)의 기본 원본 중 가장 우선적으로 적용된다.

CUBRID는 대문자 규칙(<u> 태그) 정의와 소문자 규칙(<l> 태그) 정의를 허용한다. 대문자 규칙과 소문자 규칙 각각은 원본-대상(<s> = source, <d> destination)의 쌍으로 된 구성을 설정한다. 예를 들어, 다음은 문자 “A”의 소문자가 “aa”(2개의 “a” 문자)가 되도록 정의한다.

<l>
    <s>A</s>
    <d>aa</d>
</l>

LDML 콘솔 변환

Windows에서 콘솔은 UTF-8 인코딩을 지원하지 않으므로, CUBRID는 UTF-8 인코딩을 원하는 인코딩으로 번역하도록 허용한다. 로캘에 대한 콘솔 변환을 설정한 후에, 사용자는 CSQL 응용 프로그램을 시작하기에 앞서 ‘chcp’ 명령(LDML에서 codepage 속성은 ‘windows_codepage’ 속성과 매칭되어야 한다)을 사용하여 콘솔의 코드페이지를 설정해야 한다. CSQL 입출력 시 변환은 양방향으로 동작하지만, 설정된 코드페이지로서 변환될 수 있는 유니코드 문자로만 제한된다.

<consoleconversion> 원소는 선택적이며 CSQL이 인터렉티브 명령에서 텍스트를 출력(문자 인코딩)하는 방법을 지시하게 한다. ‘type’ 속성은 변환에 대한 계획(scheme)을 정의한다. 허용되는 값은 다음과 같다.

  • ISO: 대상 코드 페이지가 단일 바이트 문자셋인 일반적인 계획(generic scheme)
  • ISO88591: ISO-8859-1 문자셋에 대해 미리 준비된 단일 바이트 계획(‘file’ 속성을 필요로 하지 않으며, 있으면 무시됨)
  • ISO88599: ISO-8859-9 문자셋에 대해 미리 준비된 단일 바이트 계획(역시 ‘file’ 속성을 필요로 하지 않음)
  • DBCS: Double Byte Code-Set. 이것은 대상 코드페이지가 2바이트 문자셋인 일반적인 계획이다.

‘windows_codepage’는 CUBRID가 콘솔 변환을 자동으로 활성화하는 Windows 코드페이지에 대한 값이다. ‘linux_charset’은 UNIX 계열 시스템의 LANG 환경 변수에서 문자셋 부분과 동일한 값이다. Linux 콘솔에서는 원래의 CUBRID 문자셋을 사용하기를 권장한다.

‘file’ 속성은 ‘type’ 속성의 값이 “ISO”와 “DBCS”인 경우에만 요구되며 번역 정보($CUBRID/locales/data/codepages/)를 포함하는 파일이다.

LDML 콜레이션

콜레이션을 설정하는 것은 CUBRID에서 LDML 로캘을 추가할 때 가장 복잡한 작업이다. UTF-8 코드셋을 가진 콜레이션만 설정될 수 있다. CUBRID는 축약과 확장을 포함하는 UCA(Unicode Collation Algorithm, http://www.unicode.org/reports/tr10/)에 의해 명시된 대부분의 구성을 설정하는 것을 허용하지만, 콜레이션에 대한 속성은 대부분 ‘settings’ 속성을 통해 제어된다.

LDML 파일은 여러 개의 콜레이션을 포함할 수 있다. 콜레이션은 ‘include’ 태그를 사용하여 외부 파일에 의해 포함될 수 있다. ‘collations’ 태그의 ‘validSubLocales’ 속성은 외부 파일에 의한 외부 콜레이션이 포함될 때 로캘 컴파일을 제어하도록 허용하는 필터이다. 이 속성의 값은 로캘의 리스트 혹은 “*”이 될 수 있으며, “*”을 사용하면 서브트리에 있는 콜레이션이 모든 로캘에 추가된다.

하나의 콜레이션은 ‘collation’ 태그와 서브트리를 사용하여 정의된다. ‘type’ 속성은 콜레이션에 대한 이름을 나타내므로 CUBRID에 추가될 것이다. ‘settings’ 태그는 콜레이션의 속성들을 정의한다.

  • ‘id’는 CUBRID에서 사용되는 (내부의) 숫자 식별자이다. 32부터 255까지의 정수이며 선택적이지만, 할당되지 않은 값의 명시적인 설정을 강력히 권장한다. 콜레이션 명명 규칙을 참고한다.
  • ‘strength’는 문자열 비교 방법의 척도이다. 콜레이션 속성을 참고한다. 허용되는 값은 다음과 같다.
    • “quaternary”: 서로 같은 문자이나 다른 그래픽 기호이면 다르게 비교되지만, 다른 유니코드 코드포인트가 같게 비교될 수 있다.
    • “tertiary”: 서로 같은 문자의 그래픽 심볼은 동일하며, 대소문자를 구분하는 콜레이션이다.
    • “secondary”: 대소문자 구분 없는 콜레이션이며, 액센트가 있는 문자 사이의 비교 결과가 다르다.
    • “primary”: 액센트는 무시되며, 모든 문자는 기본(base) 문자로 비교된다.
  • ‘caseLevel’: ‘strength’ 값이 “tertiary” 보다 작은 값을 가지는 콜레이션에 대해 대소문자 구분 있는 비교를 가능하게 하는 특별한 설정. 유효한 값은 “on” 또는 “off”이다.
  • ‘caseFirst’: 대소문자 순서. 유효한 값은 “lower”, “upper” 그리고 “off”이다. “upper” 값은 대문자가 같은 문자의 소문자보다 앞선다는 의미이다.
  • ‘CUBRIDMaxWeights’: 콜레이션에서 사용자에 의해 정의된(customized) 코드포인트의 개수(또는 최종 코드포인트 + 1). 최대 값은 65536이다. 이 값을 늘리면 콜레이션 데이터의 크기가 늘어난다.
  • ‘DUCETContractions’: 유효한 값은 “use” 또는 “ignore”이다. “use”가 명시되면 ($CUBRID/locales/data/ducet.txt)에 의해 정의된 축약을 콜레이션에서 사용할 수 있다. “ignore”이면 정의된 축약을 무시한다.
  • ‘TailoringContractions’: 위와 같으나 명시된 콜레이션 규칙으로부터 정의되거나 추출된(derived) 축약을 의미한다. 축약을 사용하면 보다 복잡한 콜레이션(더 느린 문자열 비교)이 된다.
  • ‘CUBRIDExpansions’: 허용되는 값은 “use” 또는 “ignore”(기본값)이며 DUCET 파일과 사용자 정의 규칙 둘 다에서 콜레이션 확장을 사용함을 의미한다. ‘CUBRIDExpansions’은 콜레이션 속성에서 가장 큰 영향을 준다. 이것을 가능하게 하면 문자열을 비교할 때 여러 단계(콜레이션 세기까지)로 비교하게 되며, 더 “자연스러운” 정렬 순서를 얻을 수 있는 이점이 있지만 콜레이션 데이터를 크게 증가시킨다. 확장을 참고한다.
  • ‘backwards’: “on” 또는 “off” 값이 사용된다. 액센트에 대해 문자열의 끝에서 앞으로 비교되는 “french” 순서를 적용하기 위해 사용된다. 이 값은 ‘CUBRIDExpansions’이 “use”일 때만 적용된다.
  • ‘MatchContractionBoundary’: “true” 또는 “false”. 이 값은 축약이 지정될 때 문자열 매칭에서의 동작을 설정하기 위해 확장과 축약을 가지는 콜레이션에서 사용된다.

콜레이션에 대한 주요 데이터는 DUCET 파일에서 읽혀진다. 이 단계 이후, 콜레이션은 “사용자 정의 규칙(tailoring rules)”에 의해 명시될 수 있다. 이 규칙들은 “<rules>” (LDML)와 “<cubridrules>” (CUBRID 전용)이다.

‘cubridrules’ 태그는 선택적이며 코드포인트 또는 코드포인트의 범위에 대한 가중치를 명시적으로 설정하는데 사용될 수 있다. ‘cubridrules’는 DUCET 파일로부터 기본(primary) 콜레이션을 로딩한 후 ‘<rules>’ 태그에 정의된 UCA 규칙이 적용되기 전에 적용된다. 각 규칙은 ‘<set>’ 태그로 닫힌다. 규칙이 하나의 유니코드 코드포인트만을 언급하는 경우, 코드포인트의 16진수 값을 포함하는 ‘<scp>’ 태그가 제공된다.

모든 사용 가능한 CUBRID 콜레이션은 다음과 같은 CUBRID 규칙을 포함한다.

<cubridrules>
    <set>
        <scp>20</scp>
        <w>[0.0.0.0]</w>
    </set>
</cubridrules>

이 규칙은 20(ASCII 띄어쓰기 문자)으로 시작하는 코드포인트의 가중치(UCA는 콜레이션 원소 당 네 개의 가중치를 정의)가 모두 0으로 설정된다는 것을 나타낸다. ‘<ecp>’ 태그가 없기 때문에 영향을 받는 유일한 코드포인트는 20이다. CUBRID에서 띄어쓰기 문자는 0으로 비교된다. ‘<set>’ 규칙에서 허용되는 태그는 다음과 같다.

  • ‘<cp>’: 하나의 코드포인트에 대한 가중치를 설정하는 규칙
  • ‘<ch>’: 하나의 문자에 대한 가중치를 설정하는 규칙. 위의 것과 비슷하지만, 코드포인트 대신 이것은 유니코드 문자(UTF-8 encoding)를 기대한다.
  • ‘<scp>’: 코드포인트의 범위에 대한 가중치를 설정하는 규칙. 이것이 시작 코드포인트이다.
  • ‘<sch>’: 문자의 범위에 대한 가중치를 설정하는 규칙. 이것이 시작 문자이다. 문맥에서, 문자의 순서는 유니코드 코드포인트에 의해 주어진다.
  • ‘<ecp>’: 범위 규칙에 대한 끝 코드포인트.
  • ‘<ech>’: 범위 규칙에 대한 끝 문자.
  • ‘<w>’: 설정할 가중치(단일 값). 가중치는 16진수이다. 각 콜레이션 원소는 점으로 구분되는 네 개의 값을 가지며, 이 값들은 각괄호([])로 감싸진다. 10개의 콜레이션 원소까지 포함할 수 있다.
  • ‘<wr>’: 범위에 대해 설정하는 시작 가중치. 선택적으로, 이 태그에는 ‘step’ 속성이 있는데 이는 각 코드포인트 뒤에 증가하는 단계를 설정한다. 기본 단계는 [0001.0000.0000.0000]인데, 이것은 시작 코드포인트에 대한 첫번째 가중치를 설정한 후, 하나의 값이 첫 번째 수준(primary level) 가중치에 추가되고 다음 코드포인트까지 범위로 설정됨을 의미하며, 이 절차는 마지막 코드포인트까지 반복된다.

예:

<cubridrules>
    <set>                            <!-- Rule 1 -->
        <scp>0</scp>
        <ecp>20</ecp>
        <w>[0.0.0.0]</w>
    </set>

    <set>                            <!-- Rule 2 -->
        <scp>30</scp>
        <ecp>39</ecp>
        <wr step="[1.0.0.0][1.0.0.0]">[30.0.0.0][30.0.0.0]</wr>
    </set>

</cubridrules>

Rule 1은, 가중치 0을 포함하여 0부터 20까지의 코드포인트를 설정한다. Rule 2는, 30부터 39(10진수)까지의 코드포인트와 증가하는 가중치를 가진 두 개의 콜레이션 원소의 집합을 설정한다. 이 예에서, 코드포인트 39(문자 “9”)는 2개의 콜레이션 원소[39.0.0.0][39.0.0.0]를 보유하는 가중치를 가질 것이다.

‘<rules>’ 태그 또한 선택적인데, LDML과 UCA 명세에 따라 정해진다. 하위 태그의 의미는 다음과 같다.

  • ‘<reset>’: 콜레이션 원소를 지정한다. 이 태그의 정의(다음에 나타나는 ‘<reset>’ 태그까지)에 의해 문자 순서에 대한 규칙들이 조정된다. 축약인지 확장인지에 따라 이 값은 단일 문자셋의 문자이거나 다중 문자셋의 문자가 될 수 있다. 기본적으로, 앵커 뒤에 오는 사용자 정의 규칙(tailoring rules)은 “뒤에(after)” 정렬된다(첫 번째 규칙의 원소는 앵커 뒤에 오며, 두 번째 규칙의 원소는 첫 번째 규칙에 있는 원소 뒤에 정렬됨). 선택적 속성 “before”가 존재하면, <reset> 뒤에 오는 첫 번째 규칙만 앵커 앞에 오는 반면, 두 번째와 이하 규칙들은 일반적인 “뒤(after)”의 정렬(두 번째 규칙에 있는 원소는 첫 번째 규칙에 있는 원소 뒤에 정렬됨)을 재개한다.
  • ‘<p>’: 첫 번째 수준(primary level)에서 미리 조정된(tailored) 것 뒤(또는 앞, 앵커가 ‘before’ 속성을 가지는 경우)에 오는 문자.
  • ‘<s>’: 두 번째 수준(secondary level)에서 미리 조정된(tailored) 것 뒤(또는 앞, 앵커가 ‘before’ 속성을 가지는 경우)에 오는 문자.
  • ‘<t>’: 세 번째 수준(tertiary level)에서 미리 조정된(tailored) 것 뒤(또는 앞, 앵커가 ‘before’ 속성을 가지는 경우)에 오는 문자.
  • ‘<i>’: 문자가 전의 것과 동등하게 정렬된다.
  • ‘<pc>’, ‘<sc>’, ‘<tc>’, ‘<ic>’: ‘<p>’, ‘<s>’, ‘<t>’, ‘<i>’와 같지만 문자의 범위를 적용한다.
  • ‘<x>’: 확장 문자를 지정한다.
  • ‘<extend>’: 확장의 두 번째 문자를 지정한다.
  • ‘<context>’: 규칙이 적용되는 문맥을 지정한다. 축약과 확장을 지정하는 변수.

LDML 규칙을 가지고 UCA를 조정하는 것에 대한 보다 자세한 정보는 http://www.unicode.org/reports/tr35/tr35-collation.html를 참고한다.

Footnotes

[1](1, 2) 글리프(glyph): 글자 하나의 모양에 대한 기본 단위로 문자의 모양이나 형태를 나타내는 그래픽 부호. 글리프는 눈에 보이는 모양을 지정하는 것으로서 하나의 글자에 대해 여러 개의 글리프가 존재할 수 있다.