콘텐츠로 이동

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. 기타 제약사항은 “파라미터 바인딩”을 참고한다.

주의사항#

  1. pdo_altibase의 커밋모드 기본값은 서버의 설정과 무관하며 항상 autocommit이다. 다시 말해, 서버 기본값을 non-autocommit으로 설정하더라도 pdo_altibase의 커밋모드는 기본값인 autocommit이다.
  2. pdo 객체를 닫을 때, commit, rollback을 명시적으로 지정하지 않으면 해당 작업은 rollback된다.
  3. empty string('')을 알티베이스 DB의 숫자형데이터 타입들에 bind시에, native 타입(double, real, bigint, integer, smallint)과 non-native타입(numeric, decimal, number, float) 모두에 대하여 NULL로 입력된다.
  4. 쿼리내에 "날짜타입값 - ?" 형태를 포함하고, "?"에 숫자값을 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_PL AN 수행 계획을 얻을지 여부와 그 방식.
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);