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