# frozen_string_literal: truemoduleActiveRecordmoduleConnectionAdaptersmodulePostgreSQLmoduleDatabaseStatementsdefexplain(arel,binds=[])sql="EXPLAIN #{to_sql(arel,binds)}"PostgreSQL::ExplainPrettyPrinter.new.pp(exec_query(sql,"EXPLAIN",binds))end# Queries the database and returns the results in an Array-like objectdefquery(sql,name=nil)# :nodoc:materialize_transactionsmark_transaction_written_if_write(sql)log(sql,name)doActiveSupport::Dependencies.interlock.permit_concurrent_loadsdo@connection.async_exec(sql).map_types!(@type_map_for_results).valuesendendendREAD_QUERY=ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(:close,:declare,:fetch,:move,:set,:show)# :nodoc:private_constant:READ_QUERYdefwrite_query?(sql)# :nodoc:!READ_QUERY.match?(sql)rescueArgumentError# Invalid encoding!READ_QUERY.match?(sql.b)end# Executes an SQL statement, returning a PG::Result object on success# or raising a PG::Error exception otherwise.# Note: the PG::Result object is manually memory managed; if you don't# need it specifically, you may want consider the <tt>exec_query</tt> wrapper.defexecute(sql,name=nil)sql=transform_query(sql)check_if_write_query(sql)materialize_transactionsmark_transaction_written_if_write(sql)log(sql,name)doActiveSupport::Dependencies.interlock.permit_concurrent_loadsdo@connection.async_exec(sql)endendenddefexec_query(sql,name="SQL",binds=[],prepare: false,async: false)# :nodoc:execute_and_clear(sql,name,binds,prepare: prepare,async: async)do|result|types={}fields=result.fieldsfields.each_with_indexdo|fname,i|ftype=result.ftypeifmod=result.fmoditypes[fname]=types[i]=get_oid_type(ftype,fmod,fname)endbuild_result(columns: fields,rows: result.values,column_types: types)endenddefexec_delete(sql,name=nil,binds=[])# :nodoc:execute_and_clear(sql,name,binds){|result|result.cmd_tuples}endalias:exec_update:exec_deletedefsql_for_insert(sql,pk,binds)# :nodoc:ifpk.nil?# Extract the table from the insert sql. Yuck.table_ref=extract_table_ref_from_insert_sql(sql)pk=primary_key(table_ref)iftable_refendifpk=suppress_composite_primary_key(pk)sql="#{sql} RETURNING #{quote_column_name(pk)}"endsuperendprivate:sql_for_insertdefexec_insert(sql,name=nil,binds=[],pk=nil,sequence_name=nil)# :nodoc:ifuse_insert_returning?||pk==falsesuperelseresult=exec_query(sql,name,binds)unlesssequence_nametable_ref=extract_table_ref_from_insert_sql(sql)iftable_refpk=primary_key(table_ref)ifpk.nil?pk=suppress_composite_primary_key(pk)sequence_name=default_sequence_name(table_ref,pk)endreturnresultunlesssequence_nameendlast_insert_id_result(sequence_name)endend# Begins a transaction.defbegin_db_transaction# :nodoc:execute("BEGIN","TRANSACTION")enddefbegin_isolated_db_transaction(isolation)# :nodoc:begin_db_transactionexecute"SET TRANSACTION ISOLATION LEVEL #{transaction_isolation_levels.fetch(isolation)}"end# Commits a transaction.defcommit_db_transaction# :nodoc:execute("COMMIT","TRANSACTION")end# Aborts a transaction.defexec_rollback_db_transaction# :nodoc:execute("ROLLBACK","TRANSACTION")end# From https://www.postgresql.org/docs/current/functions-datetime.html#FUNCTIONS-DATETIME-CURRENTHIGH_PRECISION_CURRENT_TIMESTAMP=Arel.sql("CURRENT_TIMESTAMP").freeze# :nodoc:private_constant:HIGH_PRECISION_CURRENT_TIMESTAMPdefhigh_precision_current_timestampHIGH_PRECISION_CURRENT_TIMESTAMPendprivatedefexecute_batch(statements,name=nil)execute(combine_multi_statements(statements))enddefbuild_truncate_statements(table_names)["TRUNCATE TABLE #{table_names.map(&method(:quote_table_name)).join(", ")}"]end# Returns the current ID of a table's sequence.deflast_insert_id_result(sequence_name)exec_query("SELECT currval(#{quote(sequence_name)})","SQL")enddefsuppress_composite_primary_key(pk)pkunlesspk.is_a?(Array)endendendendend