1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207 |
- // 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"
- "sort"
- "strconv"
- "strings"
- "github.com/go-xorm/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,
- }
- )
- type postgres struct {
- core.Base
- }
- func (db *postgres) Init(d *core.DB, uri *core.Uri, drivername, dataSourceName string) error {
- return db.Base.Init(d, db, uri, drivername, dataSourceName)
- }
- 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.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:
- res = 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
- }
- 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) QuoteStr() string {
- return "\""
- }
- 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{}) {
- args := []interface{}{tableName, idxName}
- return `SELECT indexname FROM pg_indexes ` +
- `WHERE tablename = ? AND indexname = ?`, args
- }
- func (db *postgres) TableCheckSql(tableName string) (string, []interface{}) {
- args := []interface{}{tableName}
- return `SELECT tablename FROM pg_tables WHERE tablename = ?`, args
- }
- /*func (db *postgres) ColumnCheckSql(tableName, colName string) (string, []interface{}) {
- args := []interface{}{tableName, colName}
- return "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = ?" +
- " AND column_name = ?", args
- }*/
- func (db *postgres) ModifyColumnSql(tableName string, col *core.Column) string {
- return fmt.Sprintf("alter table %s ALTER COLUMN %s TYPE %s",
- tableName, col.Name, db.SqlType(col))
- }
- func (db *postgres) DropIndexSql(tableName string, index *core.Index) string {
- //var unique string
- quote := db.Quote
- idxName := index.Name
- 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)
- }
- }
- return fmt.Sprintf("DROP INDEX %v", quote(idxName))
- }
- func (db *postgres) IsColumnExist(tableName, colName string) (bool, error) {
- 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) {
- // FIXME: the schema should be replaced by user custom's
- args := []interface{}{tableName, "public"}
- s := `SELECT column_name, column_default, is_nullable, data_type, character_maximum_length, numeric_precision, numeric_precision_radix ,
- 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 AND s.table_schema = $2 AND f.attnum > 0 ORDER BY f.attnum;`
- 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, numPrecision, numRadix *string
- var isPK, isUnique bool
- err = rows.Scan(&colName, &colDefault, &isNullable, &dataType, &maxLenStr, &numPrecision, &numRadix, &isPK, &isUnique)
- if err != nil {
- return nil, nil, err
- }
- //fmt.Println(args, colName, isNullable, dataType, maxLenStr, colDefault, numPrecision, numRadix, 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 || isPK {
- if isPK {
- col.IsPrimaryKey = true
- } else {
- col.Default = *colDefault
- }
- }
- if colDefault != nil && strings.HasPrefix(*colDefault, "nextval(") {
- col.IsAutoIncrement = 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.SQLType.IsText() || col.SQLType.IsTime() {
- if col.Default != "" {
- col.Default = "'" + col.Default + "'"
- } else {
- if col.DefaultIsEmpty {
- col.Default = "''"
- }
- }
- }
- cols[col.Name] = col
- colSeq = append(colSeq, col.Name)
- }
- return colSeq, cols, nil
- }
- func (db *postgres) GetTables() ([]*core.Table, error) {
- // FIXME: replace public to user customrize schema
- args := []interface{}{"public"}
- s := fmt.Sprintf("SELECT tablename FROM pg_tables 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 (db *postgres) GetIndexes(tableName string) (map[string]*core.Index, error) {
- // FIXME: replace the public schema to user specify schema
- args := []interface{}{"public", tableName}
- s := fmt.Sprintf("SELECT indexname, indexdef FROM pg_indexes WHERE schemaname=$1 AND tablename=$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
- }
- cs := strings.Split(indexdef, "(")
- colNames = strings.Split(cs[1][0:len(cs[1])-1], ",")
- 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 errorf(s string, args ...interface{}) {
- panic(fmt.Errorf("pq: %s", fmt.Sprintf(s, args...)))
- }
- 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)
- }
- var kvs []string
- escaper := strings.NewReplacer(` `, `\ `, `'`, `\'`, `\`, `\\`)
- accrue := func(k, v string) {
- if v != "" {
- kvs = append(kvs, k+"="+escaper.Replace(v))
- }
- }
- if u.User != nil {
- v := u.User.Username()
- accrue("user", v)
- v, _ = u.User.Password()
- accrue("password", v)
- }
- i := strings.Index(u.Host, ":")
- if i < 0 {
- accrue("host", u.Host)
- } else {
- accrue("host", u.Host[:i])
- accrue("port", u.Host[i+1:])
- }
- if u.Path != "" {
- accrue("dbname", u.Path[1:])
- }
- q := u.Query()
- for k := range q {
- accrue(k, q.Get(k))
- }
- sort.Strings(kvs) // Makes testing easier (not a performance concern)
- return strings.Join(kvs, " "), nil
- }
- func parseOpts(name string, o values) {
- if len(name) == 0 {
- return
- }
- name = strings.TrimSpace(name)
- ps := strings.Split(name, " ")
- for _, p := range ps {
- kv := strings.Split(p, "=")
- if len(kv) < 2 {
- errorf("invalid option: %q", p)
- }
- o.Set(kv[0], kv[1])
- }
- }
- func (p *pqDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) {
- db := &core.Uri{DbType: core.POSTGRES}
- o := make(values)
- var err error
- if strings.HasPrefix(dataSourceName, "postgresql://") || strings.HasPrefix(dataSourceName, "postgres://") {
- dataSourceName, err = parseURL(dataSourceName)
- if err != nil {
- return nil, err
- }
- }
- parseOpts(dataSourceName, o)
- db.DbName = o.Get("dbname")
- if db.DbName == "" {
- return nil, errors.New("dbname is empty")
- }
- /*db.Schema = o.Get("schema")
- if len(db.Schema) == 0 {
- db.Schema = "public"
- }*/
- return db, nil
- }
|