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