|
|
@@ -315,6 +315,12 @@
|
|
315
|
315
|
background: #F5F5F5;
|
|
316
|
316
|
border-color: #CCCCCC;
|
|
317
|
317
|
}
|
|
|
318
|
+
|
|
|
319
|
+ .btn:disabled {
|
|
|
320
|
+ opacity: 0.5;
|
|
|
321
|
+ cursor: not-allowed;
|
|
|
322
|
+ pointer-events: none;
|
|
|
323
|
+ }
|
|
318
|
324
|
|
|
319
|
325
|
.toast {
|
|
320
|
326
|
position: fixed;
|
|
|
@@ -633,8 +639,9 @@
|
|
633
|
639
|
<textarea class="sql-textarea" v-model="sqlQuery" placeholder="输入SQL查询语句..."></textarea>
|
|
634
|
640
|
<div class="btn-group" style="justify-content: flex-start;">
|
|
635
|
641
|
<button type="button" class="btn btn-default" @click="insertSqlClause('WHERE')">WHERE</button>
|
|
|
642
|
+ <button type="button" class="btn btn-default" @click="insertSqlClause('INNER JOIN ON')" :disabled="!hasWhere">INNER JOIN ON</button>
|
|
636
|
643
|
<button type="button" class="btn btn-default" @click="insertSqlClause('GROUP BY')">GROUP BY</button>
|
|
637
|
|
- <button type="button" class="btn btn-default" @click="insertSqlClause('HAVING')">HAVING</button>
|
|
|
644
|
+ <button type="button" class="btn btn-default" @click="insertSqlClause('HAVING')" :disabled="!hasGroupBy">HAVING</button>
|
|
638
|
645
|
<button type="button" class="btn btn-default" @click="insertSqlClause('ORDER BY')">ORDER BY</button>
|
|
639
|
646
|
<select class="btn btn-default" v-model="selectedLimit" @change="updateQueryLimit"
|
|
640
|
647
|
style="margin-left: 8px;">
|
|
|
@@ -782,7 +789,14 @@
|
|
782
|
789
|
currentColumn: null
|
|
783
|
790
|
},
|
|
784
|
791
|
computed: {
|
|
785
|
|
-
|
|
|
792
|
+ // 检查SQL查询中是否包含WHERE子句
|
|
|
793
|
+ hasWhere() {
|
|
|
794
|
+ return this.sqlQuery && this.sqlQuery.toUpperCase().includes('WHERE');
|
|
|
795
|
+ },
|
|
|
796
|
+ // 检查SQL查询中是否包含GROUP BY子句
|
|
|
797
|
+ hasGroupBy() {
|
|
|
798
|
+ return this.sqlQuery && this.sqlQuery.toUpperCase().includes('GROUP BY');
|
|
|
799
|
+ }
|
|
786
|
800
|
},
|
|
787
|
801
|
mounted() {
|
|
788
|
802
|
this.loadTables();
|
|
|
@@ -1478,6 +1492,7 @@
|
|
1478
|
1492
|
const sqlParts = {
|
|
1479
|
1493
|
select: -1,
|
|
1480
|
1494
|
from: -1,
|
|
|
1495
|
+ join: -1,
|
|
1481
|
1496
|
where: -1,
|
|
1482
|
1497
|
groupBy: -1,
|
|
1483
|
1498
|
having: -1,
|
|
|
@@ -1488,6 +1503,7 @@
|
|
1488
|
1503
|
// 查找各个子句的位置
|
|
1489
|
1504
|
sqlParts.select = sqlUpper.indexOf('SELECT');
|
|
1490
|
1505
|
sqlParts.from = sqlUpper.indexOf('FROM', sqlParts.select);
|
|
|
1506
|
+ sqlParts.join = sqlUpper.indexOf('JOIN', sqlParts.from);
|
|
1491
|
1507
|
sqlParts.where = sqlUpper.indexOf('WHERE', sqlParts.from);
|
|
1492
|
1508
|
sqlParts.groupBy = sqlUpper.indexOf('GROUP BY', sqlParts.from);
|
|
1493
|
1509
|
sqlParts.having = sqlUpper.indexOf('HAVING', sqlParts.from);
|
|
|
@@ -1504,6 +1520,38 @@
|
|
1504
|
1520
|
let insertBefore = '';
|
|
1505
|
1521
|
|
|
1506
|
1522
|
switch (clauseUpper) {
|
|
|
1523
|
+ case 'INNER JOIN ON':
|
|
|
1524
|
+ // INNER JOIN ON应该在FROM之后,WHERE/GROUP BY/HAVING/ORDER BY之前
|
|
|
1525
|
+ if (sqlParts.from > -1) {
|
|
|
1526
|
+ // 找到FROM子句后的位置
|
|
|
1527
|
+ const fromEndPos = this.findClauseEndPosition(sqlUpper, sqlParts.from);
|
|
|
1528
|
+ insertPosition = fromEndPos;
|
|
|
1529
|
+
|
|
|
1530
|
+ // 如果已经有其他JOIN子句,找到最后一个JOIN的位置
|
|
|
1531
|
+ if (sqlParts.join > -1) {
|
|
|
1532
|
+ const lastJoinPos = sqlUpper.lastIndexOf('JOIN', sqlParts.where > -1 ? sqlParts.where : sqlUpper.length);
|
|
|
1533
|
+ if (lastJoinPos > -1) {
|
|
|
1534
|
+ insertPosition = this.findClauseEndPosition(sqlUpper, lastJoinPos);
|
|
|
1535
|
+ }
|
|
|
1536
|
+ }
|
|
|
1537
|
+
|
|
|
1538
|
+ // 如果有WHERE子句,确保在WHERE之前有换行
|
|
|
1539
|
+ if (sqlParts.where > -1) {
|
|
|
1540
|
+ const beforeWhere = this.sqlQuery.substring(0, sqlParts.where).trimEnd();
|
|
|
1541
|
+ const afterWhere = this.sqlQuery.substring(sqlParts.where);
|
|
|
1542
|
+ if (!beforeWhere.endsWith('\n')) {
|
|
|
1543
|
+ this.sqlQuery = beforeWhere + '\n' + afterWhere;
|
|
|
1544
|
+ // 更新WHERE位置
|
|
|
1545
|
+ sqlParts.where = beforeWhere.length + 1;
|
|
|
1546
|
+ }
|
|
|
1547
|
+ }
|
|
|
1548
|
+ } else {
|
|
|
1549
|
+ // 如果没有FROM子句,显示错误提示
|
|
|
1550
|
+ this.showToastMessage('INNER JOIN ON子句必须在FROM子句之后', 'error');
|
|
|
1551
|
+ return;
|
|
|
1552
|
+ }
|
|
|
1553
|
+ break;
|
|
|
1554
|
+
|
|
1507
|
1555
|
case 'WHERE':
|
|
1508
|
1556
|
// WHERE应该在FROM之后,GROUP BY/HAVING/ORDER BY/LIMIT之前
|
|
1509
|
1557
|
if (sqlParts.from > -1) {
|