Completed
Push — master ( 4f50ab...5be735 )
by Ondřej
03:27
created

pg_copy.php ➔ processResult()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 36
Code Lines 31

Duplication

Lines 36
Ratio 100 %

Importance

Changes 0
Metric Value
cc 2
eloc 31
nc 2
nop 1
dl 36
loc 36
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/**
3
 * Test of PostgreSQL COPY FROM/TO facility.
4
 */
5
6
namespace Ivory\Sandpit;
7
8
$conn = pg_connect('dbname=ivory_scratch user=ivory password=ivory', PGSQL_CONNECT_FORCE_NEW);
9
if ($conn === false) {
10
    fprintf(STDERR, "Error connecting to the database\n");
11
    exit(1);
12
}
13
14
$res = pg_query($conn, 'CREATE TEMPORARY TABLE bar (a INT, b char(16), c FLOAT)');
15
processResult($res);
16
17
18
echo "\n\n=== 1. COPY FROM STDIN ===\n";
19
/* There are two ways of passing data: as an array of serialized rows, or using a stream, row-by-row.
20
 * The first option may encapsulate pg_copy_from(); on top it, offer optional check of columns similar to that for
21
 * pg_copy_to() - see below.
22
 * The second option may use pg_put_line() for each serialized row, finalized with pg_end_copy().
23
 */
24
$res = pg_query($conn, 'COPY bar (a, b, c) FROM STDIN'); // result status: PGSQL_COPY_IN
25
processResult($res);
26
27
pg_put_line($conn, "3\thello world\t4.5\n");
28
pg_put_line($conn, "4\tgoodbye world\t7.11\n");
29
pg_put_line($conn, "\\.\n");
30
pg_end_copy($conn);
31
32
$res = pg_query($conn, 'SELECT COUNT(*) FROM bar');
33
$cnt = pg_fetch_result($res, 0, 0);
34
echo "bar COUNT(): "; var_dump($cnt); // prints 2
35
36
37
echo "\n\n=== 2. COPY TO STDOUT ===\n";
38
/* pg_copy_to() is limited to pass the data exactly in the order of the columns definition.
39
 * It would be nice to optionally accept the intended column order, check it against the actual table definition, and
40
 * swap the copied data on the fly in case of different order. It would still result in list of rows serialized as
41
 * strings, just the interface would be richer.
42
 */
43
$data = pg_copy_to($conn, 'bar');
44
var_dump($data);
45
46
echo "\n\n=== 2b. COPY TO STDOUT using pg_socket()\n"; // cannot read the actual data
47
//$stream = pg_socket($conn);
48
$res = pg_query($conn, 'COPY bar (a, b, c) TO STDOUT'); // result status: PGSQL_COPY_OUT
49
processResult($res);
50
var_dump(pg_end_copy($conn));
51
//while (true) {
52
//    $read = [$stream];
53
//    $write = $except = [];
54
//    $ready = stream_select($read, $write, $except, 4);
55
//    if ($ready) {
56
//        echo "ready; reading...\n";
57
//        $res = socket_read($read[0], 1024);
58
//        if (strlen($res) == 0) {
59
//            break;
60
//        }
61
//        var_dump($res);
62
//    }
63
//    else {
64
//        echo "Not ready\n";
65
//    }
66
//}
67
68
69
echo "\n\n=== 3. COPY TO <file> ===\n";
70
$filepath = realpath(tempnam(__DIR__, 'cpy'));
71
$res = pg_query($conn, "COPY bar (a, b, c) TO '$filepath'"); // result status: PGSQL_COMMAND_OK, command tag: COPY 2
72
processResult($res);
73
74
75
echo "\n\n=== 4. COPY FROM <file> ===\n";
76
$res = pg_query($conn, "COPY bar (a, b, c) FROM '$filepath'"); // result status: PGSQL_COMMAND_OK, command tag: COPY 2
77
processResult($res);
78
79
$res = pg_query($conn, 'SELECT COUNT(*) FROM bar');
80
$cnt = pg_fetch_result($res, 0, 0);
81
echo "bar COUNT(): "; var_dump($cnt); // prints 4
82
83
84
echo "\n\n=== 5. COPY TO PROGRAM <program> ===\n";
85
$filepath2 = realpath(tempnam(__DIR__, 'cp2'));
86
$res = pg_query($conn, "COPY bar (a, b, c) TO PROGRAM 'cat > $filepath2'"); // result status: PGSQL_COMMAND_OK, command tag: COPY 4
87
processResult($res);
88
89
90
echo "\n\n=== 6. COPY FROM PROGRAM <program> ===\n";
91
$res = pg_query($conn, "COPY bar (a, b, c) FROM PROGRAM 'cat $filepath2'"); // result status: PGSQL_COMMAND_OK, command tag: COPY 4
92
processResult($res);
93
94
$res = pg_query($conn, 'SELECT COUNT(*) FROM bar');
95
$cnt = pg_fetch_result($res, 0, 0);
96
echo "bar COUNT(): "; var_dump($cnt); // prints 8
97
98
99
100
101
unlink($filepath);
102
unlink($filepath2);
103
104
105
106
function processResult($res)
107
{
108
    $statCodes = [
109
        PGSQL_EMPTY_QUERY => 'empty query',
110
        PGSQL_COMMAND_OK => 'command ok',
111
        PGSQL_TUPLES_OK => 'tuples ok',
112
        PGSQL_COPY_IN => 'copy in',
113
        PGSQL_COPY_OUT => 'copy out',
114
        PGSQL_BAD_RESPONSE => 'bad response',
115
        PGSQL_NONFATAL_ERROR => 'non-fatal error', // reported as impossible to get this status returned from php pgsql
116
        PGSQL_FATAL_ERROR => 'fatal error',
117
    ];
118
    $statCode = pg_result_status($res);
119
    $statStr = pg_result_status($res, PGSQL_STATUS_STRING);
120
    echo "Result status: $statCode ({$statCodes[$statCode]}); $statStr\n";
121
122
    echo "Error fields:\n";
123
    $fields = [
124
        'SQL state' => PGSQL_DIAG_SQLSTATE,
125
        'Severity' => PGSQL_DIAG_SEVERITY,
126
        'Message' => PGSQL_DIAG_MESSAGE_PRIMARY,
127
        'Detail' => PGSQL_DIAG_MESSAGE_DETAIL,
128
        'Hint' => PGSQL_DIAG_MESSAGE_HINT,
129
        'Statement position' => PGSQL_DIAG_STATEMENT_POSITION,
130
        'Internal position' => PGSQL_DIAG_INTERNAL_POSITION,
131
        'Internal query' => PGSQL_DIAG_INTERNAL_QUERY,
132
        'Context' => PGSQL_DIAG_CONTEXT,
133
        'Source file' => PGSQL_DIAG_SOURCE_FILE,
134
        'Source line' => PGSQL_DIAG_SOURCE_LINE,
135
        'Source function' => PGSQL_DIAG_SOURCE_FUNCTION,
136
    ];
137
    foreach ($fields as $desc => $field) {
138
        echo "$desc: "; var_dump(pg_result_error_field($res, $field));
139
    }
140
    echo "---------------------\n";
141
}
142