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
제약 및 주의사항#
제약사항#
- pdo_altibase는 pdo_odbc와 동시에 사용할 수 없다. 두 extension을 모두 사용 설정하면 예기치 않은 에러가 발생할 수 있다.
-
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
-
기타 제약사항은 "파라미터 바인딩"을 참고한다.
주의사항#
- 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);