Instance methods for datasets that connect to a PostgreSQL database.
Return the results of an EXPLAIN ANALYZE query as a string
# File lib/sequel/adapters/shared/postgres.rb, line 798 798: def analyze 799: explain(:analyze=>true) 800: end
Handle converting the ruby xor operator (^) into the PostgreSQL xor operator (#).
# File lib/sequel/adapters/shared/postgres.rb, line 804 804: def complex_expression_sql_append(sql, op, args) 805: case op 806: when :^ 807: j = XOR_OP 808: c = false 809: args.each do |a| 810: sql << j if c 811: literal_append(sql, a) 812: c ||= true 813: end 814: else 815: super 816: end 817: end
Return the results of an EXPLAIN query as a string
# File lib/sequel/adapters/shared/postgres.rb, line 820 820: def explain(opts={}) 821: with_sql((opts[:analyze] ? EXPLAIN_ANALYZE : EXPLAIN) + select_sql).map(QUERY_PLAN).join(CRLF) 822: end
PostgreSQL specific full text search syntax, using tsearch2 (included in 8.3 by default, and available for earlier versions as an add-on).
# File lib/sequel/adapters/shared/postgres.rb, line 831 831: def full_text_search(cols, terms, opts = {}) 832: lang = opts[:language] || 'simple' 833: terms = terms.join(' | ') if terms.is_a?(Array) 834: filter("to_tsvector(?::regconfig, ?) @@ to_tsquery(?::regconfig, ?)", lang, full_text_string_join(cols), lang, terms) 835: end
Insert given values into the database.
# File lib/sequel/adapters/shared/postgres.rb, line 838 838: def insert(*values) 839: if @opts[:returning] 840: # already know which columns to return, let the standard code 841: # handle it 842: super 843: elsif @opts[:sql] 844: # raw SQL used, so don't know which table is being inserted 845: # into, and therefore can't determine primary key. Run the 846: # insert statement and return nil. 847: super 848: nil 849: else 850: # Force the use of RETURNING with the primary key value. 851: returning(insert_pk).insert(*values){|r| return r.values.first} 852: end 853: end
Insert a record returning the record inserted
# File lib/sequel/adapters/shared/postgres.rb, line 856 856: def insert_select(*values) 857: returning.insert(*values){|r| return r} 858: 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, line 865 865: def lock(mode, opts={}) 866: if block_given? # perform locking inside a transaction and yield to block 867: @db.transaction(opts){lock(mode, opts); yield} 868: else 869: @db.execute(LOCK % [source_list(@opts[:from]), mode], opts) # lock without a transaction 870: end 871: nil 872: end
PostgreSQL allows inserting multiple rows at once.
# File lib/sequel/adapters/shared/postgres.rb, line 875 875: def multi_insert_sql(columns, values) 876: sql = LiteralString.new('VALUES ') 877: expression_list_append(sql, values.map{|r| Array(r)}) 878: [insert_sql(columns, sql)] 879: 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, line 883 883: def supports_cte_in_subqueries? 884: supports_cte? 885: end
DISTINCT ON is a PostgreSQL extension
# File lib/sequel/adapters/shared/postgres.rb, line 888 888: def supports_distinct_on? 889: true 890: end
PostgreSQL supports modifying joined datasets
# File lib/sequel/adapters/shared/postgres.rb, line 893 893: def supports_modifying_joins? 894: true 895: end
Returning is always supported.
# File lib/sequel/adapters/shared/postgres.rb, line 898 898: def supports_returning?(type) 899: true 900: end
PostgreSQL supports timezones in literal timestamps
# File lib/sequel/adapters/shared/postgres.rb, line 903 903: def supports_timestamp_timezones? 904: true 905: end
PostgreSQL 8.4+ supports window functions
# File lib/sequel/adapters/shared/postgres.rb, line 908 908: def supports_window_functions? 909: server_version >= 80400 910: 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" # => nil DB[:table].truncate(:cascade => true, :only=>true, :restart=>true) # TRUNCATE TABLE ONLY "table" RESTART IDENTITY CASCADE # => nil
# File lib/sequel/adapters/shared/postgres.rb, line 927 927: def truncate(opts = {}) 928: if opts.empty? 929: super() 930: else 931: clone(:truncate_opts=>opts).truncate 932: end 933: end
Return a clone of the dataset with an addition named window that can be referenced in window functions.
# File lib/sequel/adapters/shared/postgres.rb, line 936 936: def window(name, opts) 937: clone(:window=>(@opts[:window]||[]) + [[name, SQL::Window.new(opts)]]) 938: end
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, line 946 946: def _import(columns, values, opts={}) 947: if @opts[:returning] 948: statements = multi_insert_sql(columns, values) 949: @db.transaction(opts.merge(:server=>@opts[:server])) do 950: statements.map{|st| returning_fetch_rows(st)} 951: end.first.map{|v| v.length == 1 ? v.values.first : v} 952: elsif opts[:return] == :primary_key 953: returning(insert_pk)._import(columns, values, opts) 954: else 955: super 956: end 957: end
Format TRUNCATE statement with PostgreSQL specific options.
# File lib/sequel/adapters/shared/postgres.rb, line 962 962: def _truncate_sql(table) 963: to = @opts[:truncate_opts] || {} 964: "TRUNCATE TABLE#{' ONLY' if to[:only]} #{table}#{' RESTART IDENTITY' if to[:restart]}#{' CASCADE' if to[:cascade]}" 965: end
Allow truncation of multiple source tables.
# File lib/sequel/adapters/shared/postgres.rb, line 968 968: def check_truncation_allowed! 969: raise(InvalidOperation, "Grouped datasets cannot be truncated") if opts[:group] 970: raise(InvalidOperation, "Joined datasets cannot be truncated") if opts[:join] 971: 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, line 1061 1061: def compound_dataset_sql_append(sql, ds) 1062: sql << PAREN_OPEN 1063: super 1064: sql << PAREN_CLOSE 1065: end
PostgreSQL allows deleting from joined datasets
# File lib/sequel/adapters/shared/postgres.rb, line 974 974: def delete_clause_methods 975: if server_version >= 90100 976: DELETE_CLAUSE_METHODS_91 977: else 978: DELETE_CLAUSE_METHODS 979: end 980: end
Only include the primary table in the main delete clause
# File lib/sequel/adapters/shared/postgres.rb, line 983 983: def delete_from_sql(sql) 984: sql << FROM 985: source_list_append(sql, @opts[:from][0..0]) 986: end
Use USING to specify additional tables in a delete query
# File lib/sequel/adapters/shared/postgres.rb, line 989 989: def delete_using_sql(sql) 990: join_from_sql(:USING, sql) 991: end
Concatenate the expressions with a space in between
# File lib/sequel/adapters/shared/postgres.rb, line 1100 1100: def full_text_string_join(cols) 1101: cols = Array(cols).map{|x| SQL::Function.new(:COALESCE, x, EMPTY_STRING)} 1102: cols = cols.zip([SPACE] * cols.length).flatten 1103: cols.pop 1104: SQL::StringExpression.new(:'||', *cols) 1105: end
PostgreSQL allows a RETURNING clause.
# File lib/sequel/adapters/shared/postgres.rb, line 994 994: def insert_clause_methods 995: if server_version >= 90100 996: INSERT_CLAUSE_METHODS_91 997: else 998: INSERT_CLAUSE_METHODS 999: end 1000: end
Return the primary key to use for RETURNING in an INSERT statement
# File lib/sequel/adapters/shared/postgres.rb, line 1003 1003: def insert_pk 1004: if (f = opts[:from]) && !f.empty? && (pk = db.primary_key(f.first)) 1005: Sequel::SQL::Identifier.new(pk) 1006: end 1007: end
For multiple table support, PostgreSQL requires at least two from tables, with joins allowed.
# File lib/sequel/adapters/shared/postgres.rb, line 1011 1011: def join_from_sql(type, sql) 1012: if(from = @opts[:from][1..1]).empty? 1013: raise(Error, 'Need multiple FROM tables if updating/deleting a dataset with JOINs') if @opts[:join] 1014: else 1015: sql << SPACE << type.to_s << SPACE 1016: source_list_append(sql, from) 1017: select_join_sql(sql) 1018: end 1019: end
Use a generic blob quoting method, hopefully overridden in one of the subadapter methods
# File lib/sequel/adapters/shared/postgres.rb, line 1022 1022: def literal_blob_append(sql, v) 1023: sql << APOS << v.gsub(BLOB_RE){|b| "\\#{("%o" % b[0..1].unpack("C")[0]).rjust(3, '0')}"} << APOS 1024: end
PostgreSQL uses FALSE for false values
# File lib/sequel/adapters/shared/postgres.rb, line 1027 1027: def literal_false 1028: BOOL_FALSE 1029: end
PostgreSQL quotes NaN and Infinity.
# File lib/sequel/adapters/shared/postgres.rb, line 1032 1032: def literal_float(value) 1033: if value.finite? 1034: super 1035: elsif value.nan? 1036: "'NaN'" 1037: elsif value.infinite? == 1 1038: "'Infinity'" 1039: else 1040: "'-Infinity'" 1041: end 1042: end
Assume that SQL standard quoting is on, per Sequel’s defaults
# File lib/sequel/adapters/shared/postgres.rb, line 1045 1045: def literal_string_append(sql, v) 1046: sql << APOS << v.gsub(APOS_RE, DOUBLE_APOS) << APOS 1047: end
PostgreSQL uses FALSE for false values
# File lib/sequel/adapters/shared/postgres.rb, line 1050 1050: def literal_true 1051: BOOL_TRUE 1052: end
The order of clauses in the SELECT SQL statement
# File lib/sequel/adapters/shared/postgres.rb, line 1055 1055: def select_clause_methods 1056: server_version >= 80400 ? SELECT_CLAUSE_METHODS_84 : SELECT_CLAUSE_METHODS 1057: end
Support FOR SHARE locking when using the :share lock style.
# File lib/sequel/adapters/shared/postgres.rb, line 1068 1068: def select_lock_sql(sql) 1069: @opts[:lock] == :share ? (sql << FOR_SHARE) : super 1070: end
SQL fragment for named window specifications
# File lib/sequel/adapters/shared/postgres.rb, line 1073 1073: def select_window_sql(sql) 1074: if ws = @opts[:window] 1075: sql << WINDOW 1076: c = false 1077: co = COMMA 1078: as = AS 1079: ws.map do |name, window| 1080: sql << co if c 1081: literal_append(sql, name) 1082: sql << as 1083: literal_append(sql, window) 1084: c ||= true 1085: end 1086: end 1087: end
Use WITH RECURSIVE instead of WITH if any of the CTEs is recursive
# File lib/sequel/adapters/shared/postgres.rb, line 1090 1090: def select_with_sql_base 1091: opts[:with].any?{|w| w[:recursive]} ? SQL_WITH_RECURSIVE : super 1092: end
The version of the database server
# File lib/sequel/adapters/shared/postgres.rb, line 1095 1095: def server_version 1096: db.server_version(@opts[:server]) 1097: end
PostgreSQL splits the main table from the joined tables
# File lib/sequel/adapters/shared/postgres.rb, line 1108 1108: def update_clause_methods 1109: if server_version >= 90100 1110: UPDATE_CLAUSE_METHODS_91 1111: else 1112: UPDATE_CLAUSE_METHODS 1113: end 1114: end
Use FROM to specify additional tables in an update query
# File lib/sequel/adapters/shared/postgres.rb, line 1117 1117: def update_from_sql(sql) 1118: join_from_sql(:FROM, sql) 1119: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.