pglite 0.0.2-x86_64-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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 782ee720f8e6e45609d8760090f0d4ddcb4ed86f53564cd6b99fcc9d3a9d0bf8
4
+ data.tar.gz: fae0ec2a5c165631c2af2ff7388cf7aeb23ea62d4536d9481a3efc8f8985e114
5
+ SHA512:
6
+ metadata.gz: 637b3b3e2d1d63a0f9546cb5a0af4c28a5c25bf8d0fd8e2b1842d8bd06cfeb7f93b8e2c6f0f633e31c4e0c7b3102326cea2e3684dcebf293c094b624b1bf6d35
7
+ data.tar.gz: e7619bee19a3ecb64fd54a7f2efdd9a33dc36278a3a7869c42bf62987173b6c050de79aa09734dd9cb1a8bf8a2235d78c346485657912e0d5e169373e2628e95
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ # Change log
2
+
3
+ ## master
data/LICENSE.txt ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2025 Vladimir Dementyev
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
data/README.md ADDED
@@ -0,0 +1,54 @@
1
+ [![Gem Version](https://badge.fury.io/rb/pglite-rb.svg)](https://rubygems.org/gems/pglite-rb)
2
+ [![Build](https://github.com/palkan/pglite-rb/workflows/Build/badge.svg)](https://github.com/palkan/pglite-rb/actions)
3
+
4
+ # PGlite for Ruby and Rails
5
+
6
+ Let's bring [PGlite](https://pglite.dev/) to Ruby and Rails! Enjoy using PostgreSQL without dealing with databases and native libraries—great for development and testing!
7
+
8
+ ## Installation
9
+
10
+ Add the gem to your Gemfile and run `bundle install`:
11
+
12
+ ```ruby
13
+ # Gemfile
14
+ gem "pglite"
15
+ ```
16
+
17
+ ### Supported Ruby/Rails versions
18
+
19
+ - Ruby (MRI) >= 3.4
20
+ - Rails >= 7.2
21
+
22
+ ## Usage
23
+
24
+ A minimal example:
25
+
26
+ ```ruby
27
+ # First, you must provision the database (creates a bunch of PostgreSQL files in your file system)
28
+ PGlite.install!("tmp/pglite")
29
+
30
+ # Now you can perform queries!
31
+ result = PGLite.exec_query("SELECT 2 + 2 as answer")
32
+
33
+ result.row_count #=> 1
34
+ result.rows #=> [[4]]
35
+ result.columns.map(&:name) #=> ["answer"]
36
+ ```
37
+
38
+ ### Active Record integration
39
+
40
+ Specify the `pglite` adapter in your `database.yml`. Done.
41
+
42
+ The database would be provisioned the first time a connection is initialized (in the `tmp/pglite` directory or in the `mount_path` if one is specified in the configuration). Alternatively, you can manually call `PGlite.install!(path)` on the application boot.
43
+
44
+ ## Contributing
45
+
46
+ Bug reports and pull requests are welcome on GitHub at [https://github.com/palkan/pglite-rb](https://github.com/palkan/pglite-rb).
47
+
48
+ ## Credits
49
+
50
+ This gem is generated via [`newgem` template](https://github.com/palkan/newgem) by [@palkan](https://github.com/palkan).
51
+
52
+ ## License
53
+
54
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require "pg"
5
+ rescue LoadError
6
+ # Patch #gem to ignore 'pg' checks
7
+ Kernel.prepend(Module.new do
8
+ def gem(dep, *)
9
+ return if dep == "pg"
10
+ super
11
+ end
12
+ end)
13
+
14
+ # Update the $LOAD_PATH to include the pg stub
15
+ $LOAD_PATH.unshift(File.expand_path(File.join(__dir__, "pglite_shims")))
16
+ end
17
+
18
+ require "active_record/connection_adapters/postgresql_adapter"
19
+
20
+ module ActiveRecord
21
+ module ConnectionHandling # :nodoc:
22
+ def pglite_adapter_class
23
+ ConnectionAdapters::PGliteAdapter
24
+ end
25
+
26
+ def pglite_connection(config)
27
+ pglite_adapter_class.new(config)
28
+ end
29
+ end
30
+
31
+ module ConnectionAdapters
32
+ class PGliteAdapter < PostgreSQLAdapter
33
+ class << self
34
+ def database_exists?(config)
35
+ true
36
+ end
37
+
38
+ def new_client(...) = PGlite::Connection.new(...)
39
+ end
40
+
41
+ def initialize(...)
42
+ super
43
+ # Prepared statements are not currently supported
44
+ @prepared_statements = false
45
+ end
46
+
47
+ # Stub encoders/decoders
48
+ def add_pg_encoders = nil
49
+
50
+ def add_pg_decoders = nil
51
+
52
+ unless method_defined?(:query_rows)
53
+ alias_method :query_rows, :query
54
+ end
55
+
56
+ # TODO: col_description is not supported ???
57
+ def column_definitions(table_name)
58
+ query_rows(<<~SQL, "SCHEMA")
59
+ SELECT a.attname, format_type(a.atttypid, a.atttypmod),
60
+ pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
61
+ c.collname, '' AS comment,
62
+ #{supports_identity_columns? ? "attidentity" : quote("")} AS identity,
63
+ #{supports_virtual_columns? ? "attgenerated" : quote("")} as attgenerated
64
+ FROM pg_attribute a
65
+ LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
66
+ LEFT JOIN pg_type t ON a.atttypid = t.oid
67
+ LEFT JOIN pg_collation c ON a.attcollation = c.oid AND a.attcollation <> t.typcollation
68
+ WHERE a.attrelid = #{quote(quote_table_name(table_name))}::regclass
69
+ AND a.attnum > 0 AND NOT a.attisdropped
70
+ ORDER BY a.attnum
71
+ SQL
72
+ end
73
+
74
+ ::ActiveRecord::Type.add_modifier({array: true}, PostgreSQL::OID::Array, adapter: :pglite)
75
+ ::ActiveRecord::Type.add_modifier({range: true}, PostgreSQL::OID::Range, adapter: :pglite)
76
+ ::ActiveRecord::Type.register(:bit, PostgreSQL::OID::Bit, adapter: :pglite)
77
+ ::ActiveRecord::Type.register(:bit_varying, PostgreSQL::OID::BitVarying, adapter: :pglite)
78
+ ::ActiveRecord::Type.register(:binary, PostgreSQL::OID::Bytea, adapter: :pglite)
79
+ ::ActiveRecord::Type.register(:cidr, PostgreSQL::OID::Cidr, adapter: :pglite)
80
+ ::ActiveRecord::Type.register(:date, PostgreSQL::OID::Date, adapter: :pglite)
81
+ ::ActiveRecord::Type.register(:datetime, PostgreSQL::OID::DateTime, adapter: :pglite)
82
+ ::ActiveRecord::Type.register(:decimal, PostgreSQL::OID::Decimal, adapter: :pglite)
83
+ ::ActiveRecord::Type.register(:enum, PostgreSQL::OID::Enum, adapter: :pglite)
84
+ ::ActiveRecord::Type.register(:hstore, PostgreSQL::OID::Hstore, adapter: :pglite)
85
+ ::ActiveRecord::Type.register(:inet, PostgreSQL::OID::Inet, adapter: :pglite)
86
+ ::ActiveRecord::Type.register(:interval, PostgreSQL::OID::Interval, adapter: :pglite)
87
+ ::ActiveRecord::Type.register(:jsonb, PostgreSQL::OID::Jsonb, adapter: :pglite)
88
+ ::ActiveRecord::Type.register(:money, PostgreSQL::OID::Money, adapter: :pglite)
89
+ ::ActiveRecord::Type.register(:point, PostgreSQL::OID::Point, adapter: :pglite)
90
+ ::ActiveRecord::Type.register(:legacy_point, PostgreSQL::OID::LegacyPoint, adapter: :pglite)
91
+ ::ActiveRecord::Type.register(:uuid, PostgreSQL::OID::Uuid, adapter: :pglite)
92
+ ::ActiveRecord::Type.register(:vector, PostgreSQL::OID::Vector, adapter: :pglite)
93
+ ::ActiveRecord::Type.register(:xml, PostgreSQL::OID::Xml, adapter: :pglite)
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pglite/pg"
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pglite/pg"
4
+ require "pglite/result"
5
+
6
+ module PGlite
7
+ class Connection
8
+ attr_reader :mount_path
9
+
10
+ def initialize(conn_params = {})
11
+ @mount_path = conn_params[:mount_path] || File.join(Dir.pwd, "tmp", "pglite")
12
+ @prepared_statements_map = {}
13
+ PGlite.install!(mount_path)
14
+ rescue => e
15
+ raise PG::Error, e.message
16
+ end
17
+
18
+ def set_client_encoding(_)
19
+ # make no-op for now
20
+ end
21
+
22
+ def finished? = true
23
+
24
+ def transaction_status
25
+ PG::PQTRANS_IDLE
26
+ end
27
+
28
+ def escape(str) = str
29
+
30
+ def raw_query(sql, params)
31
+ # FIXME: we need to add support for prepared statements at the extension level
32
+ if params.present?
33
+ raise ArgumentError, "Prepared statements are not supported in pglite"
34
+ end
35
+
36
+ raw_res = PGlite.exec_query(sql)
37
+ result = Result.new(raw_res)
38
+ @last_result = result
39
+ result
40
+ rescue => e
41
+ raise PG::Error, e.message
42
+ end
43
+
44
+ def exec(sql)
45
+ raw_query(sql, [])
46
+ end
47
+
48
+ alias_method :query, :exec
49
+ alias_method :async_exec, :exec
50
+ alias_method :async_query, :exec
51
+
52
+ def exec_params(sql, params)
53
+ if params.empty?
54
+ return exec(sql)
55
+ end
56
+ raw_query(sql, params)
57
+ end
58
+
59
+ def exec_prepared(name, params)
60
+ sql = @prepared_statements_map[name]
61
+ exec_params(sql, params)
62
+ end
63
+
64
+ def prepare(name, sql, param_types = nil)
65
+ @prepared_statements_map[name] = sql
66
+ end
67
+
68
+ def get_last_result
69
+ @last_result
70
+ end
71
+
72
+ def reset
73
+ @prepared_statements_map = {}
74
+ end
75
+
76
+ def server_version
77
+ # The result is formed by multiplying the server's major version number by 10000 and adding the minor version number.
78
+ # For example, version 10.1 will be returned as 100001, and version 11.0 will be returned as 110000.
79
+ PGlite.database_version.match(/PostgreSQL\s(\d+)\.(\d+)/)&.then do
80
+ _1[1].to_i * 10_000 + _1[2].to_i
81
+ end
82
+ end
83
+ end
84
+ end
data/lib/pglite/pg.rb ADDED
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require "pg"
5
+ return
6
+ rescue LoadError
7
+ end
8
+
9
+ # Define minumum PG interface
10
+ module PG
11
+ PQTRANS_IDLE = 0 # (connection idle)
12
+ PQTRANS_ACTIVE = 1 # (command in progress)
13
+ PQTRANS_INTRANS = 2 # (idle, within transaction block)
14
+ PQTRANS_INERROR = 3 # (idle, within failed transaction)
15
+ PQTRANS_UNKNOWN = 4 # (cannot determine status)
16
+
17
+ class Error < StandardError; end
18
+ class ConnectionBad < Error; end
19
+ class FeatureNotSupported < Error; end
20
+
21
+ class Connection
22
+ class << self
23
+ # TODO: can we support some configuration?
24
+ def conndefaults_hash = {}
25
+
26
+ def quote_ident(str)
27
+ str = str.to_s
28
+ return '""' if str.empty?
29
+ if str =~ /[^a-zA-Z_0-9]/ || str =~ /^[0-9]/
30
+ '"' + str.gsub('"', '""') + '"'
31
+ else
32
+ str
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ # Just a stub for now
39
+ class SimpleDecoder
40
+ end
41
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PGlite
4
+ class Result
5
+ attr_reader :res
6
+
7
+ # A wrapper for a result object from Oxide
8
+ def initialize(res)
9
+ @res = res
10
+ end
11
+
12
+ def map_types!(map)
13
+ self
14
+ end
15
+
16
+ def values = res.rows
17
+
18
+ def fields = res.columns.map(&:name)
19
+
20
+ def ftype(index) = res.columns[index].oid
21
+
22
+ def fmod(index) = res.columns[index].type_modifier
23
+
24
+ def cmd_tuples = res.row_count
25
+
26
+ def ntuples = res.row_count
27
+
28
+ def clear
29
+ end
30
+
31
+ include Enumerable
32
+
33
+ def each
34
+ return to_enum(:each) unless block_given?
35
+
36
+ columns = fields
37
+ res.rows.each do |res_row|
38
+ row = {}
39
+ columns.each.with_index do |col, i|
40
+ value = res_row[i]
41
+ row[col] = value
42
+ end
43
+ yield row
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PGlite # :nodoc:
4
+ VERSION = "0.0.2"
5
+ end
data/lib/pglite.rb ADDED
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PGlite
4
+ # Main PGlite module
5
+ end
6
+
7
+ require "pglite/version"
8
+
9
+ begin
10
+ require "pglite_rb"
11
+ rescue LoadError
12
+ # Extension not available
13
+ end
14
+
15
+ require "pglite/connection"
16
+
17
+ if defined?(ActiveRecord::ConnectionAdapters) && ActiveRecord::ConnectionAdapters.respond_to?(:register)
18
+ ActiveRecord::ConnectionAdapters.register("pglite", "ActiveRecord::ConnectionAdapters::PGliteAdapter", "active_record/connection_adapters/pglite_adapter")
19
+ end
data/lib/pglite_rb.so ADDED
Binary file
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pglite
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: x86_64-linux
6
+ authors:
7
+ - Vladimir Dementyev
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: bundler
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '1.15'
19
+ type: :development
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '1.15'
26
+ - !ruby/object:Gem::Dependency
27
+ name: combustion
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '1.1'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '1.1'
40
+ - !ruby/object:Gem::Dependency
41
+ name: rake
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '13.0'
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '13.0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: rake-compiler
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.2'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '1.2'
68
+ - !ruby/object:Gem::Dependency
69
+ name: rspec
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '3.9'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '3.9'
82
+ description: PGlite for Ruby and Rails
83
+ email:
84
+ - Vladimir Dementyev
85
+ executables: []
86
+ extensions: []
87
+ extra_rdoc_files: []
88
+ files:
89
+ - CHANGELOG.md
90
+ - LICENSE.txt
91
+ - README.md
92
+ - lib/active_record/connection_adapters/pglite_adapter.rb
93
+ - lib/active_record/connection_adapters/pglite_shims/pg.rb
94
+ - lib/pglite.rb
95
+ - lib/pglite/connection.rb
96
+ - lib/pglite/pg.rb
97
+ - lib/pglite/result.rb
98
+ - lib/pglite/version.rb
99
+ - lib/pglite_rb.so
100
+ homepage: https://github.com/palkan/pglite-rb
101
+ licenses:
102
+ - MIT
103
+ metadata:
104
+ bug_tracker_uri: https://github.com/palkan/pglite-rb/issues
105
+ changelog_uri: https://github.com/palkan/pglite-rb/blob/master/CHANGELOG.md
106
+ documentation_uri: https://github.com/palkan/pglite-rb
107
+ homepage_uri: https://github.com/palkan/pglite-rb
108
+ source_code_uri: https://github.com/palkan/pglite-rb
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '3.4'
117
+ - - "<"
118
+ - !ruby/object:Gem::Version
119
+ version: 3.5.dev
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ requirements: []
126
+ rubygems_version: 3.6.9
127
+ specification_version: 4
128
+ summary: PGlite for Ruby and Rails
129
+ test_files: []