branch: elpa/pg
commit 496211a06ab46d80ef2c520d565ad3082ade641f
Author: Eric Marsden <[email protected]>
Commit: Eric Marsden <[email protected]>

    Recognize type alises in pg-exec-prepared
    
    Type aliases are recognized as type names in `pg-exec-prepared`, in 
additional
    to the type names present in the `pg_type` system table. This means that 
you can
    use `bigint` as an alternative to `int8`, `real` as an alternative to 
`float4`,
    `bit varying` as an alternative to `bit`, for example. The aliases are also 
the
    canonical type names as shown by function `pg_typeof`.
---
 CHANGELOG.md |   5 +++
 pg.el        | 123 +++++++++++++++++++++++++++--------------------------------
 2 files changed, 62 insertions(+), 66 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index cee27425d98..565b613e82c 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,11 @@
 
 - New function `pg-table-acl` which returns the access control list for a 
specified table.
 
+- Type aliases are recognized as type names in `pg-exec-prepared`, in 
additional to the type names
+  present in the `pg_type` system table. This means that you can use `bigint` 
as an alternative to
+  `int8`, `real` as an alternative to `float4`, `bit varying` as an 
alternative to `bit`, for
+  example. The aliases are also the canonical type names as shown by function 
`pg_typeof`.
+
 - Rename functions `pg-read-attributes`, `pg-read-tuple`, `pg-read-char`, 
`pg-unread-char`,
   `pg-read-net-int`, `pg-read-int`, `pg-read-chars`, `pg-read-string`, 
`pg-send-char`,
   `pg-send-string`, `pg-send-octets`, `pg-send-uint`, `pg-send-net-uint` to 
use the naming convention for
diff --git a/pg.el b/pg.el
index 2a9c2c81f54..60146e78f2e 100644
--- a/pg.el
+++ b/pg.el
@@ -2614,9 +2614,9 @@ PostgreSQL and Emacs. CON should no longer be used."
     (clrhash parser-by-oid)
     (clrhash typname-by-oid)
     (clrhash oid-by-typname)
-    (maphash (lambda (k _v) (push k type-names)) pg--serializers)
-    (maphash (lambda (k _v) (push k type-names)) pg--textual-serializers)
-    (maphash (lambda (k _v) (push k type-names)) pg--parser-by-typname)
+    (maphash (lambda (k _v) (cl-pushnew k type-names :test #'string=)) 
pg--serializers)
+    (maphash (lambda (k _v) (cl-pushnew k type-names :test #'string=)) 
pg--textual-serializers)
+    (maphash (lambda (k _v) (cl-pushnew k type-names :test #'string=)) 
pg--parser-by-typname)
     (let* ((qnames (mapcar (lambda (tn) (format "'%s'" tn)) type-names))
            (pg-type
             (pcase (pgcon-server-variant con)
@@ -2640,6 +2640,9 @@ PostgreSQL and Emacs. CON should no longer be used."
                      ("int8" "20")
                      ("int2" "21")
                      ("int4" "23")
+                     ("smallint" "21")
+                     ("integer" "23")
+                     ("bigint" "20")
                      ("text" "25")
                      ("oid" "26")
                      ("json" "114")
@@ -2682,7 +2685,28 @@ PostgreSQL and Emacs. CON should no longer be used."
           (puthash typname oid oid-by-typname)
           (puthash oid typname typname-by-oid)
           (when parser
-            (puthash oid parser parser-by-oid)))))))
+            (puthash oid parser parser-by-oid))))
+      ;; Add aliases for types whose canonical name is different from the 
typname in the pg_type
+      ;; table. There does not seem to be a system table that we can query to 
obtain information on
+      ;; these canonical names: they are generated by the function 
format_type_extended in
+      ;; format_type.c but apparently not present in the database in a format 
that can be queried.
+      ;; There is a documented list at 
https://www.postgresql.org/docs/current/datatype.html
+      (let ((aliases '(("smallint" . "int2")
+                       ("integer" . "int4")
+                       ("int" . "int4")
+                       ("bigint" . "int8")
+                       ("bit varying" . "bit")
+                       ("character" . "char")
+                       ("character varying" . "varchar")
+                       ("double precision" . "float8")
+                       ("float" . "float8")
+                       ("numeric" . "decimal")
+                       ("real" . "float4"))))
+        (cl-loop
+         for (alias . typname) in aliases
+         for oid = (gethash typname oid-by-typname)
+         when oid
+         do (puthash alias oid oid-by-typname))))))
 
 (defun pg-parse (con str oid)
   "Deserialize textual representation STR to an Emacs Lisp object.
@@ -2953,6 +2977,7 @@ Return nil if the extension could not be loaded."
          (string-to-number str))))
 
 (pg-register-parser "numeric" #'pg-float-parser)
+(pg-register-parser "decimal" #'pg-float-parser)
 (pg-register-parser "float" #'pg-float-parser)
 (pg-register-parser "float4" #'pg-float-parser)
 (pg-register-parser "float8" #'pg-float-parser)
@@ -3367,71 +3392,37 @@ Return nil if the extension could not be set up."
            (pg-signal-type-error "Expecting a character or a string, got %s" 
v)))))
 
 ;; see https://www.postgresql.org/docs/current/datatype-numeric.html
-(pg-register-serializer "int2"
-  (lambda (v _encoding)
-    (unless (integerp v)
-      (pg-signal-type-error "Expecting an integer, got %s" v))
-    (unless (<= (- (expt 2 15)) v (expt 2 15))
-      (pg-signal-type-error "Value %s out of range for INT2 type" v))
-    ;; This use of bindat-type makes us depend on Emacs 28.1, released in 
April 2022.
-    (bindat-pack (bindat-type sint 16 nil) v)))
-
-(pg-register-serializer "smallint"
-  (lambda (v _encoding)
-    (unless (integerp v)
-      (pg-signal-type-error "Expecting an integer, got %s" v))
-    (unless (<= (- (expt 2 15)) v (expt 2 15))
-      (pg-signal-type-error "Value %s out of range for SMALLINT type" v))
-    (bindat-pack (bindat-type sint 16 nil) v)))
-
-(pg-register-serializer "int4"
-  (lambda (v _encoding)
-    (unless (integerp v)
-      (pg-signal-type-error "Expecting an integer, got %s" v))
-    (bindat-pack (bindat-type sint 32 nil) v)))
-
-(pg-register-serializer "integer"
-  (lambda (v _encoding)
-    (unless (integerp v)
-      (pg-signal-type-error "Expecting an integer, got %s" v))
-    (bindat-pack (bindat-type sint 32 nil) v)))
-
+(defun pg--serialize-int2 (v _encoding)
+  (unless (integerp v)
+    (pg-signal-type-error "Expecting an integer, got %s" v))
+  (unless (<= (- (expt 2 15)) v (expt 2 15))
+    (pg-signal-type-error "Value %s out of range for INT2 type" v))
+  ;; This use of bindat-type makes us depend on Emacs 28.1, released in April 
2022.
+  (bindat-pack (bindat-type sint 16 nil) v))
+
+(pg-register-serializer "int2" #'pg--serialize-int2)
+(pg-register-serializer "smallint" #'pg--serialize-int2)
+(pg-register-serializer "smallserial" #'pg--serialize-int2)
+
+(defun pg--serialize-int4 (v _encoding)
+  (unless (integerp v)
+    (pg-signal-type-error "Expecting an integer, got %s" v))
+  (bindat-pack (bindat-type sint 32 nil) v))
+
+(pg-register-serializer "int4"  #'pg--serialize-int4)
+(pg-register-serializer "integer" #'pg--serialize-int4)
+(pg-register-serializer "serial" #'pg--serialize-int4)
 ;; see https://www.postgresql.org/docs/current/datatype-oid.html
-(pg-register-serializer "oid"
-  (lambda (v _encoding)
-    (unless (integerp v)
-      (pg-signal-type-error "Expecting an integer, got %s" v))
-    (bindat-pack (bindat-type uint 32 nil) v)))
+(pg-register-serializer "oid" #'pg--serialize-int4)
 
-(pg-register-serializer "int8"
-  (lambda (v _encoding)
-    (unless (integerp v)
-      (pg-signal-type-error "Expecting an integer, got %s" v))
-    (bindat-pack (bindat-type sint 64 nil) v)))
-
-(pg-register-serializer "bigint"
-  (lambda (v _encoding)
-    (unless (integerp v)
-      (pg-signal-type-error "Expecting an integer, got %s" v))
-    (bindat-pack (bindat-type sint 64 nil) v)))
-
-(pg-register-serializer "smallserial"
-  (lambda (v _encoding)
-    (unless (integerp v)
-      (pg-signal-type-error "Expecting an integer, got %s" v))
-    (bindat-pack (bindat-type uint 16 nil) v)))
-
-(pg-register-serializer "serial"
-  (lambda (v _encoding)
-    (unless (integerp v)
-      (pg-signal-type-error "Expecting an integer, got %s" v))
-    (bindat-pack (bindat-type uint 32 nil) v)))
+(defun pg--serialize-int8 (v _encoding)
+  (unless (integerp v)
+    (pg-signal-type-error "Expecting an integer, got %s" v))
+  (bindat-pack (bindat-type sint 64 nil) v))
 
-(pg-register-serializer "bigserial"
-  (lambda (v _encoding)
-    (unless (integerp v)
-      (pg-signal-type-error "Expecting an integer, got %s" v))
-    (bindat-pack (bindat-type uint 64 nil) v)))
+(pg-register-serializer "int8" #'pg--serialize-int8)
+(pg-register-serializer "bigint" #'pg--serialize-int8)
+(pg-register-serializer "bigserial" #'pg--serialize-int8)
 
 ;; We send floats in text format, because we don't know how to access the 
binary representation from
 ;; Emacs Lisp. Here a possible conversion routine and reader, but there is 
probably no performance

Reply via email to