tina4ruby 3.11.13 → 3.11.15
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 +4 -4
- data/CHANGELOG.md +80 -80
- data/LICENSE.txt +21 -21
- data/README.md +137 -137
- data/exe/tina4ruby +5 -5
- data/lib/tina4/ai.rb +696 -696
- data/lib/tina4/api.rb +189 -189
- data/lib/tina4/auth.rb +305 -305
- data/lib/tina4/auto_crud.rb +244 -244
- data/lib/tina4/cache.rb +154 -154
- data/lib/tina4/cli.rb +1449 -1449
- data/lib/tina4/constants.rb +46 -46
- data/lib/tina4/container.rb +74 -74
- data/lib/tina4/cors.rb +74 -74
- data/lib/tina4/crud.rb +692 -692
- data/lib/tina4/database/sqlite3_adapter.rb +165 -165
- data/lib/tina4/database.rb +625 -625
- data/lib/tina4/database_result.rb +208 -208
- data/lib/tina4/debug.rb +8 -8
- data/lib/tina4/dev.rb +14 -14
- data/lib/tina4/dev_admin.rb +935 -935
- data/lib/tina4/dev_mailbox.rb +191 -191
- data/lib/tina4/drivers/firebird_driver.rb +124 -110
- data/lib/tina4/drivers/mongodb_driver.rb +561 -561
- data/lib/tina4/drivers/mssql_driver.rb +112 -112
- data/lib/tina4/drivers/mysql_driver.rb +90 -90
- data/lib/tina4/drivers/odbc_driver.rb +191 -191
- data/lib/tina4/drivers/postgres_driver.rb +116 -106
- data/lib/tina4/drivers/sqlite_driver.rb +122 -122
- data/lib/tina4/env.rb +95 -95
- data/lib/tina4/error_overlay.rb +252 -252
- data/lib/tina4/events.rb +109 -109
- data/lib/tina4/field_types.rb +154 -154
- data/lib/tina4/frond.rb +2025 -2025
- data/lib/tina4/gallery/auth/meta.json +1 -1
- data/lib/tina4/gallery/auth/src/routes/api/gallery_auth.rb +114 -114
- data/lib/tina4/gallery/database/meta.json +1 -1
- data/lib/tina4/gallery/database/src/routes/api/gallery_db.rb +43 -43
- data/lib/tina4/gallery/error-overlay/meta.json +1 -1
- data/lib/tina4/gallery/error-overlay/src/routes/api/gallery_crash.rb +17 -17
- data/lib/tina4/gallery/orm/meta.json +1 -1
- data/lib/tina4/gallery/orm/src/routes/api/gallery_products.rb +16 -16
- data/lib/tina4/gallery/queue/meta.json +1 -1
- data/lib/tina4/gallery/queue/src/routes/api/gallery_queue.rb +325 -325
- data/lib/tina4/gallery/rest-api/meta.json +1 -1
- data/lib/tina4/gallery/rest-api/src/routes/api/gallery_hello.rb +14 -14
- data/lib/tina4/gallery/templates/meta.json +1 -1
- data/lib/tina4/gallery/templates/src/routes/gallery_page.rb +12 -12
- data/lib/tina4/gallery/templates/src/templates/gallery_page.twig +257 -257
- data/lib/tina4/graphql.rb +966 -966
- data/lib/tina4/health.rb +39 -39
- data/lib/tina4/html_element.rb +170 -170
- data/lib/tina4/job.rb +80 -80
- data/lib/tina4/localization.rb +168 -168
- data/lib/tina4/log.rb +203 -203
- data/lib/tina4/mcp.rb +696 -696
- data/lib/tina4/messenger.rb +587 -587
- data/lib/tina4/metrics.rb +793 -793
- data/lib/tina4/middleware.rb +445 -445
- data/lib/tina4/migration.rb +451 -451
- data/lib/tina4/orm.rb +790 -790
- data/lib/tina4/public/css/tina4.css +2463 -2463
- data/lib/tina4/public/css/tina4.min.css +1 -1
- data/lib/tina4/public/images/logo.svg +5 -5
- data/lib/tina4/public/js/frond.min.js +2 -2
- data/lib/tina4/public/js/tina4-dev-admin.js +565 -565
- data/lib/tina4/public/js/tina4-dev-admin.min.js +480 -480
- data/lib/tina4/public/js/tina4.min.js +92 -92
- data/lib/tina4/public/js/tina4js.min.js +48 -48
- data/lib/tina4/public/swagger/index.html +90 -90
- data/lib/tina4/public/swagger/oauth2-redirect.html +63 -63
- data/lib/tina4/query_builder.rb +380 -380
- data/lib/tina4/queue.rb +366 -366
- data/lib/tina4/queue_backends/kafka_backend.rb +80 -80
- data/lib/tina4/queue_backends/lite_backend.rb +298 -298
- data/lib/tina4/queue_backends/mongo_backend.rb +126 -126
- data/lib/tina4/queue_backends/rabbitmq_backend.rb +73 -73
- data/lib/tina4/rack_app.rb +817 -817
- data/lib/tina4/rate_limiter.rb +130 -130
- data/lib/tina4/request.rb +268 -255
- data/lib/tina4/response.rb +346 -346
- data/lib/tina4/response_cache.rb +551 -551
- data/lib/tina4/router.rb +406 -406
- data/lib/tina4/scss/tina4css/_alerts.scss +34 -34
- data/lib/tina4/scss/tina4css/_badges.scss +22 -22
- data/lib/tina4/scss/tina4css/_buttons.scss +69 -69
- data/lib/tina4/scss/tina4css/_cards.scss +49 -49
- data/lib/tina4/scss/tina4css/_forms.scss +156 -156
- data/lib/tina4/scss/tina4css/_grid.scss +81 -81
- data/lib/tina4/scss/tina4css/_modals.scss +84 -84
- data/lib/tina4/scss/tina4css/_nav.scss +149 -149
- data/lib/tina4/scss/tina4css/_reset.scss +94 -94
- data/lib/tina4/scss/tina4css/_tables.scss +54 -54
- data/lib/tina4/scss/tina4css/_typography.scss +55 -55
- data/lib/tina4/scss/tina4css/_utilities.scss +197 -197
- data/lib/tina4/scss/tina4css/_variables.scss +117 -117
- data/lib/tina4/scss/tina4css/base.scss +1 -1
- data/lib/tina4/scss/tina4css/colors.scss +48 -48
- data/lib/tina4/scss/tina4css/tina4.scss +17 -17
- data/lib/tina4/scss_compiler.rb +178 -178
- data/lib/tina4/seeder.rb +567 -567
- data/lib/tina4/service_runner.rb +303 -303
- data/lib/tina4/session.rb +297 -297
- data/lib/tina4/session_handlers/database_handler.rb +72 -72
- data/lib/tina4/session_handlers/file_handler.rb +67 -67
- data/lib/tina4/session_handlers/mongo_handler.rb +49 -49
- data/lib/tina4/session_handlers/redis_handler.rb +43 -43
- data/lib/tina4/session_handlers/valkey_handler.rb +43 -43
- data/lib/tina4/shutdown.rb +84 -84
- data/lib/tina4/sql_translation.rb +158 -158
- data/lib/tina4/swagger.rb +124 -124
- data/lib/tina4/template.rb +894 -894
- data/lib/tina4/templates/base.twig +26 -26
- data/lib/tina4/templates/errors/302.twig +14 -14
- data/lib/tina4/templates/errors/401.twig +9 -9
- data/lib/tina4/templates/errors/403.twig +29 -29
- data/lib/tina4/templates/errors/404.twig +29 -29
- data/lib/tina4/templates/errors/500.twig +38 -38
- data/lib/tina4/templates/errors/502.twig +9 -9
- data/lib/tina4/templates/errors/503.twig +12 -12
- data/lib/tina4/templates/errors/base.twig +37 -37
- data/lib/tina4/test_client.rb +159 -159
- data/lib/tina4/testing.rb +340 -340
- data/lib/tina4/validator.rb +174 -174
- data/lib/tina4/version.rb +1 -1
- data/lib/tina4/webserver.rb +312 -312
- data/lib/tina4/websocket.rb +343 -343
- data/lib/tina4/websocket_backplane.rb +190 -190
- data/lib/tina4/wsdl.rb +564 -564
- data/lib/tina4.rb +458 -458
- data/lib/tina4ruby.rb +4 -4
- metadata +3 -3
|
@@ -1,112 +1,112 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Tina4
|
|
4
|
-
module Drivers
|
|
5
|
-
class MssqlDriver
|
|
6
|
-
attr_reader :connection
|
|
7
|
-
|
|
8
|
-
def connect(connection_string, username: nil, password: nil)
|
|
9
|
-
require "tiny_tds"
|
|
10
|
-
uri = parse_connection(connection_string)
|
|
11
|
-
@connection = TinyTds::Client.new(
|
|
12
|
-
host: uri[:host],
|
|
13
|
-
port: uri[:port] || 1433,
|
|
14
|
-
username: username || uri[:username],
|
|
15
|
-
password: password || uri[:password],
|
|
16
|
-
database: uri[:database]
|
|
17
|
-
)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def close
|
|
21
|
-
@connection&.close
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def execute_query(sql, params = [])
|
|
25
|
-
effective_sql = interpolate_params(sql, params)
|
|
26
|
-
result = @connection.execute(effective_sql)
|
|
27
|
-
rows = result.each(symbolize_keys: true).to_a
|
|
28
|
-
result.cancel if result.respond_to?(:cancel)
|
|
29
|
-
rows
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def execute(sql, params = [])
|
|
33
|
-
effective_sql = interpolate_params(sql, params)
|
|
34
|
-
result = @connection.execute(effective_sql)
|
|
35
|
-
result.do
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def last_insert_id
|
|
39
|
-
result = @connection.execute("SELECT SCOPE_IDENTITY() AS id")
|
|
40
|
-
row = result.first
|
|
41
|
-
result.cancel if result.respond_to?(:cancel)
|
|
42
|
-
row[:id]&.to_i
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def placeholder
|
|
46
|
-
"?"
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def placeholders(count)
|
|
50
|
-
(["?"] * count).join(", ")
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def apply_limit(sql, limit, offset = 0)
|
|
54
|
-
"#{sql} OFFSET #{offset} ROWS FETCH NEXT #{limit} ROWS ONLY"
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def begin_transaction
|
|
58
|
-
@connection.execute("BEGIN TRANSACTION").do
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def commit
|
|
62
|
-
@connection.execute("COMMIT").do
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def rollback
|
|
66
|
-
@connection.execute("ROLLBACK").do
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def tables
|
|
70
|
-
rows = execute_query("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'")
|
|
71
|
-
rows.map { |r| r[:TABLE_NAME] || r[:table_name] }
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def columns(table_name)
|
|
75
|
-
sql = "SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_DEFAULT FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ?"
|
|
76
|
-
rows = execute_query(sql, [table_name])
|
|
77
|
-
rows.map do |r|
|
|
78
|
-
{
|
|
79
|
-
name: r[:COLUMN_NAME] || r[:column_name],
|
|
80
|
-
type: r[:DATA_TYPE] || r[:data_type],
|
|
81
|
-
nullable: (r[:IS_NULLABLE] || r[:is_nullable]) == "YES",
|
|
82
|
-
default: r[:COLUMN_DEFAULT] || r[:column_default],
|
|
83
|
-
primary_key: false
|
|
84
|
-
}
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
private
|
|
89
|
-
|
|
90
|
-
def parse_connection(str)
|
|
91
|
-
# Format: mssql://user:pass@host:port/database
|
|
92
|
-
match = str.match(%r{(?:mssql|sqlserver)://(?:(\w+):([^@]+)@)?([^:/]+)(?::(\d+))?/(.+)})
|
|
93
|
-
if match
|
|
94
|
-
{ username: match[1], password: match[2], host: match[3],
|
|
95
|
-
port: match[4]&.to_i, database: match[5] }
|
|
96
|
-
else
|
|
97
|
-
{ host: "localhost", database: str }
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def interpolate_params(sql, params)
|
|
102
|
-
return sql if params.empty?
|
|
103
|
-
result = sql.dup
|
|
104
|
-
params.each do |param|
|
|
105
|
-
escaped = param.is_a?(String) ? "'#{param.gsub("'", "''")}'" : param.to_s
|
|
106
|
-
result = result.sub("?", escaped)
|
|
107
|
-
end
|
|
108
|
-
result
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
end
|
|
112
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tina4
|
|
4
|
+
module Drivers
|
|
5
|
+
class MssqlDriver
|
|
6
|
+
attr_reader :connection
|
|
7
|
+
|
|
8
|
+
def connect(connection_string, username: nil, password: nil)
|
|
9
|
+
require "tiny_tds"
|
|
10
|
+
uri = parse_connection(connection_string)
|
|
11
|
+
@connection = TinyTds::Client.new(
|
|
12
|
+
host: uri[:host],
|
|
13
|
+
port: uri[:port] || 1433,
|
|
14
|
+
username: username || uri[:username],
|
|
15
|
+
password: password || uri[:password],
|
|
16
|
+
database: uri[:database]
|
|
17
|
+
)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def close
|
|
21
|
+
@connection&.close
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def execute_query(sql, params = [])
|
|
25
|
+
effective_sql = interpolate_params(sql, params)
|
|
26
|
+
result = @connection.execute(effective_sql)
|
|
27
|
+
rows = result.each(symbolize_keys: true).to_a
|
|
28
|
+
result.cancel if result.respond_to?(:cancel)
|
|
29
|
+
rows
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def execute(sql, params = [])
|
|
33
|
+
effective_sql = interpolate_params(sql, params)
|
|
34
|
+
result = @connection.execute(effective_sql)
|
|
35
|
+
result.do
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def last_insert_id
|
|
39
|
+
result = @connection.execute("SELECT SCOPE_IDENTITY() AS id")
|
|
40
|
+
row = result.first
|
|
41
|
+
result.cancel if result.respond_to?(:cancel)
|
|
42
|
+
row[:id]&.to_i
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def placeholder
|
|
46
|
+
"?"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def placeholders(count)
|
|
50
|
+
(["?"] * count).join(", ")
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def apply_limit(sql, limit, offset = 0)
|
|
54
|
+
"#{sql} OFFSET #{offset} ROWS FETCH NEXT #{limit} ROWS ONLY"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def begin_transaction
|
|
58
|
+
@connection.execute("BEGIN TRANSACTION").do
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def commit
|
|
62
|
+
@connection.execute("COMMIT").do
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def rollback
|
|
66
|
+
@connection.execute("ROLLBACK").do
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def tables
|
|
70
|
+
rows = execute_query("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'")
|
|
71
|
+
rows.map { |r| r[:TABLE_NAME] || r[:table_name] }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def columns(table_name)
|
|
75
|
+
sql = "SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_DEFAULT FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ?"
|
|
76
|
+
rows = execute_query(sql, [table_name])
|
|
77
|
+
rows.map do |r|
|
|
78
|
+
{
|
|
79
|
+
name: r[:COLUMN_NAME] || r[:column_name],
|
|
80
|
+
type: r[:DATA_TYPE] || r[:data_type],
|
|
81
|
+
nullable: (r[:IS_NULLABLE] || r[:is_nullable]) == "YES",
|
|
82
|
+
default: r[:COLUMN_DEFAULT] || r[:column_default],
|
|
83
|
+
primary_key: false
|
|
84
|
+
}
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
private
|
|
89
|
+
|
|
90
|
+
def parse_connection(str)
|
|
91
|
+
# Format: mssql://user:pass@host:port/database
|
|
92
|
+
match = str.match(%r{(?:mssql|sqlserver)://(?:(\w+):([^@]+)@)?([^:/]+)(?::(\d+))?/(.+)})
|
|
93
|
+
if match
|
|
94
|
+
{ username: match[1], password: match[2], host: match[3],
|
|
95
|
+
port: match[4]&.to_i, database: match[5] }
|
|
96
|
+
else
|
|
97
|
+
{ host: "localhost", database: str }
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def interpolate_params(sql, params)
|
|
102
|
+
return sql if params.empty?
|
|
103
|
+
result = sql.dup
|
|
104
|
+
params.each do |param|
|
|
105
|
+
escaped = param.is_a?(String) ? "'#{param.gsub("'", "''")}'" : param.to_s
|
|
106
|
+
result = result.sub("?", escaped)
|
|
107
|
+
end
|
|
108
|
+
result
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
@@ -1,90 +1,90 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Tina4
|
|
4
|
-
module Drivers
|
|
5
|
-
class MysqlDriver
|
|
6
|
-
attr_reader :connection
|
|
7
|
-
|
|
8
|
-
def connect(connection_string, username: nil, password: nil)
|
|
9
|
-
require "mysql2"
|
|
10
|
-
uri = URI.parse(connection_string)
|
|
11
|
-
@connection = Mysql2::Client.new(
|
|
12
|
-
host: uri.host || "localhost",
|
|
13
|
-
port: uri.port || 3306,
|
|
14
|
-
username: username || uri.user,
|
|
15
|
-
password: password || uri.password,
|
|
16
|
-
database: uri.path&.sub("/", "")
|
|
17
|
-
)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def close
|
|
21
|
-
@connection&.close
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def execute_query(sql, params = [])
|
|
25
|
-
if params.empty?
|
|
26
|
-
results = @connection.query(sql, symbolize_keys: true)
|
|
27
|
-
else
|
|
28
|
-
stmt = @connection.prepare(sql)
|
|
29
|
-
results = stmt.execute(*params, symbolize_keys: true)
|
|
30
|
-
end
|
|
31
|
-
results.to_a
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def execute(sql, params = [])
|
|
35
|
-
if params.empty?
|
|
36
|
-
@connection.query(sql)
|
|
37
|
-
else
|
|
38
|
-
stmt = @connection.prepare(sql)
|
|
39
|
-
stmt.execute(*params)
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def last_insert_id
|
|
44
|
-
@connection.last_id
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def placeholder
|
|
48
|
-
"?"
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def placeholders(count)
|
|
52
|
-
(["?"] * count).join(", ")
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def apply_limit(sql, limit, offset = 0)
|
|
56
|
-
"#{sql} LIMIT #{limit} OFFSET #{offset}"
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def begin_transaction
|
|
60
|
-
@connection.query("START TRANSACTION")
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def commit
|
|
64
|
-
@connection.query("COMMIT")
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def rollback
|
|
68
|
-
@connection.query("ROLLBACK")
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def tables
|
|
72
|
-
rows = execute_query("SHOW TABLES")
|
|
73
|
-
rows.map { |r| r.values.first }
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def columns(table_name)
|
|
77
|
-
rows = execute_query("DESCRIBE #{table_name}")
|
|
78
|
-
rows.map do |r|
|
|
79
|
-
{
|
|
80
|
-
name: r[:Field],
|
|
81
|
-
type: r[:Type],
|
|
82
|
-
nullable: r[:Null] == "YES",
|
|
83
|
-
default: r[:Default],
|
|
84
|
-
primary_key: r[:Key] == "PRI"
|
|
85
|
-
}
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tina4
|
|
4
|
+
module Drivers
|
|
5
|
+
class MysqlDriver
|
|
6
|
+
attr_reader :connection
|
|
7
|
+
|
|
8
|
+
def connect(connection_string, username: nil, password: nil)
|
|
9
|
+
require "mysql2"
|
|
10
|
+
uri = URI.parse(connection_string)
|
|
11
|
+
@connection = Mysql2::Client.new(
|
|
12
|
+
host: uri.host || "localhost",
|
|
13
|
+
port: uri.port || 3306,
|
|
14
|
+
username: username || uri.user,
|
|
15
|
+
password: password || uri.password,
|
|
16
|
+
database: uri.path&.sub("/", "")
|
|
17
|
+
)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def close
|
|
21
|
+
@connection&.close
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def execute_query(sql, params = [])
|
|
25
|
+
if params.empty?
|
|
26
|
+
results = @connection.query(sql, symbolize_keys: true)
|
|
27
|
+
else
|
|
28
|
+
stmt = @connection.prepare(sql)
|
|
29
|
+
results = stmt.execute(*params, symbolize_keys: true)
|
|
30
|
+
end
|
|
31
|
+
results.to_a
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def execute(sql, params = [])
|
|
35
|
+
if params.empty?
|
|
36
|
+
@connection.query(sql)
|
|
37
|
+
else
|
|
38
|
+
stmt = @connection.prepare(sql)
|
|
39
|
+
stmt.execute(*params)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def last_insert_id
|
|
44
|
+
@connection.last_id
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def placeholder
|
|
48
|
+
"?"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def placeholders(count)
|
|
52
|
+
(["?"] * count).join(", ")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def apply_limit(sql, limit, offset = 0)
|
|
56
|
+
"#{sql} LIMIT #{limit} OFFSET #{offset}"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def begin_transaction
|
|
60
|
+
@connection.query("START TRANSACTION")
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def commit
|
|
64
|
+
@connection.query("COMMIT")
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def rollback
|
|
68
|
+
@connection.query("ROLLBACK")
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def tables
|
|
72
|
+
rows = execute_query("SHOW TABLES")
|
|
73
|
+
rows.map { |r| r.values.first }
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def columns(table_name)
|
|
77
|
+
rows = execute_query("DESCRIBE #{table_name}")
|
|
78
|
+
rows.map do |r|
|
|
79
|
+
{
|
|
80
|
+
name: r[:Field],
|
|
81
|
+
type: r[:Type],
|
|
82
|
+
nullable: r[:Null] == "YES",
|
|
83
|
+
default: r[:Default],
|
|
84
|
+
primary_key: r[:Key] == "PRI"
|
|
85
|
+
}
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|