pglib 5.9.1__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.
Files changed (51) hide show
  1. {pglib-5.9.1/pglib.egg-info → pglib-5.10.0}/PKG-INFO +1 -1
  2. {pglib-5.9.1 → pglib-5.10.0/pglib.egg-info}/PKG-INFO +1 -1
  3. {pglib-5.9.1 → pglib-5.10.0}/setup.py +1 -1
  4. {pglib-5.9.1 → pglib-5.10.0}/src/getdata.cpp +3 -0
  5. {pglib-5.9.1 → pglib-5.10.0}/src/pgarrays.cpp +111 -1
  6. {pglib-5.9.1 → pglib-5.10.0}/src/pgarrays.h +1 -0
  7. {pglib-5.9.1 → pglib-5.10.0}/src/pglib.h +1 -0
  8. {pglib-5.9.1 → pglib-5.10.0}/test/test_sync.py +9 -1
  9. {pglib-5.9.1 → pglib-5.10.0}/LICENSE +0 -0
  10. {pglib-5.9.1 → pglib-5.10.0}/MANIFEST.in +0 -0
  11. {pglib-5.9.1 → pglib-5.10.0}/README.rst +0 -0
  12. {pglib-5.9.1 → pglib-5.10.0}/pglib/__init__.py +0 -0
  13. {pglib-5.9.1 → pglib-5.10.0}/pglib/asyncpglib.py +0 -0
  14. {pglib-5.9.1 → pglib-5.10.0}/pglib.egg-info/SOURCES.txt +0 -0
  15. {pglib-5.9.1 → pglib-5.10.0}/pglib.egg-info/dependency_links.txt +0 -0
  16. {pglib-5.9.1 → pglib-5.10.0}/pglib.egg-info/top_level.txt +0 -0
  17. {pglib-5.9.1 → pglib-5.10.0}/setup.cfg +0 -0
  18. {pglib-5.9.1 → pglib-5.10.0}/src/byteswap.h +0 -0
  19. {pglib-5.9.1 → pglib-5.10.0}/src/connection.cpp +0 -0
  20. {pglib-5.9.1 → pglib-5.10.0}/src/connection.h +0 -0
  21. {pglib-5.9.1 → pglib-5.10.0}/src/conninfoopt.cpp +0 -0
  22. {pglib-5.9.1 → pglib-5.10.0}/src/conninfoopt.h +0 -0
  23. {pglib-5.9.1 → pglib-5.10.0}/src/datatypes.cpp +0 -0
  24. {pglib-5.9.1 → pglib-5.10.0}/src/datatypes.h +0 -0
  25. {pglib-5.9.1 → pglib-5.10.0}/src/debug.cpp +0 -0
  26. {pglib-5.9.1 → pglib-5.10.0}/src/debug.h +0 -0
  27. {pglib-5.9.1 → pglib-5.10.0}/src/enums.cpp +0 -0
  28. {pglib-5.9.1 → pglib-5.10.0}/src/enums.h +0 -0
  29. {pglib-5.9.1 → pglib-5.10.0}/src/errors.cpp +0 -0
  30. {pglib-5.9.1 → pglib-5.10.0}/src/errors.h +0 -0
  31. {pglib-5.9.1 → pglib-5.10.0}/src/getdata.h +0 -0
  32. {pglib-5.9.1 → pglib-5.10.0}/src/juliandate.cpp +0 -0
  33. {pglib-5.9.1 → pglib-5.10.0}/src/juliandate.h +0 -0
  34. {pglib-5.9.1 → pglib-5.10.0}/src/params.cpp +0 -0
  35. {pglib-5.9.1 → pglib-5.10.0}/src/params.h +0 -0
  36. {pglib-5.9.1 → pglib-5.10.0}/src/pglib.cpp +0 -0
  37. {pglib-5.9.1 → pglib-5.10.0}/src/pgtypes.h +0 -0
  38. {pglib-5.9.1 → pglib-5.10.0}/src/resultset.cpp +0 -0
  39. {pglib-5.9.1 → pglib-5.10.0}/src/resultset.h +0 -0
  40. {pglib-5.9.1 → pglib-5.10.0}/src/row.cpp +0 -0
  41. {pglib-5.9.1 → pglib-5.10.0}/src/row.h +0 -0
  42. {pglib-5.9.1 → pglib-5.10.0}/src/runtime.cpp +0 -0
  43. {pglib-5.9.1 → pglib-5.10.0}/src/runtime.h +0 -0
  44. {pglib-5.9.1 → pglib-5.10.0}/src/type_hstore.cpp +0 -0
  45. {pglib-5.9.1 → pglib-5.10.0}/src/type_hstore.h +0 -0
  46. {pglib-5.9.1 → pglib-5.10.0}/src/type_json.cpp +0 -0
  47. {pglib-5.9.1 → pglib-5.10.0}/src/type_json.h +0 -0
  48. {pglib-5.9.1 → pglib-5.10.0}/src/type_ltree.cpp +0 -0
  49. {pglib-5.9.1 → pglib-5.10.0}/src/type_ltree.h +0 -0
  50. {pglib-5.9.1 → pglib-5.10.0}/test/test_async.py +0 -0
  51. {pglib-5.9.1 → pglib-5.10.0}/test/testutils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pglib
3
- Version: 5.9.1
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pglib
3
- Version: 5.9.1
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
@@ -130,7 +130,7 @@ def _get_settings():
130
130
 
131
131
  setup(
132
132
  name='pglib',
133
- version='5.9.1',
133
+ version='5.10.0',
134
134
  description='A PostgreSQL interface',
135
135
  long_description=long_description,
136
136
  maintainer='Michael Kleehammer',
@@ -398,6 +398,9 @@ PyObject* ConvertValue(PGresult* result, int iRow, int iCol, bool integer_dateti
398
398
  case INT8ARRAYOID:
399
399
  return GetInt8Array(p);
400
400
 
401
+ case FLOAT8ARRAYOID:
402
+ return GetFloat8Array(p);
403
+
401
404
  case TEXTARRAYOID:
402
405
  return GetTextArray(p);
403
406
 
@@ -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
- SetStringError(Error, "Unhandled type in parameter array");
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
  {
@@ -15,5 +15,6 @@ PyObject* GetInt8Array(const char* p);
15
15
  PyObject* GetTextArray(const char* p);
16
16
  PyObject* GetDateArray(const char* p);
17
17
  PyObject* GetJSONBArray(const char* p);
18
+ PyObject* GetFloat8Array(const char* p);
18
19
 
19
20
  #endif
@@ -69,6 +69,7 @@ extern PyObject* Error;
69
69
  #define DATEARRAYOID 1182
70
70
  #define FLOAT4OID 700
71
71
  #define FLOAT8OID 701
72
+ #define FLOAT8ARRAYOID 1022
72
73
  #define INT2ARRAYOID 1005
73
74
  #define INT2OID 21
74
75
  #define INT4ARRAYOID 1007
@@ -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