cipherstash-pg 1.0.0.beta.1-aarch64-linux

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. checksums.yaml +7 -0
  2. data/BSDL +22 -0
  3. data/Contributors.rdoc +46 -0
  4. data/Gemfile +14 -0
  5. data/History.rdoc +789 -0
  6. data/LICENSE +56 -0
  7. data/Manifest.txt +72 -0
  8. data/POSTGRES +23 -0
  9. data/README-OS_X.rdoc +68 -0
  10. data/README-Windows.rdoc +56 -0
  11. data/README.ja.rdoc +13 -0
  12. data/README.rdoc +233 -0
  13. data/Rakefile +115 -0
  14. data/certs/ged.pem +24 -0
  15. data/certs/larskanis-2022.pem +26 -0
  16. data/cipherstash-pg.gemspec +31 -0
  17. data/lib/2.7/pg_ext.so +0 -0
  18. data/lib/3.0/pg_ext.so +0 -0
  19. data/lib/3.1/pg_ext.so +0 -0
  20. data/lib/3.2/pg_ext.so +0 -0
  21. data/lib/cipherstash-pg.rb +15 -0
  22. data/lib/libpq.so.5 +0 -0
  23. data/lib/pg/basic_type_map_based_on_result.rb +47 -0
  24. data/lib/pg/basic_type_map_for_queries.rb +193 -0
  25. data/lib/pg/basic_type_map_for_results.rb +81 -0
  26. data/lib/pg/basic_type_registry.rb +301 -0
  27. data/lib/pg/binary_decoder.rb +23 -0
  28. data/lib/pg/coder.rb +104 -0
  29. data/lib/pg/connection.rb +878 -0
  30. data/lib/pg/constants.rb +12 -0
  31. data/lib/pg/exceptions.rb +18 -0
  32. data/lib/pg/result.rb +43 -0
  33. data/lib/pg/text_decoder.rb +46 -0
  34. data/lib/pg/text_encoder.rb +59 -0
  35. data/lib/pg/tuple.rb +30 -0
  36. data/lib/pg/type_map_by_column.rb +16 -0
  37. data/lib/pg/version.rb +4 -0
  38. data/lib/pg.rb +55 -0
  39. data/misc/openssl-pg-segfault.rb +31 -0
  40. data/misc/postgres/History.txt +9 -0
  41. data/misc/postgres/Manifest.txt +5 -0
  42. data/misc/postgres/README.txt +21 -0
  43. data/misc/postgres/Rakefile +21 -0
  44. data/misc/postgres/lib/postgres.rb +16 -0
  45. data/misc/ruby-pg/History.txt +9 -0
  46. data/misc/ruby-pg/Manifest.txt +5 -0
  47. data/misc/ruby-pg/README.txt +21 -0
  48. data/misc/ruby-pg/Rakefile +21 -0
  49. data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
  50. data/rakelib/task_extension.rb +46 -0
  51. data/sample/array_insert.rb +20 -0
  52. data/sample/async_api.rb +102 -0
  53. data/sample/async_copyto.rb +39 -0
  54. data/sample/async_mixed.rb +56 -0
  55. data/sample/check_conn.rb +21 -0
  56. data/sample/copydata.rb +71 -0
  57. data/sample/copyfrom.rb +81 -0
  58. data/sample/copyto.rb +19 -0
  59. data/sample/cursor.rb +21 -0
  60. data/sample/disk_usage_report.rb +177 -0
  61. data/sample/issue-119.rb +94 -0
  62. data/sample/losample.rb +69 -0
  63. data/sample/minimal-testcase.rb +17 -0
  64. data/sample/notify_wait.rb +72 -0
  65. data/sample/pg_statistics.rb +285 -0
  66. data/sample/replication_monitor.rb +222 -0
  67. data/sample/test_binary_values.rb +33 -0
  68. data/sample/wal_shipper.rb +434 -0
  69. data/sample/warehouse_partitions.rb +311 -0
  70. data/vendor/database-extensions/install.sql +317 -0
  71. data/vendor/database-extensions/uninstall.sql +20 -0
  72. metadata +118 -0
@@ -0,0 +1,311 @@
1
+ # -*- ruby -*-
2
+ # vim: set nosta noet ts=4 sw=4:
3
+ #
4
+ # Script to automatically move partitioned tables and their indexes
5
+ # to a separate area on disk.
6
+ #
7
+ # Mahlon E. Smith <mahlon@martini.nu>
8
+ #
9
+ # Example use case:
10
+ #
11
+ # - You've got a heavy insert table, such as syslog data.
12
+ # - This table has a partitioning trigger (or is manually partitioned)
13
+ # by date, to separate incoming stuff from archival/report stuff.
14
+ # - You have a tablespace on cheap or slower disk (maybe even
15
+ # ZFS compressed, or some such!)
16
+ #
17
+ # The only assumption this script makes is that your tables are dated, and
18
+ # the tablespace they're moving into already exists.
19
+ #
20
+ # A full example, using the syslog idea from above, where each child
21
+ # table is date partitioned by a convention of "syslog_YEAR-WEEKOFYEAR":
22
+ #
23
+ # syslog # <--- parent
24
+ # syslog_2012_06 # <--- inherited
25
+ # syslog_2012_07 # <--- inherited
26
+ # syslog_2012_08 # <--- inherited
27
+ # ...
28
+ #
29
+ # You'd run this script like so:
30
+ #
31
+ # ./warehouse_partitions.rb -F syslog_%Y_%U
32
+ #
33
+ # Assuming this was week 12 of the year, tables syslog_2012_06 through
34
+ # syslog_2012_11 would start sequentially migrating into the tablespace
35
+ # called 'warehouse'.
36
+ #
37
+
38
+
39
+ require 'date'
40
+ require 'ostruct'
41
+ require 'optparse'
42
+ require 'pathname'
43
+ require 'etc'
44
+ require 'pg'
45
+
46
+
47
+ ### A tablespace migration class.
48
+ ###
49
+ class PGWarehouse
50
+
51
+ def initialize( opts )
52
+ @opts = opts
53
+ @db = PG.connect(
54
+ :dbname => opts.database,
55
+ :host => opts.host,
56
+ :port => opts.port,
57
+ :user => opts.user,
58
+ :password => opts.pass,
59
+ :sslmode => 'prefer'
60
+ )
61
+ @db.exec "SET search_path TO %s" % [ opts.schema ] if opts.schema
62
+
63
+ @relations = self.relations
64
+ end
65
+
66
+ attr_reader :db
67
+
68
+ ######
69
+ public
70
+ ######
71
+
72
+ ### Perform the tablespace moves.
73
+ ###
74
+ def migrate
75
+ if @relations.empty?
76
+ $stderr.puts 'No tables were found for warehousing.'
77
+ return
78
+ end
79
+
80
+ $stderr.puts "Found %d relation%s to move." % [ relations.length, relations.length == 1 ? '' : 's' ]
81
+ @relations.sort_by{|_,v| v[:name] }.each do |_, val|
82
+ $stderr.print " - Moving table '%s' to '%s'... " % [
83
+ val[:name], @opts.tablespace
84
+ ]
85
+
86
+ if @opts.dryrun
87
+ $stderr.puts '(not really)'
88
+
89
+ else
90
+ age = self.timer do
91
+ db.exec "ALTER TABLE %s SET TABLESPACE %s;" % [
92
+ val[:name], @opts.tablespace
93
+ ]
94
+ end
95
+ puts age
96
+ end
97
+
98
+ val[ :indexes ].each do |idx|
99
+ $stderr.print " - Moving index '%s' to '%s'... " % [
100
+ idx, @opts.tablespace
101
+ ]
102
+ if @opts.dryrun
103
+ $stderr.puts '(not really)'
104
+
105
+ else
106
+ age = self.timer do
107
+ db.exec "ALTER INDEX %s SET TABLESPACE %s;" % [
108
+ idx, @opts.tablespace
109
+ ]
110
+ end
111
+ puts age
112
+ end
113
+ end
114
+ end
115
+ end
116
+
117
+
118
+ #########
119
+ protected
120
+ #########
121
+
122
+ ### Get OIDs and current tablespaces for everything under the
123
+ ### specified schema.
124
+ ###
125
+ def relations
126
+ return @relations if @relations
127
+ relations = {}
128
+
129
+ query = %q{
130
+ SELECT c.oid AS oid,
131
+ c.relname AS name,
132
+ c.relkind AS kind,
133
+ t.spcname AS tspace
134
+ FROM pg_class AS c
135
+ LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
136
+ LEFT JOIN pg_tablespace t ON t.oid = c.reltablespace
137
+ WHERE c.relkind = 'r' }
138
+ query << "AND n.nspname='#{@opts.schema}'" if @opts.schema
139
+
140
+ # Get the relations list, along with each element's current tablespace.
141
+ #
142
+ self.db.exec( query ) do |res|
143
+ res.each do |row|
144
+ relations[ row['oid'] ] = {
145
+ :name => row['name'],
146
+ :tablespace => row['tspace'],
147
+ :indexes => [],
148
+ :parent => nil
149
+ }
150
+ end
151
+ end
152
+
153
+ # Add table inheritance information.
154
+ #
155
+ db.exec 'SELECT inhrelid AS oid, inhparent AS parent FROM pg_inherits' do |res|
156
+ res.each do |row|
157
+ relations[ row['oid'] ][ :parent ] = row['parent']
158
+ end
159
+ end
160
+
161
+ # Remove tables that don't qualify for warehousing.
162
+ #
163
+ # - Tables that are not children of a parent
164
+ # - Tables that are already in the warehouse tablespace
165
+ # - The currently active child (it's likely being written to!)
166
+ # - Any table that can't be parsed into the specified format
167
+ #
168
+ relations.reject! do |oid, val|
169
+ begin
170
+ val[:parent].nil? ||
171
+ val[:tablespace] == @opts.tablespace ||
172
+ val[:name] == Time.now.strftime( @opts.format ) ||
173
+ ! DateTime.strptime( val[:name], @opts.format )
174
+ rescue ArgumentError
175
+ true
176
+ end
177
+ end
178
+
179
+ query = %q{
180
+ SELECT c.oid AS oid,
181
+ i.indexname AS name
182
+ FROM pg_class AS c
183
+ INNER JOIN pg_indexes AS i
184
+ ON i.tablename = c.relname }
185
+ query << "AND i.schemaname='#{@opts.schema}'" if @opts.schema
186
+
187
+ # Attach index names to tables.
188
+ #
189
+ db.exec( query ) do |res|
190
+ res.each do |row|
191
+ relations[ row['oid'] ][ :indexes ] << row['name'] if relations[ row['oid'] ]
192
+ end
193
+ end
194
+
195
+ return relations
196
+ end
197
+
198
+
199
+ ### Wrap arbitrary commands in a human readable timer.
200
+ ###
201
+ def timer
202
+ start = Time.now
203
+ yield
204
+ age = Time.now - start
205
+
206
+ diff = age
207
+ secs = diff % 60
208
+ diff = ( diff - secs ) / 60
209
+ mins = diff % 60
210
+ diff = ( diff - mins ) / 60
211
+ hour = diff % 24
212
+
213
+ return "%02d:%02d:%02d" % [ hour, mins, secs ]
214
+ end
215
+ end
216
+
217
+
218
+ ### Parse command line arguments. Return a struct of global options.
219
+ ###
220
+ def parse_args( args )
221
+ options = OpenStruct.new
222
+ options.database = Etc.getpwuid( Process.uid ).name
223
+ options.host = '127.0.0.1'
224
+ options.port = 5432
225
+ options.user = Etc.getpwuid( Process.uid ).name
226
+ options.sslmode = 'prefer'
227
+ options.tablespace = 'warehouse'
228
+
229
+ opts = OptionParser.new do |opts|
230
+ opts.banner = "Usage: #{$0} [options]"
231
+
232
+ opts.separator ''
233
+ opts.separator 'Connection options:'
234
+
235
+ opts.on( '-d', '--database DBNAME',
236
+ "specify the database to connect to (default: \"#{options.database}\")" ) do |db|
237
+ options.database = db
238
+ end
239
+
240
+ opts.on( '-h', '--host HOSTNAME', 'database server host' ) do |host|
241
+ options.host = host
242
+ end
243
+
244
+ opts.on( '-p', '--port PORT', Integer,
245
+ "database server port (default: \"#{options.port}\")" ) do |port|
246
+ options.port = port
247
+ end
248
+
249
+ opts.on( '-n', '--schema SCHEMA', String,
250
+ "operate on the named schema only (default: none)" ) do |schema|
251
+ options.schema = schema
252
+ end
253
+
254
+ opts.on( '-T', '--tablespace SPACE', String,
255
+ "move old tables to this tablespace (default: \"#{options.tablespace}\")" ) do |tb|
256
+ options.tablespace = tb
257
+ end
258
+
259
+ opts.on( '-F', '--tableformat FORMAT', String,
260
+ "The naming format (strftime) for the inherited tables (default: none)" ) do |format|
261
+ options.format = format
262
+ end
263
+
264
+ opts.on( '-U', '--user NAME',
265
+ "database user name (default: \"#{options.user}\")" ) do |user|
266
+ options.user = user
267
+ end
268
+
269
+ opts.on( '-W', 'force password prompt' ) do |pw|
270
+ print 'Password: '
271
+ begin
272
+ system 'stty -echo'
273
+ options.pass = gets.chomp
274
+ ensure
275
+ system 'stty echo'
276
+ puts
277
+ end
278
+ end
279
+
280
+ opts.separator ''
281
+ opts.separator 'Other options:'
282
+
283
+ opts.on_tail( '--dry-run', "don't actually do anything" ) do
284
+ options.dryrun = true
285
+ end
286
+
287
+ opts.on_tail( '--help', 'show this help, then exit' ) do
288
+ $stderr.puts opts
289
+ exit
290
+ end
291
+
292
+ opts.on_tail( '--version', 'output version information, then exit' ) do
293
+ puts Stats::VERSION
294
+ exit
295
+ end
296
+ end
297
+
298
+ opts.parse!( args )
299
+ return options
300
+ end
301
+
302
+
303
+ if __FILE__ == $0
304
+ opts = parse_args( ARGV )
305
+ raise ArgumentError, "A naming format (-F) is required." unless opts.format
306
+
307
+ $stdout.sync = true
308
+ PGWarehouse.new( opts ).migrate
309
+ end
310
+
311
+
@@ -0,0 +1,317 @@
1
+ CREATE EXTENSION IF NOT EXISTS pgcrypto;
2
+
3
+ CREATE TYPE ore_64_8_v1_term AS (
4
+ bytes bytea
5
+ );
6
+
7
+ CREATE TYPE ore_64_8_v1 AS (
8
+ terms ore_64_8_v1_term[]
9
+ );
10
+
11
+ CREATE OR REPLACE FUNCTION compare_ore_64_8_v1_term(a ore_64_8_v1_term, b ore_64_8_v1_term) returns integer AS $$
12
+ DECLARE
13
+ eq boolean := true;
14
+ unequal_block smallint := 0;
15
+ hash_key bytea;
16
+ target_block bytea;
17
+
18
+ left_block_size CONSTANT smallint := 16;
19
+ right_block_size CONSTANT smallint := 32;
20
+ right_offset CONSTANT smallint := 136; -- 8 * 17
21
+
22
+ indicator smallint := 0;
23
+ BEGIN
24
+ IF a IS NULL AND b IS NULL THEN
25
+ RETURN 0;
26
+ END IF;
27
+
28
+ IF a IS NULL THEN
29
+ RETURN -1;
30
+ END IF;
31
+
32
+ IF b IS NULL THEN
33
+ RETURN 1;
34
+ END IF;
35
+
36
+ IF bit_length(a.bytes) != bit_length(b.bytes) THEN
37
+ RAISE EXCEPTION 'Ciphertexts are different lengths';
38
+ END IF;
39
+
40
+ FOR block IN 0..7 LOOP
41
+ -- Compare each PRP (byte from the first 8 bytes) and PRF block (8 byte
42
+ -- chunks of the rest of the value).
43
+ -- NOTE:
44
+ -- * Substr is ordinally indexed (hence 1 and not 0, and 9 and not 8).
45
+ -- * We are not worrying about timing attacks here; don't fret about
46
+ -- the OR or !=.
47
+ IF
48
+ substr(a.bytes, 1 + block, 1) != substr(b.bytes, 1 + block, 1)
49
+ OR substr(a.bytes, 9 + left_block_size * block, left_block_size) != substr(b.bytes, 9 + left_block_size * BLOCK, left_block_size)
50
+ THEN
51
+ -- set the first unequal block we find
52
+ IF eq THEN
53
+ unequal_block := block;
54
+ END IF;
55
+ eq = false;
56
+ END IF;
57
+ END LOOP;
58
+
59
+ IF eq THEN
60
+ RETURN 0::integer;
61
+ END IF;
62
+
63
+ -- Hash key is the IV from the right CT of b
64
+ hash_key := substr(b.bytes, right_offset + 1, 16);
65
+
66
+ -- first right block is at right offset + nonce_size (ordinally indexed)
67
+ target_block := substr(b.bytes, right_offset + 17 + (unequal_block * right_block_size), right_block_size);
68
+
69
+ indicator := (
70
+ get_bit(
71
+ encrypt(
72
+ substr(a.bytes, 9 + (left_block_size * unequal_block), left_block_size),
73
+ hash_key,
74
+ 'aes-ecb'
75
+ ),
76
+ 0
77
+ ) + get_bit(target_block, get_byte(a.bytes, unequal_block))) % 2;
78
+
79
+ IF indicator = 1 THEN
80
+ RETURN 1::integer;
81
+ ELSE
82
+ RETURN -1::integer;
83
+ END IF;
84
+ END;
85
+ $$ LANGUAGE plpgsql;
86
+
87
+
88
+ CREATE OR REPLACE FUNCTION ore_64_8_v1_term_eq(a ore_64_8_v1_term, b ore_64_8_v1_term) RETURNS boolean AS $$
89
+ SELECT compare_ore_64_8_v1_term(a, b) = 0
90
+ $$ LANGUAGE SQL;
91
+
92
+ CREATE OR REPLACE FUNCTION ore_64_8_v1_term_neq(a ore_64_8_v1_term, b ore_64_8_v1_term) RETURNS boolean AS $$
93
+ SELECT compare_ore_64_8_v1_term(a, b) <> 0
94
+ $$ LANGUAGE SQL;
95
+
96
+ CREATE OR REPLACE FUNCTION ore_64_8_v1_term_lt(a ore_64_8_v1_term, b ore_64_8_v1_term) RETURNS boolean AS $$
97
+ SELECT compare_ore_64_8_v1_term(a, b) = -1
98
+ $$ LANGUAGE SQL;
99
+
100
+ CREATE OR REPLACE FUNCTION ore_64_8_v1_term_lte(a ore_64_8_v1_term, b ore_64_8_v1_term) RETURNS boolean AS $$
101
+ SELECT compare_ore_64_8_v1_term(a, b) != 1
102
+ $$ LANGUAGE SQL;
103
+
104
+ CREATE OR REPLACE FUNCTION ore_64_8_v1_term_gt(a ore_64_8_v1_term, b ore_64_8_v1_term) RETURNS boolean AS $$
105
+ SELECT compare_ore_64_8_v1_term(a, b) = 1
106
+ $$ LANGUAGE SQL;
107
+
108
+ CREATE OR REPLACE FUNCTION ore_64_8_v1_term_gte(a ore_64_8_v1_term, b ore_64_8_v1_term) RETURNS boolean AS $$
109
+ SELECT compare_ore_64_8_v1_term(a, b) != -1
110
+ $$ LANGUAGE SQL;
111
+
112
+ CREATE OPERATOR = (
113
+ PROCEDURE="ore_64_8_v1_term_eq",
114
+ LEFTARG=ore_64_8_v1_term,
115
+ RIGHTARG=ore_64_8_v1_term,
116
+ NEGATOR = <>,
117
+ RESTRICT = eqsel,
118
+ JOIN = eqjoinsel,
119
+ HASHES,
120
+ MERGES
121
+ );
122
+
123
+ CREATE OPERATOR <> (
124
+ PROCEDURE="ore_64_8_v1_term_neq",
125
+ LEFTARG=ore_64_8_v1_term,
126
+ RIGHTARG=ore_64_8_v1_term,
127
+ NEGATOR = =,
128
+ RESTRICT = eqsel,
129
+ JOIN = eqjoinsel,
130
+ HASHES,
131
+ MERGES
132
+ );
133
+
134
+ CREATE OPERATOR > (
135
+ PROCEDURE="ore_64_8_v1_term_gt",
136
+ LEFTARG=ore_64_8_v1_term,
137
+ RIGHTARG=ore_64_8_v1_term,
138
+ COMMUTATOR = <,
139
+ NEGATOR = <=,
140
+ RESTRICT = scalargtsel,
141
+ JOIN = scalargtjoinsel
142
+ );
143
+
144
+ CREATE OPERATOR < (
145
+ PROCEDURE="ore_64_8_v1_term_lt",
146
+ LEFTARG=ore_64_8_v1_term,
147
+ RIGHTARG=ore_64_8_v1_term,
148
+ COMMUTATOR = >,
149
+ NEGATOR = >=,
150
+ RESTRICT = scalarltsel,
151
+ JOIN = scalarltjoinsel
152
+ );
153
+
154
+ CREATE OPERATOR <= (
155
+ PROCEDURE="ore_64_8_v1_term_lte",
156
+ LEFTARG=ore_64_8_v1_term,
157
+ RIGHTARG=ore_64_8_v1_term,
158
+ COMMUTATOR = >=,
159
+ NEGATOR = >,
160
+ RESTRICT = scalarlesel,
161
+ JOIN = scalarlejoinsel
162
+ );
163
+
164
+ CREATE OPERATOR >= (
165
+ PROCEDURE="ore_64_8_v1_term_gte",
166
+ LEFTARG=ore_64_8_v1_term,
167
+ RIGHTARG=ore_64_8_v1_term,
168
+ COMMUTATOR = <=,
169
+ NEGATOR = <,
170
+ RESTRICT = scalarlesel,
171
+ JOIN = scalarlejoinsel
172
+ );
173
+
174
+ CREATE OPERATOR FAMILY ore_64_8_v1_term_btree_ops USING btree;
175
+ CREATE OPERATOR CLASS ore_64_8_v1_term_btree_ops DEFAULT FOR TYPE ore_64_8_v1_term USING btree FAMILY ore_64_8_v1_term_btree_ops AS
176
+ OPERATOR 1 <,
177
+ OPERATOR 2 <=,
178
+ OPERATOR 3 =,
179
+ OPERATOR 4 >=,
180
+ OPERATOR 5 >,
181
+ FUNCTION 1 compare_ore_64_8_v1_term(a ore_64_8_v1_term, b ore_64_8_v1_term);
182
+
183
+ -- Compare the "head" of each array and recurse if necessary
184
+ -- This function assumes an empty string is "less than" everything else
185
+ -- so if a is empty we return -1, if be is empty and a isn't, we return 1.
186
+ -- If both are empty we return 0. This cases probably isn't necessary as equality
187
+ -- doesn't always make sense but it's here for completeness.
188
+ -- If both are non-empty, we compare the first element. If they are equal
189
+ -- we need to consider the next block so we recurse, otherwise we return the comparison result.
190
+ CREATE OR REPLACE FUNCTION compare_ore_array(a ore_64_8_v1_term[], b ore_64_8_v1_term[]) returns integer AS $$
191
+ DECLARE
192
+ cmp_result integer;
193
+ BEGIN
194
+ IF (array_length(a, 1) = 0 OR a IS NULL) AND (array_length(b, 1) = 0 OR b IS NULL) THEN
195
+ RETURN 0;
196
+ END IF;
197
+ IF array_length(a, 1) = 0 OR a IS NULL THEN
198
+ RETURN -1;
199
+ END IF;
200
+ IF array_length(b, 1) = 0 OR a IS NULL THEN
201
+ RETURN 1;
202
+ END IF;
203
+
204
+ cmp_result := compare_ore_64_8_v1_term(a[1], b[1]);
205
+ IF cmp_result = 0 THEN
206
+ -- Removes the first element in the array, and calls this fn again to compare the next element/s in the array.
207
+ RETURN compare_ore_array(a[2:array_length(a,1)], b[2:array_length(b,1)]);
208
+ END IF;
209
+
210
+ RETURN cmp_result;
211
+ END
212
+ $$ LANGUAGE plpgsql;
213
+
214
+ -- This function uses lexicographic comparison
215
+ CREATE OR REPLACE FUNCTION compare_ore_64_8_v1(a ore_64_8_v1, b ore_64_8_v1) returns integer AS $$
216
+ DECLARE
217
+ cmp_result integer;
218
+ BEGIN
219
+ -- Recursively compare blocks bailing as soon as we can make a decision
220
+ RETURN compare_ore_array(a.terms, b.terms);
221
+ END
222
+ $$ LANGUAGE plpgsql;
223
+
224
+ CREATE OR REPLACE FUNCTION ore_64_8_v1_eq(a ore_64_8_v1, b ore_64_8_v1) RETURNS boolean AS $$
225
+ SELECT compare_ore_64_8_v1(a, b) = 0
226
+ $$ LANGUAGE SQL;
227
+
228
+ CREATE OR REPLACE FUNCTION ore_64_8_v1_neq(a ore_64_8_v1, b ore_64_8_v1) RETURNS boolean AS $$
229
+ SELECT compare_ore_64_8_v1(a, b) <> 0
230
+ $$ LANGUAGE SQL;
231
+
232
+ CREATE OR REPLACE FUNCTION ore_64_8_v1_lt(a ore_64_8_v1, b ore_64_8_v1) RETURNS boolean AS $$
233
+ SELECT compare_ore_64_8_v1(a, b) = -1
234
+ $$ LANGUAGE SQL;
235
+
236
+ CREATE OR REPLACE FUNCTION ore_64_8_v1_lte(a ore_64_8_v1, b ore_64_8_v1) RETURNS boolean AS $$
237
+ SELECT compare_ore_64_8_v1(a, b) != 1
238
+ $$ LANGUAGE SQL;
239
+
240
+ CREATE OR REPLACE FUNCTION ore_64_8_v1_gt(a ore_64_8_v1, b ore_64_8_v1) RETURNS boolean AS $$
241
+ SELECT compare_ore_64_8_v1(a, b) = 1
242
+ $$ LANGUAGE SQL;
243
+
244
+ CREATE OR REPLACE FUNCTION ore_64_8_v1_gte(a ore_64_8_v1, b ore_64_8_v1) RETURNS boolean AS $$
245
+ SELECT compare_ore_64_8_v1(a, b) != -1
246
+ $$ LANGUAGE SQL;
247
+
248
+ CREATE OPERATOR = (
249
+ PROCEDURE="ore_64_8_v1_eq",
250
+ LEFTARG=ore_64_8_v1,
251
+ RIGHTARG=ore_64_8_v1,
252
+ NEGATOR = <>,
253
+ RESTRICT = eqsel,
254
+ JOIN = eqjoinsel,
255
+ HASHES,
256
+ MERGES
257
+ );
258
+
259
+ CREATE OPERATOR <> (
260
+ PROCEDURE="ore_64_8_v1_neq",
261
+ LEFTARG=ore_64_8_v1,
262
+ RIGHTARG=ore_64_8_v1,
263
+ NEGATOR = =,
264
+ RESTRICT = eqsel,
265
+ JOIN = eqjoinsel,
266
+ HASHES,
267
+ MERGES
268
+ );
269
+
270
+ CREATE OPERATOR > (
271
+ PROCEDURE="ore_64_8_v1_gt",
272
+ LEFTARG=ore_64_8_v1,
273
+ RIGHTARG=ore_64_8_v1,
274
+ COMMUTATOR = <,
275
+ NEGATOR = <=,
276
+ RESTRICT = scalargtsel,
277
+ JOIN = scalargtjoinsel
278
+ );
279
+
280
+ CREATE OPERATOR < (
281
+ PROCEDURE="ore_64_8_v1_lt",
282
+ LEFTARG=ore_64_8_v1,
283
+ RIGHTARG=ore_64_8_v1,
284
+ COMMUTATOR = >,
285
+ NEGATOR = >=,
286
+ RESTRICT = scalarltsel,
287
+ JOIN = scalarltjoinsel
288
+ );
289
+
290
+ CREATE OPERATOR <= (
291
+ PROCEDURE="ore_64_8_v1_lte",
292
+ LEFTARG=ore_64_8_v1,
293
+ RIGHTARG=ore_64_8_v1,
294
+ COMMUTATOR = >=,
295
+ NEGATOR = >,
296
+ RESTRICT = scalarlesel,
297
+ JOIN = scalarlejoinsel
298
+ );
299
+
300
+ CREATE OPERATOR >= (
301
+ PROCEDURE="ore_64_8_v1_gte",
302
+ LEFTARG=ore_64_8_v1,
303
+ RIGHTARG=ore_64_8_v1,
304
+ COMMUTATOR = <=,
305
+ NEGATOR = <,
306
+ RESTRICT = scalarlesel,
307
+ JOIN = scalarlejoinsel
308
+ );
309
+
310
+ CREATE OPERATOR FAMILY ore_64_8_v1_btree_ops USING btree;
311
+ CREATE OPERATOR CLASS ore_64_8_v1_btree_ops DEFAULT FOR TYPE ore_64_8_v1 USING btree FAMILY ore_64_8_v1_btree_ops AS
312
+ OPERATOR 1 <,
313
+ OPERATOR 2 <=,
314
+ OPERATOR 3 =,
315
+ OPERATOR 4 >=,
316
+ OPERATOR 5 >,
317
+ FUNCTION 1 compare_ore_64_8_v1(a ore_64_8_v1, b ore_64_8_v1);
@@ -0,0 +1,20 @@
1
+ -- TODO: what happens if we try to uninstall a type which is in use?
2
+ DROP OPERATOR IF EXISTS = (ore_64_8_v1_term, ore_64_8_v1_term) CASCADE;
3
+ DROP OPERATOR IF EXISTS <> (ore_64_8_v1_term, ore_64_8_v1_term) CASCADE;
4
+ DROP OPERATOR IF EXISTS > (ore_64_8_v1_term, ore_64_8_v1_term) CASCADE;
5
+ DROP OPERATOR IF EXISTS < (ore_64_8_v1_term, ore_64_8_v1_term) CASCADE;
6
+ DROP OPERATOR IF EXISTS <= (ore_64_8_v1_term, ore_64_8_v1_term) CASCADE;
7
+ DROP OPERATOR IF EXISTS >= (ore_64_8_v1_term, ore_64_8_v1_term) CASCADE;
8
+ DROP OPERATOR CLASS IF EXISTS ore_64_8_v1_term_btree_ops USING btree CASCADE;
9
+ DROP OPERATOR FAMILY IF EXISTS ore_64_8_v1_term_btree_ops USING btree CASCADE;
10
+ DROP TYPE IF EXISTS ore_64_8_v1_term CASCADE;
11
+
12
+ DROP OPERATOR IF EXISTS = (ore_64_8_v1, ore_64_8_v1) CASCADE;
13
+ DROP OPERATOR IF EXISTS <> (ore_64_8_v1, ore_64_8_v1) CASCADE;
14
+ DROP OPERATOR IF EXISTS > (ore_64_8_v1, ore_64_8_v1) CASCADE;
15
+ DROP OPERATOR IF EXISTS < (ore_64_8_v1, ore_64_8_v1) CASCADE;
16
+ DROP OPERATOR IF EXISTS <= (ore_64_8_v1, ore_64_8_v1) CASCADE;
17
+ DROP OPERATOR IF EXISTS >= (ore_64_8_v1, ore_64_8_v1) CASCADE;
18
+ DROP OPERATOR CLASS IF EXISTS ore_64_8_v1_btree_ops USING btree CASCADE;
19
+ DROP OPERATOR FAMILY IF EXISTS ore_64_8_v1_btree_ops USING btree CASCADE;
20
+ DROP TYPE IF EXISTS ore_64_8_v1 CASCADE;