UNPKG

29.9 kBJavaScriptView Raw
1/*
2Language: PostgreSQL and PL/pgSQL
3Author: Egor Rogov (e.rogov@postgrespro.ru)
4Website: https://www.postgresql.org/docs/11/sql.html
5Description:
6 This language incorporates both PostgreSQL SQL dialect and PL/pgSQL language.
7 It is based on PostgreSQL version 11. Some notes:
8 - Text in double-dollar-strings is _always_ interpreted as some programming code. Text
9 in ordinary quotes is _never_ interpreted that way and highlighted just as a string.
10 - There are quite a bit "special cases". That's because many keywords are not strictly
11 they are keywords in some contexts and ordinary identifiers in others. Only some
12 of such cases are handled; you still can get some of your identifiers highlighted
13 wrong way.
14 - Function names deliberately are not highlighted. There is no way to tell function
15 call from other constructs, hence we can't highlight _all_ function names. And
16 some names highlighted while others not looks ugly.
17*/
18
19function pgsql(hljs) {
20 const COMMENT_MODE = hljs.COMMENT('--', '$');
21 const UNQUOTED_IDENT = '[a-zA-Z_][a-zA-Z_0-9$]*';
22 const DOLLAR_STRING = '\\$([a-zA-Z_]?|[a-zA-Z_][a-zA-Z_0-9]*)\\$';
23 const LABEL = '<<\\s*' + UNQUOTED_IDENT + '\\s*>>';
24
25 const SQL_KW =
26 // https://www.postgresql.org/docs/11/static/sql-keywords-appendix.html
27 // https://www.postgresql.org/docs/11/static/sql-commands.html
28 // SQL commands (starting words)
29 'ABORT ALTER ANALYZE BEGIN CALL CHECKPOINT|10 CLOSE CLUSTER COMMENT COMMIT COPY CREATE DEALLOCATE DECLARE ' +
30 'DELETE DISCARD DO DROP END EXECUTE EXPLAIN FETCH GRANT IMPORT INSERT LISTEN LOAD LOCK MOVE NOTIFY ' +
31 'PREPARE REASSIGN|10 REFRESH REINDEX RELEASE RESET REVOKE ROLLBACK SAVEPOINT SECURITY SELECT SET SHOW ' +
32 'START TRUNCATE UNLISTEN|10 UPDATE VACUUM|10 VALUES ' +
33 // SQL commands (others)
34 'AGGREGATE COLLATION CONVERSION|10 DATABASE DEFAULT PRIVILEGES DOMAIN TRIGGER EXTENSION FOREIGN ' +
35 'WRAPPER|10 TABLE FUNCTION GROUP LANGUAGE LARGE OBJECT MATERIALIZED VIEW OPERATOR CLASS ' +
36 'FAMILY POLICY PUBLICATION|10 ROLE RULE SCHEMA SEQUENCE SERVER STATISTICS SUBSCRIPTION SYSTEM ' +
37 'TABLESPACE CONFIGURATION DICTIONARY PARSER TEMPLATE TYPE USER MAPPING PREPARED ACCESS ' +
38 'METHOD CAST AS TRANSFORM TRANSACTION OWNED TO INTO SESSION AUTHORIZATION ' +
39 'INDEX PROCEDURE ASSERTION ' +
40 // additional reserved key words
41 'ALL ANALYSE AND ANY ARRAY ASC ASYMMETRIC|10 BOTH CASE CHECK ' +
42 'COLLATE COLUMN CONCURRENTLY|10 CONSTRAINT CROSS ' +
43 'DEFERRABLE RANGE ' +
44 'DESC DISTINCT ELSE EXCEPT FOR FREEZE|10 FROM FULL HAVING ' +
45 'ILIKE IN INITIALLY INNER INTERSECT IS ISNULL JOIN LATERAL LEADING LIKE LIMIT ' +
46 'NATURAL NOT NOTNULL NULL OFFSET ON ONLY OR ORDER OUTER OVERLAPS PLACING PRIMARY ' +
47 'REFERENCES RETURNING SIMILAR SOME SYMMETRIC TABLESAMPLE THEN ' +
48 'TRAILING UNION UNIQUE USING VARIADIC|10 VERBOSE WHEN WHERE WINDOW WITH ' +
49 // some of non-reserved (which are used in clauses or as PL/pgSQL keyword)
50 'BY RETURNS INOUT OUT SETOF|10 IF STRICT CURRENT CONTINUE OWNER LOCATION OVER PARTITION WITHIN ' +
51 'BETWEEN ESCAPE EXTERNAL INVOKER DEFINER WORK RENAME VERSION CONNECTION CONNECT ' +
52 'TABLES TEMP TEMPORARY FUNCTIONS SEQUENCES TYPES SCHEMAS OPTION CASCADE RESTRICT ADD ADMIN ' +
53 'EXISTS VALID VALIDATE ENABLE DISABLE REPLICA|10 ALWAYS PASSING COLUMNS PATH ' +
54 'REF VALUE OVERRIDING IMMUTABLE STABLE VOLATILE BEFORE AFTER EACH ROW PROCEDURAL ' +
55 'ROUTINE NO HANDLER VALIDATOR OPTIONS STORAGE OIDS|10 WITHOUT INHERIT DEPENDS CALLED ' +
56 'INPUT LEAKPROOF|10 COST ROWS NOWAIT SEARCH UNTIL ENCRYPTED|10 PASSWORD CONFLICT|10 ' +
57 'INSTEAD INHERITS CHARACTERISTICS WRITE CURSOR ALSO STATEMENT SHARE EXCLUSIVE INLINE ' +
58 'ISOLATION REPEATABLE READ COMMITTED SERIALIZABLE UNCOMMITTED LOCAL GLOBAL SQL PROCEDURES ' +
59 'RECURSIVE SNAPSHOT ROLLUP CUBE TRUSTED|10 INCLUDE FOLLOWING PRECEDING UNBOUNDED RANGE GROUPS ' +
60 'UNENCRYPTED|10 SYSID FORMAT DELIMITER HEADER QUOTE ENCODING FILTER OFF ' +
61 // some parameters of VACUUM/ANALYZE/EXPLAIN
62 'FORCE_QUOTE FORCE_NOT_NULL FORCE_NULL COSTS BUFFERS TIMING SUMMARY DISABLE_PAGE_SKIPPING ' +
63 //
64 'RESTART CYCLE GENERATED IDENTITY DEFERRED IMMEDIATE LEVEL LOGGED UNLOGGED ' +
65 'OF NOTHING NONE EXCLUDE ATTRIBUTE ' +
66 // from GRANT (not keywords actually)
67 'USAGE ROUTINES ' +
68 // actually literals, but look better this way (due to IS TRUE, IS FALSE, ISNULL etc)
69 'TRUE FALSE NAN INFINITY ';
70
71 const ROLE_ATTRS = // only those not in keywrods already
72 'SUPERUSER NOSUPERUSER CREATEDB NOCREATEDB CREATEROLE NOCREATEROLE INHERIT NOINHERIT ' +
73 'LOGIN NOLOGIN REPLICATION NOREPLICATION BYPASSRLS NOBYPASSRLS ';
74
75 const PLPGSQL_KW =
76 'ALIAS BEGIN CONSTANT DECLARE END EXCEPTION RETURN PERFORM|10 RAISE GET DIAGNOSTICS ' +
77 'STACKED|10 FOREACH LOOP ELSIF EXIT WHILE REVERSE SLICE DEBUG LOG INFO NOTICE WARNING ASSERT ' +
78 'OPEN ';
79
80 const TYPES =
81 // https://www.postgresql.org/docs/11/static/datatype.html
82 'BIGINT INT8 BIGSERIAL SERIAL8 BIT VARYING VARBIT BOOLEAN BOOL BOX BYTEA CHARACTER CHAR VARCHAR ' +
83 'CIDR CIRCLE DATE DOUBLE PRECISION FLOAT8 FLOAT INET INTEGER INT INT4 INTERVAL JSON JSONB LINE LSEG|10 ' +
84 'MACADDR MACADDR8 MONEY NUMERIC DEC DECIMAL PATH POINT POLYGON REAL FLOAT4 SMALLINT INT2 ' +
85 'SMALLSERIAL|10 SERIAL2|10 SERIAL|10 SERIAL4|10 TEXT TIME ZONE TIMETZ|10 TIMESTAMP TIMESTAMPTZ|10 TSQUERY|10 TSVECTOR|10 ' +
86 'TXID_SNAPSHOT|10 UUID XML NATIONAL NCHAR ' +
87 'INT4RANGE|10 INT8RANGE|10 NUMRANGE|10 TSRANGE|10 TSTZRANGE|10 DATERANGE|10 ' +
88 // pseudotypes
89 'ANYELEMENT ANYARRAY ANYNONARRAY ANYENUM ANYRANGE CSTRING INTERNAL ' +
90 'RECORD PG_DDL_COMMAND VOID UNKNOWN OPAQUE REFCURSOR ' +
91 // spec. type
92 'NAME ' +
93 // OID-types
94 'OID REGPROC|10 REGPROCEDURE|10 REGOPER|10 REGOPERATOR|10 REGCLASS|10 REGTYPE|10 REGROLE|10 ' +
95 'REGNAMESPACE|10 REGCONFIG|10 REGDICTIONARY|10 ';// +
96
97 const TYPES_RE =
98 TYPES.trim()
99 .split(' ')
100 .map(function(val) { return val.split('|')[0]; })
101 .join('|');
102
103 const SQL_BI =
104 'CURRENT_TIME CURRENT_TIMESTAMP CURRENT_USER CURRENT_CATALOG|10 CURRENT_DATE LOCALTIME LOCALTIMESTAMP ' +
105 'CURRENT_ROLE|10 CURRENT_SCHEMA|10 SESSION_USER PUBLIC ';
106
107 const PLPGSQL_BI =
108 'FOUND NEW OLD TG_NAME|10 TG_WHEN|10 TG_LEVEL|10 TG_OP|10 TG_RELID|10 TG_RELNAME|10 ' +
109 'TG_TABLE_NAME|10 TG_TABLE_SCHEMA|10 TG_NARGS|10 TG_ARGV|10 TG_EVENT|10 TG_TAG|10 ' +
110 // get diagnostics
111 'ROW_COUNT RESULT_OID|10 PG_CONTEXT|10 RETURNED_SQLSTATE COLUMN_NAME CONSTRAINT_NAME ' +
112 'PG_DATATYPE_NAME|10 MESSAGE_TEXT TABLE_NAME SCHEMA_NAME PG_EXCEPTION_DETAIL|10 ' +
113 'PG_EXCEPTION_HINT|10 PG_EXCEPTION_CONTEXT|10 ';
114
115 const PLPGSQL_EXCEPTIONS =
116 // exceptions https://www.postgresql.org/docs/current/static/errcodes-appendix.html
117 'SQLSTATE SQLERRM|10 ' +
118 'SUCCESSFUL_COMPLETION WARNING DYNAMIC_RESULT_SETS_RETURNED IMPLICIT_ZERO_BIT_PADDING ' +
119 'NULL_VALUE_ELIMINATED_IN_SET_FUNCTION PRIVILEGE_NOT_GRANTED PRIVILEGE_NOT_REVOKED ' +
120 'STRING_DATA_RIGHT_TRUNCATION DEPRECATED_FEATURE NO_DATA NO_ADDITIONAL_DYNAMIC_RESULT_SETS_RETURNED ' +
121 'SQL_STATEMENT_NOT_YET_COMPLETE CONNECTION_EXCEPTION CONNECTION_DOES_NOT_EXIST CONNECTION_FAILURE ' +
122 'SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION SQLSERVER_REJECTED_ESTABLISHMENT_OF_SQLCONNECTION ' +
123 'TRANSACTION_RESOLUTION_UNKNOWN PROTOCOL_VIOLATION TRIGGERED_ACTION_EXCEPTION FEATURE_NOT_SUPPORTED ' +
124 'INVALID_TRANSACTION_INITIATION LOCATOR_EXCEPTION INVALID_LOCATOR_SPECIFICATION INVALID_GRANTOR ' +
125 'INVALID_GRANT_OPERATION INVALID_ROLE_SPECIFICATION DIAGNOSTICS_EXCEPTION ' +
126 'STACKED_DIAGNOSTICS_ACCESSED_WITHOUT_ACTIVE_HANDLER CASE_NOT_FOUND CARDINALITY_VIOLATION ' +
127 'DATA_EXCEPTION ARRAY_SUBSCRIPT_ERROR CHARACTER_NOT_IN_REPERTOIRE DATETIME_FIELD_OVERFLOW ' +
128 'DIVISION_BY_ZERO ERROR_IN_ASSIGNMENT ESCAPE_CHARACTER_CONFLICT INDICATOR_OVERFLOW ' +
129 'INTERVAL_FIELD_OVERFLOW INVALID_ARGUMENT_FOR_LOGARITHM INVALID_ARGUMENT_FOR_NTILE_FUNCTION ' +
130 'INVALID_ARGUMENT_FOR_NTH_VALUE_FUNCTION INVALID_ARGUMENT_FOR_POWER_FUNCTION ' +
131 'INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION INVALID_CHARACTER_VALUE_FOR_CAST ' +
132 'INVALID_DATETIME_FORMAT INVALID_ESCAPE_CHARACTER INVALID_ESCAPE_OCTET INVALID_ESCAPE_SEQUENCE ' +
133 'NONSTANDARD_USE_OF_ESCAPE_CHARACTER INVALID_INDICATOR_PARAMETER_VALUE INVALID_PARAMETER_VALUE ' +
134 'INVALID_REGULAR_EXPRESSION INVALID_ROW_COUNT_IN_LIMIT_CLAUSE ' +
135 'INVALID_ROW_COUNT_IN_RESULT_OFFSET_CLAUSE INVALID_TABLESAMPLE_ARGUMENT INVALID_TABLESAMPLE_REPEAT ' +
136 'INVALID_TIME_ZONE_DISPLACEMENT_VALUE INVALID_USE_OF_ESCAPE_CHARACTER MOST_SPECIFIC_TYPE_MISMATCH ' +
137 'NULL_VALUE_NOT_ALLOWED NULL_VALUE_NO_INDICATOR_PARAMETER NUMERIC_VALUE_OUT_OF_RANGE ' +
138 'SEQUENCE_GENERATOR_LIMIT_EXCEEDED STRING_DATA_LENGTH_MISMATCH STRING_DATA_RIGHT_TRUNCATION ' +
139 'SUBSTRING_ERROR TRIM_ERROR UNTERMINATED_C_STRING ZERO_LENGTH_CHARACTER_STRING ' +
140 'FLOATING_POINT_EXCEPTION INVALID_TEXT_REPRESENTATION INVALID_BINARY_REPRESENTATION ' +
141 'BAD_COPY_FILE_FORMAT UNTRANSLATABLE_CHARACTER NOT_AN_XML_DOCUMENT INVALID_XML_DOCUMENT ' +
142 'INVALID_XML_CONTENT INVALID_XML_COMMENT INVALID_XML_PROCESSING_INSTRUCTION ' +
143 'INTEGRITY_CONSTRAINT_VIOLATION RESTRICT_VIOLATION NOT_NULL_VIOLATION FOREIGN_KEY_VIOLATION ' +
144 'UNIQUE_VIOLATION CHECK_VIOLATION EXCLUSION_VIOLATION INVALID_CURSOR_STATE ' +
145 'INVALID_TRANSACTION_STATE ACTIVE_SQL_TRANSACTION BRANCH_TRANSACTION_ALREADY_ACTIVE ' +
146 'HELD_CURSOR_REQUIRES_SAME_ISOLATION_LEVEL INAPPROPRIATE_ACCESS_MODE_FOR_BRANCH_TRANSACTION ' +
147 'INAPPROPRIATE_ISOLATION_LEVEL_FOR_BRANCH_TRANSACTION ' +
148 'NO_ACTIVE_SQL_TRANSACTION_FOR_BRANCH_TRANSACTION READ_ONLY_SQL_TRANSACTION ' +
149 'SCHEMA_AND_DATA_STATEMENT_MIXING_NOT_SUPPORTED NO_ACTIVE_SQL_TRANSACTION ' +
150 'IN_FAILED_SQL_TRANSACTION IDLE_IN_TRANSACTION_SESSION_TIMEOUT INVALID_SQL_STATEMENT_NAME ' +
151 'TRIGGERED_DATA_CHANGE_VIOLATION INVALID_AUTHORIZATION_SPECIFICATION INVALID_PASSWORD ' +
152 'DEPENDENT_PRIVILEGE_DESCRIPTORS_STILL_EXIST DEPENDENT_OBJECTS_STILL_EXIST ' +
153 'INVALID_TRANSACTION_TERMINATION SQL_ROUTINE_EXCEPTION FUNCTION_EXECUTED_NO_RETURN_STATEMENT ' +
154 'MODIFYING_SQL_DATA_NOT_PERMITTED PROHIBITED_SQL_STATEMENT_ATTEMPTED ' +
155 'READING_SQL_DATA_NOT_PERMITTED INVALID_CURSOR_NAME EXTERNAL_ROUTINE_EXCEPTION ' +
156 'CONTAINING_SQL_NOT_PERMITTED MODIFYING_SQL_DATA_NOT_PERMITTED ' +
157 'PROHIBITED_SQL_STATEMENT_ATTEMPTED READING_SQL_DATA_NOT_PERMITTED ' +
158 'EXTERNAL_ROUTINE_INVOCATION_EXCEPTION INVALID_SQLSTATE_RETURNED NULL_VALUE_NOT_ALLOWED ' +
159 'TRIGGER_PROTOCOL_VIOLATED SRF_PROTOCOL_VIOLATED EVENT_TRIGGER_PROTOCOL_VIOLATED ' +
160 'SAVEPOINT_EXCEPTION INVALID_SAVEPOINT_SPECIFICATION INVALID_CATALOG_NAME ' +
161 'INVALID_SCHEMA_NAME TRANSACTION_ROLLBACK TRANSACTION_INTEGRITY_CONSTRAINT_VIOLATION ' +
162 'SERIALIZATION_FAILURE STATEMENT_COMPLETION_UNKNOWN DEADLOCK_DETECTED ' +
163 'SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION SYNTAX_ERROR INSUFFICIENT_PRIVILEGE CANNOT_COERCE ' +
164 'GROUPING_ERROR WINDOWING_ERROR INVALID_RECURSION INVALID_FOREIGN_KEY INVALID_NAME ' +
165 'NAME_TOO_LONG RESERVED_NAME DATATYPE_MISMATCH INDETERMINATE_DATATYPE COLLATION_MISMATCH ' +
166 'INDETERMINATE_COLLATION WRONG_OBJECT_TYPE GENERATED_ALWAYS UNDEFINED_COLUMN ' +
167 'UNDEFINED_FUNCTION UNDEFINED_TABLE UNDEFINED_PARAMETER UNDEFINED_OBJECT ' +
168 'DUPLICATE_COLUMN DUPLICATE_CURSOR DUPLICATE_DATABASE DUPLICATE_FUNCTION ' +
169 'DUPLICATE_PREPARED_STATEMENT DUPLICATE_SCHEMA DUPLICATE_TABLE DUPLICATE_ALIAS ' +
170 'DUPLICATE_OBJECT AMBIGUOUS_COLUMN AMBIGUOUS_FUNCTION AMBIGUOUS_PARAMETER AMBIGUOUS_ALIAS ' +
171 'INVALID_COLUMN_REFERENCE INVALID_COLUMN_DEFINITION INVALID_CURSOR_DEFINITION ' +
172 'INVALID_DATABASE_DEFINITION INVALID_FUNCTION_DEFINITION ' +
173 'INVALID_PREPARED_STATEMENT_DEFINITION INVALID_SCHEMA_DEFINITION INVALID_TABLE_DEFINITION ' +
174 'INVALID_OBJECT_DEFINITION WITH_CHECK_OPTION_VIOLATION INSUFFICIENT_RESOURCES DISK_FULL ' +
175 'OUT_OF_MEMORY TOO_MANY_CONNECTIONS CONFIGURATION_LIMIT_EXCEEDED PROGRAM_LIMIT_EXCEEDED ' +
176 'STATEMENT_TOO_COMPLEX TOO_MANY_COLUMNS TOO_MANY_ARGUMENTS OBJECT_NOT_IN_PREREQUISITE_STATE ' +
177 'OBJECT_IN_USE CANT_CHANGE_RUNTIME_PARAM LOCK_NOT_AVAILABLE OPERATOR_INTERVENTION ' +
178 'QUERY_CANCELED ADMIN_SHUTDOWN CRASH_SHUTDOWN CANNOT_CONNECT_NOW DATABASE_DROPPED ' +
179 'SYSTEM_ERROR IO_ERROR UNDEFINED_FILE DUPLICATE_FILE SNAPSHOT_TOO_OLD CONFIG_FILE_ERROR ' +
180 'LOCK_FILE_EXISTS FDW_ERROR FDW_COLUMN_NAME_NOT_FOUND FDW_DYNAMIC_PARAMETER_VALUE_NEEDED ' +
181 'FDW_FUNCTION_SEQUENCE_ERROR FDW_INCONSISTENT_DESCRIPTOR_INFORMATION ' +
182 'FDW_INVALID_ATTRIBUTE_VALUE FDW_INVALID_COLUMN_NAME FDW_INVALID_COLUMN_NUMBER ' +
183 'FDW_INVALID_DATA_TYPE FDW_INVALID_DATA_TYPE_DESCRIPTORS ' +
184 'FDW_INVALID_DESCRIPTOR_FIELD_IDENTIFIER FDW_INVALID_HANDLE FDW_INVALID_OPTION_INDEX ' +
185 'FDW_INVALID_OPTION_NAME FDW_INVALID_STRING_LENGTH_OR_BUFFER_LENGTH ' +
186 'FDW_INVALID_STRING_FORMAT FDW_INVALID_USE_OF_NULL_POINTER FDW_TOO_MANY_HANDLES ' +
187 'FDW_OUT_OF_MEMORY FDW_NO_SCHEMAS FDW_OPTION_NAME_NOT_FOUND FDW_REPLY_HANDLE ' +
188 'FDW_SCHEMA_NOT_FOUND FDW_TABLE_NOT_FOUND FDW_UNABLE_TO_CREATE_EXECUTION ' +
189 'FDW_UNABLE_TO_CREATE_REPLY FDW_UNABLE_TO_ESTABLISH_CONNECTION PLPGSQL_ERROR ' +
190 'RAISE_EXCEPTION NO_DATA_FOUND TOO_MANY_ROWS ASSERT_FAILURE INTERNAL_ERROR DATA_CORRUPTED ' +
191 'INDEX_CORRUPTED ';
192
193 const FUNCTIONS =
194 // https://www.postgresql.org/docs/11/static/functions-aggregate.html
195 'ARRAY_AGG AVG BIT_AND BIT_OR BOOL_AND BOOL_OR COUNT EVERY JSON_AGG JSONB_AGG JSON_OBJECT_AGG ' +
196 'JSONB_OBJECT_AGG MAX MIN MODE STRING_AGG SUM XMLAGG ' +
197 'CORR COVAR_POP COVAR_SAMP REGR_AVGX REGR_AVGY REGR_COUNT REGR_INTERCEPT REGR_R2 REGR_SLOPE ' +
198 'REGR_SXX REGR_SXY REGR_SYY STDDEV STDDEV_POP STDDEV_SAMP VARIANCE VAR_POP VAR_SAMP ' +
199 'PERCENTILE_CONT PERCENTILE_DISC ' +
200 // https://www.postgresql.org/docs/11/static/functions-window.html
201 'ROW_NUMBER RANK DENSE_RANK PERCENT_RANK CUME_DIST NTILE LAG LEAD FIRST_VALUE LAST_VALUE NTH_VALUE ' +
202 // https://www.postgresql.org/docs/11/static/functions-comparison.html
203 'NUM_NONNULLS NUM_NULLS ' +
204 // https://www.postgresql.org/docs/11/static/functions-math.html
205 'ABS CBRT CEIL CEILING DEGREES DIV EXP FLOOR LN LOG MOD PI POWER RADIANS ROUND SCALE SIGN SQRT ' +
206 'TRUNC WIDTH_BUCKET ' +
207 'RANDOM SETSEED ' +
208 'ACOS ACOSD ASIN ASIND ATAN ATAND ATAN2 ATAN2D COS COSD COT COTD SIN SIND TAN TAND ' +
209 // https://www.postgresql.org/docs/11/static/functions-string.html
210 'BIT_LENGTH CHAR_LENGTH CHARACTER_LENGTH LOWER OCTET_LENGTH OVERLAY POSITION SUBSTRING TREAT TRIM UPPER ' +
211 'ASCII BTRIM CHR CONCAT CONCAT_WS CONVERT CONVERT_FROM CONVERT_TO DECODE ENCODE INITCAP ' +
212 'LEFT LENGTH LPAD LTRIM MD5 PARSE_IDENT PG_CLIENT_ENCODING QUOTE_IDENT|10 QUOTE_LITERAL|10 ' +
213 'QUOTE_NULLABLE|10 REGEXP_MATCH REGEXP_MATCHES REGEXP_REPLACE REGEXP_SPLIT_TO_ARRAY ' +
214 'REGEXP_SPLIT_TO_TABLE REPEAT REPLACE REVERSE RIGHT RPAD RTRIM SPLIT_PART STRPOS SUBSTR ' +
215 'TO_ASCII TO_HEX TRANSLATE ' +
216 // https://www.postgresql.org/docs/11/static/functions-binarystring.html
217 'OCTET_LENGTH GET_BIT GET_BYTE SET_BIT SET_BYTE ' +
218 // https://www.postgresql.org/docs/11/static/functions-formatting.html
219 'TO_CHAR TO_DATE TO_NUMBER TO_TIMESTAMP ' +
220 // https://www.postgresql.org/docs/11/static/functions-datetime.html
221 'AGE CLOCK_TIMESTAMP|10 DATE_PART DATE_TRUNC ISFINITE JUSTIFY_DAYS JUSTIFY_HOURS JUSTIFY_INTERVAL ' +
222 'MAKE_DATE MAKE_INTERVAL|10 MAKE_TIME MAKE_TIMESTAMP|10 MAKE_TIMESTAMPTZ|10 NOW STATEMENT_TIMESTAMP|10 ' +
223 'TIMEOFDAY TRANSACTION_TIMESTAMP|10 ' +
224 // https://www.postgresql.org/docs/11/static/functions-enum.html
225 'ENUM_FIRST ENUM_LAST ENUM_RANGE ' +
226 // https://www.postgresql.org/docs/11/static/functions-geometry.html
227 'AREA CENTER DIAMETER HEIGHT ISCLOSED ISOPEN NPOINTS PCLOSE POPEN RADIUS WIDTH ' +
228 'BOX BOUND_BOX CIRCLE LINE LSEG PATH POLYGON ' +
229 // https://www.postgresql.org/docs/11/static/functions-net.html
230 'ABBREV BROADCAST HOST HOSTMASK MASKLEN NETMASK NETWORK SET_MASKLEN TEXT INET_SAME_FAMILY ' +
231 'INET_MERGE MACADDR8_SET7BIT ' +
232 // https://www.postgresql.org/docs/11/static/functions-textsearch.html
233 'ARRAY_TO_TSVECTOR GET_CURRENT_TS_CONFIG NUMNODE PLAINTO_TSQUERY PHRASETO_TSQUERY WEBSEARCH_TO_TSQUERY ' +
234 'QUERYTREE SETWEIGHT STRIP TO_TSQUERY TO_TSVECTOR JSON_TO_TSVECTOR JSONB_TO_TSVECTOR TS_DELETE ' +
235 'TS_FILTER TS_HEADLINE TS_RANK TS_RANK_CD TS_REWRITE TSQUERY_PHRASE TSVECTOR_TO_ARRAY ' +
236 'TSVECTOR_UPDATE_TRIGGER TSVECTOR_UPDATE_TRIGGER_COLUMN ' +
237 // https://www.postgresql.org/docs/11/static/functions-xml.html
238 'XMLCOMMENT XMLCONCAT XMLELEMENT XMLFOREST XMLPI XMLROOT ' +
239 'XMLEXISTS XML_IS_WELL_FORMED XML_IS_WELL_FORMED_DOCUMENT XML_IS_WELL_FORMED_CONTENT ' +
240 'XPATH XPATH_EXISTS XMLTABLE XMLNAMESPACES ' +
241 'TABLE_TO_XML TABLE_TO_XMLSCHEMA TABLE_TO_XML_AND_XMLSCHEMA ' +
242 'QUERY_TO_XML QUERY_TO_XMLSCHEMA QUERY_TO_XML_AND_XMLSCHEMA ' +
243 'CURSOR_TO_XML CURSOR_TO_XMLSCHEMA ' +
244 'SCHEMA_TO_XML SCHEMA_TO_XMLSCHEMA SCHEMA_TO_XML_AND_XMLSCHEMA ' +
245 'DATABASE_TO_XML DATABASE_TO_XMLSCHEMA DATABASE_TO_XML_AND_XMLSCHEMA ' +
246 'XMLATTRIBUTES ' +
247 // https://www.postgresql.org/docs/11/static/functions-json.html
248 'TO_JSON TO_JSONB ARRAY_TO_JSON ROW_TO_JSON JSON_BUILD_ARRAY JSONB_BUILD_ARRAY JSON_BUILD_OBJECT ' +
249 'JSONB_BUILD_OBJECT JSON_OBJECT JSONB_OBJECT JSON_ARRAY_LENGTH JSONB_ARRAY_LENGTH JSON_EACH ' +
250 'JSONB_EACH JSON_EACH_TEXT JSONB_EACH_TEXT JSON_EXTRACT_PATH JSONB_EXTRACT_PATH ' +
251 'JSON_OBJECT_KEYS JSONB_OBJECT_KEYS JSON_POPULATE_RECORD JSONB_POPULATE_RECORD JSON_POPULATE_RECORDSET ' +
252 'JSONB_POPULATE_RECORDSET JSON_ARRAY_ELEMENTS JSONB_ARRAY_ELEMENTS JSON_ARRAY_ELEMENTS_TEXT ' +
253 'JSONB_ARRAY_ELEMENTS_TEXT JSON_TYPEOF JSONB_TYPEOF JSON_TO_RECORD JSONB_TO_RECORD JSON_TO_RECORDSET ' +
254 'JSONB_TO_RECORDSET JSON_STRIP_NULLS JSONB_STRIP_NULLS JSONB_SET JSONB_INSERT JSONB_PRETTY ' +
255 // https://www.postgresql.org/docs/11/static/functions-sequence.html
256 'CURRVAL LASTVAL NEXTVAL SETVAL ' +
257 // https://www.postgresql.org/docs/11/static/functions-conditional.html
258 'COALESCE NULLIF GREATEST LEAST ' +
259 // https://www.postgresql.org/docs/11/static/functions-array.html
260 'ARRAY_APPEND ARRAY_CAT ARRAY_NDIMS ARRAY_DIMS ARRAY_FILL ARRAY_LENGTH ARRAY_LOWER ARRAY_POSITION ' +
261 'ARRAY_POSITIONS ARRAY_PREPEND ARRAY_REMOVE ARRAY_REPLACE ARRAY_TO_STRING ARRAY_UPPER CARDINALITY ' +
262 'STRING_TO_ARRAY UNNEST ' +
263 // https://www.postgresql.org/docs/11/static/functions-range.html
264 'ISEMPTY LOWER_INC UPPER_INC LOWER_INF UPPER_INF RANGE_MERGE ' +
265 // https://www.postgresql.org/docs/11/static/functions-srf.html
266 'GENERATE_SERIES GENERATE_SUBSCRIPTS ' +
267 // https://www.postgresql.org/docs/11/static/functions-info.html
268 'CURRENT_DATABASE CURRENT_QUERY CURRENT_SCHEMA|10 CURRENT_SCHEMAS|10 INET_CLIENT_ADDR INET_CLIENT_PORT ' +
269 'INET_SERVER_ADDR INET_SERVER_PORT ROW_SECURITY_ACTIVE FORMAT_TYPE ' +
270 'TO_REGCLASS TO_REGPROC TO_REGPROCEDURE TO_REGOPER TO_REGOPERATOR TO_REGTYPE TO_REGNAMESPACE TO_REGROLE ' +
271 'COL_DESCRIPTION OBJ_DESCRIPTION SHOBJ_DESCRIPTION ' +
272 'TXID_CURRENT TXID_CURRENT_IF_ASSIGNED TXID_CURRENT_SNAPSHOT TXID_SNAPSHOT_XIP TXID_SNAPSHOT_XMAX ' +
273 'TXID_SNAPSHOT_XMIN TXID_VISIBLE_IN_SNAPSHOT TXID_STATUS ' +
274 // https://www.postgresql.org/docs/11/static/functions-admin.html
275 'CURRENT_SETTING SET_CONFIG BRIN_SUMMARIZE_NEW_VALUES BRIN_SUMMARIZE_RANGE BRIN_DESUMMARIZE_RANGE ' +
276 'GIN_CLEAN_PENDING_LIST ' +
277 // https://www.postgresql.org/docs/11/static/functions-trigger.html
278 'SUPPRESS_REDUNDANT_UPDATES_TRIGGER ' +
279 // ihttps://www.postgresql.org/docs/devel/static/lo-funcs.html
280 'LO_FROM_BYTEA LO_PUT LO_GET LO_CREAT LO_CREATE LO_UNLINK LO_IMPORT LO_EXPORT LOREAD LOWRITE ' +
281 //
282 'GROUPING CAST ';
283
284 const FUNCTIONS_RE =
285 FUNCTIONS.trim()
286 .split(' ')
287 .map(function(val) { return val.split('|')[0]; })
288 .join('|');
289
290 return {
291 name: 'PostgreSQL',
292 aliases: [
293 'postgres',
294 'postgresql'
295 ],
296 supersetOf: "sql",
297 case_insensitive: true,
298 keywords: {
299 keyword:
300 SQL_KW + PLPGSQL_KW + ROLE_ATTRS,
301 built_in:
302 SQL_BI + PLPGSQL_BI + PLPGSQL_EXCEPTIONS
303 },
304 // Forbid some cunstructs from other languages to improve autodetect. In fact
305 // "[a-z]:" is legal (as part of array slice), but improbabal.
306 illegal: /:==|\W\s*\(\*|(^|\s)\$[a-z]|\{\{|[a-z]:\s*$|\.\.\.|TO:|DO:/,
307 contains: [
308 // special handling of some words, which are reserved only in some contexts
309 {
310 className: 'keyword',
311 variants: [
312 {
313 begin: /\bTEXT\s*SEARCH\b/
314 },
315 {
316 begin: /\b(PRIMARY|FOREIGN|FOR(\s+NO)?)\s+KEY\b/
317 },
318 {
319 begin: /\bPARALLEL\s+(UNSAFE|RESTRICTED|SAFE)\b/
320 },
321 {
322 begin: /\bSTORAGE\s+(PLAIN|EXTERNAL|EXTENDED|MAIN)\b/
323 },
324 {
325 begin: /\bMATCH\s+(FULL|PARTIAL|SIMPLE)\b/
326 },
327 {
328 begin: /\bNULLS\s+(FIRST|LAST)\b/
329 },
330 {
331 begin: /\bEVENT\s+TRIGGER\b/
332 },
333 {
334 begin: /\b(MAPPING|OR)\s+REPLACE\b/
335 },
336 {
337 begin: /\b(FROM|TO)\s+(PROGRAM|STDIN|STDOUT)\b/
338 },
339 {
340 begin: /\b(SHARE|EXCLUSIVE)\s+MODE\b/
341 },
342 {
343 begin: /\b(LEFT|RIGHT)\s+(OUTER\s+)?JOIN\b/
344 },
345 {
346 begin: /\b(FETCH|MOVE)\s+(NEXT|PRIOR|FIRST|LAST|ABSOLUTE|RELATIVE|FORWARD|BACKWARD)\b/
347 },
348 {
349 begin: /\bPRESERVE\s+ROWS\b/
350 },
351 {
352 begin: /\bDISCARD\s+PLANS\b/
353 },
354 {
355 begin: /\bREFERENCING\s+(OLD|NEW)\b/
356 },
357 {
358 begin: /\bSKIP\s+LOCKED\b/
359 },
360 {
361 begin: /\bGROUPING\s+SETS\b/
362 },
363 {
364 begin: /\b(BINARY|INSENSITIVE|SCROLL|NO\s+SCROLL)\s+(CURSOR|FOR)\b/
365 },
366 {
367 begin: /\b(WITH|WITHOUT)\s+HOLD\b/
368 },
369 {
370 begin: /\bWITH\s+(CASCADED|LOCAL)\s+CHECK\s+OPTION\b/
371 },
372 {
373 begin: /\bEXCLUDE\s+(TIES|NO\s+OTHERS)\b/
374 },
375 {
376 begin: /\bFORMAT\s+(TEXT|XML|JSON|YAML)\b/
377 },
378 {
379 begin: /\bSET\s+((SESSION|LOCAL)\s+)?NAMES\b/
380 },
381 {
382 begin: /\bIS\s+(NOT\s+)?UNKNOWN\b/
383 },
384 {
385 begin: /\bSECURITY\s+LABEL\b/
386 },
387 {
388 begin: /\bSTANDALONE\s+(YES|NO|NO\s+VALUE)\b/
389 },
390 {
391 begin: /\bWITH\s+(NO\s+)?DATA\b/
392 },
393 {
394 begin: /\b(FOREIGN|SET)\s+DATA\b/
395 },
396 {
397 begin: /\bSET\s+(CATALOG|CONSTRAINTS)\b/
398 },
399 {
400 begin: /\b(WITH|FOR)\s+ORDINALITY\b/
401 },
402 {
403 begin: /\bIS\s+(NOT\s+)?DOCUMENT\b/
404 },
405 {
406 begin: /\bXML\s+OPTION\s+(DOCUMENT|CONTENT)\b/
407 },
408 {
409 begin: /\b(STRIP|PRESERVE)\s+WHITESPACE\b/
410 },
411 {
412 begin: /\bNO\s+(ACTION|MAXVALUE|MINVALUE)\b/
413 },
414 {
415 begin: /\bPARTITION\s+BY\s+(RANGE|LIST|HASH)\b/
416 },
417 {
418 begin: /\bAT\s+TIME\s+ZONE\b/
419 },
420 {
421 begin: /\bGRANTED\s+BY\b/
422 },
423 {
424 begin: /\bRETURN\s+(QUERY|NEXT)\b/
425 },
426 {
427 begin: /\b(ATTACH|DETACH)\s+PARTITION\b/
428 },
429 {
430 begin: /\bFORCE\s+ROW\s+LEVEL\s+SECURITY\b/
431 },
432 {
433 begin: /\b(INCLUDING|EXCLUDING)\s+(COMMENTS|CONSTRAINTS|DEFAULTS|IDENTITY|INDEXES|STATISTICS|STORAGE|ALL)\b/
434 },
435 {
436 begin: /\bAS\s+(ASSIGNMENT|IMPLICIT|PERMISSIVE|RESTRICTIVE|ENUM|RANGE)\b/
437 }
438 ]
439 },
440 // functions named as keywords, followed by '('
441 {
442 begin: /\b(FORMAT|FAMILY|VERSION)\s*\(/
443 // keywords: { built_in: 'FORMAT FAMILY VERSION' }
444 },
445 // INCLUDE ( ... ) in index_parameters in CREATE TABLE
446 {
447 begin: /\bINCLUDE\s*\(/,
448 keywords: 'INCLUDE'
449 },
450 // not highlight RANGE if not in frame_clause (not 100% correct, but seems satisfactory)
451 {
452 begin: /\bRANGE(?!\s*(BETWEEN|UNBOUNDED|CURRENT|[-0-9]+))/
453 },
454 // disable highlighting in commands CREATE AGGREGATE/COLLATION/DATABASE/OPERTOR/TEXT SEARCH .../TYPE
455 // and in PL/pgSQL RAISE ... USING
456 {
457 begin: /\b(VERSION|OWNER|TEMPLATE|TABLESPACE|CONNECTION\s+LIMIT|PROCEDURE|RESTRICT|JOIN|PARSER|COPY|START|END|COLLATION|INPUT|ANALYZE|STORAGE|LIKE|DEFAULT|DELIMITER|ENCODING|COLUMN|CONSTRAINT|TABLE|SCHEMA)\s*=/
458 },
459 // PG_smth; HAS_some_PRIVILEGE
460 {
461 // className: 'built_in',
462 begin: /\b(PG_\w+?|HAS_[A-Z_]+_PRIVILEGE)\b/,
463 relevance: 10
464 },
465 // extract
466 {
467 begin: /\bEXTRACT\s*\(/,
468 end: /\bFROM\b/,
469 returnEnd: true,
470 keywords: {
471 // built_in: 'EXTRACT',
472 type: 'CENTURY DAY DECADE DOW DOY EPOCH HOUR ISODOW ISOYEAR MICROSECONDS ' +
473 'MILLENNIUM MILLISECONDS MINUTE MONTH QUARTER SECOND TIMEZONE TIMEZONE_HOUR ' +
474 'TIMEZONE_MINUTE WEEK YEAR'
475 }
476 },
477 // xmlelement, xmlpi - special NAME
478 {
479 begin: /\b(XMLELEMENT|XMLPI)\s*\(\s*NAME/,
480 keywords: {
481 // built_in: 'XMLELEMENT XMLPI',
482 keyword: 'NAME'
483 }
484 },
485 // xmlparse, xmlserialize
486 {
487 begin: /\b(XMLPARSE|XMLSERIALIZE)\s*\(\s*(DOCUMENT|CONTENT)/,
488 keywords: {
489 // built_in: 'XMLPARSE XMLSERIALIZE',
490 keyword: 'DOCUMENT CONTENT'
491 }
492 },
493 // Sequences. We actually skip everything between CACHE|INCREMENT|MAXVALUE|MINVALUE and
494 // nearest following numeric constant. Without with trick we find a lot of "keywords"
495 // in 'avrasm' autodetection test...
496 {
497 beginKeywords: 'CACHE INCREMENT MAXVALUE MINVALUE',
498 end: hljs.C_NUMBER_RE,
499 returnEnd: true,
500 keywords: 'BY CACHE INCREMENT MAXVALUE MINVALUE'
501 },
502 // WITH|WITHOUT TIME ZONE as part of datatype
503 {
504 className: 'type',
505 begin: /\b(WITH|WITHOUT)\s+TIME\s+ZONE\b/
506 },
507 // INTERVAL optional fields
508 {
509 className: 'type',
510 begin: /\bINTERVAL\s+(YEAR|MONTH|DAY|HOUR|MINUTE|SECOND)(\s+TO\s+(MONTH|HOUR|MINUTE|SECOND))?\b/
511 },
512 // Pseudo-types which allowed only as return type
513 {
514 begin: /\bRETURNS\s+(LANGUAGE_HANDLER|TRIGGER|EVENT_TRIGGER|FDW_HANDLER|INDEX_AM_HANDLER|TSM_HANDLER)\b/,
515 keywords: {
516 keyword: 'RETURNS',
517 type: 'LANGUAGE_HANDLER TRIGGER EVENT_TRIGGER FDW_HANDLER INDEX_AM_HANDLER TSM_HANDLER'
518 }
519 },
520 // Known functions - only when followed by '('
521 {
522 begin: '\\b(' + FUNCTIONS_RE + ')\\s*\\('
523 // keywords: { built_in: FUNCTIONS }
524 },
525 // Types
526 {
527 begin: '\\.(' + TYPES_RE + ')\\b' // prevent highlight as type, say, 'oid' in 'pgclass.oid'
528 },
529 {
530 begin: '\\b(' + TYPES_RE + ')\\s+PATH\\b', // in XMLTABLE
531 keywords: {
532 keyword: 'PATH', // hopefully no one would use PATH type in XMLTABLE...
533 type: TYPES.replace('PATH ', '')
534 }
535 },
536 {
537 className: 'type',
538 begin: '\\b(' + TYPES_RE + ')\\b'
539 },
540 // Strings, see https://www.postgresql.org/docs/11/static/sql-syntax-lexical.html#SQL-SYNTAX-CONSTANTS
541 {
542 className: 'string',
543 begin: '\'',
544 end: '\'',
545 contains: [
546 {
547 begin: '\'\''
548 }
549 ]
550 },
551 {
552 className: 'string',
553 begin: '(e|E|u&|U&)\'',
554 end: '\'',
555 contains: [
556 {
557 begin: '\\\\.'
558 }
559 ],
560 relevance: 10
561 },
562 hljs.END_SAME_AS_BEGIN({
563 begin: DOLLAR_STRING,
564 end: DOLLAR_STRING,
565 contains: [
566 {
567 // actually we want them all except SQL; listed are those with known implementations
568 // and XML + JSON just in case
569 subLanguage: [
570 'pgsql',
571 'perl',
572 'python',
573 'tcl',
574 'r',
575 'lua',
576 'java',
577 'php',
578 'ruby',
579 'bash',
580 'scheme',
581 'xml',
582 'json'
583 ],
584 endsWithParent: true
585 }
586 ]
587 }),
588 // identifiers in quotes
589 {
590 begin: '"',
591 end: '"',
592 contains: [
593 {
594 begin: '""'
595 }
596 ]
597 },
598 // numbers
599 hljs.C_NUMBER_MODE,
600 // comments
601 hljs.C_BLOCK_COMMENT_MODE,
602 COMMENT_MODE,
603 // PL/pgSQL staff
604 // %ROWTYPE, %TYPE, $n
605 {
606 className: 'meta',
607 variants: [
608 { // %TYPE, %ROWTYPE
609 begin: '%(ROW)?TYPE',
610 relevance: 10
611 },
612 { // $n
613 begin: '\\$\\d+'
614 },
615 { // #compiler option
616 begin: '^#\\w',
617 end: '$'
618 }
619 ]
620 },
621 // <<labeles>>
622 {
623 className: 'symbol',
624 begin: LABEL,
625 relevance: 10
626 }
627 ]
628 };
629}
630
631export { pgsql as default };