module Sequel::Postgres::DatasetMethods
Constants
- LOCK_MODES
- NULL
Public Instance Methods
Return the results of an EXPLAIN ANALYZE query as a string
# File lib/sequel/adapters/shared/postgres.rb 1530 def analyze 1531 explain(:analyze=>true) 1532 end
Handle converting the ruby xor operator (^) into the PostgreSQL xor operator (#), and use the ILIKE and NOT ILIKE operators.
# File lib/sequel/adapters/shared/postgres.rb 1537 def complex_expression_sql_append(sql, op, args) 1538 case op 1539 when :^ 1540 j = ' # ' 1541 c = false 1542 args.each do |a| 1543 sql << j if c 1544 literal_append(sql, a) 1545 c ||= true 1546 end 1547 when :ILIKE, :'NOT ILIKE' 1548 sql << '(' 1549 literal_append(sql, args[0]) 1550 sql << ' ' << op.to_s << ' ' 1551 literal_append(sql, args[1]) 1552 sql << " ESCAPE " 1553 literal_append(sql, "\\") 1554 sql << ')' 1555 else 1556 super 1557 end 1558 end
Disables automatic use of INSERT … RETURNING. You can still use returning manually to force the use of RETURNING when inserting.
This is designed for cases where INSERT RETURNING cannot be used, such as when you are using partitioning with trigger functions or conditional rules, or when you are using a PostgreSQL version less than 8.2, or a PostgreSQL derivative that does not support returning.
Note that when this method is used, insert will not return the primary key of the inserted row, you will have to get the primary key of the inserted row before inserting via nextval, or after inserting via currval or lastval (making sure to use the same database connection for currval or lastval).
# File lib/sequel/adapters/shared/postgres.rb 1574 def disable_insert_returning 1575 clone(:disable_insert_returning=>true) 1576 end
Return the results of an EXPLAIN query as a string
# File lib/sequel/adapters/shared/postgres.rb 1579 def explain(opts=OPTS) 1580 with_sql((opts[:analyze] ? 'EXPLAIN ANALYZE ' : 'EXPLAIN ') + select_sql).map(:'QUERY PLAN').join("\r\n") 1581 end
Run a full text search on PostgreSQL. By default, searching for the inclusion of any of the terms in any of the cols.
Options:
- :headline
-
Append a expression to the selected columns aliased to headline that contains an extract of the matched text.
- :language
-
The language to use for the search (default: 'simple')
- :plain
-
Whether a plain search should be used (default: false). In this case, terms should be a single string, and it will do a search where cols contains all of the words in terms. This ignores search operators in terms.
- :phrase
-
Similar to :plain, but also adding an ILIKE filter to ensure that returned rows also include the exact phrase used.
- :rank
-
Set to true to order by the rank, so that closer matches are returned first.
- :to_tsquery
-
Can be set to :plain or :phrase to specify the function to use to convert the terms to a ts_query.
- :tsquery
-
Specifies the terms argument is already a valid
SQL
expression returning a tsquery, and can be used directly in the query. - :tsvector
-
Specifies the cols argument is already a valid
SQL
expression returning a tsvector, and can be used directly in the query.
# File lib/sequel/adapters/shared/postgres.rb 1607 def full_text_search(cols, terms, opts = OPTS) 1608 lang = Sequel.cast(opts[:language] || 'simple', :regconfig) 1609 1610 unless opts[:tsvector] 1611 phrase_cols = full_text_string_join(cols) 1612 cols = Sequel.function(:to_tsvector, lang, phrase_cols) 1613 end 1614 1615 unless opts[:tsquery] 1616 phrase_terms = terms.is_a?(Array) ? terms.join(' | ') : terms 1617 1618 query_func = case to_tsquery = opts[:to_tsquery] 1619 when :phrase, :plain 1620 :"#{to_tsquery}to_tsquery" 1621 else 1622 (opts[:phrase] || opts[:plain]) ? :plainto_tsquery : :to_tsquery 1623 end 1624 1625 terms = Sequel.function(query_func, lang, phrase_terms) 1626 end 1627 1628 ds = where(Sequel.lit(["", " @@ ", ""], cols, terms)) 1629 1630 if opts[:phrase] 1631 raise Error, "can't use :phrase with either :tsvector or :tsquery arguments to full_text_search together" if opts[:tsvector] || opts[:tsquery] 1632 ds = ds.grep(phrase_cols, "%#{escape_like(phrase_terms)}%", :case_insensitive=>true) 1633 end 1634 1635 if opts[:rank] 1636 ds = ds.reverse{ts_rank_cd(cols, terms)} 1637 end 1638 1639 if opts[:headline] 1640 ds = ds.select_append{ts_headline(lang, phrase_cols, terms).as(:headline)} 1641 end 1642 1643 ds 1644 end
Insert given values into the database.
# File lib/sequel/adapters/shared/postgres.rb 1647 def insert(*values) 1648 if @opts[:returning] 1649 # Already know which columns to return, let the standard code handle it 1650 super 1651 elsif @opts[:sql] || @opts[:disable_insert_returning] 1652 # Raw SQL used or RETURNING disabled, just use the default behavior 1653 # and return nil since sequence is not known. 1654 super 1655 nil 1656 else 1657 # Force the use of RETURNING with the primary key value, 1658 # unless it has been disabled. 1659 returning(insert_pk).insert(*values){|r| return r.values.first} 1660 end 1661 end
Handle uniqueness violations when inserting, by updating the conflicting row, using ON CONFLICT. With no options, uses ON CONFLICT DO NOTHING. Options:
- :conflict_where
-
The index filter, when using a partial index to determine uniqueness.
- :constraint
-
An explicit constraint name, has precendence over :target.
- :target
-
The column name or expression to handle uniqueness violations on.
- :update
-
A hash of columns and values to set. Uses ON CONFLICT DO UPDATE.
- :update_where
-
A WHERE condition to use for the update.
Examples:
DB[:table].insert_conflict.insert(a: 1, b: 2) # INSERT INTO TABLE (a, b) VALUES (1, 2) # ON CONFLICT DO NOTHING DB[:table].insert_conflict(constraint: :table_a_uidx).insert(a: 1, b: 2) # INSERT INTO TABLE (a, b) VALUES (1, 2) # ON CONFLICT ON CONSTRAINT table_a_uidx DO NOTHING DB[:table].insert_conflict(target: :a).insert(a: 1, b: 2) # INSERT INTO TABLE (a, b) VALUES (1, 2) # ON CONFLICT (a) DO NOTHING DB[:table].insert_conflict(target: :a, conflict_where: {c: true}).insert(a: 1, b: 2) # INSERT INTO TABLE (a, b) VALUES (1, 2) # ON CONFLICT (a) WHERE (c IS TRUE) DO NOTHING DB[:table].insert_conflict(target: :a, update: {b: Sequel[:excluded][:b]}).insert(a: 1, b: 2) # INSERT INTO TABLE (a, b) VALUES (1, 2) # ON CONFLICT (a) DO UPDATE SET b = excluded.b DB[:table].insert_conflict(constraint: :table_a_uidx, update: {b: Sequel[:excluded][:b]}, update_where: {Sequel[:table][:status_id] => 1}).insert(a: 1, b: 2) # INSERT INTO TABLE (a, b) VALUES (1, 2) # ON CONFLICT ON CONSTRAINT table_a_uidx # DO UPDATE SET b = excluded.b WHERE (table.status_id = 1)
# File lib/sequel/adapters/shared/postgres.rb 1698 def insert_conflict(opts=OPTS) 1699 clone(:insert_conflict => opts) 1700 end
Ignore uniqueness/exclusion violations when inserting, using ON CONFLICT DO NOTHING. Exists mostly for compatibility to MySQL's insert_ignore. Example:
DB[:table].insert_ignore.insert(a: 1, b: 2) # INSERT INTO TABLE (a, b) VALUES (1, 2) # ON CONFLICT DO NOTHING
# File lib/sequel/adapters/shared/postgres.rb 1708 def insert_ignore 1709 insert_conflict 1710 end
Insert a record, returning the record inserted, using RETURNING. Always returns nil without running an INSERT statement if disable_insert_returning
is used. If the query runs but returns no values, returns false.
# File lib/sequel/adapters/shared/postgres.rb 1715 def insert_select(*values) 1716 return unless supports_insert_select? 1717 # Handle case where query does not return a row 1718 server?(:default).with_sql_first(insert_select_sql(*values)) || false 1719 end
The SQL
to use for an insert_select
, adds a RETURNING clause to the insert unless the RETURNING clause is already present.
# File lib/sequel/adapters/shared/postgres.rb 1723 def insert_select_sql(*values) 1724 ds = opts[:returning] ? self : returning 1725 ds.insert_sql(*values) 1726 end
Locks all tables in the dataset's FROM clause (but not in JOINs) with the specified mode (e.g. 'EXCLUSIVE'). If a block is given, starts a new transaction, locks the table, and yields. If a block is not given, just locks the tables. Note that PostgreSQL will probably raise an error if you lock the table outside of an existing transaction. Returns nil.
# File lib/sequel/adapters/shared/postgres.rb 1733 def lock(mode, opts=OPTS) 1734 if block_given? # perform locking inside a transaction and yield to block 1735 @db.transaction(opts){lock(mode, opts); yield} 1736 else 1737 sql = 'LOCK TABLE '.dup 1738 source_list_append(sql, @opts[:from]) 1739 mode = mode.to_s.upcase.strip 1740 unless LOCK_MODES.include?(mode) 1741 raise Error, "Unsupported lock mode: #{mode}" 1742 end 1743 sql << " IN #{mode} MODE" 1744 @db.execute(sql, opts) 1745 end 1746 nil 1747 end
Use OVERRIDING USER VALUE for INSERT statements, so that identity columns always use the user supplied value, and an error is not raised for identity columns that are GENERATED ALWAYS.
# File lib/sequel/adapters/shared/postgres.rb 1752 def overriding_system_value 1753 clone(:override=>:system) 1754 end
Use OVERRIDING USER VALUE for INSERT statements, so that identity columns always use the sequence value instead of the user supplied value.
# File lib/sequel/adapters/shared/postgres.rb 1758 def overriding_user_value 1759 clone(:override=>:user) 1760 end
# File lib/sequel/adapters/shared/postgres.rb 1762 def supports_cte?(type=:select) 1763 if type == :select 1764 server_version >= 80400 1765 else 1766 server_version >= 90100 1767 end 1768 end
PostgreSQL supports using the WITH clause in subqueries if it supports using WITH at all (i.e. on PostgreSQL 8.4+).
# File lib/sequel/adapters/shared/postgres.rb 1772 def supports_cte_in_subqueries? 1773 supports_cte? 1774 end
DISTINCT ON is a PostgreSQL extension
# File lib/sequel/adapters/shared/postgres.rb 1777 def supports_distinct_on? 1778 true 1779 end
PostgreSQL 9.5+ supports GROUP CUBE
# File lib/sequel/adapters/shared/postgres.rb 1782 def supports_group_cube? 1783 server_version >= 90500 1784 end
PostgreSQL 9.5+ supports GROUP ROLLUP
# File lib/sequel/adapters/shared/postgres.rb 1787 def supports_group_rollup? 1788 server_version >= 90500 1789 end
PostgreSQL 9.5+ supports GROUPING SETS
# File lib/sequel/adapters/shared/postgres.rb 1792 def supports_grouping_sets? 1793 server_version >= 90500 1794 end
PostgreSQL 9.5+ supports the ON CONFLICT clause to INSERT.
# File lib/sequel/adapters/shared/postgres.rb 1802 def supports_insert_conflict? 1803 server_version >= 90500 1804 end
True unless insert returning has been disabled for this dataset.
# File lib/sequel/adapters/shared/postgres.rb 1797 def supports_insert_select? 1798 !@opts[:disable_insert_returning] 1799 end
PostgreSQL 9.3+ supports lateral subqueries
# File lib/sequel/adapters/shared/postgres.rb 1807 def supports_lateral_subqueries? 1808 server_version >= 90300 1809 end
PostgreSQL supports modifying joined datasets
# File lib/sequel/adapters/shared/postgres.rb 1812 def supports_modifying_joins? 1813 true 1814 end
PostgreSQL supports NOWAIT.
# File lib/sequel/adapters/shared/postgres.rb 1817 def supports_nowait? 1818 true 1819 end
PostgreSQL supports pattern matching via regular expressions
# File lib/sequel/adapters/shared/postgres.rb 1827 def supports_regexp? 1828 true 1829 end
Returning is always supported.
# File lib/sequel/adapters/shared/postgres.rb 1822 def supports_returning?(type) 1823 true 1824 end
PostgreSQL 9.5+ supports SKIP LOCKED.
# File lib/sequel/adapters/shared/postgres.rb 1832 def supports_skip_locked? 1833 server_version >= 90500 1834 end
PostgreSQL supports timezones in literal timestamps
# File lib/sequel/adapters/shared/postgres.rb 1837 def supports_timestamp_timezones? 1838 true 1839 end
PostgreSQL 8.4+ supports WINDOW clause.
# File lib/sequel/adapters/shared/postgres.rb 1842 def supports_window_clause? 1843 server_version >= 80400 1844 end
Base support added in 8.4, offset supported added in 9.0, GROUPS and EXCLUDE support added in 11.0.
# File lib/sequel/adapters/shared/postgres.rb 1853 def supports_window_function_frame_option?(option) 1854 case option 1855 when :rows, :range 1856 true 1857 when :offset 1858 server_version >= 90000 1859 when :groups, :exclude 1860 server_version >= 110000 1861 end 1862 end
PostgreSQL 8.4+ supports window functions
# File lib/sequel/adapters/shared/postgres.rb 1847 def supports_window_functions? 1848 server_version >= 80400 1849 end
Truncates the dataset. Returns nil.
Options:
- :cascade
-
whether to use the CASCADE option, useful when truncating tables with foreign keys.
- :only
-
truncate using ONLY, so child tables are unaffected
- :restart
-
use RESTART IDENTITY to restart any related sequences
:only and :restart only work correctly on PostgreSQL 8.4+.
Usage:
DB[:table].truncate # TRUNCATE TABLE "table" DB[:table].truncate(cascade: true, only: true, restart: true) # TRUNCATE TABLE ONLY "table" RESTART IDENTITY CASCADE
# File lib/sequel/adapters/shared/postgres.rb 1880 def truncate(opts = OPTS) 1881 if opts.empty? 1882 super() 1883 else 1884 clone(:truncate_opts=>opts).truncate 1885 end 1886 end
Use WITH TIES when limiting the result set to also include additional rules that have the same results for the order column as the final row. Requires PostgreSQL 13.
# File lib/sequel/adapters/shared/postgres.rb 1891 def with_ties 1892 clone(:limit_with_ties=>true) 1893 end
Protected Instance Methods
If returned primary keys are requested, use RETURNING unless already set on the dataset. If RETURNING is already set, use existing returning values. If RETURNING is only set to return a single columns, return an array of just that column. Otherwise, return an array of hashes.
# File lib/sequel/adapters/shared/postgres.rb 1901 def _import(columns, values, opts=OPTS) 1902 if @opts[:returning] 1903 statements = multi_insert_sql(columns, values) 1904 trans_opts = Hash[opts] 1905 trans_opts[:server] = @opts[:server] 1906 @db.transaction(trans_opts) do 1907 statements.map{|st| returning_fetch_rows(st)} 1908 end.first.map{|v| v.length == 1 ? v.values.first : v} 1909 elsif opts[:return] == :primary_key 1910 returning(insert_pk)._import(columns, values, opts) 1911 else 1912 super 1913 end 1914 end
# File lib/sequel/adapters/shared/postgres.rb 1916 def to_prepared_statement(type, *a) 1917 if type == :insert && !@opts.has_key?(:returning) 1918 returning(insert_pk).send(:to_prepared_statement, :insert_pk, *a) 1919 else 1920 super 1921 end 1922 end
Private Instance Methods
Format TRUNCATE statement with PostgreSQL specific options.
# File lib/sequel/adapters/shared/postgres.rb 1927 def _truncate_sql(table) 1928 to = @opts[:truncate_opts] || OPTS 1929 "TRUNCATE TABLE#{' ONLY' if to[:only]} #{table}#{' RESTART IDENTITY' if to[:restart]}#{' CASCADE' if to[:cascade]}" 1930 end
Allow truncation of multiple source tables.
# File lib/sequel/adapters/shared/postgres.rb 1933 def check_truncation_allowed! 1934 raise(InvalidOperation, "Grouped datasets cannot be truncated") if opts[:group] 1935 raise(InvalidOperation, "Joined datasets cannot be truncated") if opts[:join] 1936 end
PostgreSQL requires parentheses around compound datasets if they use CTEs, and using them in other places doesn't hurt.
# File lib/sequel/adapters/shared/postgres.rb 2069 def compound_dataset_sql_append(sql, ds) 2070 sql << '(' 2071 super 2072 sql << ')' 2073 end
Only include the primary table in the main delete clause
# File lib/sequel/adapters/shared/postgres.rb 1939 def delete_from_sql(sql) 1940 sql << ' FROM ' 1941 source_list_append(sql, @opts[:from][0..0]) 1942 end
Use USING to specify additional tables in a delete query
# File lib/sequel/adapters/shared/postgres.rb 1945 def delete_using_sql(sql) 1946 join_from_sql(:USING, sql) 1947 end
Concatenate the expressions with a space in between
# File lib/sequel/adapters/shared/postgres.rb 2170 def full_text_string_join(cols) 2171 cols = Array(cols).map{|x| SQL::Function.new(:COALESCE, x, '')} 2172 cols = cols.zip([' '] * cols.length).flatten 2173 cols.pop 2174 SQL::StringExpression.new(:'||', *cols) 2175 end
Add ON CONFLICT clause if it should be used
# File lib/sequel/adapters/shared/postgres.rb 1950 def insert_conflict_sql(sql) 1951 if opts = @opts[:insert_conflict] 1952 sql << " ON CONFLICT" 1953 1954 if target = opts[:constraint] 1955 sql << " ON CONSTRAINT " 1956 identifier_append(sql, target) 1957 elsif target = opts[:target] 1958 sql << ' ' 1959 identifier_append(sql, Array(target)) 1960 if conflict_where = opts[:conflict_where] 1961 sql << " WHERE " 1962 literal_append(sql, conflict_where) 1963 end 1964 end 1965 1966 if values = opts[:update] 1967 sql << " DO UPDATE SET " 1968 update_sql_values_hash(sql, values) 1969 if update_where = opts[:update_where] 1970 sql << " WHERE " 1971 literal_append(sql, update_where) 1972 end 1973 else 1974 sql << " DO NOTHING" 1975 end 1976 end 1977 end
Include aliases when inserting into a single table on PostgreSQL 9.5+.
# File lib/sequel/adapters/shared/postgres.rb 1980 def insert_into_sql(sql) 1981 sql << " INTO " 1982 if (f = @opts[:from]) && f.length == 1 1983 identifier_append(sql, server_version >= 90500 ? f.first : unaliased_identifier(f.first)) 1984 else 1985 source_list_append(sql, f) 1986 end 1987 end
Return the primary key to use for RETURNING in an INSERT statement
# File lib/sequel/adapters/shared/postgres.rb 1990 def insert_pk 1991 if (f = opts[:from]) && !f.empty? 1992 case t = f.first 1993 when Symbol, String, SQL::Identifier, SQL::QualifiedIdentifier 1994 if pk = db.primary_key(t) 1995 Sequel::SQL::Identifier.new(pk) 1996 end 1997 end 1998 end 1999 end
Support OVERRIDING SYSTEM|USER VALUE in insert statements
# File lib/sequel/adapters/shared/postgres.rb 2002 def insert_values_sql(sql) 2003 case opts[:override] 2004 when :system 2005 sql << " OVERRIDING SYSTEM VALUE" 2006 when :user 2007 sql << " OVERRIDING USER VALUE" 2008 end 2009 super 2010 end
For multiple table support, PostgreSQL requires at least two from tables, with joins allowed.
# File lib/sequel/adapters/shared/postgres.rb 2014 def join_from_sql(type, sql) 2015 if(from = @opts[:from][1..-1]).empty? 2016 raise(Error, 'Need multiple FROM tables if updating/deleting a dataset with JOINs') if @opts[:join] 2017 else 2018 sql << ' ' << type.to_s << ' ' 2019 source_list_append(sql, from) 2020 select_join_sql(sql) 2021 end 2022 end
Use a generic blob quoting method, hopefully overridden in one of the subadapter methods
# File lib/sequel/adapters/shared/postgres.rb 2025 def literal_blob_append(sql, v) 2026 sql << "'" << v.gsub(/[\000-\037\047\134\177-\377]/n){|b| "\\#{("%o" % b[0..1].unpack("C")[0]).rjust(3, '0')}"} << "'" 2027 end
PostgreSQL uses FALSE for false values
# File lib/sequel/adapters/shared/postgres.rb 2030 def literal_false 2031 'false' 2032 end
PostgreSQL quotes NaN and Infinity.
# File lib/sequel/adapters/shared/postgres.rb 2035 def literal_float(value) 2036 if value.finite? 2037 super 2038 elsif value.nan? 2039 "'NaN'" 2040 elsif value.infinite? == 1 2041 "'Infinity'" 2042 else 2043 "'-Infinity'" 2044 end 2045 end
Assume that SQL
standard quoting is on, per Sequel's defaults
# File lib/sequel/adapters/shared/postgres.rb 2048 def literal_string_append(sql, v) 2049 sql << "'" << v.gsub("'", "''") << "'" 2050 end
PostgreSQL uses true for true values
# File lib/sequel/adapters/shared/postgres.rb 2053 def literal_true 2054 'true' 2055 end
PostgreSQL supports multiple rows in INSERT.
# File lib/sequel/adapters/shared/postgres.rb 2058 def multi_insert_sql_strategy 2059 :values 2060 end
Backslash is supported by default as the escape character on PostgreSQL, and using ESCAPE can break LIKE ANY() usage.
# File lib/sequel/adapters/shared/postgres.rb 2077 def requires_like_escape? 2078 false 2079 end
Support FETCH FIRST WITH TIES on PostgreSQL 13+.
# File lib/sequel/adapters/shared/postgres.rb 2082 def select_limit_sql(sql) 2083 l = @opts[:limit] 2084 o = @opts[:offset] 2085 2086 return unless l || o 2087 2088 if @opts[:limit_with_ties] 2089 if o 2090 sql << " OFFSET " 2091 literal_append(sql, o) 2092 end 2093 2094 if l 2095 sql << " FETCH FIRST " 2096 literal_append(sql, l) 2097 sql << " ROWS WITH TIES" 2098 end 2099 else 2100 if l 2101 sql << " LIMIT " 2102 literal_append(sql, l) 2103 end 2104 2105 if o 2106 sql << " OFFSET " 2107 literal_append(sql, o) 2108 end 2109 end 2110 end
Support FOR SHARE locking when using the :share lock style. Use SKIP LOCKED if skipping locked rows.
# File lib/sequel/adapters/shared/postgres.rb 2114 def select_lock_sql(sql) 2115 lock = @opts[:lock] 2116 if lock == :share 2117 sql << ' FOR SHARE' 2118 else 2119 super 2120 end 2121 2122 if lock 2123 if @opts[:skip_locked] 2124 sql << " SKIP LOCKED" 2125 elsif @opts[:nowait] 2126 sql << " NOWAIT" 2127 end 2128 end 2129 end
Support VALUES clause instead of the SELECT clause to return rows.
# File lib/sequel/adapters/shared/postgres.rb 2132 def select_values_sql(sql) 2133 sql << "VALUES " 2134 expression_list_append(sql, opts[:values]) 2135 end
Use WITH RECURSIVE instead of WITH if any of the CTEs is recursive
# File lib/sequel/adapters/shared/postgres.rb 2138 def select_with_sql_base 2139 opts[:with].any?{|w| w[:recursive]} ? "WITH RECURSIVE " : super 2140 end
Support WITH AS [NOT] MATERIALIZED if :materialized option is used.
# File lib/sequel/adapters/shared/postgres.rb 2143 def select_with_sql_prefix(sql, w) 2144 super 2145 2146 case w[:materialized] 2147 when true 2148 sql << "MATERIALIZED " 2149 when false 2150 sql << "NOT MATERIALIZED " 2151 end 2152 end
The version of the database server
# File lib/sequel/adapters/shared/postgres.rb 2155 def server_version 2156 db.server_version(@opts[:server]) 2157 end
PostgreSQL 9.4+ supports the FILTER clause for aggregate functions.
# File lib/sequel/adapters/shared/postgres.rb 2160 def supports_filtered_aggregates? 2161 server_version >= 90400 2162 end
PostgreSQL supports quoted function names.
# File lib/sequel/adapters/shared/postgres.rb 2165 def supports_quoted_function_names? 2166 true 2167 end
Use FROM to specify additional tables in an update query
# File lib/sequel/adapters/shared/postgres.rb 2178 def update_from_sql(sql) 2179 join_from_sql(:FROM, sql) 2180 end
Only include the primary table in the main update clause
# File lib/sequel/adapters/shared/postgres.rb 2183 def update_table_sql(sql) 2184 sql << ' ' 2185 source_list_append(sql, @opts[:from][0..0]) 2186 end