2 # -*- coding: latin-1; -*-
4 # PgWorksheet - PostgreSQL Front End
5 # http://pgworksheet.projects.postgresql.org/
7 # Copyright © 2004-2008 Henri Michelon & CML http://www.e-cml.org/
9 # This program is free software; you can redistribute it and/or
10 # modify it under the terms of the GNU General Public License
11 # as published by the Free Software Foundation; either version 2
12 # of the License, or (at your option) any later version.
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details (read LICENSE.txt).
19 # You should have received a copy of the GNU General Public License
20 # along with this program; if not, write to the Free Software
21 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 # $Id: Syntax.py,v 1.30 2008/03/12 20:26:23 hmichelon Exp $
30 # built-in data types and extensions
31 TYPES
= [ 'BIGINT', 'INT8', 'BIGSERIAL', 'SERIAL8', 'BIT', 'VARYING',
32 'VARBIT', 'BOOL', 'BOOLEAN', 'BOX', 'BYTEA', 'CHARACTER', 'VARCHAR',
33 'CHAR', 'CIDR', 'CIRCLE', 'DATE', 'DOUBLE', 'PRECISION',
34 'INET', 'INTEGER', 'FLOAT8', 'INT', 'INT4', 'INTERVAL',
35 'LINE', 'LSEG', 'MACADDR', 'MONEY', 'NUMERIC', 'DECIMAL',
36 'PATH', 'POINT', 'POLYGON', 'REAL', 'FLOAT4', 'SMALLINT',
37 'INT2', 'SERIAL', 'SERIAL4', 'TEXT','TIME', 'TIMESTAMP',
38 'TIMETZ', 'TIMESTAMPTZ', 'WITHOUT', 'TIME', 'ZONE'
42 SPECIALS
= [ 'FALSE', 'NULL', 'TRUE', 'UNKNOWN', 'ALL', 'ANY', 'SOME' ]
45 # named operators, constructs, conditionals and subqueries
46 OPERATORS2
= [ 'OVERLAPS', 'AND', 'OR', 'NOT', 'BETWEEN', 'IS', 'ISNULL',
47 'NOTNULL', 'CAST', 'LIKE', 'ILIKE', 'SIMILAR',
49 'CASE', 'WHEN', 'THEN', 'ELSE', 'END',
53 # SQL and PostgreSQL statements
54 STATEMENTS
= [ 'ABORT', 'ALTER', 'ANALYSE', 'BEGIN', 'CHECKPOINT', 'CLOSE',
55 'CLUSTER', 'COMMENT', 'COMMIT', 'COPY', 'CREATE', 'DEALLOCATE',
56 'DECLARE', 'DELETE', 'DROP', 'END', 'EXECUTE', 'EXPLAIN',
57 'FETCH', 'GRANT', 'INSERT', 'LISTEN', 'LOAD', 'LOCK', 'MOVE',
58 'NOTIFY', 'PREPARE', 'REINDEX', 'RELEASE', 'RESET', 'REVOKE',
59 'ROLLBACK', 'SAVEPOINT', 'SELECT', 'SET', 'SHOW', 'START',
60 'TRUNCATE', 'UNLISTEN', 'UPDATE', 'VACUUM' ]
65 'ABS', 'CBTR', 'CEIL', 'CEILING', 'DEGREES', 'EXP', 'FLOOR', 'LN',
66 'LOG', 'MOD', 'PI', 'POWER', 'RADIANS', 'RANDOM', 'ROUND',
67 'SETSEED', 'SIGN', 'SQRT', 'TRUNC', 'WIDTH_BUCKET', 'ACOS',
68 'ASIN', 'ATAN', 'ATAN2', 'COS', 'COT', 'SIN', 'TAN',
70 'BIT_LENGTH', 'CHAR_LENGTH', 'CONVERT', 'LOWER', 'OCTET_LENGTH',
71 'OVERLAY', 'POSITION', 'SUBSTRING', 'TRIM', 'UPPER', 'ASCII',
72 'BTRIM', 'CHR', 'DECODE', 'ENCODE', 'INITCAP', 'LENGTH',
73 'LPAD', 'LTRIM', 'MD5', 'PG_CLIENT_ENCODING', 'QUOTE_IDENT',
74 'QUOTE_LITERAL', 'REPEAT', 'RPAD', 'RTRIM', 'SPLIT_PART',
75 'STRPOS', 'TO_ASCII', 'TO_HEX', 'TRANSLATE',
77 'GET_BYTE', 'SET_BYTE', 'GET_BIT', 'SET_BIT',
79 'TO_CHAR', 'TO_DATE', 'TO_TIMESTAMP', 'TO_NUMBER',
80 'AGE', 'DATE_PART', 'DATE_TRUNC', 'EXTRACT', 'ISFINITE',
83 'AREA', 'BOX_INTERSECT', 'CENTER', 'DIAMETER', 'HEIGHT',
84 'ISCLOSED', 'ISOPEN', 'LENGTH', 'NPOINTS', 'PCLOSE',
85 'POPEN', 'RADIUS', 'WIDTH', 'BOX', 'CIRCLE', 'LSEG',
86 'PATH', 'POINT', 'POLYGON',
88 'BROADCAST', 'HOST', 'MASKLEN', 'SET_MASKLEN',
89 'NETMASK', 'HOSTMASK', 'NETWORK', 'TEXT', 'ABBREV',
96 'ARRAY_CAT', 'ARRAY_APPEND', 'ARRAY_PREPEND', 'ARRAY_DIMS',
97 'ARRAY_LOWER', 'ARRAY_UPPER', 'ARRAY_TO_STRING',
100 'AVG', 'BIT_AND', 'BIT_OR', 'BOOL_AND', 'BOOL_OR',
101 'COUNT', 'EVERY', 'MAX', 'MIN', 'STDDEV', 'SUM',
106 'CURRENT_DATABASE', 'CURRENT_SCHEMA',
107 'INET_CLIENT_ADDR', 'INET_CLIENT_PORT',
108 'INET_SERVER_ADDR', 'INET_SERVER_PORT', 'VERSION',
109 'HAS_TABLE_PRIVILEGE', 'HAS_DATABASE_PRIVILEGE',
110 'HAS_FUNCTION_PRIVILEGE', 'HAS_LANGUAGE_PRIVILEGE',
111 'HAS_SCHEMA_PRIVILEGE', 'HAS_TABLESPACE_PRIVILEGE'
112 'PG_TABLE_IS_VISIBLE', 'PG_TYPE_IS_VISIBLE',
113 'PG_FUNCTION_IS_VISIBLE', 'PG_OPERATOR_IS_VISIBLE',
114 'PG_OPCLASS_IS_VISIBLE', 'PG_CONVERSION_IS_VISIBLE',
115 'FORMAT_TYPE', 'PG_GET_VIEWDEF', 'PG_GET_RULEGET',
116 'PG_GET_INDEXDEF', 'PG_GET_TRIGGERDEF',
117 'PG_GET_CONSTRAINTDEF', 'PG_GET_EXPR', 'PG_GET_USERBYID',
118 'PG_GET_SERIAL_SEQUENCE', 'PG_TABLESPACE_DATABASES',
121 'CURRENT_SETTINGS', 'SET_CONFIG', 'PG_CANCEL_BACKEND',
122 'PG_START_BACKUP', 'PG_STOP_BACKUP',
126 # built-in functions that can be used without ()
127 # or conditional expressions
129 'CURRENT_DATE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP',
130 'LOCALTIME', 'LOCALTIMESTAMP',
132 'CURRENT_USER', 'SESSION_USER', 'USER',
138 PLPGSQL = [ # structure
139 'DECLARE', 'BEGIN', 'END',
141 'RECORD', 'DEFAULT', 'CONSTANT', 'ALIAS', 'FOR', 'TYPE', 'ROWTYPE',
144 'FOUND', 'PERFORM', 'GET', 'DIAGNOSTICS',
146 'RETURN', 'NEXT', 'IF', 'THEN', 'ELSE', 'END', 'ELSIF', 'LOOP',
147 'EXIT', 'WHILE', 'REVERSE', 'IN', 'EXCEPTION', 'WHEN',
149 'CURSOR', 'OPEN', 'EXECUTE', 'FETCH', 'INTO', 'CLOSE',
151 'RAISE', 'DEBUG', 'LOG', 'INFO', 'NOTICE', 'WARNING', 'EXCEPTION',
153 'NEW', 'OLD', 'TG_NAME', 'TG_WHEN', 'TG_LEVEL', 'TG_OP',
154 'TG_RELID', 'TG_RELNAME', 'TG_NARGS', 'TG_ARGV',
158 # keywords for each statement
159 KEYWORDS
= { 'ABORT' : [ 'WORK', 'TRANSACTION' ],
160 'ALTER' : { 'AGGREGATE' : [ [ 'RENAME', 'TO' ],
163 'CONVERSION' : [ [ 'RENAME', 'TO' ],
166 'DATABASE' : [ 'SET', 'TO', 'DEFAULT',
167 'RESET', [ 'RENAME', 'TO' ],
170 'DOMAIN' : [ [ 'SET', 'DEFAULT' ],
171 [ 'DROP', 'DEFAULT' ],
173 [ 'DROP', 'CONSTRAINT' ],
174 'RESTRICT', 'CASCADE',
177 'FUNCTION' : [ [ 'RENAME', 'TO' ],
180 'GROUP' : [ [ 'ADD', 'USER' ],
184 'INDEX' : [ [ 'RENAME', 'TO' ],
186 [ 'SET', 'TABLESPACE' ]
188 'LANGUAGE' : [ [ 'RENAME', 'TO' ] ],
189 'OPERATOR' : [ 'NONE', [ 'OWNER', 'TO' ],
192 'SCHEMA' : [ [ 'RENAME', 'TO' ],
195 'SEQUENCE' : [ [ 'INCREMENT', 'BY' ],
196 'MINVALUE', 'MAXVALUE',
197 [ 'RESTART', 'WITH' ], 'CACHE',
200 'TABLE' : [ 'ONLY', [ 'RENAME', 'COLUMN' ],
201 [ 'RENAME', 'TO' ], 'TO',
203 [ 'DROP', 'COLUMN' ], 'RESTRICT',
204 'CASCADE', 'TYPE', 'USING',
205 [ 'ALTER', 'COLUMN' ],
206 [ 'SET', 'DEFAULT' ],
207 [ 'DROP', 'DEFAULT' ],
209 [ 'SET', 'STATISTICS' ],
210 [ 'SET', 'STORAGE' ], 'PLAIN',
211 'EXTERNAL', 'EXTERNAL', 'MAIN',
212 [ 'DROP', 'CONSTRAINT' ],
214 [ 'SET', 'WITHOUT', 'CLUSTER' ],
215 [ 'SET', 'WITHOUT', 'OIDS' ],
217 [ 'SET', 'TABLESPACE' ],
219 [ 'FOREIGN', 'KEY' ], 'CASCADE',
220 [ 'PRIMARY', 'KEY' ],
222 [ 'ON', 'UPDATE' ], 'REFERENCES',
224 'TABLESPACE' : [ [ 'RENAME', 'TO' ],
227 'TRIGGER' : [ 'ON', [ 'RENAME', 'TO' ] ],
228 'TYPE' : [ [ 'OWNER', 'TO' ] ],
229 'USER' : [ 'WITH', 'CREATEDB', 'NOCREATEDB',
230 'CREATEUSER', 'NOCREATEUSER',
231 'ENCRYPTED', 'UNENCRYPTED',
232 'PASSWORD', [ 'VALID', 'UNTIL' ],
233 [ 'RENAME', 'TO' ], 'SET',
234 'TO', 'DEFAULT', 'RESET'
237 'ANALYZE' : [ 'VERBOSE' ],
238 'BEGIN' : [ 'WORK', 'TRANSACTION', [ 'ISOLATION', 'LEVEL' ],
239 'SERIALIZABLE', [ 'REPEATABLE', 'READ' ],
240 [ 'READ', 'COMMITTED' ], [ 'READ', 'UNCOMMITTED' ],
241 [ 'READ', 'WRITE' ], [ 'READ', 'ONLY' ]
245 'CLUSTER' : [ 'ON' ],
246 'COMMENT' : { 'ON' : [ 'TABLE', 'COLUMN', 'AGGREGATE', 'CAST',
247 'AS', 'CONSTRAINT', 'ON', 'CONVERSION',
248 'DATABASE', 'DOMAIN', 'FUNCTION', 'INDEX',
249 [ 'LARGE', 'OBJECT' ], 'OPERATOR',
250 [ 'OPERATOR', 'CLASS' ], 'USING',
251 'PROCEDURAL', 'LANGUAGE', 'RULE',
252 'SCHEMA', 'SEQUENCE', 'TRIGGER',
256 'COMMIT' : [ 'WORK', 'TRANSACTION' ],
257 'COPY' : [ 'FROM', 'STDIN', 'WITH', 'BINARY', 'OIDS',
258 'DELIMITER', 'CSV', 'AS', 'ESCAPE'
259 'FORCE', 'TO', 'STDOUT', 'QUOTE'
261 'CREATE' : { 'AGGREGATE' : [ 'BASETYPE', 'SFUNC', 'STYPE',
262 'FINALFUNC', 'INITCOND' ],
263 'CAST' : [ [ 'WITH', 'FUNCTION' ],
264 [ 'AS', 'ASSIGNMENT' ],
265 [ 'AS', 'IMPLICIT' ],
266 [ 'WITHOUT', 'FUNCTION']
268 'CONSTRAINT' : [ 'TRIGGER', 'AFTER', 'ON',
269 [ 'FOR', 'EACH', 'ROW', 'EXECUTE'
272 'CONVERSION' : [ 'FOR', 'TO', 'FROM' ],
273 'DEFAULT' : [ 'CONVERSION', 'FOR',
275 'DATABASE' : [ 'WITH', 'OWNER', 'TEMPLATE',
276 'ENCODING', 'TABLESPACE',
278 'DOMAIN' : [ 'AS', 'DEFAULT', 'CONSTRAINT',
281 'OR' : [ 'REPLACE', 'FUNCTION',
282 'RETURNS', 'LANGUAGE', 'AS',
283 'IMMUTABLE', 'STABLE',
284 'VOLATILE', [ 'CALLED', 'ON',
285 'NULL', 'INPUT' ], [ 'RETURNS',
286 'NULL', 'ON', 'NULL', 'INPUT' ],
287 'STRICT', 'EXTERNAL',
288 [ 'SECURITY', 'INVOKER' ],
289 [ 'SECURITY', 'DEFINER' ], 'WITH',
292 'AS', 'ON', 'TO', 'WHERE',
293 'DO', 'ALSO', 'INSTEAD',
297 'FUNCTION' : [ 'RETURNS', 'LANGUAGE', 'AS',
298 'IMMUTABLE', 'STABLE',
299 'VOLATILE', [ 'CALLED', 'ON',
300 'NULL', 'INPUT' ], [ 'RETURNS',
301 'NULL', 'ON', 'NULL', 'INPUT' ],
302 'STRICT', 'EXTERNAL',
303 [ 'SECURITY', 'INVOKER' ],
304 [ 'SECURITY', 'DEFINER' ], 'WITH'
306 'GROUP' : [ 'WITH', 'SYSID', 'USER' ],
307 'UNIQUE' : [ 'ON', 'USING', 'TABLESPACE',
309 'INDEX' : [ 'ON', 'USING', 'TABLESPACE',
310 'WHERE', 'RTREE', 'HASH' ],
311 'LANGUAGE' : [ 'HANDLER', 'VALIDATOR' ],
312 'PROCEDURAL' : [ 'HANDLER', 'VALIDATOR',
314 'TRUSTED' : [ 'HANDLER', 'VALIDATOR',
316 'OPERATOR' : [ 'PROCEDURE', 'LEFTARG',
317 'RIGHTARG', 'COMMUTATOR',
318 'NEGATOR', 'RESTRICT',
319 'JOIN', 'HASHES', 'MERGES',
320 'SORT1', 'SORT2', 'LTCMP',
323 [ 'FOR', 'TYPE' ], 'USING',
324 'AS', 'OPERATOR', 'RECHECK',
325 'FUNCTION', 'STORAGE' ],
326 'RULE' : [ 'AS', 'ON', 'TO', 'WHERE',
327 'DO', 'ALSO', 'INSTEAD',
329 'SCHEMA' : [ 'AUTHORIZATION' ],
330 'SEQUENCE' : [ 'INCREMENT', 'BY', 'MINVALUE',
331 'NO', 'MAXVALUE', [ 'START',
332 'WITH' ], 'CACHE', 'CYCLE' ],
333 'TEMPORARY' : [ 'SEQUENCE',
334 'INCREMENT', 'BY', 'MINVALUE',
335 'NO', 'MAXVALUE', [ 'START',
336 'WITH' ], 'CACHE', 'CYCLE',
339 'DEFAULT', 'INCLUDING',
340 'EXCLUDING', 'DEFAULTS',
344 [ 'PRESERVE', 'ROWS' ],
345 [ 'DELETE', 'ROWS' ], 'DROP',
346 'TABLESPACE', 'CONSTRAINT',
348 [ 'USING', 'INDEX', 'TABLESPACE'],
349 [ 'PRIMARY', 'KEY' ], 'CHECK',
350 'REFERENCES', [ 'MATCH', 'FULL' ],
351 [ 'MATCH', 'PARTIAL' ],
352 [ 'MATCH', 'SIMPLE' ],
354 [ 'ON', 'UPDATE' ], 'DEFERRABLE',
355 [ 'INITIALLY', 'DEFERRED' ],
356 [ 'INITIALLY', 'IMMEDIATE' ],
357 [ 'FOREIGN', 'KEY' ],
360 'TEMP' : [ 'SEQUENCE',
361 'INCREMENT', 'BY', 'MINVALUE',
362 'NO', 'MAXVALUE', [ 'START',
363 'WITH' ], 'CACHE', 'CYCLE',
366 'DEFAULT', 'INCLUDING',
367 'EXCLUDING', 'DEFAULTS',
368 'INHERITS', 'WITH', 'OIDS',
371 [ 'PRESERVE', 'ROWS' ],
372 [ 'DELETE', 'ROWS' ], 'DROP',
373 'TABLESPACE', 'CONSTRAINT',
375 [ 'USING', 'INDEX', 'TABLESPACE'],
376 [ 'PRIMARY', 'KEY' ], 'CHECK',
377 'REFERENCES', [ 'MATCH', 'FULL' ],
378 [ 'MATCH', 'PARTIAL' ],
379 [ 'MATCH', 'SIMPLE' ],
381 [ 'ON', 'UPDATE' ], 'DEFERRABLE',
382 [ 'INITIALLY', 'DEFERRED' ],
383 [ 'INITIALLY', 'IMMEDIATE' ],
384 [ 'FOREIGN', 'KEY' ],
388 'DEFAULT', 'INCLUDING',
389 'EXCLUDING', 'DEFAULTS',
393 [ 'PRESERVE', 'ROWS' ],
394 [ 'DELETE', 'ROWS' ], 'DROP',
395 'TABLESPACE', 'CONSTRAINT',
397 [ 'USING', 'INDEX', 'TABLESPACE'],
398 [ 'PRIMARY', 'KEY' ], 'CHECK',
399 'REFERENCES', [ 'MATCH', 'FULL' ],
400 [ 'MATCH', 'PARTIAL' ],
401 [ 'MATCH', 'SIMPLE' ],
403 [ 'ON', 'UPDATE' ], 'DEFERRABLE',
404 [ 'INITIALLY', 'DEFERRED' ],
405 [ 'INITIALLY', 'IMMEDIATE' ],
406 [ 'FOREIGN', 'KEY' ],
409 'GLOBAL' : [ 'TABLE',
410 'DEFAULT', 'INCLUDING',
411 'EXCLUDING', 'DEFAULTS',
412 'INHERITS', 'WITH', 'OIDS',
415 [ 'PRESERVE', 'ROWS' ],
416 [ 'DELETE', 'ROWS' ], 'DROP',
417 'TABLESPACE', 'CONSTRAINT',
419 [ 'USING', 'INDEX', 'TABLESPACE'],
420 [ 'PRIMARY', 'KEY' ], 'CHECK',
421 'REFERENCES', [ 'MATCH', 'FULL' ],
422 [ 'MATCH', 'PARTIAL' ],
423 [ 'MATCH', 'SIMPLE' ],
425 [ 'ON', 'UPDATE' ], 'DEFERRABLE',
426 [ 'INITIALLY', 'DEFERRED' ],
427 [ 'INITIALLY', 'IMMEDIATE' ],
428 [ 'FOREIGN', 'KEY' ],
431 'TABLE' : [ 'DEFAULT', 'INCLUDING',
432 'EXCLUDING', 'DEFAULTS',
433 'INHERITS', 'WITH', 'OIDS',
436 [ 'PRESERVE', 'ROWS' ],
437 [ 'DELETE', 'ROWS' ], 'DROP',
438 'TABLESPACE', 'CONSTRAINT',
440 [ 'USING', 'INDEX', 'TABLESPACE'],
441 [ 'PRIMARY', 'KEY' ], 'CHECK',
442 'REFERENCES', [ 'MATCH', 'FULL' ],
443 [ 'MATCH', 'PARTIAL' ],
444 [ 'MATCH', 'SIMPLE' ],
446 [ 'ON', 'UPDATE' ], 'DEFERRABLE',
447 'INITIALLY', 'DEFERRED',
448 'IMMEDIATE', 'RESTRICT',
449 [ 'FOREIGN', 'KEY' ], 'CASCADE'
452 'TABLESPACE' : [ 'OWNER', 'LOCATION' ],
453 'TRIGGER' : [ 'BEFORE', 'AFTER', 'OR', 'ON',
454 'FOR', 'EACH', 'ROW', 'STATEMENT',
455 [ 'EXECUTE', 'PROCEDURE' ]
457 'TYPE' : [ 'AS', 'INPUT', 'OUTPUT',
458 'RECEIVE', 'SEND', 'ANALYZE',
459 'INTERNALLENGTH', 'VARIABLE',
460 'PASSEDBYVALUE', 'ALIGNMENT',
461 'STORAGE', 'DEFAULT',
462 'ELEMENT', 'DELIMITER' ],
463 'USER' : [ 'WITH', 'SYSID', 'CREATEDB',
464 'NOCREATEDB', 'CREATEUSER',
465 'NOCREATEUSER', [ 'IN', 'GROUP' ],
466 'ENCRYPTED', 'UNENCRYPTED',
467 'PASSWORD', [ 'VALID', 'UNTIL' ]
471 'SELECT', 'DISTINCT', 'ON',
472 'AS', 'FROM', 'WHERE',
473 [ 'GROUP', 'BY' ], 'HAVING',
474 'UNION', 'INTERSECT', 'EXCEPT',
475 [ 'ORDER', 'BY' ], 'ASC',
476 'DESC', 'USING', 'LIMIT',
477 'OFFSET', [ 'FOR', 'UPDATE',
478 'OF' ], 'ONLY', 'NATURAL',
479 'USING', 'INNER', 'LEFT', 'OUTER',
480 'RIGHT', 'FULL', 'JOIN', 'CROSS',
483 'DEALLOCATE': [ 'PREPARE' ],
484 'DECLARE' : [ 'BINARY', 'INSENSITIVE', 'NO', 'SCROLL',
485 'CURSOR', 'WITH', 'WITHOUT', 'HOLD', 'FOR',
486 [ 'READ', 'ONLY' ], 'UPDATE', 'OF' ],
487 'DELETE' : { 'FROM' : [ 'ONLY', 'WHERE' ] },
488 'DROP' : { 'AGGREGATE' : [ 'CASCADE', 'RESTRICT' ],
489 'CAST' : [ 'AS', 'CASCADE', 'RESTRICT' ],
490 'CONVERSION' : [ 'CASCADE', 'RESTRICT' ],
492 'DOMAIN' : [ 'CASCADE', 'RESTRICT' ],
493 'FUNCTION' : [ 'CASCADE', 'RESTRICT' ],
495 'INDEX' : [ 'CASCADE', 'RESTRICT' ],
496 'LANGUAGE' : [ 'CASCADE', 'RESTRICT' ],
497 'PROCEDURAL' : ['LANGUAGE', 'CASCADE', 'RESTRICT'],
498 'OPERATOR' : [ 'NONE', 'CASCADE', 'RESTRICT',
500 'RULE' : [ 'ON', 'CASCADE', 'RESTRICT' ],
501 'SCHEMA' : [ 'CASCADE', 'RESTRICT' ],
502 'SEQUENCE' : [ 'CASCADE', 'RESTRICT' ],
503 'TABLE' : [ 'CASCADE', 'RESTRICT' ],
505 'TRIGGER' : [ 'ON', 'CASCADE', 'RESTRICT' ],
506 'TYPE' : [ 'CASCADE', 'RESTRICT' ],
508 'VIEW' : [ 'CASCADE', 'RESTRICT' ],
510 'END' : [ 'WORK', 'TRANSACTION' ],
512 'EXPLAIN' : [ 'ANALYZE', 'VERBOSE' ],
513 'FETCH' : [ 'FROM', 'IN', 'NEXT', 'PRIOR', 'FIRST', 'LAST',
514 'ABSOLUTE', 'RELATIVE', 'FORWARD',
516 'GRANT' : [ 'SELECT', 'INSERT', 'UPDATE', 'DELETE', 'RULE',
517 'REFERENCES', 'TRIGGER', 'PRIVILEGES',
518 'ON', 'TABLE', 'TO', 'GROUP', 'PUBLIC',
519 [ 'WITH', 'GRANT', 'OPTION' ],
520 'CREATE', 'TEMPORARY', 'TEMP', 'PRIVILEGES',
521 'DATABASE', 'EXECUTE', 'FUNCTION', 'USAGE',
522 'LANGUAGE', 'SCHEMA', 'TABLESPACE' ],
523 'INSERT' : { 'INTO' : [ 'DEFAULT', 'VALUES',
524 'SELECT', 'DISTINCT', 'ON', 'AS',
525 'FROM', 'WHERE', [ 'GROUP', 'BY' ],
526 'HAVING', 'UNION', 'INTERSECT', 'EXCEPT',
528 'ASC', 'DESC', 'USING', 'LIMIT',
529 'OFFSET', [ 'FOR', 'UPDATE', 'OF' ],
530 'ONLY', 'NATURAL', 'USING', 'INNER',
531 'LEFT', 'OUTER', 'RIGHT', 'FULL',
532 'JOIN', 'CROSS', 'INTO',
537 'LOCK' : [ 'TABLE', 'IN', 'MODE', 'NOWAIT',
538 [ 'ACCESS', 'SHARE' ], [ 'ROW', 'SHARE' ],
539 [ 'ROW', 'EXCLUSIVE' ],
540 [ 'SHARE', 'UPDATE', 'EXCLUSIVE' ],
541 'SHARE', [ 'SHARE', 'ROW', 'EXCLUSIVE' ],
542 'EXCLUSIVE', [ 'ACCESS', 'EXCLUSIVE' ] ],
543 'MOVE' : [ 'FROM', 'IN' ],
545 'PREPARE' : [ 'AS' ],
546 'REINDEX' : [ 'DATABASE', 'TABLE', 'TABLE', 'FORCE' ],
547 'RELEASE' : [ 'SAVEPOINT' ],
549 'REVOKE' : [ [ 'GRANT', 'OPTION', 'FOR' ], 'SELECT', 'INSERT',
550 'UPDATE', 'DELETE', 'RULE', 'REFERENCES',
551 'TRIGGER', 'PRIVILEGES', 'ON', 'TABLE',
552 'FROM', 'GROUP', 'PUBLIC', 'CASCADE', 'RESTRICT',
553 'CREATE', 'TEMPORARY', 'TEMP', 'EXECUTE',
554 'USAGE', 'SCHEMA', 'LANGUAGE', 'TABLESPACE' ],
555 'ROLLBACK' : [ 'WORK', 'TRANSACTION', 'TO', 'SAVEPOINT' ],
558 'SELECT' : [ 'SELECT', 'INTO', 'DISTINCT', 'ON', 'AS', 'FROM',
559 'WHERE', [ 'GROUP', 'BY' ], 'HAVING', 'UNION',
560 'INTERSECT', 'EXCEPT', [ 'ORDER', 'BY' ],
561 'ASC', 'DESC', 'USING', 'LIMIT', 'OFFSET',
562 [ 'FOR', 'UPDATE', 'OF' ], 'ONLY', 'NATURAL',
563 'USING', 'INNER', 'LEFT', 'OUTER', 'RIGHT', 'FULL',
564 'JOIN', 'CROSS', 'INTO' ],
565 'SET' : [ 'SESSION', 'LOCAL', 'TO', 'DEFAULT', 'LOCAL',
566 [ 'TIME', 'ZONE' ], 'CONSTRAINTS',
567 'DEFERRED', 'IMMEDIATE', 'AUTHORIZATION',
568 'TRANSACTION', 'CHARACTERISTICS',
569 [ 'ISOLATION', 'LEVEL' ], 'SERIALIZABLE',
570 [ 'REPEATABLE', 'READ' ], [ 'READ', 'COMMITTED' ],
571 [ 'READ', 'UNCOMMITTED' ], [ 'READ', 'WRITE' ],
575 'START' : { 'TRANSACTION' : [ [ 'ISOLATION', 'LEVEL' ],
577 [ 'REPEATABLE', 'READ' ],
578 [ 'READ', 'COMMITTED' ],
579 [ 'READ', 'UNCOMMITTED' ],
584 'TRUNCATE' : [ 'TABLE' ],
586 'UPDATE' : [ 'ONLY', 'SET', 'DEFAULT', 'FROM', 'WHERE' ],
587 'VACUUM' : [ 'FULL', 'FREEZE', 'VERBOSE', 'ANALYSE' ]
592 """Syntax highlight"""
594 def __init__(self
, buffer):
595 self
.lexical
= pgw
.Lexical
.Lexical()
600 self
.tag
['font'] = self
.buffer.create_tag("font")
601 if (pgw
.mswindows()):
602 self
.tag
['font'].set_property('font', 'Courier New 10')
604 self
.tag
['font'].set_property('family', 'monospace')
605 self
.tag
['function'] = self
.buffer.create_tag("function")
606 self
.tag
['function'].set_property('foreground', '#009999')
607 self
.tag
['dollarquote'] = self
.buffer.create_tag("dollarquote")
608 self
.tag
['dollarquote'].set_property('foreground', '#000000')
609 self
.tag
['identifier'] = self
.buffer.create_tag("identifier")
610 self
.tag
['identifier'].set_property('foreground', '#000000')
611 self
.tag
['keyword'] = self
.buffer.create_tag("keyword")
612 self
.tag
['keyword'].set_property('foreground', '#0000FF')
613 self
.tag
['type'] = self
.buffer.create_tag("type")
614 self
.tag
['type'].set_property('foreground', '#009900')
615 self
.tag
['string'] = self
.buffer.create_tag("string")
616 self
.tag
['string'].set_property('foreground', '#F700BF')
617 self
.tag
['numeric_constant'] = self
.buffer.create_tag("numeric_constant")
618 self
.tag
['numeric_constant'].set_property('foreground', '#c53838')
619 self
.tag
['special'] = self
.buffer.create_tag("special")
620 self
.tag
['special'].set_property('foreground', '#c53838')
621 self
.tag
['comment'] = self
.buffer.create_tag("comment")
622 self
.tag
['comment'].set_property('foreground', '#999999')
623 self
.tag
['comment2'] = self
.buffer.create_tag("comment2")
624 self
.tag
['comment2'].set_property('style', pango
.STYLE_ITALIC
)
625 self
.tag
['operator'] = self
.buffer.create_tag("operator")
626 self
.tag
['operator'].set_property('foreground', '#555555')
627 self
.tag
['psql'] = self
.buffer.create_tag("psql")
628 self
.tag
['psql'].set_property('background', '#d0d4df')
631 def start_of_prev_statement(self
, iter):
632 """Find the first character of a statement"""
633 if (self
.last
is not None):
635 for token
in self
.last
:
636 if (token
.start_iter
.compare(iter) >= 0):
637 if (self
.found
is None):
639 return self
.found
.start_iter
640 if (token
.value
== ';'):
643 return self
.found
.start_iter
644 return iter.get_buffer().get_start_iter()
647 def start_of_next_statement(self
, iter):
648 """Find the last character of a statement"""
649 if (self
.last
is not None):
651 for token
in reversed(self
.last
):
652 if (token
.end_iter
.compare(iter) <= 0):
653 if (self
.found
is None):
655 return self
.found
.end_iter
656 if (token
.value
== ';'):
659 return self
.found
.end_iter
660 return iter.get_buffer().get_end_iter()
663 def text_inserted(self
, buffer, iter, text
, length
):
664 """Called by Gtk when text is inserted in the buffer:
665 prepare 'start' and 'end' for text_changed()"""
666 self
.start
= self
.start_of_prev_statement(iter.copy()).get_offset()
667 self
.end
= self
.start_of_next_statement(iter.copy()).get_offset() + length
670 def text_deleted(self
, buffer, start
, end
):
671 """Called by Gtk when text is deleted from the buffer:
672 prepare 'start' and 'end' for text_changed()"""
673 self
.start
= self
.start_of_prev_statement(start
.copy()).get_offset()
674 self
.end
= self
.start_of_next_statement(end
.copy()).get_offset()
677 def text_changed(self
, buffer):
678 """Called by Gtk when (after) text is deleted or inserted
679 in the buffer. Uses 'start' and 'end' prepared in text_inserted
680 and text_deleted then run the analyse"""
681 start
= self
.buffer.get_iter_at_offset(self
.start
)
682 end
= self
.buffer.get_iter_at_offset(self
.end
)
683 self
.analyse(start
, end
)
687 """Used when you want to manually refresh the syntax highlight
688 of the whole buffer"""
689 start
= self
.buffer.get_start_iter()
690 end
= self
.buffer.get_end_iter()
691 self
.analyse(start
, end
)
694 def analyse(self
, start
, end
):
695 """Run the lexical and syntaxical analysers then
696 apply the syntax highlight to the buffer"""
697 self
.tokens
= self
.lexical
.analyse(self
.buffer, start
, end
)
698 self
.syntaxical_analyser()
699 self
.buffer.remove_all_tags(start
, end
)
700 self
.buffer.apply_tag(self
.tag
['font'], start
, end
)
701 self
.last
= self
.tokens
702 for token
in self
.tokens
:
703 self
.buffer.apply_tag(self
.tag
[token
.token
], \
706 if (token
.token
== 'comment'):
707 self
.buffer.apply_tag(self
.tag
['comment2'], \
712 def syntaxical_analyser(self
):
717 while (len(tokens
) > 0):
718 token
= tokens
.pop(0)
719 # only statements, other tokens
720 # are analysed below or already founds in
721 # the lexical analyser
722 if (token
.value
in STATEMENTS
):
723 token
.token
= 'keyword'
724 self
.tokens
.append(token
)
725 statement
= token
.value
726 token
= tokens
.pop(0)
727 # get the list containing the
728 # keywords for this statement
730 keywords
= KEYWORDS
[statement
]
733 if (type(keywords
) is dict):
735 keywords
= keywords
[token
.value
]
736 token
.token
= 'keyword'
737 self
.tokens
.append(token
)
738 token
= tokens
.pop(0)
741 self
.tokens
.append(token
)
742 # identify each token inside the statement
743 while (token
.value
!= ';'):
744 # only identifiers, other tokens are
745 # analysed in the lexical analyser
746 if (token
.token
== 'identifier'):
748 if (token
.value
in SPECIALS
):
749 token
.token
= 'special'
751 elif (token
.value
in TYPES
):
752 # TODO : manage composed types names
755 elif (token
.value
in OPERATORS2
):
756 token
.token
= 'operator'
758 elif (token
.value
in BUILTINS
):
760 if (next
.value
== '('):
761 token
.token
= 'function'
762 self
.tokens
.append(next
)
764 tokens
.insert(0, next
)
765 # built-in function that can be used without ()
766 if (token
.value
in BUILTINS2
):
767 token
.token
= 'function'
768 # everything else : keywords or indentifiers
770 for keyword
in keywords
:
771 if (type(keyword
) is list):
772 # TODO : write the right code here
773 # to manage composed keywords
774 if (token
.value
in keyword
):
775 token
.token
= 'keyword'
776 elif (token
.value
== keyword
):
777 token
.token
= 'keyword'
778 self
.tokens
.append(token
)
779 token
= tokens
.pop(0)
780 self
.tokens
.append(token
)