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 1532 def analyze 1533 explain(:analyze=>true) 1534 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 1539 def complex_expression_sql_append(sql, op, args) 1540 case op 1541 when :^ 1542 j = ' # ' 1543 c = false 1544 args.each do |a| 1545 sql << j if c 1546 literal_append(sql, a) 1547 c ||= true 1548 end 1549 when :ILIKE, :'NOT ILIKE' 1550 sql << '(' 1551 literal_append(sql, args[0]) 1552 sql << ' ' << op.to_s << ' ' 1553 literal_append(sql, args[1]) 1554 sql << " ESCAPE " 1555 literal_append(sql, "\\") 1556 sql << ')' 1557 else 1558 super 1559 end 1560 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 1576 def disable_insert_returning 1577 clone(:disable_insert_returning=>true) 1578 end
Return the results of an EXPLAIN query as a string
# File lib/sequel/adapters/shared/postgres.rb 1581 def explain(opts=OPTS) 1582 with_sql((opts[:analyze] ? 'EXPLAIN ANALYZE ' : 'EXPLAIN ') + select_sql).map(:'QUERY PLAN').join("\r\n") 1583 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 1609 def full_text_search(cols, terms, opts = OPTS) 1610 lang = Sequel.cast(opts[:language] || 'simple', :regconfig) 1611 1612 unless opts[:tsvector] 1613 phrase_cols = full_text_string_join(cols) 1614 cols = Sequel.function(:to_tsvector, lang, phrase_cols) 1615 end 1616 1617 unless opts[:tsquery] 1618 phrase_terms = terms.is_a?(Array) ? terms.join(' | ') : terms 1619 1620 query_func = case to_tsquery = opts[:to_tsquery] 1621 when :phrase, :plain 1622 :"#{to_tsquery}to_tsquery" 1623 else 1624 (opts[:phrase] || opts[:plain]) ? :plainto_tsquery : :to_tsquery 1625 end 1626 1627 terms = Sequel.function(query_func, lang, phrase_terms) 1628 end 1629 1630 ds = where(Sequel.lit(["", " @@ ", ""], cols, terms)) 1631 1632 if opts[:phrase] 1633 raise Error, "can't use :phrase with either :tsvector or :tsquery arguments to full_text_search together" if opts[:tsvector] || opts[:tsquery] 1634 ds = ds.grep(phrase_cols, "%#{escape_like(phrase_terms)}%", :case_insensitive=>true) 1635 end 1636 1637 if opts[:rank] 1638 ds = ds.reverse{ts_rank_cd(cols, terms)} 1639 end 1640 1641 if opts[:headline] 1642 ds = ds.select_append{ts_headline(lang, phrase_cols, terms).as(:headline)} 1643 end 1644 1645 ds 1646 end
Insert given values into the database.
# File lib/sequel/adapters/shared/postgres.rb 1649 def insert(*values) 1650 if @opts[:returning] 1651 # Already know which columns to return, let the standard code handle it 1652 super 1653 elsif @opts[:sql] || @opts[:disable_insert_returning] 1654 # Raw SQL used or RETURNING disabled, just use the default behavior 1655 # and return nil since sequence is not known. 1656 super 1657 nil 1658 else 1659 # Force the use of RETURNING with the primary key value, 1660 # unless it has been disabled. 1661 returning(insert_pk).insert(*values){|r| return r.values.first} 1662 end 1663 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 1700 def insert_conflict(opts=OPTS) 1701 clone(:insert_conflict => opts) 1702 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 1710 def insert_ignore 1711 insert_conflict 1712 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 1717 def insert_select(*values) 1718 return unless supports_insert_select? 1719 # Handle case where query does not return a row 1720 server?(:default).with_sql_first(insert_select_sql(*values)) || false 1721 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 1725 def insert_select_sql(*values) 1726 ds = opts[:returning] ? self : returning 1727 ds.insert_sql(*values) 1728 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 1735 def lock(mode, opts=OPTS) 1736 if block_given? # perform locking inside a transaction and yield to block 1737 @db.transaction(opts){lock(mode, opts); yield} 1738 else 1739 sql = 'LOCK TABLE '.dup 1740 source_list_append(sql, @opts[:from]) 1741 mode = mode.to_s.upcase.strip 1742 unless LOCK_MODES.include?(mode) 1743 raise Error, "Unsupported lock mode: #{mode}" 1744 end 1745 sql << " IN #{mode} MODE" 1746 @db.execute(sql, opts) 1747 end 1748 nil 1749 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 1754 def overriding_system_value 1755 clone(:override=>:system) 1756 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 1760 def overriding_user_value 1761 clone(:override=>:user) 1762 end
# File lib/sequel/adapters/shared/postgres.rb 1764 def supports_cte?(type=:select) 1765 if type == :select 1766 server_version >= 80400 1767 else 1768 server_version >= 90100 1769 end 1770 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 1774 def supports_cte_in_subqueries? 1775 supports_cte? 1776 end
DISTINCT ON is a PostgreSQL extension
# File lib/sequel/adapters/shared/postgres.rb 1779 def supports_distinct_on? 1780 true 1781 end
PostgreSQL 9.5+ supports GROUP CUBE
# File lib/sequel/adapters/shared/postgres.rb 1784 def supports_group_cube? 1785 server_version >= 90500 1786 end
PostgreSQL 9.5+ supports GROUP ROLLUP
# File lib/sequel/adapters/shared/postgres.rb 1789 def supports_group_rollup? 1790 server_version >= 90500 1791 end
PostgreSQL 9.5+ supports GROUPING SETS
# File lib/sequel/adapters/shared/postgres.rb 1794 def supports_grouping_sets? 1795 server_version >= 90500 1796 end
PostgreSQL 9.5+ supports the ON CONFLICT clause to INSERT.
# File lib/sequel/adapters/shared/postgres.rb 1804 def supports_insert_conflict? 1805 server_version >= 90500 1806 end
True unless insert returning has been disabled for this dataset.
# File lib/sequel/adapters/shared/postgres.rb 1799 def supports_insert_select? 1800 !@opts[:disable_insert_returning] 1801 end
PostgreSQL 9.3+ supports lateral subqueries
# File lib/sequel/adapters/shared/postgres.rb 1809 def supports_lateral_subqueries? 1810 server_version >= 90300 1811 end
PostgreSQL supports modifying joined datasets
# File lib/sequel/adapters/shared/postgres.rb 1814 def supports_modifying_joins? 1815 true 1816 end
PostgreSQL supports NOWAIT.
# File lib/sequel/adapters/shared/postgres.rb 1819 def supports_nowait? 1820 true 1821 end
PostgreSQL supports pattern matching via regular expressions
# File lib/sequel/adapters/shared/postgres.rb 1829 def supports_regexp? 1830 true 1831 end
Returning is always supported.
# File lib/sequel/adapters/shared/postgres.rb 1824 def supports_returning?(type) 1825 true 1826 end
PostgreSQL 9.5+ supports SKIP LOCKED.
# File lib/sequel/adapters/shared/postgres.rb 1834 def supports_skip_locked? 1835 server_version >= 90500 1836 end
PostgreSQL supports timezones in literal timestamps
# File lib/sequel/adapters/shared/postgres.rb 1839 def supports_timestamp_timezones? 1840 true 1841 end
PostgreSQL 8.4+ supports WINDOW clause.
# File lib/sequel/adapters/shared/postgres.rb 1844 def supports_window_clause? 1845 server_version >= 80400 1846 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 1855 def supports_window_function_frame_option?(option) 1856 case option 1857 when :rows, :range 1858 true 1859 when :offset 1860 server_version >= 90000 1861 when :groups, :exclude 1862 server_version >= 110000 1863 end 1864 end
PostgreSQL 8.4+ supports window functions
# File lib/sequel/adapters/shared/postgres.rb 1849 def supports_window_functions? 1850 server_version >= 80400 1851 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 1882 def truncate(opts = OPTS) 1883 if opts.empty? 1884 super() 1885 else 1886 clone(:truncate_opts=>opts).truncate 1887 end 1888 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 1893 def with_ties 1894 clone(:limit_with_ties=>true) 1895 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 1903 def _import(columns, values, opts=OPTS) 1904 if @opts[:returning] 1905 statements = multi_insert_sql(columns, values) 1906 trans_opts = Hash[opts] 1907 trans_opts[:server] = @opts[:server] 1908 @db.transaction(trans_opts) do 1909 statements.map{|st| returning_fetch_rows(st)} 1910 end.first.map{|v| v.length == 1 ? v.values.first : v} 1911 elsif opts[:return] == :primary_key 1912 returning(insert_pk)._import(columns, values, opts) 1913 else 1914 super 1915 end 1916 end
# File lib/sequel/adapters/shared/postgres.rb 1918 def to_prepared_statement(type, *a) 1919 if type == :insert && !@opts.has_key?(:returning) 1920 returning(insert_pk).send(:to_prepared_statement, :insert_pk, *a) 1921 else 1922 super 1923 end 1924 end
Private Instance Methods
Format TRUNCATE statement with PostgreSQL specific options.
# File lib/sequel/adapters/shared/postgres.rb 1929 def _truncate_sql(table) 1930 to = @opts[:truncate_opts] || OPTS 1931 "TRUNCATE TABLE#{' ONLY' if to[:only]} #{table}#{' RESTART IDENTITY' if to[:restart]}#{' CASCADE' if to[:cascade]}" 1932 end
Allow truncation of multiple source tables.
# File lib/sequel/adapters/shared/postgres.rb 1935 def check_truncation_allowed! 1936 raise(InvalidOperation, "Grouped datasets cannot be truncated") if opts[:group] 1937 raise(InvalidOperation, "Joined datasets cannot be truncated") if opts[:join] 1938 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 2071 def compound_dataset_sql_append(sql, ds) 2072 sql << '(' 2073 super 2074 sql << ')' 2075 end
Only include the primary table in the main delete clause
# File lib/sequel/adapters/shared/postgres.rb 1941 def delete_from_sql(sql) 1942 sql << ' FROM ' 1943 source_list_append(sql, @opts[:from][0..0]) 1944 end
Use USING to specify additional tables in a delete query
# File lib/sequel/adapters/shared/postgres.rb 1947 def delete_using_sql(sql) 1948 join_from_sql(:USING, sql) 1949 end
Concatenate the expressions with a space in between
# File lib/sequel/adapters/shared/postgres.rb 2172 def full_text_string_join(cols) 2173 cols = Array(cols).map{|x| SQL::Function.new(:COALESCE, x, '')} 2174 cols = cols.zip([' '] * cols.length).flatten 2175 cols.pop 2176 SQL::StringExpression.new(:'||', *cols) 2177 end
Add ON CONFLICT clause if it should be used
# File lib/sequel/adapters/shared/postgres.rb 1952 def insert_conflict_sql(sql) 1953 if opts = @opts[:insert_conflict] 1954 sql << " ON CONFLICT" 1955 1956 if target = opts[:constraint] 1957 sql << " ON CONSTRAINT " 1958 identifier_append(sql, target) 1959 elsif target = opts[:target] 1960 sql << ' ' 1961 identifier_append(sql, Array(target)) 1962 if conflict_where = opts[:conflict_where] 1963 sql << " WHERE " 1964 literal_append(sql, conflict_where) 1965 end 1966 end 1967 1968 if values = opts[:update] 1969 sql << " DO UPDATE SET " 1970 update_sql_values_hash(sql, values) 1971 if update_where = opts[:update_where] 1972 sql << " WHERE " 1973 literal_append(sql, update_where) 1974 end 1975 else 1976 sql << " DO NOTHING" 1977 end 1978 end 1979 end
Include aliases when inserting into a single table on PostgreSQL 9.5+.
# File lib/sequel/adapters/shared/postgres.rb 1982 def insert_into_sql(sql) 1983 sql << " INTO " 1984 if (f = @opts[:from]) && f.length == 1 1985 identifier_append(sql, server_version >= 90500 ? f.first : unaliased_identifier(f.first)) 1986 else 1987 source_list_append(sql, f) 1988 end 1989 end
Return the primary key to use for RETURNING in an INSERT statement
# File lib/sequel/adapters/shared/postgres.rb 1992 def insert_pk 1993 if (f = opts[:from]) && !f.empty? 1994 case t = f.first 1995 when Symbol, String, SQL::Identifier, SQL::QualifiedIdentifier 1996 if pk = db.primary_key(t) 1997 Sequel::SQL::Identifier.new(pk) 1998 end 1999 end 2000 end 2001 end
Support OVERRIDING SYSTEM|USER VALUE in insert statements
# File lib/sequel/adapters/shared/postgres.rb 2004 def insert_values_sql(sql) 2005 case opts[:override] 2006 when :system 2007 sql << " OVERRIDING SYSTEM VALUE" 2008 when :user 2009 sql << " OVERRIDING USER VALUE" 2010 end 2011 super 2012 end
For multiple table support, PostgreSQL requires at least two from tables, with joins allowed.
# File lib/sequel/adapters/shared/postgres.rb 2016 def join_from_sql(type, sql) 2017 if(from = @opts[:from][1..-1]).empty? 2018 raise(Error, 'Need multiple FROM tables if updating/deleting a dataset with JOINs') if @opts[:join] 2019 else 2020 sql << ' ' << type.to_s << ' ' 2021 source_list_append(sql, from) 2022 select_join_sql(sql) 2023 end 2024 end
Use a generic blob quoting method, hopefully overridden in one of the subadapter methods
# File lib/sequel/adapters/shared/postgres.rb 2027 def literal_blob_append(sql, v) 2028 sql << "'" << v.gsub(/[\000-\037\047\134\177-\377]/n){|b| "\\#{("%o" % b[0..1].unpack("C")[0]).rjust(3, '0')}"} << "'" 2029 end
PostgreSQL uses FALSE for false values
# File lib/sequel/adapters/shared/postgres.rb 2032 def literal_false 2033 'false' 2034 end
PostgreSQL quotes NaN and Infinity.
# File lib/sequel/adapters/shared/postgres.rb 2037 def literal_float(value) 2038 if value.finite? 2039 super 2040 elsif value.nan? 2041 "'NaN'" 2042 elsif value.infinite? == 1 2043 "'Infinity'" 2044 else 2045 "'-Infinity'" 2046 end 2047 end
Assume that SQL
standard quoting is on, per Sequel's defaults
# File lib/sequel/adapters/shared/postgres.rb 2050 def literal_string_append(sql, v) 2051 sql << "'" << v.gsub("'", "''") << "'" 2052 end
PostgreSQL uses true for true values
# File lib/sequel/adapters/shared/postgres.rb 2055 def literal_true 2056 'true' 2057 end
PostgreSQL supports multiple rows in INSERT.
# File lib/sequel/adapters/shared/postgres.rb 2060 def multi_insert_sql_strategy 2061 :values 2062 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 2079 def requires_like_escape? 2080 false 2081 end
Support FETCH FIRST WITH TIES on PostgreSQL 13+.
# File lib/sequel/adapters/shared/postgres.rb 2084 def select_limit_sql(sql) 2085 l = @opts[:limit] 2086 o = @opts[:offset] 2087 2088 return unless l || o 2089 2090 if @opts[:limit_with_ties] 2091 if o 2092 sql << " OFFSET " 2093 literal_append(sql, o) 2094 end 2095 2096 if l 2097 sql << " FETCH FIRST " 2098 literal_append(sql, l) 2099 sql << " ROWS WITH TIES" 2100 end 2101 else 2102 if l 2103 sql << " LIMIT " 2104 literal_append(sql, l) 2105 end 2106 2107 if o 2108 sql << " OFFSET " 2109 literal_append(sql, o) 2110 end 2111 end 2112 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 2116 def select_lock_sql(sql) 2117 lock = @opts[:lock] 2118 if lock == :share 2119 sql << ' FOR SHARE' 2120 else 2121 super 2122 end 2123 2124 if lock 2125 if @opts[:skip_locked] 2126 sql << " SKIP LOCKED" 2127 elsif @opts[:nowait] 2128 sql << " NOWAIT" 2129 end 2130 end 2131 end
Support VALUES clause instead of the SELECT clause to return rows.
# File lib/sequel/adapters/shared/postgres.rb 2134 def select_values_sql(sql) 2135 sql << "VALUES " 2136 expression_list_append(sql, opts[:values]) 2137 end
Use WITH RECURSIVE instead of WITH if any of the CTEs is recursive
# File lib/sequel/adapters/shared/postgres.rb 2140 def select_with_sql_base 2141 opts[:with].any?{|w| w[:recursive]} ? "WITH RECURSIVE " : super 2142 end
Support WITH AS [NOT] MATERIALIZED if :materialized option is used.
# File lib/sequel/adapters/shared/postgres.rb 2145 def select_with_sql_prefix(sql, w) 2146 super 2147 2148 case w[:materialized] 2149 when true 2150 sql << "MATERIALIZED " 2151 when false 2152 sql << "NOT MATERIALIZED " 2153 end 2154 end
The version of the database server
# File lib/sequel/adapters/shared/postgres.rb 2157 def server_version 2158 db.server_version(@opts[:server]) 2159 end
PostgreSQL 9.4+ supports the FILTER clause for aggregate functions.
# File lib/sequel/adapters/shared/postgres.rb 2162 def supports_filtered_aggregates? 2163 server_version >= 90400 2164 end
PostgreSQL supports quoted function names.
# File lib/sequel/adapters/shared/postgres.rb 2167 def supports_quoted_function_names? 2168 true 2169 end
Use FROM to specify additional tables in an update query
# File lib/sequel/adapters/shared/postgres.rb 2180 def update_from_sql(sql) 2181 join_from_sql(:FROM, sql) 2182 end
Only include the primary table in the main update clause
# File lib/sequel/adapters/shared/postgres.rb 2185 def update_table_sql(sql) 2186 sql << ' ' 2187 source_list_append(sql, @opts[:from][0..0]) 2188 end