콘텐츠로 이동

2. PDO 드라이버#

이 장에서는 Altibase PDO 드라이버를 이용하여 Altibase와 연동하는 방법을 설명한다.

Altibase PDO 드라이버(이하 pdo_altibase)는 Altibase 공식 사이트에서 pecl 패키지 형태로 제공한다. pdo_altibase는 Altibase CLI 드라이버를 기반으로 개발되었기 때문에 CLI가 설치되어 있어야 하며, CLI에서 사용하는 환경변수의 영향을 받는다.

설치 및 설정#

pdo_altibase를 다운로드 후 설치하고 환경을 설정하는 방법을 기술한다.

다운로드#

pdo_altibase를 사용하기 위해서는 pecl 사용환경을 갖춰야 한다. 아래 url에서 pecl 패키지를 다운로드 한다.

  • http://support.altibase.com/kr/product 으로 이동
  • PDO_ALTIBASE-*.*.*.tgz 다운로드
    • PDO_ALTIBASE-1.*.*.tgz : PHP 5.3.3, PHP 7.1.20 버전 용
    • PDO_ALTIBASE-2.*.*.tgz : PHP 8.1.8 버전 용

소프트웨어 요구사항#

  • Altibase : Altibase 6.5.1.5.1 이상

  • OS : Linux (상세 버전은 Altibase Release Notes 참고)

  • PHP : PHP 5.3.3, PHP 7.1.20, PHP 8.1.8

설치#

pecl을 사용하여 pdo_altibase를 설치한다.

pecl install PDO_ALTIBASE-1.0.0.tgz

환경설정#

php.ini 등 설정파일에 확장 사용설정을 추가한다.

extension=pdo_altibase.so


제약 및 주의사항#

제약사항#

  1. pdo_altibase는 pdo_odbc와 동시에 사용할 수 없다. 두 extension을 모두 사용 설정하면 예기치 않은 에러가 발생할 수 있다.
  2. PDO 매뉴얼에 기술된 항목 중 아래 항목은 지원하지 않는다.

    • PDO::lastInsertId
    • PDO::getAttribute, PDO::setAttribute
      • PDO::ATTR_CONNECTION_STATUS
      • PDO::ATTR_ORACLE_NULLS
      • PDO::ATTR_PERSISTENT
      • PDO::ATTR_SERVER_INFO
      • PDO::ATTR_STRINGIFY_FETCHES
      • PDO::ATTR_EMULATE_PREPARES
      • PDO::MYSQL_ATTR_USE_BUFFERED_QUERY
    • PDOStatement::getAttribute, PDOStatement::setAttribute

      • PDO::ATTR_CURSOR_NAME
    • PDOStatement::getColumnMeta

  3. 기타 제약사항은 "파라미터 바인딩"을 참고한다.

주의사항#

  • pdo_altibase의 커밋모드 기본값은 서버의 설정과 무관하며 항상 autocommit이다. 다시 말해, 서버 기본값을 non-autocommit으로 설정하더라도 pdo_altibase의 커밋모드는 기본값인 autocommit이다.
  • pdo 객체를 닫을 때, commit, rollback을 명시적으로 지정하지 않으면 해당 작업은 rollback 된다.
  • empty string('')을 알티베이스 DB의 숫자형데이터 타입들에 bind 시에, native 타입(double, real, bigint, integer, smallint)과 non-native타입(numeric, decimal, number, float) 모두에 대하여 NULL로 입력된다.
  • 쿼리 내에 "날짜타입값 - ?" 형태를 포함하고, "?"에 숫자 값을 bind하여 사용시에는 "ERR-21038 : Literals in the input do not match the format string." 에러가 발생한다. 이때, 날짜 타입 값이란 날짜 타입 칼럼 및 날짜 타입 반환 함수를 포함한다. 이러한 에러가 발생하는 이유는 pdo_altibase가 숫자 값 bind시에 내부적으로 문자열로 처리하는데, Altibase 질의 처리기가 날짜 타입 값에 대한 문자열 빼기 연산을 할 때에 문자열을 날짜 타입으로 변환하려고 하기 때문이다. 이 경우에는 "?"을 "to_number(?)" 등으로 "?"을 문자열이 아닌 다른 의도하는 데이터타입을 갖도록 명시적으로 변경하여 사용하면 된다.


사용 방법#

DSN 구성#

pdo_altibase의 DSN 구성은 다음과 같다.

속성 설명
DSN prefix "altibase"
Server 서버의 호스트 이름 또는 ip 주소
Port 서버의 포트 번호
NLS_USE 캐릭터 셋.
US7ASCII가 기본값이며, 환경변수 ALTIBASE_NLS_USE가 설정된 경우에는 지정된 값을 사용한다.

예제#

"altibase:Server=127.0.0.1;Port=20333;NLS_USE=US7ASCII"

연결속성#

PDO::getAttribute(), PDO::setAttribute() 함수에서 사용할 수 있는 속성은 다음과 같다. 사용할 수 없는 속성은 "제약 및 주의사항"을 참조한다.

속성 ID 설명
PDO::ALTIBASE_DATE_FORMAT DATE를 표현하는데 사용할 포맷. 사용예제, DATE 포맷 변경 참고.
PDO::ALTIBASE_EXPLAIN_PLAN 수행 계획을 얻을지 여부와 그 방식.
- PDO::ALTIBASE_EXPLAIN_PLAN_OFF : 수행 계획을 얻지 않는다.
- PDO::ALTIBASE_EXPLAIN_PLAN_ON : Prepare 및 Execution 후 결정된 수행 계획을 얻는다.
- PDO::ALTIBASE_EXPLAIN_PLAN_ONLY : Prepare 후 Execution 전에 결정된 수행 계획을 얻는다.
자세한 내용은 사용 예제 > 수행계획 확인을 참고하라.
PDO::ALTIBASE_DEFER_PROTOCOLS Prepare, execute를 반복하여 호출하는 구조로 작성된 프로그램의 성능 향상을 위한 프로토콜 최적화 여부를 설정한다.
이 속성을 사용하기 위해서는, 하나의 커넥션 객체를 여러 쓰레드에서 공유해서 사용하지 않아야 한다.
또한 성능을 위해서는 prepare를 한번만 호출한 후, execute를 반복 호출하는 구조로 프로그램을 작성해야 한다.
- 0 : 프로토콜 최적화하지 않음 (default)
- 1 : execute 관련 프로토콜 최적화
- 2 : execute, close 관련 프로토콜 최적화

ex> $db->setAttribute(PDO::ALTIBASE_DEFER_PROTOCOLS, 1);

파라미터 바인딩#

pdo_altibase는 named parameter를 지원하지 않는다.

또한, 4번째인 length 인자는 현재 hint로만 사용하며, 유효한 값으로 처리하지 않는다. 만약 length에 의한 동작이 필요하다면 length 인자 대신 값 자체를 잘라서 사용해야 한다.

바인딩 예제#

$stmt = $db->prepare("SELECT * FROM t1 WHERE val = ? OR val = ?");
$stmt->bindParam(1, $val1);
$stmt->bindParam(2, $val2);
$stmt->execute();

칼럼 바인딩#

pdo_altibase는 bindColumn()의 type 및 maxlen을 지정해도 동작에 영향을 끼치지 않는다. SQL data type에 따라 바이너리 또는 문자열로 값을 가져오며, 이후 처리는 PDO 동작에 따른다.

기타 바인딩 제약사항#

BIT, VARBIT, BYTE, VARBYTE, NIBBLE, LOB, GEOMETRY 타입은 제한적으로 지원한다. 단순 INSERT 등 일부 쿼리에 한해서만 제한적으로 사용할 수 있다.


사용 예제#

연결 및 쿼리 수행#

$db = new PDO("altibase:Server=127.0.0.1;Port=20333", "sys", "manager");
foreach ($db->query("SELECT * FROM dual") as $row) {
    print_r($row);
}

DATE 포맷 변경#

DATE를 위해 기본으로 어떤 문자열 포맷을 사용할 것인지 설정할 수 있다.

$db->setAttribute(PDO::ALTIBASE_DATE_FORMAT, "YYYY-MM-DD");
$attr_dateform = $db->getAttribute(PDO::ALTIBASE_DATE_FORMAT);
echo "attr_dateform = $attr_dateform\n";
$stmt->execute();
echo $stmt->fetchColumn(), "\n";

출력 결과#

attr_dateform = YYYY-MM-DD
2017-04-18

수행계획 확인#

PDO 객체의 setAttribute() 함수를 통해 수행 계획 출력 여부를 설정할 수 있다.

$attr_plan = $db->getAttribute(PDO::ALTIBASE_EXPLAIN_PLAN);
echo "attr_plan = $attr_plan\n";

$db->setAttribute(PDO::ALTIBASE_EXPLAIN_PLAN, PDO::ALTIBASE_EXPLAIN_PLAN_ONLY);
$attr_plan = $db->getAttribute(PDO::ALTIBASE_EXPLAIN_PLAN);
echo "attr_plan = $attr_plan\n";
$stmt = $db->prepare("SELECT * FROM dual");
$stmt->execute();
print_r($stmt->fetchAll());
echo $stmt->getPlanText();
$stmt = null;
$db->setAttribute(PDO::ALTIBASE_EXPLAIN_PLAN, PDO::ALTIBASE_EXPLAIN_PLAN_ON);
$attr_plan = $db->getAttribute(PDO::ALTIBASE_EXPLAIN_PLAN);
echo "attr_plan = $attr_plan\n";
$stmt = $db->prepare("SELECT * FROM dual");
$stmt->execute();
print_r($stmt->fetchAll());
echo $stmt->getPlanText();
$stmt = null;

출력 결과#

attr_plan = 0
attr_plan = 2
Array
(
    [0] => Array
        (
            [dummy] => X
            [0] => X
        )
)
------------------------------------------------------------
PROJECT ( COLUMN_COUNT: 1, TUPLE_SIZE: 3, COST: 0.01 )
 SCAN ( TABLE: DUAL, FULL SCAN, ACCESS: ??, COST: 0.01 )
------------------------------------------------------------
attr_plan = 1
Array
(
    [0] => Array
        (
            [dummy] => X
            [0] => X
        )
)
------------------------------------------------------------
PROJECT ( COLUMN_COUNT: 1, TUPLE_SIZE: 3, COST: 0.01 )
 SCAN ( TABLE: DUAL, FULL SCAN, ACCESS: 1, COST: 0.01 )
------------------------------------------------------------

커서 유지#

commit, rollback을 수행해도 fetch중인 커서를 유지해준다.

// HOLD를 쓰려면 AUTOCOMMIT 속성이 false여야 함
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, false);

// prepare 때 HOLD 속성을 줘야 함
$stmt_sel = $db->prepare("SELECT * FROM pdo_hold", array(PDO::ALTIBASE_CURSOR_HOLD => PDO::ALTIBASE_CURSOR_HOLD_ON));
$stmt_del = $db->prepare("DELETE pdo_hold WHERE id = ?");

// TODO

// AUTOCOMMIT을 바꾸려면 stmt를 모두 정리해야 함
unset($stmt_sel);
unset($stmt_del);
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, true);