pglib 5.9.0__tar.gz → 5.10.0__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.9.0/pglib.egg-info → pglib-5.10.0}/PKG-INFO +4 -1
- {pglib-5.9.0 → pglib-5.10.0/pglib.egg-info}/PKG-INFO +4 -1
- {pglib-5.9.0 → pglib-5.10.0}/setup.py +1 -1
- {pglib-5.9.0 → pglib-5.10.0}/src/connection.cpp +10 -1
- {pglib-5.9.0 → pglib-5.10.0}/src/getdata.cpp +3 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/pgarrays.cpp +111 -1
- {pglib-5.9.0 → pglib-5.10.0}/src/pgarrays.h +1 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/pglib.h +1 -0
- {pglib-5.9.0 → pglib-5.10.0}/test/test_sync.py +9 -1
- {pglib-5.9.0 → pglib-5.10.0}/LICENSE +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/MANIFEST.in +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/README.rst +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/pglib/__init__.py +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/pglib/asyncpglib.py +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/pglib.egg-info/SOURCES.txt +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/pglib.egg-info/dependency_links.txt +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/pglib.egg-info/top_level.txt +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/setup.cfg +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/byteswap.h +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/connection.h +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/conninfoopt.cpp +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/conninfoopt.h +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/datatypes.cpp +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/datatypes.h +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/debug.cpp +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/debug.h +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/enums.cpp +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/enums.h +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/errors.cpp +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/errors.h +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/getdata.h +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/juliandate.cpp +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/juliandate.h +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/params.cpp +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/params.h +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/pglib.cpp +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/pgtypes.h +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/resultset.cpp +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/resultset.h +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/row.cpp +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/row.h +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/runtime.cpp +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/runtime.h +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/type_hstore.cpp +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/type_hstore.h +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/type_json.cpp +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/type_json.h +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/type_ltree.cpp +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/src/type_ltree.h +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/test/test_async.py +0 -0
- {pglib-5.9.0 → pglib-5.10.0}/test/testutils.py +0 -0
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pglib
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.10.0
|
|
4
4
|
Summary: A PostgreSQL interface
|
|
5
5
|
Home-page: https://gitlab.com/mkleehammer/pglib
|
|
6
6
|
Maintainer: Michael Kleehammer
|
|
7
7
|
Maintainer-email: michael@kleehammer.com
|
|
8
8
|
License: MIT
|
|
9
9
|
Keywords: postgresql postgres
|
|
10
|
+
Platform: UNKNOWN
|
|
10
11
|
Classifier: Development Status :: 5 - Production/Stable
|
|
11
12
|
Classifier: Intended Audience :: Developers
|
|
12
13
|
Classifier: Topic :: Database
|
|
@@ -20,3 +21,5 @@ A PostgreSQL interface for Python.
|
|
|
20
21
|
This provides an interface to the libpq library. It is not an DB API
|
|
21
22
|
library, but is instead designed to match the interface PostgreSQL
|
|
22
23
|
offers.
|
|
24
|
+
|
|
25
|
+
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pglib
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.10.0
|
|
4
4
|
Summary: A PostgreSQL interface
|
|
5
5
|
Home-page: https://gitlab.com/mkleehammer/pglib
|
|
6
6
|
Maintainer: Michael Kleehammer
|
|
7
7
|
Maintainer-email: michael@kleehammer.com
|
|
8
8
|
License: MIT
|
|
9
9
|
Keywords: postgresql postgres
|
|
10
|
+
Platform: UNKNOWN
|
|
10
11
|
Classifier: Development Status :: 5 - Production/Stable
|
|
11
12
|
Classifier: Intended Audience :: Developers
|
|
12
13
|
Classifier: Topic :: Database
|
|
@@ -20,3 +21,5 @@ A PostgreSQL interface for Python.
|
|
|
20
21
|
This provides an interface to the libpq library. It is not an DB API
|
|
21
22
|
library, but is instead designed to match the interface PostgreSQL
|
|
22
23
|
offers.
|
|
24
|
+
|
|
25
|
+
|
|
@@ -1378,7 +1378,16 @@ static PyObject* Connection_notifications(PyObject* self, PyObject* args, PyObje
|
|
|
1378
1378
|
Py_END_ALLOW_THREADS
|
|
1379
1379
|
|
|
1380
1380
|
if (retval == -1) {
|
|
1381
|
-
|
|
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
|
+
|
|
1382
1391
|
return 0;
|
|
1383
1392
|
}
|
|
1384
1393
|
|
|
@@ -91,6 +91,11 @@ inline uint32_t ReadU32(const char ** pp) {
|
|
|
91
91
|
return htonl(n);
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
inline double ReadDouble(const char ** pp) {
|
|
95
|
+
double n = **(double**)pp;
|
|
96
|
+
*pp += sizeof(double);
|
|
97
|
+
return swapdouble(n);
|
|
98
|
+
}
|
|
94
99
|
|
|
95
100
|
|
|
96
101
|
static PyObject* FindFirstParam(Object& seq)
|
|
@@ -375,6 +380,69 @@ bool BindLongArray(Params& params, Object& seq, Py_ssize_t cItems)
|
|
|
375
380
|
}
|
|
376
381
|
|
|
377
382
|
|
|
383
|
+
static bool BindFloatArray(Params& params, Object& seq, Py_ssize_t cItems)
|
|
384
|
+
{
|
|
385
|
+
// Loop through the array and make sure each entry is a float (or None).
|
|
386
|
+
|
|
387
|
+
int cNonNull = 0; // count of non-null items
|
|
388
|
+
|
|
389
|
+
for (Py_ssize_t iItem = 0; iItem < cItems; iItem++)
|
|
390
|
+
{
|
|
391
|
+
PyObject* item = PySequence_Fast_GET_ITEM(seq.Get(), iItem);
|
|
392
|
+
if (item != Py_None)
|
|
393
|
+
{
|
|
394
|
+
if (!PyFloat_Check(item))
|
|
395
|
+
{
|
|
396
|
+
SetStringError(Error, "array parameters must all be the same type");
|
|
397
|
+
return false;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
cNonNull += 1;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
int cbItem = sizeof(double);
|
|
405
|
+
|
|
406
|
+
Py_ssize_t cb = sizeof(ArrayHeader) +
|
|
407
|
+
(4 * cItems) + // length indicators
|
|
408
|
+
(cbItem * cNonNull); // values
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
WriteBuffer buf = params.Allocate(cb);
|
|
412
|
+
if (!buf)
|
|
413
|
+
return false;
|
|
414
|
+
|
|
415
|
+
ArrayHeader* phdr = (ArrayHeader*)buf.pbStart;
|
|
416
|
+
phdr->ndim = htonl(1);
|
|
417
|
+
phdr->flags = htonl(1);
|
|
418
|
+
phdr->oid = htonl(FLOAT8OID);
|
|
419
|
+
phdr->dim = htonl(cItems);
|
|
420
|
+
phdr->lbound = htonl(1);
|
|
421
|
+
|
|
422
|
+
char* pT = &phdr->buffer[0];
|
|
423
|
+
|
|
424
|
+
for (Py_ssize_t iItem = 0; iItem < cItems; iItem++)
|
|
425
|
+
{
|
|
426
|
+
PyObject* item = PySequence_Fast_GET_ITEM(seq.Get(), iItem);
|
|
427
|
+
if (item != Py_None)
|
|
428
|
+
{
|
|
429
|
+
(*(uint32_t*)pT) = htonl(cbItem); // could be swapped and cached
|
|
430
|
+
pT += 4;
|
|
431
|
+
|
|
432
|
+
(*(double*)pT) = swapdouble(PyFloat_AS_DOUBLE(item));
|
|
433
|
+
pT += cbItem;
|
|
434
|
+
}
|
|
435
|
+
else
|
|
436
|
+
{
|
|
437
|
+
(*(uint32_t*)pT) = htonl(-1);
|
|
438
|
+
pT += 4;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
return params.Bind(FLOAT8ARRAYOID, buf, FORMAT_BINARY);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
|
|
378
446
|
bool BindArray(Params& params, PyObject* param)
|
|
379
447
|
{
|
|
380
448
|
// Binds a list or tuple as an array. All elements must be of the same type, though None
|
|
@@ -399,7 +467,10 @@ bool BindArray(Params& params, PyObject* param)
|
|
|
399
467
|
if (PyDate_Check(first))
|
|
400
468
|
return BindDateArray(params, seq, cItems);
|
|
401
469
|
|
|
402
|
-
|
|
470
|
+
if (PyFloat_Check(first))
|
|
471
|
+
return BindFloatArray(params, seq, cItems);
|
|
472
|
+
|
|
473
|
+
SetStringError(Error, "Unhandled type in array parameter");
|
|
403
474
|
|
|
404
475
|
return false;
|
|
405
476
|
}
|
|
@@ -527,6 +598,45 @@ PyObject* GetInt8Array(const char* p)
|
|
|
527
598
|
}
|
|
528
599
|
|
|
529
600
|
|
|
601
|
+
PyObject* GetFloat8Array(const char* p)
|
|
602
|
+
{
|
|
603
|
+
// Reads an FLOAT8ARRAYOID array result and returns a list of floats.
|
|
604
|
+
|
|
605
|
+
ArrayInfo info;
|
|
606
|
+
if (!ReadArrayInfo(p, info, FLOAT8OID)) {
|
|
607
|
+
return 0;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
Object list(PyList_New(info.len));
|
|
611
|
+
if (!list)
|
|
612
|
+
return 0;
|
|
613
|
+
|
|
614
|
+
if (info.len) {
|
|
615
|
+
const char* data = info.data;
|
|
616
|
+
|
|
617
|
+
for (uint32_t i = 0; i < info.len; i++)
|
|
618
|
+
{
|
|
619
|
+
int32_t len = Read32(&data);
|
|
620
|
+
|
|
621
|
+
if (len == -1)
|
|
622
|
+
{
|
|
623
|
+
Py_INCREF(Py_None);
|
|
624
|
+
PyList_SET_ITEM(list.Get(), i, Py_None);
|
|
625
|
+
}
|
|
626
|
+
else
|
|
627
|
+
{
|
|
628
|
+
double val = ReadDouble(&data);
|
|
629
|
+
PyObject* o = PyFloat_FromDouble(val);
|
|
630
|
+
if (!o)
|
|
631
|
+
return 0;
|
|
632
|
+
|
|
633
|
+
PyList_SET_ITEM(list.Get(), i, o);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
return list.Detach();
|
|
639
|
+
}
|
|
530
640
|
|
|
531
641
|
PyObject* GetTextArray(const char* p)
|
|
532
642
|
{
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
# Run with pytest.
|
|
3
2
|
|
|
4
3
|
# pylint: disable=missing-function-docstring,redefined-outer-name,unidiomatic-typecheck
|
|
@@ -711,6 +710,15 @@ def test_array_bigint(cnxn):
|
|
|
711
710
|
assert result == value
|
|
712
711
|
|
|
713
712
|
|
|
713
|
+
def test_array_float(cnxn):
|
|
714
|
+
cnxn.execute("create table t1(id int, v float[])")
|
|
715
|
+
value = [None, -100000.0, -32768.0, -123.45, -1.0, 0.0,
|
|
716
|
+
1.0, 123.45, 32767.0, 2147483647.0, 10101010.8989]
|
|
717
|
+
cnxn.execute("insert into t1 values (1, $1)", value)
|
|
718
|
+
result = cnxn.fetchval("select v from t1")
|
|
719
|
+
assert result == value
|
|
720
|
+
|
|
721
|
+
|
|
714
722
|
def test_array_text(cnxn):
|
|
715
723
|
cnxn.execute("create table t1(id int, v text[])")
|
|
716
724
|
value = ['one', None, 'two']
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|