pglib 5.7.0__tar.gz → 5.9.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pglib-5.7.0/pglib.egg-info → pglib-5.9.1}/PKG-INFO +1 -1
- {pglib-5.7.0 → pglib-5.9.1}/pglib/__init__.py +0 -4
- {pglib-5.7.0 → pglib-5.9.1/pglib.egg-info}/PKG-INFO +1 -1
- {pglib-5.7.0 → pglib-5.9.1}/pglib.egg-info/SOURCES.txt +0 -1
- {pglib-5.7.0 → pglib-5.9.1}/setup.py +1 -1
- {pglib-5.7.0 → pglib-5.9.1}/src/connection.cpp +184 -11
- {pglib-5.7.0 → pglib-5.9.1}/src/getdata.cpp +7 -2
- {pglib-5.7.0 → pglib-5.9.1}/src/params.cpp +1 -1
- {pglib-5.7.0 → pglib-5.9.1}/src/pgarrays.cpp +172 -59
- {pglib-5.7.0 → pglib-5.9.1}/src/pgarrays.h +1 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/pglib.h +3 -2
- {pglib-5.7.0 → pglib-5.9.1}/src/resultset.cpp +4 -4
- {pglib-5.7.0 → pglib-5.9.1}/test/test_sync.py +86 -10
- {pglib-5.7.0 → pglib-5.9.1}/test/testutils.py +5 -1
- pglib-5.7.0/pglib/_version.py +0 -484
- {pglib-5.7.0 → pglib-5.9.1}/LICENSE +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/MANIFEST.in +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/README.rst +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/pglib/asyncpglib.py +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/pglib.egg-info/dependency_links.txt +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/pglib.egg-info/top_level.txt +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/setup.cfg +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/byteswap.h +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/connection.h +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/conninfoopt.cpp +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/conninfoopt.h +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/datatypes.cpp +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/datatypes.h +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/debug.cpp +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/debug.h +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/enums.cpp +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/enums.h +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/errors.cpp +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/errors.h +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/getdata.h +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/juliandate.cpp +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/juliandate.h +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/params.h +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/pglib.cpp +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/pgtypes.h +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/resultset.h +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/row.cpp +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/row.h +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/runtime.cpp +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/runtime.h +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/type_hstore.cpp +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/type_hstore.h +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/type_json.cpp +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/type_json.h +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/type_ltree.cpp +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/src/type_ltree.h +0 -0
- {pglib-5.7.0 → pglib-5.9.1}/test/test_async.py +0 -0
|
@@ -149,6 +149,9 @@ static PGresult* internal_execute(PyObject* self, PyObject* args)
|
|
|
149
149
|
PyErr_SetString(PyExc_TypeError, "The first argument must be a string.");
|
|
150
150
|
return 0;
|
|
151
151
|
}
|
|
152
|
+
const char* szSQL = PyUnicode_AsUTF8(pSql);
|
|
153
|
+
if (!szSQL)
|
|
154
|
+
return 0;
|
|
152
155
|
|
|
153
156
|
Params params(cParams);
|
|
154
157
|
if (!BindParams(cnxn, params, args))
|
|
@@ -156,7 +159,7 @@ static PGresult* internal_execute(PyObject* self, PyObject* args)
|
|
|
156
159
|
|
|
157
160
|
PGresult* result;
|
|
158
161
|
Py_BEGIN_ALLOW_THREADS
|
|
159
|
-
result = PQexecParams(cnxn->pgconn,
|
|
162
|
+
result = PQexecParams(cnxn->pgconn, szSQL,
|
|
160
163
|
cParams,
|
|
161
164
|
params.types,
|
|
162
165
|
params.values,
|
|
@@ -175,6 +178,7 @@ static PGresult* internal_execute(PyObject* self, PyObject* args)
|
|
|
175
178
|
return result;
|
|
176
179
|
}
|
|
177
180
|
|
|
181
|
+
|
|
178
182
|
static const char doc_script[] = "Connection.script(sql) --> None\n\n"
|
|
179
183
|
"Executes a script which can contain multiple statements separated by semicolons.";
|
|
180
184
|
|
|
@@ -188,7 +192,11 @@ static PyObject* Connection_script(PyObject* self, PyObject* args)
|
|
|
188
192
|
if (!PyArg_ParseTuple(args, "U", &pScript))
|
|
189
193
|
return 0;
|
|
190
194
|
|
|
191
|
-
|
|
195
|
+
const char* szScript = PyUnicode_AsUTF8(pScript);
|
|
196
|
+
if (!szScript)
|
|
197
|
+
return 0;
|
|
198
|
+
|
|
199
|
+
ResultHolder result = PQexec(cnxn->pgconn, szScript);
|
|
192
200
|
if (result == 0)
|
|
193
201
|
return 0;
|
|
194
202
|
|
|
@@ -203,6 +211,7 @@ static PyObject* Connection_script(PyObject* self, PyObject* args)
|
|
|
203
211
|
}
|
|
204
212
|
}
|
|
205
213
|
|
|
214
|
+
|
|
206
215
|
const char* doc_copy_from =
|
|
207
216
|
"Connection.copy_from(command, source) --> int\n"
|
|
208
217
|
"\n"
|
|
@@ -233,7 +242,7 @@ static PyObject* Connection_copy_from(PyObject* self, PyObject* args)
|
|
|
233
242
|
// an object with a read method (e.g. file).
|
|
234
243
|
const char* buffer = 0;
|
|
235
244
|
Py_ssize_t buffer_size = 0;
|
|
236
|
-
|
|
245
|
+
Object read_method;
|
|
237
246
|
|
|
238
247
|
if (PyUnicode_Check(source))
|
|
239
248
|
{
|
|
@@ -245,7 +254,7 @@ static PyObject* Connection_copy_from(PyObject* self, PyObject* args)
|
|
|
245
254
|
{
|
|
246
255
|
if (!PyObject_HasAttrString(source, "read"))
|
|
247
256
|
return PyErr_Format(Error, "CSV source must be a string or file-like object.");
|
|
248
|
-
read_method
|
|
257
|
+
read_method.Attach(PyObject_GetAttrString(source, "read"));
|
|
249
258
|
}
|
|
250
259
|
|
|
251
260
|
Connection* cnxn = CastConnection(self, REQUIRE_OPEN);
|
|
@@ -253,6 +262,9 @@ static PyObject* Connection_copy_from(PyObject* self, PyObject* args)
|
|
|
253
262
|
return 0;
|
|
254
263
|
|
|
255
264
|
const char* szSQL = PyUnicode_AsUTF8(command);
|
|
265
|
+
if (!szSQL)
|
|
266
|
+
return 0;
|
|
267
|
+
|
|
256
268
|
ResultHolder result;
|
|
257
269
|
Py_BEGIN_ALLOW_THREADS
|
|
258
270
|
result = PQexec(cnxn->pgconn, szSQL);
|
|
@@ -353,6 +365,145 @@ static PyObject* Connection_copy_from(PyObject* self, PyObject* args)
|
|
|
353
365
|
}
|
|
354
366
|
|
|
355
367
|
|
|
368
|
+
const char* doc_copy_to_csv =
|
|
369
|
+
"Connection.copy_to_csv(table, dest, header=0, delimiter=',', quote='\"')\n"
|
|
370
|
+
"\n"
|
|
371
|
+
"Execute a COPY TO command and return the number of records copied.\n"
|
|
372
|
+
"\n"
|
|
373
|
+
"table\n"
|
|
374
|
+
" The table to copy from.\n"
|
|
375
|
+
"\n"
|
|
376
|
+
"dest\n"
|
|
377
|
+
" The file-like object to write to. Strings will be written, not bytes, so\n"
|
|
378
|
+
" open in text mode.\n"
|
|
379
|
+
"\n"
|
|
380
|
+
"header\n"
|
|
381
|
+
" If non-zero, a CSV header will be written.\n";
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
static PyObject* Connection_copy_to_csv(PyObject* self, PyObject* args, PyObject* kwargs)
|
|
385
|
+
{
|
|
386
|
+
// This is not nearly as efficient as I'd like since newer Python versions no longer give
|
|
387
|
+
// us access to underlying file objects. We have to write strings through a write method
|
|
388
|
+
// since there are io layers involved.
|
|
389
|
+
//
|
|
390
|
+
// For maximum performance, we should probably offer an option where we open the file given
|
|
391
|
+
// a filename. We can either check the parameter type here or we could make a separate
|
|
392
|
+
// method with "file" in the name like copy_to_file.
|
|
393
|
+
|
|
394
|
+
static const char* kwlist[] = {"table", "dest", "header", "delimiter", "quote", 0};
|
|
395
|
+
|
|
396
|
+
PyObject* table;
|
|
397
|
+
PyObject* dest;
|
|
398
|
+
int header = 0;
|
|
399
|
+
char* szDelimiter = 0;
|
|
400
|
+
char* szQuote = 0;
|
|
401
|
+
|
|
402
|
+
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "UO|pzz", (char**)kwlist, &table, &dest, &header,
|
|
403
|
+
&szDelimiter, &szQuote)) {
|
|
404
|
+
return 0;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
Connection* cnxn = CastConnection(self, REQUIRE_OPEN);
|
|
408
|
+
if (!cnxn)
|
|
409
|
+
return 0;
|
|
410
|
+
|
|
411
|
+
if (!PyObject_HasAttrString(dest, "write"))
|
|
412
|
+
return PyErr_Format(Error, "CSV destination must be a file-like object.");
|
|
413
|
+
Object write_method(PyObject_GetAttrString(dest, "write"));
|
|
414
|
+
|
|
415
|
+
char header_token[] = "header";
|
|
416
|
+
if (header == 0) {
|
|
417
|
+
header_token[0] = 0;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
const char* pszDelimiter = szDelimiter ? szDelimiter : ",";
|
|
421
|
+
const char* pszQuote = szQuote ? szQuote : "\"";
|
|
422
|
+
|
|
423
|
+
Object sql(PyUnicode_FromFormat("copy %U to stdout with csv %s delimiter '%s' quote '%s'",
|
|
424
|
+
table, header_token, pszDelimiter, pszQuote));
|
|
425
|
+
if (!sql)
|
|
426
|
+
return 0;
|
|
427
|
+
|
|
428
|
+
const char* szSQL = PyUnicode_AsUTF8(sql);
|
|
429
|
+
if (!szSQL)
|
|
430
|
+
return 0;
|
|
431
|
+
|
|
432
|
+
ResultHolder result;
|
|
433
|
+
Py_BEGIN_ALLOW_THREADS
|
|
434
|
+
result = PQexec(cnxn->pgconn, szSQL);
|
|
435
|
+
Py_END_ALLOW_THREADS
|
|
436
|
+
|
|
437
|
+
if (result == 0)
|
|
438
|
+
return 0;
|
|
439
|
+
|
|
440
|
+
switch (PQresultStatus(result)) {
|
|
441
|
+
case PGRES_COPY_OUT:
|
|
442
|
+
// This is what we are expecting.
|
|
443
|
+
break;
|
|
444
|
+
|
|
445
|
+
case PGRES_BAD_RESPONSE:
|
|
446
|
+
case PGRES_NONFATAL_ERROR:
|
|
447
|
+
case PGRES_FATAL_ERROR:
|
|
448
|
+
return SetResultError(result.Detach());
|
|
449
|
+
|
|
450
|
+
default:
|
|
451
|
+
return PyErr_Format(Error, "Result was not PGRES_COPY_IN: %d", (int)PQresultStatus(result));
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
for (;;) {
|
|
456
|
+
int cb = 0;
|
|
457
|
+
char* buffer;
|
|
458
|
+
Py_BEGIN_ALLOW_THREADS
|
|
459
|
+
cb = PQgetCopyData(cnxn->pgconn, &buffer, 0);
|
|
460
|
+
Py_END_ALLOW_THREADS
|
|
461
|
+
|
|
462
|
+
if (cb == -2) {
|
|
463
|
+
return SetResultError(result.Detach());
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
if (cb == -1) {
|
|
467
|
+
// The copy is complete.
|
|
468
|
+
break;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// We have a buffer of byte data. We have the length, but the libpq docs say that the
|
|
472
|
+
// string is also zero terminated, so we're going to try not calling 'write'.
|
|
473
|
+
|
|
474
|
+
int err = PyFile_WriteString(buffer, dest);
|
|
475
|
+
|
|
476
|
+
// while (cb > 0) {
|
|
477
|
+
// PyObject* res = PyObject_CallObject(write_method)
|
|
478
|
+
// }
|
|
479
|
+
|
|
480
|
+
PQfreemem(buffer);
|
|
481
|
+
if (err) {
|
|
482
|
+
return 0;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// After a copy, you have to get another result to know if it was successful.
|
|
487
|
+
|
|
488
|
+
ResultHolder final_result;
|
|
489
|
+
ExecStatusType status = PGRES_COMMAND_OK;
|
|
490
|
+
Py_BEGIN_ALLOW_THREADS
|
|
491
|
+
final_result = PQgetResult(cnxn->pgconn);
|
|
492
|
+
status = PQresultStatus(final_result);
|
|
493
|
+
Py_END_ALLOW_THREADS
|
|
494
|
+
|
|
495
|
+
if (status != PGRES_COMMAND_OK) {
|
|
496
|
+
// SetResultError will take ownership of `result`.
|
|
497
|
+
return SetResultError(final_result.Detach());
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
const char* sz = PQcmdTuples(final_result);
|
|
501
|
+
if (sz == 0 || *sz == 0)
|
|
502
|
+
Py_RETURN_NONE;
|
|
503
|
+
return PyLong_FromLong(atoi(sz));
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
|
|
356
507
|
const char* doc_copy_from_csv =
|
|
357
508
|
"Connection.copy_from_csv(table, source, header=0) --> int\n"
|
|
358
509
|
"\n"
|
|
@@ -389,15 +540,16 @@ static PyObject* Connection_copy_from_csv(PyObject* self, PyObject* args, PyObje
|
|
|
389
540
|
|
|
390
541
|
const char* pszDelimiter = szDelimiter ? szDelimiter : ",";
|
|
391
542
|
const char* pszQuote = szQuote ? szQuote : "\"";
|
|
392
|
-
|
|
393
|
-
|
|
543
|
+
Object sql(PyUnicode_FromFormat("copy %U from stdin with csv %s delimiter '%s' quote '%s'",
|
|
544
|
+
table, header_token, pszDelimiter, pszQuote));
|
|
394
545
|
|
|
395
546
|
// If source is a string (Unicode), store the UTF-encoded value in buffer. If a byte
|
|
396
547
|
// object, store directly in buffer. Otherwise, buffer will be zero and `source` must be
|
|
397
548
|
// an object with a read method (e.g. file).
|
|
398
549
|
const char* buffer = 0;
|
|
399
550
|
Py_ssize_t buffer_size = 0;
|
|
400
|
-
|
|
551
|
+
Object read_method;
|
|
552
|
+
// PyObject* read_method = 0;
|
|
401
553
|
|
|
402
554
|
if (PyUnicode_Check(source))
|
|
403
555
|
{
|
|
@@ -409,7 +561,7 @@ static PyObject* Connection_copy_from_csv(PyObject* self, PyObject* args, PyObje
|
|
|
409
561
|
{
|
|
410
562
|
if (!PyObject_HasAttrString(source, "read"))
|
|
411
563
|
return PyErr_Format(Error, "CSV source must be a string or file-like object.");
|
|
412
|
-
read_method
|
|
564
|
+
read_method.Attach(PyObject_GetAttrString(source, "read"));
|
|
413
565
|
}
|
|
414
566
|
|
|
415
567
|
Connection* cnxn = CastConnection(self, REQUIRE_OPEN);
|
|
@@ -417,6 +569,9 @@ static PyObject* Connection_copy_from_csv(PyObject* self, PyObject* args, PyObje
|
|
|
417
569
|
return 0;
|
|
418
570
|
|
|
419
571
|
const char* szSQL = PyUnicode_AsUTF8(sql);
|
|
572
|
+
if (!szSQL)
|
|
573
|
+
return 0;
|
|
574
|
+
|
|
420
575
|
ResultHolder result;
|
|
421
576
|
Py_BEGIN_ALLOW_THREADS
|
|
422
577
|
result = PQexec(cnxn->pgconn, szSQL);
|
|
@@ -998,8 +1153,12 @@ static PyObject* Connection_sendQuery(PyObject* self, PyObject* args)
|
|
|
998
1153
|
return 0;
|
|
999
1154
|
|
|
1000
1155
|
int sent;
|
|
1156
|
+
const char* szSQL = PyUnicode_AsUTF8(pScript);
|
|
1157
|
+
if (!szSQL)
|
|
1158
|
+
return 0;
|
|
1159
|
+
|
|
1001
1160
|
Py_BEGIN_ALLOW_THREADS
|
|
1002
|
-
sent = PQsendQuery(cnxn->pgconn,
|
|
1161
|
+
sent = PQsendQuery(cnxn->pgconn, szSQL);
|
|
1003
1162
|
Py_END_ALLOW_THREADS
|
|
1004
1163
|
|
|
1005
1164
|
if (!sent)
|
|
@@ -1038,6 +1197,10 @@ static PyObject* Connection_sendQueryParams(PyObject* self, PyObject* args)
|
|
|
1038
1197
|
return 0;
|
|
1039
1198
|
}
|
|
1040
1199
|
|
|
1200
|
+
const char* szSQL = PyUnicode_AsUTF8(pSql);
|
|
1201
|
+
if (!szSQL)
|
|
1202
|
+
return 0;
|
|
1203
|
+
|
|
1041
1204
|
Params params(cParams);
|
|
1042
1205
|
if (!BindParams(cnxn, params, args))
|
|
1043
1206
|
return 0;
|
|
@@ -1047,7 +1210,7 @@ static PyObject* Connection_sendQueryParams(PyObject* self, PyObject* args)
|
|
|
1047
1210
|
int needs_flush = -1;
|
|
1048
1211
|
|
|
1049
1212
|
Py_BEGIN_ALLOW_THREADS
|
|
1050
|
-
error = PQsendQueryParams(cnxn->pgconn,
|
|
1213
|
+
error = PQsendQueryParams(cnxn->pgconn, szSQL,
|
|
1051
1214
|
cParams,
|
|
1052
1215
|
params.types,
|
|
1053
1216
|
params.values,
|
|
@@ -1215,7 +1378,16 @@ static PyObject* Connection_notifications(PyObject* self, PyObject* args, PyObje
|
|
|
1215
1378
|
Py_END_ALLOW_THREADS
|
|
1216
1379
|
|
|
1217
1380
|
if (retval == -1) {
|
|
1218
|
-
|
|
1381
|
+
// Allow the Python (or application) signal handler deal with Ctrl-C. If it raises an
|
|
1382
|
+
// exception, -1 is returned. This only works on the main Python thread, but it is
|
|
1383
|
+
// just a convenience for command line utilities to raise a KeyboardInterrupt instead a
|
|
1384
|
+
// pglib error that *then* raises a KeyboardInterrupt. So it is OK if we call on
|
|
1385
|
+
// another thread and it is a no-op.
|
|
1386
|
+
|
|
1387
|
+
if (PyErr_CheckSignals() != -1) {
|
|
1388
|
+
SetStringError(Error, "An error occurred waiting for notifications");
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1219
1391
|
return 0;
|
|
1220
1392
|
}
|
|
1221
1393
|
|
|
@@ -1459,6 +1631,7 @@ static struct PyMethodDef Connection_methods[] =
|
|
|
1459
1631
|
{ "script", Connection_script, METH_VARARGS, doc_script },
|
|
1460
1632
|
{ "copy_from", (PyCFunction) Connection_copy_from, METH_VARARGS | METH_KEYWORDS, doc_copy_from },
|
|
1461
1633
|
{ "copy_from_csv", (PyCFunction) Connection_copy_from_csv, METH_VARARGS | METH_KEYWORDS, doc_copy_from_csv },
|
|
1634
|
+
{ "copy_to_csv", (PyCFunction) Connection_copy_to_csv, METH_VARARGS | METH_KEYWORDS, doc_copy_to_csv},
|
|
1462
1635
|
{ "begin", Connection_begin, METH_NOARGS, doc_begin },
|
|
1463
1636
|
{ "commit", Connection_commit, METH_NOARGS, doc_commit },
|
|
1464
1637
|
{ "rollback", Connection_rollback, METH_NOARGS, doc_rollback },
|
|
@@ -286,8 +286,10 @@ static PyObject* GetInterval(const char* p) // , bool integer_datetimes)
|
|
|
286
286
|
uint32_t month = swaps4(pinterval->month);
|
|
287
287
|
uint32_t year = month / 12;
|
|
288
288
|
|
|
289
|
-
if (month || year)
|
|
290
|
-
|
|
289
|
+
if (month || year) {
|
|
290
|
+
PyErr_SetString(Error, "Years and months are not supported in intervals");
|
|
291
|
+
return 0;
|
|
292
|
+
}
|
|
291
293
|
|
|
292
294
|
int seconds = (second) + (60 * minute) + (3600 * hour);
|
|
293
295
|
int days = day;
|
|
@@ -399,6 +401,9 @@ PyObject* ConvertValue(PGresult* result, int iRow, int iCol, bool integer_dateti
|
|
|
399
401
|
case TEXTARRAYOID:
|
|
400
402
|
return GetTextArray(p);
|
|
401
403
|
|
|
404
|
+
case JSONBARRAYOID:
|
|
405
|
+
return GetJSONBArray(p);
|
|
406
|
+
|
|
402
407
|
case DATEARRAYOID:
|
|
403
408
|
return GetDateArray(p);
|
|
404
409
|
|