Skip to content

Commit 077c0a1

Browse files
committed
Revert "Fix query explorer quoting for PostgreSQL"
This reverts commit 5adbd36.
1 parent 0dc60ab commit 077c0a1

6 files changed

Lines changed: 14 additions & 54 deletions

File tree

app/controllers/mysql_genius/queries_controller.rb

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ def index
1717
@ai_enabled = mysql_genius_config.ai_enabled?
1818
@framework_version_major = Rails::VERSION::MAJOR
1919
@framework_version_minor = Rails::VERSION::MINOR
20-
@identifier_quote_char = identifier_quote_char
2120
render("mysql_genius/queries/dashboard")
2221
end
2322

@@ -78,10 +77,6 @@ def slow_queries
7877

7978
private
8079

81-
def identifier_quote_char
82-
ActiveRecord::Base.connection.quote_table_name("mysql_genius_identifier_probe")[0]
83-
end
84-
8580
def queryable_tables
8681
ActiveRecord::Base.connection.tables - mysql_genius_config.blocked_tables
8782
end

gems/mysql_genius-core/lib/mysql_genius/core/sql_validator.rb

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,9 @@ def validate(sql, blocked_tables:, connection:)
3333

3434
def extract_table_references(sql, connection)
3535
tables = []
36-
identifier = /(?:`([^`]+)`|"((?:""|[^"])+)"|(\w+))/
37-
sql.scan(/\bFROM\s+((?:#{identifier.source}(?:\s*,\s*#{identifier.source})*)+)/i) do |match|
38-
match[0].scan(identifier) { |parts| tables << unquote_identifier(parts) }
39-
end
40-
sql.scan(/\bJOIN\s+#{identifier.source}/i) { |parts| tables << unquote_identifier(parts) }
41-
sql.scan(/\b(?:INTO|UPDATE)\s+#{identifier.source}/i) { |parts| tables << unquote_identifier(parts) }
36+
sql.scan(/\bFROM\s+((?:`?\w+`?(?:\s*,\s*`?\w+`?)*)+)/i) { |m| m[0].scan(/`?(\w+)`?/) { |t| tables << t[0] } }
37+
sql.scan(/\bJOIN\s+`?(\w+)`?/i) { |m| tables << m[0] }
38+
sql.scan(/\b(?:INTO|UPDATE)\s+`?(\w+)`?/i) { |m| tables << m[0] }
4239
tables.uniq.map(&:downcase) & connection.tables
4340
end
4441

@@ -57,10 +54,6 @@ def apply_row_limit(sql, limit)
5754
def masked_column?(column_name, patterns)
5855
patterns.any? { |pattern| column_name.downcase.include?(pattern) }
5956
end
60-
61-
def unquote_identifier(parts)
62-
(parts.find { |part| part && !part.empty? } || "").gsub('""', '"')
63-
end
6457
end
6558
end
6659
end

gems/mysql_genius-core/lib/mysql_genius/core/views/mysql_genius/queries/dashboard.html.erb

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@
7171
query_detail: '/queries/'
7272
};
7373

74-
var IDENTIFIER_QUOTE = String.fromCharCode(<%= (@identifier_quote_char || "`").ord %>);
7574
var RAILS_MIGRATION_VERSION = '<%= @framework_version_major %>.<%= @framework_version_minor %>';
7675

7776
var csrfMeta = document.querySelector('meta[name="csrf-token"]');
@@ -89,12 +88,6 @@
8988
function show(e) { e.classList.remove('mg-hidden'); }
9089
function hide(e) { e.classList.add('mg-hidden'); }
9190
function escHtml(s) { var d = document.createElement('div'); d.textContent = s; return d.innerHTML; }
92-
function quoteIdentifier(name) {
93-
var quote = IDENTIFIER_QUOTE || '`';
94-
var identifier = String(name);
95-
if (quote === '[') return '[' + identifier.split(']').join(']]') + ']';
96-
return quote + identifier.split(quote).join(quote + quote) + quote;
97-
}
9891

9992
// --- Table Sorting ---
10093

@@ -159,8 +152,8 @@
159152
'COUNT SUM AVG MIN MAX COALESCE IFNULL NULLIF CAST CONVERT CONCAT CONCAT_WS GROUP_CONCAT SUBSTRING SUBSTR REPLACE TRIM LTRIM RTRIM UPPER LOWER UCASE LCASE LENGTH CHAR_LENGTH NOW CURDATE CURTIME DATE_FORMAT DATE_ADD DATE_SUB DATEDIFF TIMESTAMPDIFF UNIX_TIMESTAMP FROM_UNIXTIME IF ELT FIELD FIND_IN_SET FORMAT HEX UNHEX MD5 SHA1 SHA2 AES_ENCRYPT AES_DECRYPT ROUND CEIL CEILING FLOOR ABS MOD POWER SQRT LOG LOG2 LOG10 RAND GREATEST LEAST JSON_EXTRACT JSON_UNQUOTE JSON_SET JSON_OBJECT JSON_ARRAY JSON_CONTAINS JSON_LENGTH ROW_NUMBER RANK DENSE_RANK LAG LEAD FIRST_VALUE LAST_VALUE NTH_VALUE'.split(' ').forEach(function(w) { SQL_FN_SET[w] = true; });
160153

161154
// Single-pass tokenizer regex: matches tokens in order of priority
162-
// 1) single-quoted strings 2) quoted identifiers 3) numbers 4) words 5) operators 6) punctuation 7) ? placeholder 8) * star 9) whitespace 10) anything else
163-
var SQL_TOKEN_RE = /'[^']*'|`[^`]*`|"(?:""|[^"])*"|\b\d+(?:\.\d+)?\b|[A-Za-z_]\w*|\?|>=|<=|<>|!=|[><=]|[(),;*]|\s+|./g;
155+
// 1) single-quoted strings 2) backtick identifiers 3) numbers 4) words 5) operators 6) punctuation 7) ? placeholder 8) * star 9) whitespace 10) anything else
156+
var SQL_TOKEN_RE = /'[^']*'|`[^`]*`|\b\d+(?:\.\d+)?\b|[A-Za-z_]\w*|\?\|>=|<=|<>|!=|[><=]|[(),;*]|\s+|./g;
164157

165158
function highlightSql(sql) {
166159
if (!sql) return '';
@@ -174,8 +167,8 @@
174167
if (ch === "'") {
175168
// String literal
176169
result.push('<span class="mg-sql-str">' + escHtml(tok) + '</span>');
177-
} else if (ch === '`' || ch === '"') {
178-
// Quoted identifier
170+
} else if (ch === '`') {
171+
// Backtick-quoted identifier
179172
result.push('<span class="mg-sql-tbl">' + escHtml(tok) + '</span>');
180173
} else if (/^\d/.test(tok)) {
181174
// Number
@@ -665,9 +658,9 @@
665658
var table = el('vb-table').value;
666659
if (!table) return '';
667660
var cols = [];
668-
qsa('.vb-col-check:checked').forEach(function(c) { cols.push(quoteIdentifier(c.value)); });
661+
qsa('.vb-col-check:checked').forEach(function(c) { cols.push('`' + c.value + '`'); });
669662
if (!cols.length) cols = ['*'];
670-
var sql = 'SELECT ' + cols.join(', ') + ' FROM ' + quoteIdentifier(table);
663+
var sql = 'SELECT ' + cols.join(', ') + ' FROM `' + table + '`';
671664
var wheres = [];
672665
qsa('.vb-filter-row').forEach(function(row) {
673666
var col = qs('.vb-filter-col', row).value;
@@ -676,23 +669,23 @@
676669
var val = valEl ? valEl.value : '';
677670
if (!col) return;
678671
if (op === 'IS NULL' || op === 'IS NOT NULL') {
679-
wheres.push(quoteIdentifier(col) + ' ' + op);
672+
wheres.push('`' + col + '` ' + op);
680673
} else if (op === 'BETWEEN') {
681674
var endEl = qs('.vb-filter-val-end', row);
682675
var endVal = endEl ? endEl.value : '';
683-
wheres.push(quoteIdentifier(col) + " BETWEEN '" + val.replace(/'/g, "''") + "' AND '" + endVal.replace(/'/g, "''") + "'");
676+
wheres.push("`" + col + "` BETWEEN '" + val.replace(/'/g, "''") + "' AND '" + endVal.replace(/'/g, "''") + "'");
684677
} else if (op === 'LIKE') {
685-
wheres.push(quoteIdentifier(col) + " LIKE '" + val.replace(/'/g, "''") + "'");
678+
wheres.push("`" + col + "` LIKE '" + val.replace(/'/g, "''") + "'");
686679
} else {
687-
wheres.push(quoteIdentifier(col) + " " + op + " '" + val.replace(/'/g, "''") + "'");
680+
wheres.push("`" + col + "` " + op + " '" + val.replace(/'/g, "''") + "'");
688681
}
689682
});
690683
if (wheres.length) sql += ' WHERE ' + wheres.join(' AND ');
691684
var orders = [];
692685
qsa('.vb-order-row').forEach(function(row) {
693686
var col = qs('.vb-order-col', row).value;
694687
var dir = qs('.vb-order-dir', row).value;
695-
if (col) orders.push(quoteIdentifier(col) + ' ' + dir);
688+
if (col) orders.push('`' + col + '` ' + dir);
696689
});
697690
if (orders.length) sql += ' ORDER BY ' + orders.join(', ');
698691
return sql;

gems/mysql_genius-core/spec/mysql_genius/core/sql_validator_spec.rb

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,6 @@ def validate(sql)
7777
tables = described_class.extract_table_references("SELECT * FROM `users`", connection)
7878
expect(tables).to(include("users"))
7979
end
80-
81-
it "handles double-quoted table names" do
82-
tables = described_class.extract_table_references('SELECT * FROM "users" JOIN "posts" ON "users"."id" = "posts"."user_id"', connection)
83-
expect(tables).to(include("users", "posts"))
84-
end
85-
86-
it "rejects blocked double-quoted table names" do
87-
result = validate('SELECT * FROM "sessions"')
88-
expect(result).to(include("sessions"))
89-
end
9080
end
9181

9282
describe ".apply_row_limit" do

gems/mysql_genius-desktop/lib/mysql_genius/desktop/app.rb

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,6 @@ def capability?(name)
7474
@ai_enabled = settings.mysql_genius_config.ai.enabled?
7575
@framework_version_major = MysqlGenius::Core::VERSION.split(".")[0]
7676
@framework_version_minor = MysqlGenius::Core::VERSION.split(".")[1]
77-
@identifier_quote_char = settings.active_session.checkout do |adapter|
78-
adapter.quote_table_name("mysql_genius_identifier_probe")[0]
79-
end
8077

8178
render_dashboard
8279
end

spec/requests/mysql_genius/index_spec.rb

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,6 @@
1818
expect(last_response.body).to(include("mg-tab"))
1919
end
2020

21-
it "renders the connection-specific identifier quote character" do
22-
allow(ActiveRecord::Base.connection).to(receive(:quote_table_name).and_return('"mysql_genius_identifier_probe"'))
23-
24-
get "/mysql_genius/"
25-
26-
expect(last_response.body).to(include("var IDENTIFIER_QUOTE = String.fromCharCode(34);"))
27-
end
28-
2921
it "respects blocked_tables when building the table lists" do
3022
MysqlGenius.configure { |c| c.blocked_tables = ["orders"] }
3123
get "/mysql_genius/"

0 commit comments

Comments
 (0)