quote-sql 0.0.5 → 0.0.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cb47e85b4c7c4e1f945748295390c9e1bd49b7e0ba5291e0f7310058f6f91ddc
4
- data.tar.gz: 0f5bde1afc31eb573bb3e24727b530bf5909048284114d45c56c1b24a63e97aa
3
+ metadata.gz: 7e308b3aef586983a61155c9ba3be6c39c2397fa5fbae069ab45522e51681caa
4
+ data.tar.gz: 6a3945e1a4cfc16fed91c46216d1a10c5a69e85a6b3a0df10db45a9f162c07eb
5
5
  SHA512:
6
- metadata.gz: 6596b9bb50ee373030e401dcb9d0067ae31857b6467fdd7b0341e21b3dcbe8fb0e78714ec24f56615618bbf965849307474a4030978e6c98d2d728166e235151
7
- data.tar.gz: f38366de3e2227835fd11f512a9c9d2a99d130d896a17f6b0a58788dd8ed7ebd13f46682992b762e2d50f09716c3bd5654d525dc4b03f350d3a52cc6b19b322e
6
+ metadata.gz: 3ce751f52d51a6b7b989062673f9c849b5a8b44e5e4227f0f453290d41b20856b45f0d0bbddd6cea6f5256405b313d82367a27fdd2381dd2b37f27c3ac3442e6
7
+ data.tar.gz: 2656c2cbacc7375fd22f2148d4a929fbba1822c97b61467bdf5794c7bcf78b75d5ba4a9bfb90a6f01b282479bad95c77d354ca2211a6f3561a6eaa60e9d90db4
data/README.md CHANGED
@@ -1,22 +1,25 @@
1
1
  # QuoteSql - Tool to build and run SQL queries easier
2
- I've built this library as an addition to ActiveRecord and Arel, however you can use it with any sql database and plain Ruby.
3
- However currently it is just used with PostgreSQL.
4
-
5
2
  Creating SQL queries and proper quoting becomes complicated especially when you need advanced queries.
6
3
 
7
- I created this library while coding for different projects, and had lots of Heredoc SQL queries, which pretty quickly becomes the kind of:
8
- > When I wrote these lines of code, just me and God knew what they mean. Now its just God.
4
+ I created this library while coding for different projects, and had lots of Heredoc SQL queries, which pretty quickly became unreadable.
5
+
6
+ With QuoteSql you segment SQL Queries in readable junks, which can be individually tested and then combine them to the final query.
7
+ When us use RoR, you can combine queries or get the output with fields other than `pick` or `pluck`
8
+
9
+ Please have a look at the *unfinished* documentation below or run `QuoteSql.test` in a Ruby console
9
10
 
10
- My strategy is to segment SQL Queries in readable junks, which can be individually tested and then combine their sql to the final query.
11
+ If you think QuoteSql is interesting but needs extension, let's chat!
11
12
 
12
- If you think QuoteSql is interesting, let's chat!
13
- Also if you have problems using it, just drop me a note.
13
+ If you run into problems, drop me a note.
14
14
 
15
15
  Best Martin
16
16
 
17
17
  ## Caveats & Notes
18
+ - Currently its just built for Ruby 3, if you need Ruby 2, let me know.
18
19
  - QuoteSql is used in production, but is still bleeding edge - and there is not a fully sync between doc and code.
19
- - Just for my examples and in the docs, I'm using for Yajl for JSON parsing, and changed in my environments the standard parse output to *symbolized keys*.
20
+ - Just for my examples and in the docs, I'm using for Yajl for JSON parsing, and changed in my environments the standard parse output to *symbolized keys*.
21
+ - I've built this library as an addition to ActiveRecord and Arel, however you can use it with any sql database and plain Ruby.
22
+ - It is currently built for PostgreSQL only. If you want to use other DBs, please contribute your code!
20
23
 
21
24
  ## Examples
22
25
  ### Simple quoting
@@ -31,11 +34,12 @@ Best Martin
31
34
  => SELECT first_name, last_name FROM users LIMIT 10
32
35
 
33
36
  ### Quoting of columns and table from a model - or an object responding to table_name and column_names or columns
34
- `QuoteSql.new("SELECT %columns FROM %table_name").quote(table: User).to_sql`
37
+ `QuoteSql.new("SELECT %columns FROM %table").quote(table: User).to_sql`
35
38
  => SELECT "id",firstname","lastname",... FROM "users"
39
+
36
40
  ### Injecting raw sql in a query
37
- `QuoteSql.new("SELECT a,b,%raw FROM table").quote(raw: "jsonb_build_object('a', 1)").to_sql`
38
- => SELECT "a,b,jsonb_build_object('a', 1) FROM table
41
+ `QuoteSql.new("SELECT a,b,%raw FROM my_table").quote(raw: "jsonb_build_object('a', 1)").to_sql`
42
+ => SELECT "a,b,jsonb_build_object('a', 1) FROM my_table
39
43
 
40
44
  ### Injecting ActiveRecord, Arel.sql or QuoteSql
41
45
  `QuoteSql.new("SELECT %column_names FROM (%any_name) a").
@@ -54,15 +58,34 @@ Values are be ordered in sequence of columns. Missing value entries are substitu
54
58
  ON CONFLICT ("id") DO NOTHING
55
59
 
56
60
  ### Columns from a list
57
- `QuoteSql.new("SELECT %columns").quote(columns: [:a, :"b.c", c: {d: field}]).to_sql`
58
- => SELECT "a","b"."c",jsonb_build_object('d', field) AS c
61
+ `QuoteSql.new("SELECT %columns").quote(columns: [:a, "b.c", d: {e: field}]).to_sql`
62
+ => SELECT "a","b"."c",jsonb_build_object('e', field) AS d
63
+
64
+ `QuoteSql.new("SELECT %columns").quote(columns: [:a, "b.c", d: {e: field, nil: false}]).to_sql`
65
+ => SELECT "a","b"."c",jsonb_strip_nulls(jsonb_build_object('e', 1)) AS d
66
+
67
+ ## Executing
68
+ ### Getting the results
69
+ `QuoteSql.new('SELECT %x AS a').quote(x: 1).result`
70
+ => [{:a=>1}]
71
+
72
+ ### Binds
73
+ You can use binds ($1, $2, ...) in the SQL and add arguments to the result call
74
+ `QuoteSql.new('SELECT $1 AS a').result(1)`
75
+
76
+ #### using JSON
59
77
 
60
- `QuoteSql.new("SELECT %columns").quote(columns: [:a, :"b.c", c: {d: field, nil: false}]).to_sql`
61
- => SELECT "a","b"."c",jsonb_strip_nulls(jsonb_build_object('d', 1)) AS c
78
+ v = {a: 1, b: "foo", c: true}
79
+ QuoteSQL(%q{SELECT * FROM %x_json}, x_json: 1, x_casts: {a: "int", b: "text", c: "boolean"}).result(v.to_json)
80
+
81
+ => SELECT * FROM json_to_recordset($1) AS "x"("a" int,"b" text,"c" boolean) => [{a: 1, b: "foo", c: true}]
82
+
83
+ Insert fom json
84
+
85
+ v = {a: 1, b: "foo", c: true}
86
+ QuoteSql.new("INSERT INTO table (%x_columns) SELECT * FROM %x_json").quote({:x_json=>1}).result(v.to_json)
62
87
 
63
88
 
64
- ### Execution of a query
65
- `QuoteSql.new("Select 1 as abc").result` => [{:abc=>1}]
66
89
 
67
90
 
68
91
  ## Substitution of mixins with quoted values
@@ -73,24 +96,14 @@ Values are be ordered in sequence of columns. Missing value entries are substitu
73
96
  **Caution! You need to take care, no protection against infinite recursion **
74
97
 
75
98
  ### Special mixins
76
- - `%table` | `%table_name` | `%table_names`
77
- - `%column` | `%columns` | `%column_names`
99
+ - `%table` +String+, +ActiveRecord::Base+, Object responding to #to_sql, and +Array+ of these
100
+ - `%columns` +Array+ of +String+, +Hash+ keys: AS +Symbol+, +String+. fallback: 1) %casts keys, 2) %table.columns
101
+ - `%casts` +Hash+ keys: column name, values: Cast e.g. "text", "integer"
78
102
  - `%ident` | `%constraint` | `%constraints` quoting for database columns
79
103
  - `%raw` | `%sql` inserting raw SQL
80
- - `%value` | `%values` creates value section for e.g. insert
81
- - In the right order
82
- - Single value => (2)
83
- - +Array+ => (column, column, column) n.b. has to be the correct order
84
- - +Array+ of +Array+ => (...),(...),(...),...
85
- - if the columns option is given (or implicitely by setting table)
86
- - +Hash+ values are ordered according to the columns option, missing values are replaced by `DEFAULT`
87
- - +Array+ of +Hash+ multiple record insert
88
- - `%bind` is replaced with the current bind sequence.
89
- Without appended number the first %bind => $1, the second => $2 etc.
90
- - %bind\\d+ => $+Integer+ e.g. `%bind7` => $7
91
- - `%bind__text` => $1 and it is registered as text - this is used in prepared statements (TO BE IMPLEMENTED)
92
- - `%key_bind__text` => $1 and it is registered as text when using +Hash+ in the execute
93
- $1 will be mapped to the key's value in the +Hash+ TODO
104
+ - `%values` creates the value section for INSERT `INSERT INTO foo (a,b) %values`
105
+ - `%x_values` creates the value secion for FROM `SELECT column1, column2, column3 FROM %x_values`
106
+ - `%x_json` creates `json_for_recordset(JSON) x (CASTS)`. "x" can be any other identifier, you need to define the casts e.g. `quotes(x_json: {a: "a", b: 1}, x_casts: {a: :text, b: :integer)`
94
107
 
95
108
  All can be preceded by additional letters and underscore e.g. `%foo_bar_column`
96
109
 
@@ -110,22 +123,27 @@ with optional array dimension
110
123
  - When the value responds to :to_sql or is a +Arel::Nodes::SqlLiteral+ its added as raw SQL
111
124
  - +Proc+ are executed with the +QuoteSQL::Quoter+ object as parameter and added as raw SQL
112
125
 
113
- ### Special quoting columns
114
- - +String+ or +Symbol+ without a dot e.g. :firstname => "firstname"
115
- - +String+ or +Symbol+ containing a dot e.g. "users.firstname" or => "users"."firstname"
126
+ ### Special quoting for %columns
127
+
128
+ `QuoteSql.new("SELECT %columns FROM %table, other_table").quote(columns: ["a", "other_table.a", :a ], table: "my_table")`
129
+ => SELECT "a", "other_table"."a", "my_table"."a" from "my_table", "other_table"
130
+
131
+ - +String+ without a dot e.g. "firstname" => "firstname"
132
+ - +String+ containing a dot e.g. "users.firstname" or => "users"."firstname"
133
+ - +Symbol+ prepended with table from table: quote if present.
134
+ - +Proc+ is called in the current context
135
+ - +QuoteSql::Raw+ or +Arel::Nodes::SqlLiteral+ are injected as is
136
+ - Object responding to #to_sql is called and injected
116
137
  - +Array+
117
- - +String+ and +Symbols+ see above
118
138
  - +Hash+ see below
119
- - +Hash+ or within the +Array+
120
- - +Symbol+ value will become the column name e.g. {table: :column} => "table"."column"
121
- - +String+ value will become the expression, the key the AS {result: "SUM(*)"} => SUM(*) AS result
122
- - +Proc+ are executed with the +QuoteSQL::Quoter+ object as parameter and added as raw SQL
139
+ - other see above
140
+ - +Hash+
141
+ - keys become the "AS"
142
+ - values
143
+ - +Hash+, +Array+ casted as JSONB
144
+ - others see above
145
+
123
146
 
124
- ## Executing
125
- ### Getting the results
126
- ### Binds
127
- `v = {a: 1, b: "foo", c: true};QuoteSQL(%q{Select * From %x_json}, x_json: 1, x_casts: {a: "int", b: "text", c: "boolean"}).result(v.to_json)`
128
- => Select * From json_to_recordset($1) AS "x"("a" int,"b" text,"c" boolean) => [{a: 1, b: "foo", c: true}]
129
147
 
130
148
  ## Shortcuts and functions
131
149
  - `QuoteSQL("select %abc", abc: 1)` == `QuoteSql.new("select %abc").quote(abc: 1)`
@@ -137,8 +155,8 @@ If you have pg_format installed you can get the resulting query inspected:
137
155
  `QuoteSql.new("select %abc").quote(abc: 1).dsql`
138
156
 
139
157
  # Test
140
- Minimal tests you can run by
141
- `QuoteSql.test.all`
158
+ Currently there are just minimal tests
159
+ run `QuoteSql.test`
142
160
  You can find them in /lib/quote_sql/test.rb
143
161
 
144
162
  ## Installing
@@ -151,8 +169,15 @@ Add this to config/initializers/quote_sql.rb
151
169
 
152
170
  ActiveSupport.on_load(:active_record) do
153
171
  require 'quote_sql'
154
- QuoteSql.db_connector = ActiveRecord::Base
172
+
173
+ # if you want to execute from Strings
174
+ # e.g. "select %a".quote_sql(a: 1).result
155
175
  String.include QuoteSql::Extension
176
+
177
+ # if you use Active Record
178
+ QuoteSql.db_connector = ActiveRecord::Base
179
+ # if you want to execute from a Model
180
+ # e.g. User.select("name, %a").quote_sql(a: 1).result
156
181
  ActiveRecord::Relation.include QuoteSql::Extension
157
182
  end
158
183
 
@@ -49,14 +49,14 @@ class QuoteSql::Test
49
49
  )
50
50
  end
51
51
 
52
- def test_binds
53
- expected <<~SQL
54
- SELECT $1, $2::UUID, $1 AS get_bind_1_again FROM "my_table"
55
- SQL
56
- QuoteSql.new("SELECT %bind, %bind__uuid, %bind1 AS get_bind_1_again FROM %table").quote(
57
- table: "my_table"
58
- )
59
- end
52
+ # def test_binds
53
+ # expected <<~SQL
54
+ # SELECT $1, $2::UUID, $1 AS get_bind_1_again FROM "my_table"
55
+ # SQL
56
+ # QuoteSql.new("SELECT %bind, %bind__uuid, %bind1 AS get_bind_1_again FROM %table").quote(
57
+ # table: "my_table"
58
+ # )
59
+ # end
60
60
 
61
61
  def test_from_values_array
62
62
  expected <<~SQL
@@ -1,3 +1,3 @@
1
1
  class QuoteSql
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quote-sql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Kufner