summaryrefslogtreecommitdiffstats
path: root/vendor/xorm.io/xorm/dialect_postgres.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/xorm.io/xorm/dialect_postgres.go')
-rw-r--r--vendor/xorm.io/xorm/dialect_postgres.go1253
1 files changed, 1253 insertions, 0 deletions
diff --git a/vendor/xorm.io/xorm/dialect_postgres.go b/vendor/xorm.io/xorm/dialect_postgres.go
new file mode 100644
index 0000000000..ccef3086b2
--- /dev/null
+++ b/vendor/xorm.io/xorm/dialect_postgres.go
@@ -0,0 +1,1253 @@
+// Copyright 2015 The Xorm Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xorm
+
+import (
+ "errors"
+ "fmt"
+ "net/url"
+ "strconv"
+ "strings"
+
+ "xorm.io/core"
+)
+
+// from http://www.postgresql.org/docs/current/static/sql-keywords-appendix.html
+var (
+ postgresReservedWords = map[string]bool{
+ "A": true,
+ "ABORT": true,
+ "ABS": true,
+ "ABSENT": true,
+ "ABSOLUTE": true,
+ "ACCESS": true,
+ "ACCORDING": true,
+ "ACTION": true,
+ "ADA": true,
+ "ADD": true,
+ "ADMIN": true,
+ "AFTER": true,
+ "AGGREGATE": true,
+ "ALL": true,
+ "ALLOCATE": true,
+ "ALSO": true,
+ "ALTER": true,
+ "ALWAYS": true,
+ "ANALYSE": true,
+ "ANALYZE": true,
+ "AND": true,
+ "ANY": true,
+ "ARE": true,
+ "ARRAY": true,
+ "ARRAY_AGG": true,
+ "ARRAY_MAX_CARDINALITY": true,
+ "AS": true,
+ "ASC": true,
+ "ASENSITIVE": true,
+ "ASSERTION": true,
+ "ASSIGNMENT": true,
+ "ASYMMETRIC": true,
+ "AT": true,
+ "ATOMIC": true,
+ "ATTRIBUTE": true,
+ "ATTRIBUTES": true,
+ "AUTHORIZATION": true,
+ "AVG": true,
+ "BACKWARD": true,
+ "BASE64": true,
+ "BEFORE": true,
+ "BEGIN": true,
+ "BEGIN_FRAME": true,
+ "BEGIN_PARTITION": true,
+ "BERNOULLI": true,
+ "BETWEEN": true,
+ "BIGINT": true,
+ "BINARY": true,
+ "BIT": true,
+ "BIT_LENGTH": true,
+ "BLOB": true,
+ "BLOCKED": true,
+ "BOM": true,
+ "BOOLEAN": true,
+ "BOTH": true,
+ "BREADTH": true,
+ "BY": true,
+ "C": true,
+ "CACHE": true,
+ "CALL": true,
+ "CALLED": true,
+ "CARDINALITY": true,
+ "CASCADE": true,
+ "CASCADED": true,
+ "CASE": true,
+ "CAST": true,
+ "CATALOG": true,
+ "CATALOG_NAME": true,
+ "CEIL": true,
+ "CEILING": true,
+ "CHAIN": true,
+ "CHAR": true,
+ "CHARACTER": true,
+ "CHARACTERISTICS": true,
+ "CHARACTERS": true,
+ "CHARACTER_LENGTH": true,
+ "CHARACTER_SET_CATALOG": true,
+ "CHARACTER_SET_NAME": true,
+ "CHARACTER_SET_SCHEMA": true,
+ "CHAR_LENGTH": true,
+ "CHECK": true,
+ "CHECKPOINT": true,
+ "CLASS": true,
+ "CLASS_ORIGIN": true,
+ "CLOB": true,
+ "CLOSE": true,
+ "CLUSTER": true,
+ "COALESCE": true,
+ "COBOL": true,
+ "COLLATE": true,
+ "COLLATION": true,
+ "COLLATION_CATALOG": true,
+ "COLLATION_NAME": true,
+ "COLLATION_SCHEMA": true,
+ "COLLECT": true,
+ "COLUMN": true,
+ "COLUMNS": true,
+ "COLUMN_NAME": true,
+ "COMMAND_FUNCTION": true,
+ "COMMAND_FUNCTION_CODE": true,
+ "COMMENT": true,
+ "COMMENTS": true,
+ "COMMIT": true,
+ "COMMITTED": true,
+ "CONCURRENTLY": true,
+ "CONDITION": true,
+ "CONDITION_NUMBER": true,
+ "CONFIGURATION": true,
+ "CONNECT": true,
+ "CONNECTION": true,
+ "CONNECTION_NAME": true,
+ "CONSTRAINT": true,
+ "CONSTRAINTS": true,
+ "CONSTRAINT_CATALOG": true,
+ "CONSTRAINT_NAME": true,
+ "CONSTRAINT_SCHEMA": true,
+ "CONSTRUCTOR": true,
+ "CONTAINS": true,
+ "CONTENT": true,
+ "CONTINUE": true,
+ "CONTROL": true,
+ "CONVERSION": true,
+ "CONVERT": true,
+ "COPY": true,
+ "CORR": true,
+ "CORRESPONDING": true,
+ "COST": true,
+ "COUNT": true,
+ "COVAR_POP": true,
+ "COVAR_SAMP": true,
+ "CREATE": true,
+ "CROSS": true,
+ "CSV": true,
+ "CUBE": true,
+ "CUME_DIST": true,
+ "CURRENT": true,
+ "CURRENT_CATALOG": true,
+ "CURRENT_DATE": true,
+ "CURRENT_DEFAULT_TRANSFORM_GROUP": true,
+ "CURRENT_PATH": true,
+ "CURRENT_ROLE": true,
+ "CURRENT_ROW": true,
+ "CURRENT_SCHEMA": true,
+ "CURRENT_TIME": true,
+ "CURRENT_TIMESTAMP": true,
+ "CURRENT_TRANSFORM_GROUP_FOR_TYPE": true,
+ "CURRENT_USER": true,
+ "CURSOR": true,
+ "CURSOR_NAME": true,
+ "CYCLE": true,
+ "DATA": true,
+ "DATABASE": true,
+ "DATALINK": true,
+ "DATE": true,
+ "DATETIME_INTERVAL_CODE": true,
+ "DATETIME_INTERVAL_PRECISION": true,
+ "DAY": true,
+ "DB": true,
+ "DEALLOCATE": true,
+ "DEC": true,
+ "DECIMAL": true,
+ "DECLARE": true,
+ "DEFAULT": true,
+ "DEFAULTS": true,
+ "DEFERRABLE": true,
+ "DEFERRED": true,
+ "DEFINED": true,
+ "DEFINER": true,
+ "DEGREE": true,
+ "DELETE": true,
+ "DELIMITER": true,
+ "DELIMITERS": true,
+ "DENSE_RANK": true,
+ "DEPTH": true,
+ "DEREF": true,
+ "DERIVED": true,
+ "DESC": true,
+ "DESCRIBE": true,
+ "DESCRIPTOR": true,
+ "DETERMINISTIC": true,
+ "DIAGNOSTICS": true,
+ "DICTIONARY": true,
+ "DISABLE": true,
+ "DISCARD": true,
+ "DISCONNECT": true,
+ "DISPATCH": true,
+ "DISTINCT": true,
+ "DLNEWCOPY": true,
+ "DLPREVIOUSCOPY": true,
+ "DLURLCOMPLETE": true,
+ "DLURLCOMPLETEONLY": true,
+ "DLURLCOMPLETEWRITE": true,
+ "DLURLPATH": true,
+ "DLURLPATHONLY": true,
+ "DLURLPATHWRITE": true,
+ "DLURLSCHEME": true,
+ "DLURLSERVER": true,
+ "DLVALUE": true,
+ "DO": true,
+ "DOCUMENT": true,
+ "DOMAIN": true,
+ "DOUBLE": true,
+ "DROP": true,
+ "DYNAMIC": true,
+ "DYNAMIC_FUNCTION": true,
+ "DYNAMIC_FUNCTION_CODE": true,
+ "EACH": true,
+ "ELEMENT": true,
+ "ELSE": true,
+ "EMPTY": true,
+ "ENABLE": true,
+ "ENCODING": true,
+ "ENCRYPTED": true,
+ "END": true,
+ "END-EXEC": true,
+ "END_FRAME": true,
+ "END_PARTITION": true,
+ "ENFORCED": true,
+ "ENUM": true,
+ "EQUALS": true,
+ "ESCAPE": true,
+ "EVENT": true,
+ "EVERY": true,
+ "EXCEPT": true,
+ "EXCEPTION": true,
+ "EXCLUDE": true,
+ "EXCLUDING": true,
+ "EXCLUSIVE": true,
+ "EXEC": true,
+ "EXECUTE": true,
+ "EXISTS": true,
+ "EXP": true,
+ "EXPLAIN": true,
+ "EXPRESSION": true,
+ "EXTENSION": true,
+ "EXTERNAL": true,
+ "EXTRACT": true,
+ "FALSE": true,
+ "FAMILY": true,
+ "FETCH": true,
+ "FILE": true,
+ "FILTER": true,
+ "FINAL": true,
+ "FIRST": true,
+ "FIRST_VALUE": true,
+ "FLAG": true,
+ "FLOAT": true,
+ "FLOOR": true,
+ "FOLLOWING": true,
+ "FOR": true,
+ "FORCE": true,
+ "FOREIGN": true,
+ "FORTRAN": true,
+ "FORWARD": true,
+ "FOUND": true,
+ "FRAME_ROW": true,
+ "FREE": true,
+ "FREEZE": true,
+ "FROM": true,
+ "FS": true,
+ "FULL": true,
+ "FUNCTION": true,
+ "FUNCTIONS": true,
+ "FUSION": true,
+ "G": true,
+ "GENERAL": true,
+ "GENERATED": true,
+ "GET": true,
+ "GLOBAL": true,
+ "GO": true,
+ "GOTO": true,
+ "GRANT": true,
+ "GRANTED": true,
+ "GREATEST": true,
+ "GROUP": true,
+ "GROUPING": true,
+ "GROUPS": true,
+ "HANDLER": true,
+ "HAVING": true,
+ "HEADER": true,
+ "HEX": true,
+ "HIERARCHY": true,
+ "HOLD": true,
+ "HOUR": true,
+ "ID": true,
+ "IDENTITY": true,
+ "IF": true,
+ "IGNORE": true,
+ "ILIKE": true,
+ "IMMEDIATE": true,
+ "IMMEDIATELY": true,
+ "IMMUTABLE": true,
+ "IMPLEMENTATION": true,
+ "IMPLICIT": true,
+ "IMPORT": true,
+ "IN": true,
+ "INCLUDING": true,
+ "INCREMENT": true,
+ "INDENT": true,
+ "INDEX": true,
+ "INDEXES": true,
+ "INDICATOR": true,
+ "INHERIT": true,
+ "INHERITS": true,
+ "INITIALLY": true,
+ "INLINE": true,
+ "INNER": true,
+ "INOUT": true,
+ "INPUT": true,
+ "INSENSITIVE": true,
+ "INSERT": true,
+ "INSTANCE": true,
+ "INSTANTIABLE": true,
+ "INSTEAD": true,
+ "INT": true,
+ "INTEGER": true,
+ "INTEGRITY": true,
+ "INTERSECT": true,
+ "INTERSECTION": true,
+ "INTERVAL": true,
+ "INTO": true,
+ "INVOKER": true,
+ "IS": true,
+ "ISNULL": true,
+ "ISOLATION": true,
+ "JOIN": true,
+ "K": true,
+ "KEY": true,
+ "KEY_MEMBER": true,
+ "KEY_TYPE": true,
+ "LABEL": true,
+ "LAG": true,
+ "LANGUAGE": true,
+ "LARGE": true,
+ "LAST": true,
+ "LAST_VALUE": true,
+ "LATERAL": true,
+ "LC_COLLATE": true,
+ "LC_CTYPE": true,
+ "LEAD": true,
+ "LEADING": true,
+ "LEAKPROOF": true,
+ "LEAST": true,
+ "LEFT": true,
+ "LENGTH": true,
+ "LEVEL": true,
+ "LIBRARY": true,
+ "LIKE": true,
+ "LIKE_REGEX": true,
+ "LIMIT": true,
+ "LINK": true,
+ "LISTEN": true,
+ "LN": true,
+ "LOAD": true,
+ "LOCAL": true,
+ "LOCALTIME": true,
+ "LOCALTIMESTAMP": true,
+ "LOCATION": true,
+ "LOCATOR": true,
+ "LOCK": true,
+ "LOWER": true,
+ "M": true,
+ "MAP": true,
+ "MAPPING": true,
+ "MATCH": true,
+ "MATCHED": true,
+ "MATERIALIZED": true,
+ "MAX": true,
+ "MAXVALUE": true,
+ "MAX_CARDINALITY": true,
+ "MEMBER": true,
+ "MERGE": true,
+ "MESSAGE_LENGTH": true,
+ "MESSAGE_OCTET_LENGTH": true,
+ "MESSAGE_TEXT": true,
+ "METHOD": true,
+ "MIN": true,
+ "MINUTE": true,
+ "MINVALUE": true,
+ "MOD": true,
+ "MODE": true,
+ "MODIFIES": true,
+ "MODULE": true,
+ "MONTH": true,
+ "MORE": true,
+ "MOVE": true,
+ "MULTISET": true,
+ "MUMPS": true,
+ "NAME": true,
+ "NAMES": true,
+ "NAMESPACE": true,
+ "NATIONAL": true,
+ "NATURAL": true,
+ "NCHAR": true,
+ "NCLOB": true,
+ "NESTING": true,
+ "NEW": true,
+ "NEXT": true,
+ "NFC": true,
+ "NFD": true,
+ "NFKC": true,
+ "NFKD": true,
+ "NIL": true,
+ "NO": true,
+ "NONE": true,
+ "NORMALIZE": true,
+ "NORMALIZED": true,
+ "NOT": true,
+ "NOTHING": true,
+ "NOTIFY": true,
+ "NOTNULL": true,
+ "NOWAIT": true,
+ "NTH_VALUE": true,
+ "NTILE": true,
+ "NULL": true,
+ "NULLABLE": true,
+ "NULLIF": true,
+ "NULLS": true,
+ "NUMBER": true,
+ "NUMERIC": true,
+ "OBJECT": true,
+ "OCCURRENCES_REGEX": true,
+ "OCTETS": true,
+ "OCTET_LENGTH": true,
+ "OF": true,
+ "OFF": true,
+ "OFFSET": true,
+ "OIDS": true,
+ "OLD": true,
+ "ON": true,
+ "ONLY": true,
+ "OPEN": true,
+ "OPERATOR": true,
+ "OPTION": true,
+ "OPTIONS": true,
+ "OR": true,
+ "ORDER": true,
+ "ORDERING": true,
+ "ORDINALITY": true,
+ "OTHERS": true,
+ "OUT": true,
+ "OUTER": true,
+ "OUTPUT": true,
+ "OVER": true,
+ "OVERLAPS": true,
+ "OVERLAY": true,
+ "OVERRIDING": true,
+ "OWNED": true,
+ "OWNER": true,
+ "P": true,
+ "PAD": true,
+ "PARAMETER": true,
+ "PARAMETER_MODE": true,
+ "PARAMETER_NAME": true,
+ "PARAMETER_ORDINAL_POSITION": true,
+ "PARAMETER_SPECIFIC_CATALOG": true,
+ "PARAMETER_SPECIFIC_NAME": true,
+ "PARAMETER_SPECIFIC_SCHEMA": true,
+ "PARSER": true,
+ "PARTIAL": true,
+ "PARTITION": true,
+ "PASCAL": true,
+ "PASSING": true,
+ "PASSTHROUGH": true,
+ "PASSWORD": true,
+ "PATH": true,
+ "PERCENT": true,
+ "PERCENTILE_CONT": true,
+ "PERCENTILE_DISC": true,
+ "PERCENT_RANK": true,
+ "PERIOD": true,
+ "PERMISSION": true,
+ "PLACING": true,
+ "PLANS": true,
+ "PLI": true,
+ "PORTION": true,
+ "POSITION": true,
+ "POSITION_REGEX": true,
+ "POWER": true,
+ "PRECEDES": true,
+ "PRECEDING": true,
+ "PRECISION": true,
+ "PREPARE": true,
+ "PREPARED": true,
+ "PRESERVE": true,
+ "PRIMARY": true,
+ "PRIOR": true,
+ "PRIVILEGES": true,
+ "PROCEDURAL": true,
+ "PROCEDURE": true,
+ "PROGRAM": true,
+ "PUBLIC": true,
+ "QUOTE": true,
+ "RANGE": true,
+ "RANK": true,
+ "READ": true,
+ "READS": true,
+ "REAL": true,
+ "REASSIGN": true,
+ "RECHECK": true,
+ "RECOVERY": true,
+ "RECURSIVE": true,
+ "REF": true,
+ "REFERENCES": true,
+ "REFERENCING": true,
+ "REFRESH": true,
+ "REGR_AVGX": true,
+ "REGR_AVGY": true,
+ "REGR_COUNT": true,
+ "REGR_INTERCEPT": true,
+ "REGR_R2": true,
+ "REGR_SLOPE": true,
+ "REGR_SXX": true,
+ "REGR_SXY": true,
+ "REGR_SYY": true,
+ "REINDEX": true,
+ "RELATIVE": true,
+ "RELEASE": true,
+ "RENAME": true,
+ "REPEATABLE": true,
+ "REPLACE": true,
+ "REPLICA": true,
+ "REQUIRING": true,
+ "RESET": true,
+ "RESPECT": true,
+ "RESTART": true,
+ "RESTORE": true,
+ "RESTRICT": true,
+ "RESULT": true,
+ "RETURN": true,
+ "RETURNED_CARDINALITY": true,
+ "RETURNED_LENGTH": true,
+ "RETURNED_OCTET_LENGTH": true,
+ "RETURNED_SQLSTATE": true,
+ "RETURNING": true,
+ "RETURNS": true,
+ "REVOKE": true,
+ "RIGHT": true,
+ "ROLE": true,
+ "ROLLBACK": true,
+ "ROLLUP": true,
+ "ROUTINE": true,
+ "ROUTINE_CATALOG": true,
+ "ROUTINE_NAME": true,
+ "ROUTINE_SCHEMA": true,
+ "ROW": true,
+ "ROWS": true,
+ "ROW_COUNT": true,
+ "ROW_NUMBER": true,
+ "RULE": true,
+ "SAVEPOINT": true,
+ "SCALE": true,
+ "SCHEMA": true,
+ "SCHEMA_NAME": true,
+ "SCOPE": true,
+ "SCOPE_CATALOG": true,
+ "SCOPE_NAME": true,
+ "SCOPE_SCHEMA": true,
+ "SCROLL": true,
+ "SEARCH": true,
+ "SECOND": true,
+ "SECTION": true,
+ "SECURITY": true,
+ "SELECT": true,
+ "SELECTIVE": true,
+ "SELF": true,
+ "SENSITIVE": true,
+ "SEQUENCE": true,
+ "SEQUENCES": true,
+ "SERIALIZABLE": true,
+ "SERVER": true,
+ "SERVER_NAME": true,
+ "SESSION": true,
+ "SESSION_USER": true,
+ "SET": true,
+ "SETOF": true,
+ "SETS": true,
+ "SHARE": true,
+ "SHOW": true,
+ "SIMILAR": true,
+ "SIMPLE": true,
+ "SIZE": true,
+ "SMALLINT": true,
+ "SNAPSHOT": true,
+ "SOME": true,
+ "SOURCE": true,
+ "SPACE": true,
+ "SPECIFIC": true,
+ "SPECIFICTYPE": true,
+ "SPECIFIC_NAME": true,
+ "SQL": true,
+ "SQLCODE": true,
+ "SQLERROR": true,
+ "SQLEXCEPTION": true,
+ "SQLSTATE": true,
+ "SQLWARNING": true,
+ "SQRT": true,
+ "STABLE": true,
+ "STANDALONE": true,
+ "START": true,
+ "STATE": true,
+ "STATEMENT": true,
+ "STATIC": true,
+ "STATISTICS": true,
+ "STDDEV_POP": true,
+ "STDDEV_SAMP": true,
+ "STDIN": true,
+ "STDOUT": true,
+ "STORAGE": true,
+ "STRICT": true,
+ "STRIP": true,
+ "STRUCTURE": true,
+ "STYLE": true,
+ "SUBCLASS_ORIGIN": true,
+ "SUBMULTISET": true,
+ "SUBSTRING": true,
+ "SUBSTRING_REGEX": true,
+ "SUCCEEDS": true,
+ "SUM": true,
+ "SYMMETRIC": true,
+ "SYSID": true,
+ "SYSTEM": true,
+ "SYSTEM_TIME": true,
+ "SYSTEM_USER": true,
+ "T": true,
+ "TABLE": true,
+ "TABLES": true,
+ "TABLESAMPLE": true,
+ "TABLESPACE": true,
+ "TABLE_NAME": true,
+ "TEMP": true,
+ "TEMPLATE": true,
+ "TEMPORARY": true,
+ "TEXT": true,
+ "THEN": true,
+ "TIES": true,
+ "TIME": true,
+ "TIMESTAMP": true,
+ "TIMEZONE_HOUR": true,
+ "TIMEZONE_MINUTE": true,
+ "TO": true,
+ "TOKEN": true,
+ "TOP_LEVEL_COUNT": true,
+ "TRAILING": true,
+ "TRANSACTION": true,
+ "TRANSACTIONS_COMMITTED": true,
+ "TRANSACTIONS_ROLLED_BACK": true,
+ "TRANSACTION_ACTIVE": true,
+ "TRANSFORM": true,
+ "TRANSFORMS": true,
+ "TRANSLATE": true,
+ "TRANSLATE_REGEX": true,
+ "TRANSLATION": true,
+ "TREAT": true,
+ "TRIGGER": true,
+ "TRIGGER_CATALOG": true,
+ "TRIGGER_NAME": true,
+ "TRIGGER_SCHEMA": true,
+ "TRIM": true,
+ "TRIM_ARRAY": true,
+ "TRUE": true,
+ "TRUNCATE": true,
+ "TRUSTED": true,
+ "TYPE": true,
+ "TYPES": true,
+ "UESCAPE": true,
+ "UNBOUNDED": true,
+ "UNCOMMITTED": true,
+ "UNDER": true,
+ "UNENCRYPTED": true,
+ "UNION": true,
+ "UNIQUE": true,
+ "UNKNOWN": true,
+ "UNLINK": true,
+ "UNLISTEN": true,
+ "UNLOGGED": true,
+ "UNNAMED": true,
+ "UNNEST": true,
+ "UNTIL": true,
+ "UNTYPED": true,
+ "UPDATE": true,
+ "UPPER": true,
+ "URI": true,
+ "USAGE": true,
+ "USER": true,
+ "USER_DEFINED_TYPE_CATALOG": true,
+ "USER_DEFINED_TYPE_CODE": true,
+ "USER_DEFINED_TYPE_NAME": true,
+ "USER_DEFINED_TYPE_SCHEMA": true,
+ "USING": true,
+ "VACUUM": true,
+ "VALID": true,
+ "VALIDATE": true,
+ "VALIDATOR": true,
+ "VALUE": true,
+ "VALUES": true,
+ "VALUE_OF": true,
+ "VARBINARY": true,
+ "VARCHAR": true,
+ "VARIADIC": true,
+ "VARYING": true,
+ "VAR_POP": true,
+ "VAR_SAMP": true,
+ "VERBOSE": true,
+ "VERSION": true,
+ "VERSIONING": true,
+ "VIEW": true,
+ "VOLATILE": true,
+ "WHEN": true,
+ "WHENEVER": true,
+ "WHERE": true,
+ "WHITESPACE": true,
+ "WIDTH_BUCKET": true,
+ "WINDOW": true,
+ "WITH": true,
+ "WITHIN": true,
+ "WITHOUT": true,
+ "WORK": true,
+ "WRAPPER": true,
+ "WRITE": true,
+ "XML": true,
+ "XMLAGG": true,
+ "XMLATTRIBUTES": true,
+ "XMLBINARY": true,
+ "XMLCAST": true,
+ "XMLCOMMENT": true,
+ "XMLCONCAT": true,
+ "XMLDECLARATION": true,
+ "XMLDOCUMENT": true,
+ "XMLELEMENT": true,
+ "XMLEXISTS": true,
+ "XMLFOREST": true,
+ "XMLITERATE": true,
+ "XMLNAMESPACES": true,
+ "XMLPARSE": true,
+ "XMLPI": true,
+ "XMLQUERY": true,
+ "XMLROOT": true,
+ "XMLSCHEMA": true,
+ "XMLSERIALIZE": true,
+ "XMLTABLE": true,
+ "XMLTEXT": true,
+ "XMLVALIDATE": true,
+ "YEAR": true,
+ "YES": true,
+ "ZONE": true,
+ }
+
+ // DefaultPostgresSchema default postgres schema
+ DefaultPostgresSchema = "public"
+)
+
+const postgresPublicSchema = "public"
+
+type postgres struct {
+ core.Base
+}
+
+func (db *postgres) Init(d *core.DB, uri *core.Uri, drivername, dataSourceName string) error {
+ err := db.Base.Init(d, db, uri, drivername, dataSourceName)
+ if err != nil {
+ return err
+ }
+ if db.Schema == "" {
+ db.Schema = DefaultPostgresSchema
+ }
+ return nil
+}
+
+func (db *postgres) SqlType(c *core.Column) string {
+ var res string
+ switch t := c.SQLType.Name; t {
+ case core.TinyInt:
+ res = core.SmallInt
+ return res
+ case core.Bit:
+ res = core.Boolean
+ return res
+ case core.MediumInt, core.Int, core.Integer:
+ if c.IsAutoIncrement {
+ return core.Serial
+ }
+ return core.Integer
+ case core.BigInt:
+ if c.IsAutoIncrement {
+ return core.BigSerial
+ }
+ return core.BigInt
+ case core.Serial, core.BigSerial:
+ c.IsAutoIncrement = true
+ c.Nullable = false
+ res = t
+ case core.Binary, core.VarBinary:
+ return core.Bytea
+ case core.DateTime:
+ res = core.TimeStamp
+ case core.TimeStampz:
+ return "timestamp with time zone"
+ case core.Float:
+ res = core.Real
+ case core.TinyText, core.MediumText, core.LongText:
+ res = core.Text
+ case core.NVarchar:
+ res = core.Varchar
+ case core.Uuid:
+ return core.Uuid
+ case core.Blob, core.TinyBlob, core.MediumBlob, core.LongBlob:
+ return core.Bytea
+ case core.Double:
+ return "DOUBLE PRECISION"
+ default:
+ if c.IsAutoIncrement {
+ return core.Serial
+ }
+ res = t
+ }
+
+ if strings.EqualFold(res, "bool") {
+ // for bool, we don't need length information
+ return res
+ }
+ hasLen1 := (c.Length > 0)
+ hasLen2 := (c.Length2 > 0)
+
+ if hasLen2 {
+ res += "(" + strconv.Itoa(c.Length) + "," + strconv.Itoa(c.Length2) + ")"
+ } else if hasLen1 {
+ res += "(" + strconv.Itoa(c.Length) + ")"
+ }
+ return res
+}
+
+func (db *postgres) SupportInsertMany() bool {
+ return true
+}
+
+func (db *postgres) IsReserved(name string) bool {
+ _, ok := postgresReservedWords[name]
+ return ok
+}
+
+func (db *postgres) Quote(name string) string {
+ name = strings.Replace(name, ".", `"."`, -1)
+ return "\"" + name + "\""
+}
+
+func (db *postgres) AutoIncrStr() string {
+ return ""
+}
+
+func (db *postgres) SupportEngine() bool {
+ return false
+}
+
+func (db *postgres) SupportCharset() bool {
+ return false
+}
+
+func (db *postgres) IndexOnTable() bool {
+ return false
+}
+
+func (db *postgres) IndexCheckSql(tableName, idxName string) (string, []interface{}) {
+ if len(db.Schema) == 0 {
+ args := []interface{}{tableName, idxName}
+ return `SELECT indexname FROM pg_indexes WHERE tablename = ? AND indexname = ?`, args
+ }
+
+ args := []interface{}{db.Schema, tableName, idxName}
+ return `SELECT indexname FROM pg_indexes ` +
+ `WHERE schemaname = ? AND tablename = ? AND indexname = ?`, args
+}
+
+func (db *postgres) TableCheckSql(tableName string) (string, []interface{}) {
+ if len(db.Schema) == 0 {
+ args := []interface{}{tableName}
+ return `SELECT tablename FROM pg_tables WHERE tablename = ?`, args
+ }
+
+ args := []interface{}{db.Schema, tableName}
+ return `SELECT tablename FROM pg_tables WHERE schemaname = ? AND tablename = ?`, args
+}
+
+func (db *postgres) ModifyColumnSql(tableName string, col *core.Column) string {
+ if len(db.Schema) == 0 {
+ return fmt.Sprintf("alter table %s ALTER COLUMN %s TYPE %s",
+ tableName, col.Name, db.SqlType(col))
+ }
+ return fmt.Sprintf("alter table %s.%s ALTER COLUMN %s TYPE %s",
+ db.Schema, tableName, col.Name, db.SqlType(col))
+}
+
+func (db *postgres) DropIndexSql(tableName string, index *core.Index) string {
+ quote := db.Quote
+ idxName := index.Name
+
+ tableName = strings.Replace(tableName, `"`, "", -1)
+ tableName = strings.Replace(tableName, `.`, "_", -1)
+
+ if !strings.HasPrefix(idxName, "UQE_") &&
+ !strings.HasPrefix(idxName, "IDX_") {
+ if index.Type == core.UniqueType {
+ idxName = fmt.Sprintf("UQE_%v_%v", tableName, index.Name)
+ } else {
+ idxName = fmt.Sprintf("IDX_%v_%v", tableName, index.Name)
+ }
+ }
+ if db.Uri.Schema != "" {
+ idxName = db.Uri.Schema + "." + idxName
+ }
+ return fmt.Sprintf("DROP INDEX %v", quote(idxName))
+}
+
+func (db *postgres) IsColumnExist(tableName, colName string) (bool, error) {
+ args := []interface{}{db.Schema, tableName, colName}
+ query := "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = $1 AND table_name = $2" +
+ " AND column_name = $3"
+ if len(db.Schema) == 0 {
+ args = []interface{}{tableName, colName}
+ query = "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = $1" +
+ " AND column_name = $2"
+ }
+ db.LogSQL(query, args)
+
+ rows, err := db.DB().Query(query, args...)
+ if err != nil {
+ return false, err
+ }
+ defer rows.Close()
+
+ return rows.Next(), nil
+}
+
+func (db *postgres) GetColumns(tableName string) ([]string, map[string]*core.Column, error) {
+ args := []interface{}{tableName}
+ s := `SELECT column_name, column_default, is_nullable, data_type, character_maximum_length,
+ CASE WHEN p.contype = 'p' THEN true ELSE false END AS primarykey,
+ CASE WHEN p.contype = 'u' THEN true ELSE false END AS uniquekey
+FROM pg_attribute f
+ JOIN pg_class c ON c.oid = f.attrelid JOIN pg_type t ON t.oid = f.atttypid
+ LEFT JOIN pg_attrdef d ON d.adrelid = c.oid AND d.adnum = f.attnum
+ LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
+ LEFT JOIN pg_constraint p ON p.conrelid = c.oid AND f.attnum = ANY (p.conkey)
+ LEFT JOIN pg_class AS g ON p.confrelid = g.oid
+ LEFT JOIN INFORMATION_SCHEMA.COLUMNS s ON s.column_name=f.attname AND c.relname=s.table_name
+WHERE c.relkind = 'r'::char AND c.relname = $1%s AND f.attnum > 0 ORDER BY f.attnum;`
+
+ var f string
+ if len(db.Schema) != 0 {
+ args = append(args, db.Schema)
+ f = " AND s.table_schema = $2"
+ }
+ s = fmt.Sprintf(s, f)
+
+ db.LogSQL(s, args)
+
+ rows, err := db.DB().Query(s, args...)
+ if err != nil {
+ return nil, nil, err
+ }
+ defer rows.Close()
+
+ cols := make(map[string]*core.Column)
+ colSeq := make([]string, 0)
+
+ for rows.Next() {
+ col := new(core.Column)
+ col.Indexes = make(map[string]int)
+
+ var colName, isNullable, dataType string
+ var maxLenStr, colDefault *string
+ var isPK, isUnique bool
+ err = rows.Scan(&colName, &colDefault, &isNullable, &dataType, &maxLenStr, &isPK, &isUnique)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // fmt.Println(args, colName, isNullable, dataType, maxLenStr, colDefault, isPK, isUnique)
+ var maxLen int
+ if maxLenStr != nil {
+ maxLen, err = strconv.Atoi(*maxLenStr)
+ if err != nil {
+ return nil, nil, err
+ }
+ }
+
+ col.Name = strings.Trim(colName, `" `)
+
+ if colDefault != nil {
+ col.Default = *colDefault
+ col.DefaultIsEmpty = false
+ if strings.HasPrefix(col.Default, "nextval(") {
+ col.IsAutoIncrement = true
+ }
+ } else {
+ col.DefaultIsEmpty = true
+ }
+
+ if isPK {
+ col.IsPrimaryKey = true
+ }
+
+ col.Nullable = (isNullable == "YES")
+
+ switch dataType {
+ case "character varying", "character":
+ col.SQLType = core.SQLType{Name: core.Varchar, DefaultLength: 0, DefaultLength2: 0}
+ case "timestamp without time zone":
+ col.SQLType = core.SQLType{Name: core.DateTime, DefaultLength: 0, DefaultLength2: 0}
+ case "timestamp with time zone":
+ col.SQLType = core.SQLType{Name: core.TimeStampz, DefaultLength: 0, DefaultLength2: 0}
+ case "double precision":
+ col.SQLType = core.SQLType{Name: core.Double, DefaultLength: 0, DefaultLength2: 0}
+ case "boolean":
+ col.SQLType = core.SQLType{Name: core.Bool, DefaultLength: 0, DefaultLength2: 0}
+ case "time without time zone":
+ col.SQLType = core.SQLType{Name: core.Time, DefaultLength: 0, DefaultLength2: 0}
+ case "oid":
+ col.SQLType = core.SQLType{Name: core.BigInt, DefaultLength: 0, DefaultLength2: 0}
+ default:
+ col.SQLType = core.SQLType{Name: strings.ToUpper(dataType), DefaultLength: 0, DefaultLength2: 0}
+ }
+ if _, ok := core.SqlTypes[col.SQLType.Name]; !ok {
+ return nil, nil, fmt.Errorf("Unknown colType: %v", dataType)
+ }
+
+ col.Length = maxLen
+
+ if !col.DefaultIsEmpty {
+ if col.SQLType.IsText() {
+ if strings.HasSuffix(col.Default, "::character varying") {
+ col.Default = strings.TrimRight(col.Default, "::character varying")
+ } else if !strings.HasPrefix(col.Default, "'") {
+ col.Default = "'" + col.Default + "'"
+ }
+ } else if col.SQLType.IsTime() {
+ if strings.HasSuffix(col.Default, "::timestamp without time zone") {
+ col.Default = strings.TrimRight(col.Default, "::timestamp without time zone")
+ }
+ }
+ }
+ cols[col.Name] = col
+ colSeq = append(colSeq, col.Name)
+ }
+
+ return colSeq, cols, nil
+}
+
+func (db *postgres) GetTables() ([]*core.Table, error) {
+ args := []interface{}{}
+ s := "SELECT tablename FROM pg_tables"
+ if len(db.Schema) != 0 {
+ args = append(args, db.Schema)
+ s = s + " WHERE schemaname = $1"
+ }
+
+ db.LogSQL(s, args)
+
+ rows, err := db.DB().Query(s, args...)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+
+ tables := make([]*core.Table, 0)
+ for rows.Next() {
+ table := core.NewEmptyTable()
+ var name string
+ err = rows.Scan(&name)
+ if err != nil {
+ return nil, err
+ }
+ table.Name = name
+ tables = append(tables, table)
+ }
+ return tables, nil
+}
+
+func getIndexColName(indexdef string) []string {
+ var colNames []string
+
+ cs := strings.Split(indexdef, "(")
+ for _, v := range strings.Split(strings.Split(cs[1], ")")[0], ",") {
+ colNames = append(colNames, strings.Split(strings.TrimLeft(v, " "), " ")[0])
+ }
+
+ return colNames
+}
+
+func (db *postgres) GetIndexes(tableName string) (map[string]*core.Index, error) {
+ args := []interface{}{tableName}
+ s := fmt.Sprintf("SELECT indexname, indexdef FROM pg_indexes WHERE tablename=$1")
+ if len(db.Schema) != 0 {
+ args = append(args, db.Schema)
+ s = s + " AND schemaname=$2"
+ }
+ db.LogSQL(s, args)
+
+ rows, err := db.DB().Query(s, args...)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+
+ indexes := make(map[string]*core.Index, 0)
+ for rows.Next() {
+ var indexType int
+ var indexName, indexdef string
+ var colNames []string
+ err = rows.Scan(&indexName, &indexdef)
+ if err != nil {
+ return nil, err
+ }
+ indexName = strings.Trim(indexName, `" `)
+ if strings.HasSuffix(indexName, "_pkey") {
+ continue
+ }
+ if strings.HasPrefix(indexdef, "CREATE UNIQUE INDEX") {
+ indexType = core.UniqueType
+ } else {
+ indexType = core.IndexType
+ }
+ colNames = getIndexColName(indexdef)
+ var isRegular bool
+ if strings.HasPrefix(indexName, "IDX_"+tableName) || strings.HasPrefix(indexName, "UQE_"+tableName) {
+ newIdxName := indexName[5+len(tableName):]
+ isRegular = true
+ if newIdxName != "" {
+ indexName = newIdxName
+ }
+ }
+
+ index := &core.Index{Name: indexName, Type: indexType, Cols: make([]string, 0)}
+ for _, colName := range colNames {
+ index.Cols = append(index.Cols, strings.Trim(colName, `" `))
+ }
+ index.IsRegular = isRegular
+ indexes[index.Name] = index
+ }
+ return indexes, nil
+}
+
+func (db *postgres) Filters() []core.Filter {
+ return []core.Filter{&core.IdFilter{}, &core.QuoteFilter{}, &core.SeqFilter{Prefix: "$", Start: 1}}
+}
+
+type pqDriver struct {
+}
+
+type values map[string]string
+
+func (vs values) Set(k, v string) {
+ vs[k] = v
+}
+
+func (vs values) Get(k string) (v string) {
+ return vs[k]
+}
+
+func parseURL(connstr string) (string, error) {
+ u, err := url.Parse(connstr)
+ if err != nil {
+ return "", err
+ }
+
+ if u.Scheme != "postgresql" && u.Scheme != "postgres" {
+ return "", fmt.Errorf("invalid connection protocol: %s", u.Scheme)
+ }
+
+ escaper := strings.NewReplacer(` `, `\ `, `'`, `\'`, `\`, `\\`)
+
+ if u.Path != "" {
+ return escaper.Replace(u.Path[1:]), nil
+ }
+
+ return "", nil
+}
+
+func parseOpts(name string, o values) error {
+ if len(name) == 0 {
+ return fmt.Errorf("invalid options: %s", name)
+ }
+
+ name = strings.TrimSpace(name)
+
+ ps := strings.Split(name, " ")
+ for _, p := range ps {
+ kv := strings.Split(p, "=")
+ if len(kv) < 2 {
+ return fmt.Errorf("invalid option: %q", p)
+ }
+ o.Set(kv[0], kv[1])
+ }
+
+ return nil
+}
+
+func (p *pqDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) {
+ db := &core.Uri{DbType: core.POSTGRES}
+ var err error
+
+ if strings.HasPrefix(dataSourceName, "postgresql://") || strings.HasPrefix(dataSourceName, "postgres://") {
+ db.DbName, err = parseURL(dataSourceName)
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ o := make(values)
+ err = parseOpts(dataSourceName, o)
+ if err != nil {
+ return nil, err
+ }
+
+ db.DbName = o.Get("dbname")
+ }
+
+ if db.DbName == "" {
+ return nil, errors.New("dbname is empty")
+ }
+
+ return db, nil
+}
+
+type pqDriverPgx struct {
+ pqDriver
+}
+
+func (pgx *pqDriverPgx) Parse(driverName, dataSourceName string) (*core.Uri, error) {
+ // Remove the leading characters for driver to work
+ if len(dataSourceName) >= 9 && dataSourceName[0] == 0 {
+ dataSourceName = dataSourceName[9:]
+ }
+ return pgx.pqDriver.Parse(driverName, dataSourceName)
+}