5

PHP(CentOS 6および7)のODBCドライバーを介してSnowflakeに接続し、PDOを利用して簡単にアクセスしようとしています。

PHP のネイティブ ODBC 関数はかなりうまく機能するため、ODBC ドライバーがインストールされ、適切に動作しているようです。

$dsn = "Driver=SnowflakeDSIIDriver;Server=" . SNOWFLAKE_HOST;
$dsn .= ";Account=" . SNOWFLAKE_ACCOUNT;
$dsn .= ";Port=" . SNOWFLAKE_PORT;
$dsn .= ";Schema=" . SNOWFLAKE_SCHEMA;
$dsn .= ";Warehouse=" . SNOWFLAKE_WAREHOUSE;
$dsn .= ";Database=" . SNOWFLAKE_DATABASAE;

$conn_id = odbc_connect($dsn, SNOWFLAKE_USER, SNOWFLAKE_PASSWORD);
odbc_exec($conn_id, "USE WAREHOUSE " . SNOWFLAKE_WAREHOUSE);

$res = odbc_exec($conn_id, 'SHOW TABLES IN SCHEMA ' . SNOWFLAKE_SCHEMA . ';');
if ($res) {
    print "Tables in schema\n";
    while($row = odbc_fetch_array($res)) {
        print_r($row);
    }
}

$res = odbc_exec($conn_id, 'SELECT * FROM TEST;');
if ($res) {
    print "Test table content\n";
    while($row = odbc_fetch_array($res)) {
        print_r($row);
    }
}

戻り値

Tables in schema
Array
(
    [created_on] => 2015-09-09 17:34:43.517000
    [name] => TEST
    [database_name] => TESTSUITE
    [schema_name] => TESTSUITE
    [kind] => TRANSIENT
    [comment] =>
    [cluster_by] =>
    [rows] => 3
    [bytes] => 8192
    [owner] => TESTSUITE
    [account_name] => ****
    [retention_time] => 1
)
Test table content
Array
(
    [C1] => c
    [C2] =>
)
Array
(
    [C1] => a
    [C2] =>
)
Array
(
    [C1] => a
    [C2] =>
)

これは、DB に直接クエリを実行したときに得られるものとまったく同じです。

しかし、PDO を使用したい場合、結果がおかしくなっています。

$dsn = "Driver=SnowflakeDSIIDriver;Server=" . SNOWFLAKE_HOST;
$dsn .= ";Account=" . SNOWFLAKE_ACCOUNT;
$dsn .= ";Port=" . SNOWFLAKE_PORT;
$dsn .= ";Schema=" . SNOWFLAKE_SCHEMA;
$dsn .= ";Database=" . SNOWFLAKE_DATABASE;
$dsn .= ";Warehouse=" . SNOWFLAKE_WAREHOUSE;

$pdo = new PDO("odbc:" . $dsn, SNOWFLAKE_USER, SNOWFLAKE_PASSWORD, array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL));
$pdo->exec("USE WAREHOUSE " . SNOWFLAKE_WAREHOUSE);

$query = 'SHOW TABLES IN SCHEMA ' . SNOWFLAKE_SCHEMA . ';';
$statement = $pdo->query($query);
print "Tables in schema\n";
print "Rows: " . $statement->rowCount() . "\n";
while ($row = $statement->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_NEXT)) {
    print_r($row);
}

$query = 'SELECT * FROM TEST;';
$statement = $pdo->prepare($query);
$statement->execute();
print "Test table content\n";
print "Rows: " . $statement->rowCount() . "\n";
while ($row = $statement->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_NEXT)) {
    print_r($row);
}

戻り値

Tables in schema
Rows: 1
Array
(
    [created_on] => 2015-09-09 17:34:43.517000
    [name] =>
    [database_name] =>
    [schema_name] =>
    [kind] =>
    [comment] =>
    [cluster_by] =>
    [rows] =>
    [bytes] =>
    [owner] =>
    [account_name] =>
    [retention_time] =>
)
Test table content
Rows: 3

注: の後にそれ以上の出力はありませんRows: 3

したがって、PDOStatement は正しい行数を認識していますが、の内容SHOW TABLESは不完全であり、SELECT * FROM TESTどういうわけか完全に欠落しています (すぐに$statement->fetch()戻ります)。false

ここで PDO オプションが役立つかどうか、何か考えはありますか?

また、この場合、ネイティブ ODBC 関数が最大 200MB のメモリを消費することにも気付きました。

4

1 に答える 1

1

Snowflake を使用した PDO を介して CAST が正しく機能しないという同様の問題がありました。

例外 'PDOException' とメッセージ 'SQLSTATE[SL009]: <>: 0 [unixODBC][Driver Manager]SQLFetch または SQLFetchScroll を呼び出す前にバインドされた列はありません

簡単に言えば、Snowflake サポートと数通の電子メールを交換した後、PDO が Snowflake でサポートされていないことがわかりました。

現時点では、STRING/VARCHAR 型のバインドと 16M バイトの列サイズに起因するいくつかの問題が見つかったため、PHP PDO はサポートされていません。サポート性を前に進めないという決定でした。ODBC で PHP を引き続き使用できますが、発生した問題やバグに対処できない場合があります。

したがって、最善の策はodbc_*、PHP のネイティブ関数ファミリーを使用することです (これが私たちが行っていることです)。

于 2016-08-25T23:45:47.130 に答える