self.analyze

in lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb [61:132]


        def self.analyze(parsed)
          
          return unless parsed.pg

          database = ::Gitlab::Database.db_config_name(parsed.connection)
          sql = parsed.sql

          
          
          if self.transaction_begin?(parsed)
            context[:transaction_depth_by_db][database] += 1

            return
          elsif self.transaction_end?(parsed)
            context[:transaction_depth_by_db][database] -= 1
            if context[:transaction_depth_by_db][database] == 0
              context[:modified_tables_by_db][database].clear
              clear_queries

              
              ::CrossDatabaseModification::TransactionStackTrackRecord.log_gitlab_transactions_stack(action: :end_of_transaction)
            elsif context[:transaction_depth_by_db][database] < 0
              context[:transaction_depth_by_db][database] = 0
              raise CrossDatabaseModificationAcrossUnsupportedTablesError, "Misaligned cross-DB transactions discovered at query #{sql}. This could be a bug in #{self.class} or a valid issue to investigate. Read more at https://docs.gitlab.com/ee/development/database/multiple_databases.html#removing-cross-database-transactions ."
            end

            return
          end

          return unless self.in_transaction?
          return if Thread.current[:factory_bot_objects] && Thread.current[:factory_bot_objects] > 0

          
          
          tables = sql.downcase.include?(' for update') ? parsed.pg.tables : parsed.pg.dml_tables

          
          
          
          tables -= %w[plans gitlab_subscriptions]

          
          tables -= context[:ignored_tables].to_a

          return if tables.empty?

          
          
          
          return if tables == ['schema_migrations']

          add_to_queries(sql)
          context[:modified_tables_by_db][database].merge(tables)
          all_tables = context[:modified_tables_by_db].values.flat_map(&:to_a)
          schemas = ::Gitlab::Database::GitlabSchema.table_schemas!(all_tables)
          schemas += ApplicationRecord.gitlab_transactions_stack

          unless ::Gitlab::Database::GitlabSchema.cross_transactions_allowed?(schemas, all_tables)
            messages = []
            messages << "Cross-database data modification of '#{schemas.to_a.join(', ')}' were detected within " \
                        "a transaction modifying the '#{all_tables.to_a.join(', ')}' tables. "
            messages << "Please refer to https://docs.gitlab.com/ee/development/database/multiple_databases.html#removing-cross-database-transactions " \
                        "for details on how to resolve this exception."
            messages += cleaned_queries

            raise CrossDatabaseModificationAcrossUnsupportedTablesError, messages.join("\n\n")
          end
        rescue CrossDatabaseModificationAcrossUnsupportedTablesError => e
          ::Gitlab::ErrorTracking.track_exception(e, { gitlab_schemas: schemas, tables: all_tables, query: parsed.sql })
          raise if dev_or_test_env?
        end