Class: PgQuery
- Inherits:
-
Object
- Object
- PgQuery
- Defined in:
- lib/pg_query/node_types.rb,
lib/pg_query/parse.rb,
lib/pg_query/deparse.rb,
lib/pg_query/version.rb,
lib/pg_query/deep_dup.rb,
lib/pg_query/truncate.rb,
lib/pg_query/param_refs.rb,
lib/pg_query/treewalker.rb,
lib/pg_query/fingerprint.rb,
lib/pg_query/parse_error.rb,
lib/pg_query/deparse/rename.rb,
lib/pg_query/filter_columns.rb,
lib/pg_query/deparse/interval.rb,
lib/pg_query/deparse/keywords.rb,
lib/pg_query/legacy_parsetree.rb,
lib/pg_query/deparse/alter_table.rb
Overview
rubocop:disable Style/ConstantName
Defined Under Namespace
Modules: Deparse Classes: FingerprintSubHash, ParseError, PossibleTruncation
Constant Summary collapse
- VERSION =
'1.3.0'.freeze
- A_TRUNCATED =
'A_Truncated'.freeze
- A_ARRAY_EXPR =
NODE TYPES
'A_ArrayExpr'.freeze
- A_CONST =
'A_Const'.freeze
- A_EXPR =
'A_Expr'.freeze
- A_INDICES =
'A_Indices'.freeze
- A_INDIRECTION =
'A_Indirection'.freeze
- A_STAR =
'A_Star'.freeze
- ACCESS_PRIV =
'AccessPriv'.freeze
- ALIAS =
'Alias'.freeze
- ALTER_TABLE_CMD =
'AlterTableCmd'.freeze
- ALTER_TABLE_STMT =
'AlterTableStmt'.freeze
- BIT_STRING =
'BitString'.freeze
- BOOL_EXPR =
'BoolExpr'.freeze
- BOOLEAN_TEST =
'BooleanTest'.freeze
- CASE_EXPR =
'CaseExpr'.freeze
- CASE_WHEN =
'CaseWhen'.freeze
- CHECK_POINT_STMT =
'CheckPointStmt'.freeze
- CLOSE_PORTAL_STMT =
'ClosePortalStmt'.freeze
- COALESCE_EXPR =
'CoalesceExpr'.freeze
- COLLATE_CLAUSE =
'CollateClause'.freeze
- COLUMN_DEF =
'ColumnDef'.freeze
- COLUMN_REF =
'ColumnRef'.freeze
- COMMON_TABLE_EXPR =
'CommonTableExpr'.freeze
- COMPOSITE_TYPE_STMT =
'CompositeTypeStmt'.freeze
- CONSTRAINT =
'Constraint'.freeze
- COPY_STMT =
'CopyStmt'.freeze
- CREATE_CAST_STMT =
'CreateCastStmt'.freeze
- CREATE_DOMAIN_STMT =
'CreateDomainStmt'.freeze
- CREATE_ENUM_STMT =
'CreateEnumStmt'.freeze
- CREATE_FUNCTION_STMT =
'CreateFunctionStmt'.freeze
- CREATE_RANGE_STMT =
'CreateRangeStmt'.freeze
- CREATE_SCHEMA_STMT =
'CreateSchemaStmt'.freeze
- CREATE_STMT =
'CreateStmt'.freeze
- CREATE_TABLE_AS_STMT =
'CreateTableAsStmt'.freeze
- CREATE_TRIG_STMT =
'CreateTrigStmt'.freeze
- DEALLOCATE_STMT =
'DeallocateStmt'.freeze
- DECLARE_CURSOR_STMT =
'DeclareCursorStmt'.freeze
- DEF_ELEM =
'DefElem'.freeze
- DEFINE_STMT =
'DefineStmt'.freeze
- DELETE_STMT =
'DeleteStmt'.freeze
- DISCARD_STMT =
'DiscardStmt'.freeze
- DO_STMT =
'DoStmt'.freeze
- DROP_STMT =
'DropStmt'.freeze
- DROP_SUBSCRIPTION =
'DropSubscriptionStmt'.freeze
- DROP_TABLESPACE =
'DropTableSpaceStmt'.freeze
- DROP_ROLE =
'DropRoleStmt'.freeze
- EXECUTE_STMT =
'ExecuteStmt'.freeze
- EXPLAIN_STMT =
'ExplainStmt'.freeze
- FETCH_STMT =
'FetchStmt'.freeze
- FLOAT =
'Float'.freeze
- FUNC_CALL =
'FuncCall'.freeze
- FUNCTION_PARAMETER =
'FunctionParameter'.freeze
- GRANT_ROLE_STMT =
'GrantRoleStmt'.freeze
- GRANT_STMT =
'GrantStmt'.freeze
- INDEX_ELEM =
'IndexElem'.freeze
- INDEX_STMT =
'IndexStmt'.freeze
- INSERT_STMT =
'InsertStmt'.freeze
- INT_LIST =
'IntList'.freeze
- INTEGER =
'Integer'.freeze
- INTO_CLAUSE =
'IntoClause'.freeze
- JOIN_EXPR =
'JoinExpr'.freeze
- LOCK_STMT =
'LockStmt'.freeze
- LOCKING_CLAUSE =
'LockingClause'.freeze
- NULL =
'Null'.freeze
- NULL_TEST =
'NullTest'.freeze
- OBJECT_WITH_ARGS =
'ObjectWithArgs'.freeze
- OID_LIST =
'OidList'.freeze
- ON_CONFLICT_CLAUSE =
'OnConflictClause'.freeze
- PARAM_REF =
'ParamRef'.freeze
- PREPARE_STMT =
'PrepareStmt'.freeze
- RANGE_FUNCTION =
'RangeFunction'.freeze
- RANGE_SUBSELECT =
'RangeSubselect'.freeze
- RANGE_VAR =
'RangeVar'.freeze
- RAW_STMT =
'RawStmt'.freeze
- REFRESH_MAT_VIEW_STMT =
'RefreshMatViewStmt'.freeze
- RENAME_STMT =
'RenameStmt'.freeze
- RES_TARGET =
'ResTarget'.freeze
- ROLE_SPEC =
'RoleSpec'.freeze
- ROW_EXPR =
'RowExpr'.freeze
- RULE_STMT =
'RuleStmt'.freeze
- SELECT_STMT =
'SelectStmt'.freeze
- SET_TO_DEFAULT =
'SetToDefault'.freeze
- SORT_BY =
'SortBy'.freeze
- SQL_VALUE_FUNCTION =
'SQLValueFunction'.freeze
- STRING =
'String'.freeze
- SUB_LINK =
'SubLink'.freeze
- TRANSACTION_STMT =
'TransactionStmt'.freeze
- TRUNCATE_STMT =
'TruncateStmt'.freeze
- TYPE_CAST =
'TypeCast'.freeze
- TYPE_NAME =
'TypeName'.freeze
- UPDATE_STMT =
'UpdateStmt'.freeze
- VACUUM_STMT =
'VacuumStmt'.freeze
- VARIABLE_SET_STMT =
'VariableSetStmt'.freeze
- VARIABLE_SHOW_STMT =
'VariableShowStmt'.freeze
- VIEW_STMT =
'ViewStmt'.freeze
- WINDOW_DEF =
'WindowDef'.freeze
- WITH_CLAUSE =
'WithClause'.freeze
- COLS_FIELD =
FIELDS
'cols'.freeze
- FROM_CLAUSE_FIELD =
'fromClause'.freeze
- RELPERSISTENCE_FIELD =
'relpersistence'.freeze
- REXPR_FIELD =
'rexpr'.freeze
- STMT_FIELD =
'stmt'.freeze
- TARGET_LIST_FIELD =
'targetList'.freeze
- VALUES_LISTS_FIELD =
'valuesLists'.freeze
- CONSTR_TYPE_NULL =
ENUMS
0
- CONSTR_TYPE_NOTNULL =
not standard SQL, but a lot of people expect it
1
- CONSTR_TYPE_DEFAULT =
2
- CONSTR_TYPE_IDENTITY =
3
- CONSTR_TYPE_CHECK =
4
- CONSTR_TYPE_PRIMARY =
5
- CONSTR_TYPE_UNIQUE =
6
- CONSTR_TYPE_EXCLUSION =
7
- CONSTR_TYPE_FOREIGN =
8
- CONSTR_TYPE_ATTR_DEFERRABLE =
attributes for previous constraint node
9
- CONSTR_TYPE_ATTR_NOT_DEFERRABLE =
10
- CONSTR_TYPE_ATTR_DEFERRED =
11
- CONSTR_TYPE_ATTR_IMMEDIATE =
12
- OBJECT_TYPE_ACCESS_METHOD =
0
- OBJECT_TYPE_AGGREGATE =
1
- OBJECT_TYPE_AMOP =
2
- OBJECT_TYPE_AMPROC =
3
- OBJECT_TYPE_ATTRIBUTE =
4
- OBJECT_TYPE_CAST =
5
- OBJECT_TYPE_COLUMN =
6
- OBJECT_TYPE_COLLATION =
7
- OBJECT_TYPE_CONVERSION =
8
- OBJECT_TYPE_DATABASE =
9
- OBJECT_TYPE_DEFAULT =
10
- OBJECT_TYPE_DEFACL =
11
- OBJECT_TYPE_DOMAIN =
12
- OBJECT_TYPE_DOMCONSTRAINT =
13
- OBJECT_TYPE_EVENT_TRIGGER =
14
- OBJECT_TYPE_EXTENSION =
15
- OBJECT_TYPE_FDW =
16
- OBJECT_TYPE_FOREIGN_SERVER =
17
- OBJECT_TYPE_FOREIGN_TABLE =
18
- OBJECT_TYPE_FUNCTION =
19
- OBJECT_TYPE_INDEX =
20
- OBJECT_TYPE_LANGUAGE =
21
- OBJECT_TYPE_LARGEOBJECT =
22
- OBJECT_TYPE_MATVIEW =
23
- OBJECT_TYPE_OPCLASS =
24
- OBJECT_TYPE_OPERATOR =
25
- OBJECT_TYPE_OPFAMILY =
26
- OBJECT_TYPE_POLICY =
27
- OBJECT_TYPE_PUBLICATION =
28
- OBJECT_TYPE_PUBLICATION_REL =
29
- OBJECT_TYPE_ROLE =
30
- OBJECT_TYPE_RULE =
31
- OBJECT_TYPE_SCHEMA =
32
- OBJECT_TYPE_SEQUENCE =
33
- OBJECT_TYPE_SUBSCRIPTION =
34
- OBJECT_TYPE_STATISTIC_EXT =
35
- OBJECT_TYPE_TABCONSTRAINT =
36
- OBJECT_TYPE_TABLE =
37
- OBJECT_TYPE_TABLESPACE =
38
- OBJECT_TYPE_TRANSFORM =
39
- OBJECT_TYPE_TRIGGER =
40
- OBJECT_TYPE_TSCONFIGURATION =
41
- OBJECT_TYPE_TSDICTIONARY =
42
- OBJECT_TYPE_TSPARSER =
43
- OBJECT_TYPE_TSTEMPLATE =
44
- OBJECT_TYPE_TYPE =
45
- OBJECT_TYPE_USER_MAPPING =
46
- OBJECT_TYPE_VIEW =
47
- BOOL_EXPR_AND =
0
- BOOL_EXPR_OR =
1
- BOOL_EXPR_NOT =
2
- BOOLEAN_TEST_TRUE =
0
- BOOLEAN_TEST_NOT_TRUE =
1
- BOOLEAN_TEST_FALSE =
2
- BOOLEAN_TEST_NOT_FALSE =
3
- BOOLEAN_TEST_UNKNOWN =
4
- BOOLEAN_TEST_NOT_UNKNOWN =
5
- AEXPR_OP =
normal operator
0
- AEXPR_OP_ANY =
scalar op ANY (array)
1
- AEXPR_OP_ALL =
scalar op ALL (array)
2
- AEXPR_DISTINCT =
IS DISTINCT FROM - name must be “=”
3
- AEXPR_NOT_DISTINCT =
IS NOT DISTINCT FROM - name must be “=”
4
- AEXPR_NULLIF =
NULLIF - name must be “=”
5
- AEXPR_OF =
IS [NOT] OF - name must be “=” or “<>”
6
- AEXPR_IN =
- NOT
-
IN - name must be “=” or “<>”
7
- AEXPR_LIKE =
- NOT
-
LIKE - name must be “~~” or “!~~”
8
- AEXPR_ILIKE =
- NOT
-
ILIKE - name must be “~~*” or “!~~*”
9
- AEXPR_SIMILAR =
- NOT
-
SIMILAR - name must be “~” or “!~”
10
- AEXPR_BETWEEN =
name must be “BETWEEN”
11
- AEXPR_NOT_BETWEEN =
name must be “NOT BETWEEN”
12
- AEXPR_BETWEEN_SYM =
name must be “BETWEEN SYMMETRIC”
13
- AEXPR_NOT_BETWEEN_SYM =
name must be “NOT BETWEEN SYMMETRIC”
14
- AEXPR_PAREN =
nameless dummy node for parentheses
15
- TRANS_STMT_BEGIN =
0
- TRANS_STMT_START =
semantically identical to BEGIN
1
- TRANS_STMT_COMMIT =
2
- TRANS_STMT_ROLLBACK =
3
- TRANS_STMT_SAVEPOINT =
4
- TRANS_STMT_RELEASE =
5
- TRANS_STMT_ROLLBACK_TO =
6
- TRANS_STMT_PREPARE =
7
- TRANS_STMT_COMMIT_PREPARED =
8
- TRANS_STMT_ROLLBACK_PREPARED =
9
- SUBLINK_TYPE_EXISTS =
EXISTS(SELECT …)
0
- SUBLINK_TYPE_ALL =
(lefthand) op ALL (SELECT …)
1
- SUBLINK_TYPE_ANY =
(lefthand) op ANY (SELECT …)
2
- SUBLINK_TYPE_ROWCOMPARE =
(lefthand) op (SELECT …)
3
- SUBLINK_TYPE_EXPR =
(SELECT with single targetlist item …)
4
- SUBLINK_TYPE_MULTIEXPR =
(SELECT with multiple targetlist items …)
5
- SUBLINK_TYPE_ARRAY =
ARRAY(SELECT with single targetlist item …)
6
- SUBLINK_TYPE_CTE =
WITH query (never actually part of an expression), for SubPlans only
7
- LCS_NONE =
no such clause - only used in PlanRowMark
0
- LCS_FORKEYSHARE =
FOR KEY SHARE
1
- LCS_FORSHARE =
FOR SHARE
2
- LCS_FORNOKEYUPDATE =
FOR NO KEY UPDATE
3
- LCS_FORUPDATE =
FOR UPDATE
4
- AT_AddColumn =
add column
0
- AT_AddColumnRecurse =
internal to commands/tablecmds.c
1
- AT_AddColumnToView =
implicitly via CREATE OR REPLACE VIEW
2
- AT_ColumnDefault =
alter column default
3
- AT_DropNotNull =
alter column drop not null
4
- AT_SetNotNull =
alter column set not null
5
- AT_SetStatistics =
alter column set statistics
6
- AT_SetOptions =
alter column set ( options )
7
- AT_ResetOptions =
alter column reset ( options )
8
- AT_SetStorage =
alter column set storage
9
- AT_DropColumn =
drop column
10
- AT_DropColumnRecurse =
internal to commands/tablecmds.c
11
- AT_AddIndex =
add index
12
- AT_ReAddIndex =
internal to commands/tablecmds.c
13
- AT_AddConstraint =
add constraint
14
- AT_AddConstraintRecurse =
internal to commands/tablecmds.c
15
- AT_ReAddConstraint =
internal to commands/tablecmds.c
16
- AT_AlterConstraint =
alter constraint
17
- AT_ValidateConstraint =
validate constraint
18
- AT_ValidateConstraintRecurse =
internal to commands/tablecmds.c
19
- AT_ProcessedConstraint =
pre-processed add constraint (local in parser/parse_utilcmd.c)
20
- AT_AddIndexConstraint =
add constraint using existing index
21
- AT_DropConstraint =
drop constraint
22
- AT_DropConstraintRecurse =
internal to commands/tablecmds.c
23
- AT_ReAddComment =
internal to commands/tablecmds.c
24
- AT_AlterColumnType =
alter column type
25
- AT_AlterColumnGenericOptions =
alter column OPTIONS (…)
26
- AT_ChangeOwner =
change owner
27
- AT_ClusterOn =
CLUSTER ON
28
- AT_DropCluster =
SET WITHOUT CLUSTER
29
- AT_SetLogged =
SET LOGGED
30
- AT_SetUnLogged =
SET UNLOGGED
31
- AT_AddOids =
SET WITH OIDS
32
- AT_AddOidsRecurse =
internal to commands/tablecmds.c
33
- AT_DropOids =
SET WITHOUT OIDS
34
- AT_SetTableSpace =
SET TABLESPACE
35
- AT_SetRelOptions =
SET (…) – AM specific parameters
36
- AT_ResetRelOptions =
RESET (…) – AM specific parameters
37
- AT_ReplaceRelOptions =
replace reloption list in its entirety
38
- AT_EnableTrig =
ENABLE TRIGGER name
39
- AT_EnableAlwaysTrig =
ENABLE ALWAYS TRIGGER name
40
- AT_EnableReplicaTrig =
ENABLE REPLICA TRIGGER name
41
- AT_DisableTrig =
DISABLE TRIGGER name
42
- AT_EnableTrigAll =
ENABLE TRIGGER ALL
43
- AT_DisableTrigAll =
DISABLE TRIGGER ALL
44
- AT_EnableTrigUser =
ENABLE TRIGGER USER
45
- AT_DisableTrigUser =
DISABLE TRIGGER USER
46
- AT_EnableRule =
ENABLE RULE name
47
- AT_EnableAlwaysRule =
ENABLE ALWAYS RULE name
48
- AT_EnableReplicaRule =
ENABLE REPLICA RULE name
49
- AT_DisableRule =
DISABLE RULE name
50
- AT_AddInherit =
INHERIT parent
51
- AT_DropInherit =
NO INHERIT parent
52
- AT_AddOf =
OF <type_name>
53
- AT_DropOf =
NOT OF
54
- AT_ReplicaIdentity =
REPLICA IDENTITY
55
- AT_EnableRowSecurity =
ENABLE ROW SECURITY
56
- AT_DisableRowSecurity =
DISABLE ROW SECURITY
57
- AT_ForceRowSecurity =
FORCE ROW SECURITY
58
- AT_NoForceRowSecurity =
NO FORCE ROW SECURITY
59
- AT_GenericOptions =
OPTIONS (…)
60
- AT_AttachPartition =
ATTACH PARTITION
61
- AT_DetachPartition =
DETACH PARTITION
62
- AT_AddIdentity =
ADD IDENTITY
63
- AT_SetIdentity =
SET identity column options
64
- AT_DropIdentity =
DROP IDENTITY
65
Instance Attribute Summary collapse
-
#query ⇒ Object
readonly
Returns the value of attribute query.
-
#tree ⇒ Object
readonly
Returns the value of attribute tree.
-
#warnings ⇒ Object
readonly
Returns the value of attribute warnings.
Class Method Summary collapse
Instance Method Summary collapse
- #aliases ⇒ Object
- #cte_names ⇒ Object
- #ddl_tables ⇒ Object
- #deep_dup(obj) ⇒ Object
-
#deparse(tree = @tree) ⇒ Object
Reconstruct all of the parsed queries into their original form.
- #dml_tables ⇒ Object
-
#filter_columns ⇒ Object
Returns a list of columns that the query filters by - this excludes the target list, but includes things like JOIN condition and WHERE clause.
- #fingerprint ⇒ Object
-
#initialize(query, tree, warnings = []) ⇒ PgQuery
constructor
A new instance of PgQuery.
-
#param_refs ⇒ Object
rubocop:disable Metrics/CyclomaticComplexity.
-
#parsetree ⇒ Object
Legacy parsetree from 0.7 and earlier versions - migrate to “tree” format if you can.
- #select_tables ⇒ Object
- #tables ⇒ Object
- #tables_with_types ⇒ Object
-
#truncate(max_length) ⇒ Object
Truncates the query string to be below the specified length, first trying to omit less important parts of the query, and only then cutting off the end.
Constructor Details
#initialize(query, tree, warnings = []) ⇒ PgQuery
Returns a new instance of PgQuery.
26 27 28 29 30 31 32 33 |
# File 'lib/pg_query/parse.rb', line 26 def initialize(query, tree, warnings = []) @query = query @tree = tree @warnings = warnings @tables = nil @aliases = nil @cte_names = nil end |
Instance Attribute Details
#query ⇒ Object (readonly)
Returns the value of attribute query.
22 23 24 |
# File 'lib/pg_query/parse.rb', line 22 def query @query end |
#tree ⇒ Object (readonly)
Returns the value of attribute tree.
23 24 25 |
# File 'lib/pg_query/parse.rb', line 23 def tree @tree end |
#warnings ⇒ Object (readonly)
Returns the value of attribute warnings.
24 25 26 |
# File 'lib/pg_query/parse.rb', line 24 def warnings @warnings end |
Class Method Details
._raw_parse ⇒ Object
7 |
# File 'ext/pg_query/pg_query_ruby.c', line 7
VALUE pg_query_ruby_parse(VALUE self, VALUE input);
|
.fingerprint ⇒ Object
9 |
# File 'ext/pg_query/pg_query_ruby.c', line 9
VALUE pg_query_ruby_fingerprint(VALUE self, VALUE input);
|
.normalize ⇒ Object
8 |
# File 'ext/pg_query/pg_query_ruby.c', line 8
VALUE pg_query_ruby_normalize(VALUE self, VALUE input);
|
.parse(query) ⇒ Object
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# File 'lib/pg_query/parse.rb', line 4 def self.parse(query) tree, stderr = _raw_parse(query) begin tree = JSON.parse(tree, max_nesting: 1000) rescue JSON::ParserError raise ParseError.new('Failed to parse JSON', __FILE__, __LINE__, -1) end warnings = [] stderr.each_line do |line| next unless line[/^WARNING/] warnings << line.strip end PgQuery.new(query, tree, warnings) end |
Instance Method Details
#aliases ⇒ Object
56 57 58 59 |
# File 'lib/pg_query/parse.rb', line 56 def aliases load_tables_and_aliases! if @aliases.nil? @aliases end |
#cte_names ⇒ Object
51 52 53 54 |
# File 'lib/pg_query/parse.rb', line 51 def cte_names load_tables_and_aliases! if @cte_names.nil? @cte_names end |
#ddl_tables ⇒ Object
47 48 49 |
# File 'lib/pg_query/parse.rb', line 47 def ddl_tables tables_with_types.select { |t| t[:type] == :ddl }.map { |t| t[:table] } end |
#deep_dup(obj) ⇒ Object
2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# File 'lib/pg_query/deep_dup.rb', line 2 def deep_dup(obj) case obj when Hash obj.each_with_object(obj.dup) do |(key, value), hash| hash[deep_dup(key)] = deep_dup(value) end when Array obj.map { |it| deep_dup(it) } when NilClass, FalseClass, TrueClass, Symbol, Numeric obj # Can't be duplicated else obj.dup end end |
#deparse(tree = @tree) ⇒ Object
Reconstruct all of the parsed queries into their original form
8 9 10 11 12 |
# File 'lib/pg_query/deparse.rb', line 8 def deparse(tree = @tree) tree.map do |item| Deparse.from(item) end.join('; ') end |
#dml_tables ⇒ Object
43 44 45 |
# File 'lib/pg_query/parse.rb', line 43 def dml_tables tables_with_types.select { |t| t[:type] == :dml }.map { |t| t[:table] } end |
#filter_columns ⇒ Object
Returns a list of columns that the query filters by - this excludes the target list, but includes things like JOIN condition and WHERE clause.
Note: This also traverses into sub-selects.
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/pg_query/filter_columns.rb', line 6 def filter_columns # rubocop:disable Metrics/CyclomaticComplexity load_tables_and_aliases! if @aliases.nil? # Get condition items from the parsetree statements = @tree.dup condition_items = [] filter_columns = [] loop do statement = statements.shift if statement if statement[RAW_STMT] statements << statement[RAW_STMT][STMT_FIELD] elsif statement[SELECT_STMT] case statement[SELECT_STMT]['op'] when 0 if statement[SELECT_STMT][FROM_CLAUSE_FIELD] # FROM subselects statement[SELECT_STMT][FROM_CLAUSE_FIELD].each do |item| next unless item['RangeSubselect'] statements << item['RangeSubselect']['subquery'] end # JOIN ON conditions condition_items += conditions_from_join_clauses(statement[SELECT_STMT][FROM_CLAUSE_FIELD]) end # WHERE clause condition_items << statement[SELECT_STMT]['whereClause'] if statement[SELECT_STMT]['whereClause'] # CTEs if statement[SELECT_STMT]['withClause'] statement[SELECT_STMT]['withClause']['WithClause']['ctes'].each do |item| statements << item['CommonTableExpr']['ctequery'] if item['CommonTableExpr'] end end when 1 statements << statement[SELECT_STMT]['larg'] if statement[SELECT_STMT]['larg'] statements << statement[SELECT_STMT]['rarg'] if statement[SELECT_STMT]['rarg'] end elsif statement['UpdateStmt'] condition_items << statement['UpdateStmt']['whereClause'] if statement['UpdateStmt']['whereClause'] elsif statement['DeleteStmt'] condition_items << statement['DeleteStmt']['whereClause'] if statement['DeleteStmt']['whereClause'] end end # Process both JOIN and WHERE conditions here next_item = condition_items.shift if next_item if next_item[A_EXPR] %w[lexpr rexpr].each do |side| expr = next_item.values[0][side] next unless expr && expr.is_a?(Hash) condition_items << expr end elsif next_item[BOOL_EXPR] condition_items += next_item[BOOL_EXPR]['args'] elsif next_item[ROW_EXPR] condition_items += next_item[ROW_EXPR]['args'] elsif next_item[COLUMN_REF] column, table = next_item[COLUMN_REF]['fields'].map { |f| f['String']['str'] }.reverse filter_columns << [@aliases[table] || table, column] elsif next_item[NULL_TEST] condition_items << next_item[NULL_TEST]['arg'] elsif next_item[BOOLEAN_TEST] condition_items << next_item[BOOLEAN_TEST]['arg'] elsif next_item[FUNC_CALL] # FIXME: This should actually be extracted as a funccall and be compared with those indices condition_items += next_item[FUNC_CALL]['args'] if next_item[FUNC_CALL]['args'] elsif next_item[SUB_LINK] condition_items << next_item[SUB_LINK]['testexpr'] statements << next_item[SUB_LINK]['subselect'] end end break if statements.empty? && condition_items.empty? end filter_columns.uniq end |
#fingerprint ⇒ Object
4 5 6 7 8 |
# File 'lib/pg_query/fingerprint.rb', line 4 def fingerprint hash = Digest::SHA1.new fingerprint_tree(hash) format('%02x', FINGERPRINT_VERSION) + hash.hexdigest end |
#param_refs ⇒ Object
rubocop:disable Metrics/CyclomaticComplexity
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/pg_query/param_refs.rb', line 2 def param_refs # rubocop:disable Metrics/CyclomaticComplexity results = [] treewalker! @tree do |_, _, v| next unless v.is_a?(Hash) if v[PARAM_REF] results << { 'location' => v[PARAM_REF]['location'], 'length' => param_ref_length(v[PARAM_REF]) } elsif v[TYPE_CAST] next unless v[TYPE_CAST]['arg'] && v[TYPE_CAST]['typeName'] p = v[TYPE_CAST]['arg'].delete(PARAM_REF) t = v[TYPE_CAST]['typeName'].delete(TYPE_NAME) next unless p && t location = p['location'] typeloc = t['location'] typename = t['names'] length = param_ref_length(p) if typeloc < location length += location - typeloc location = typeloc end results << { 'location' => location, 'length' => length, 'typename' => typename } end end results.sort_by! { |r| r['location'] } results end |
#parsetree ⇒ Object
Legacy parsetree from 0.7 and earlier versions - migrate to “tree” format if you can
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/pg_query/legacy_parsetree.rb', line 3 def parsetree # rubocop:disable Metrics/CyclomaticComplexity @parsetree ||= transform_nodes!(@tree) do |raw_node| node = raw_node.keys[0] == RAW_STMT ? raw_node.delete(RAW_STMT)[STMT_FIELD] : raw_node key = node.keys[0] new_key = LEGACY_NODE_NAMES[key] || key.upcase case key when A_CONST transform_parsetree_a_const(node) when A_EXPR node[A_EXPR]['name'] = transform_string_list(node[A_EXPR]['name']) node[key].delete('kind') when COLUMN_REF node[COLUMN_REF]['fields'] = transform_string_list(node[COLUMN_REF]['fields']) when CREATE_FUNCTION_STMT node[CREATE_FUNCTION_STMT]['funcname'] = transform_string_list(node[CREATE_FUNCTION_STMT]['funcname']) when CREATE_TRIG_STMT node[CREATE_TRIG_STMT]['funcname'] = transform_string_list(node[CREATE_TRIG_STMT]['funcname']) when CONSTRAINT node[CONSTRAINT]['contype'] = LEGACY_CONSTRAINT_TYPES[node[CONSTRAINT]['contype']] node[CONSTRAINT]['keys'] = transform_string_list(node[CONSTRAINT]['keys']) when COPY_STMT node[COPY_STMT]['attlist'] = transform_string_list(node[COPY_STMT]['attlist']) when DEF_ELEM node[DEF_ELEM]['arg'] = node[DEF_ELEM]['arg'][INTEGER]['ival'] if node[DEF_ELEM]['arg'].is_a?(Hash) && node[DEF_ELEM]['arg'].keys[0] == INTEGER node[DEF_ELEM]['arg'] = node[DEF_ELEM]['arg'][STRING]['str'] if node[DEF_ELEM]['arg'].is_a?(Hash) && node[DEF_ELEM]['arg'].keys[0] == STRING node[DEF_ELEM]['arg'] = transform_string_list(node[DEF_ELEM]['arg']) if node[DEF_ELEM]['arg'].is_a?(Array) when DROP_STMT node[DROP_STMT]['objects'].each_with_index do |obj, idx| node[DROP_STMT]['objects'][idx] = transform_string_list(obj) end when FUNC_CALL node[FUNC_CALL]['funcname'] = transform_string_list(node[FUNC_CALL]['funcname']) when GRANT_ROLE_STMT node[GRANT_ROLE_STMT]['grantee_roles'] = transform_string_list(node[GRANT_ROLE_STMT]['grantee_roles']) when RANGE_VAR node[RANGE_VAR]['inhOpt'] = node[RANGE_VAR].delete('inh') ? 2 : 0 when TYPE_NAME node[TYPE_NAME]['names'] = transform_string_list(node[TYPE_NAME]['names']) end raw_node[new_key] = node.delete(key) end end |
#select_tables ⇒ Object
39 40 41 |
# File 'lib/pg_query/parse.rb', line 39 def select_tables tables_with_types.select { |t| t[:type] == :select }.map { |t| t[:table] } end |
#tables ⇒ Object
35 36 37 |
# File 'lib/pg_query/parse.rb', line 35 def tables tables_with_types.map { |t| t[:table] } end |
#tables_with_types ⇒ Object
61 62 63 64 |
# File 'lib/pg_query/parse.rb', line 61 def tables_with_types load_tables_and_aliases! if @tables.nil? @tables end |
#truncate(max_length) ⇒ Object
Truncates the query string to be below the specified length, first trying to omit less important parts of the query, and only then cutting off the end.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/pg_query/truncate.rb', line 8 def truncate(max_length) output = deparse(@tree) # Early exit if we're already below the max length return output if output.size <= max_length truncations = find_possible_truncations # Truncate the deepest possible truncation that is the longest first truncations.sort_by! { |t| [-t.location.size, -t.length] } tree = deep_dup(@tree) truncations.each do |truncation| next if truncation.length < 3 find_tree_location(tree, truncation.location) do |expr, k| expr[k] = { A_TRUNCATED => nil } expr[k] = [expr[k]] if truncation.is_array end output = deparse(tree) return output if output.size <= max_length end # We couldn't do a proper smart truncation, so we need a hard cut-off output[0..max_length - 4] + '...' end |