diff --git a/lib/pg_query/parse.rb b/lib/pg_query/parse.rb index 0dd08851..81b8b3b1 100644 --- a/lib/pg_query/parse.rb +++ b/lib/pg_query/parse.rb @@ -149,6 +149,12 @@ def load_objects! # rubocop:disable Metrics/CyclomaticComplexity subselect_items << statement.update_stmt.where_clause if statement.node == :update_stmt && statement.update_stmt.where_clause subselect_items << statement.delete_stmt.where_clause if statement.node == :delete_stmt && statement.delete_stmt.where_clause + if statement.node == :delete_stmt + statement.delete_stmt.using_clause.each do |using_clause| + from_clause_items << { item: using_clause, type: :select } + end + end + if value.with_clause cte_statements, cte_names = statements_and_cte_names_for_with_clause(value.with_clause) @cte_names.concat(cte_names) diff --git a/spec/lib/parse_spec.rb b/spec/lib/parse_spec.rb index 8514818f..d3114e19 100644 --- a/spec/lib/parse_spec.rb +++ b/spec/lib/parse_spec.rb @@ -1534,16 +1534,52 @@ it 'finds tables referenced in the FROM clause' do query = described_class.parse(<<-SQL) - UPDATE users SET name = users_new.name FROM users_new WHERE users.id = users_new.id + UPDATE users SET name = users_new.name + FROM users_new + INNER JOIN join_table ON join_table.user_id = new_users.id + WHERE users.id = users_new.id SQL expect(query.warnings).to be_empty - expect(query.tables).to eq(['users', 'users_new']) - expect(query.select_tables).to eq(['users_new']) + expect(query.tables).to eq(['users', 'users_new', 'join_table']) + expect(query.select_tables).to eq(['users_new', 'join_table']) expect(query.dml_tables).to eq(['users']) expect(query.ddl_tables).to eq([]) end end + describe 'parsing DELETE' do + it 'finds the deleted table' do + query = described_class.parse(<<-SQL) + DELETE FROM users; + SQL + expect(query.warnings).to be_empty + expect(query.tables).to eq(['users']) + expect(query.dml_tables).to eq(['users']) + end + + it 'finds the used table' do + query = described_class.parse(<<-SQL) + DELETE FROM users USING foo + WHERE foo_id = foo.id AND foo.action = 'delete'; + SQL + expect(query.warnings).to be_empty + expect(query.tables).to eq(['users', 'foo']) + expect(query.dml_tables).to eq(['users']) + expect(query.select_tables).to eq(['foo']) + end + + it 'finds the table in the where subquery' do + query = described_class.parse(<<-SQL) + DELETE FROM users + WHERE foo_id IN (SELECT id FROM foo WHERE action = 'delete'); + SQL + expect(query.warnings).to be_empty + expect(query.tables).to eq(['users', 'foo']) + expect(query.dml_tables).to eq(['users']) + expect(query.select_tables).to eq(['foo']) + end + end + it 'handles DROP TYPE' do query = described_class.parse("DROP TYPE IF EXISTS repack.pk_something") expect(query.warnings).to eq []