dbviewer 0.4.8 → 0.5.1

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.
@@ -32,9 +32,11 @@
32
32
  /* Base styles and typography */
33
33
  body {
34
34
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
35
- font-size: 0.95rem;
35
+ font-size: 0.875rem;
36
36
  line-height: 1.5;
37
37
  letter-spacing: -0.01em;
38
+ color: #464c54; /* More subdued text color for light theme */
39
+ background-color: #f5f6f9; /* Subtle gray background */
38
40
  }
39
41
 
40
42
  h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
@@ -43,11 +45,11 @@
43
45
  line-height: 1.25;
44
46
  }
45
47
 
46
- /* Core layout styles */
48
+ /* Core layout styles - Grafana-like compact layout */
47
49
  .dbviewer-wrapper { display: flex; flex-direction: column; min-height: 100vh; }
48
- .dbviewer-navbar { height: 60px; }
49
- .dbviewer-navbar-spacer { height: 60px; } /* Creates space for the fixed navbar */
50
- .dbviewer-content { display: flex; flex: 1; min-height: calc(100vh - 60px); padding-top: 0; }
50
+ .dbviewer-navbar { height: 48px; } /* Reduced height for more compact header */
51
+ .dbviewer-navbar-spacer { height: 48px; } /* Creates space for the fixed navbar */
52
+ .dbviewer-content { display: flex; flex: 1; min-height: calc(100vh - 48px); padding-top: 0; }
51
53
 
52
54
  /* Smooth theme transitions */
53
55
  html {
@@ -67,19 +69,19 @@
67
69
  transition: color 0.2s ease, background-color 0.2s ease;
68
70
  }
69
71
 
70
- /* Sidebar styles - enhanced for elegance */
72
+ /* Sidebar styles - enhanced for elegance with Grafana-like compact design */
71
73
  .dbviewer-sidebar {
72
- width: 260px;
73
- height: calc(100vh - 60px);
74
+ width: 240px; /* More compact sidebar width */
75
+ height: calc(100vh - 48px);
74
76
  position: fixed;
75
- top: 60px; /* Positioned right below the fixed navbar */
77
+ top: 48px; /* Positioned right below the fixed navbar */
76
78
  left: 0;
77
79
  z-index: 1000;
78
80
  display: flex;
79
81
  flex-direction: column;
80
82
  transition: transform 0.3s ease-in-out, background-color 0.2s ease, border-color 0.2s ease;
81
- overflow: hidden; /* Changed from overflow-y: auto */
82
- box-shadow: 3px 0 20px rgba(0, 0, 0, 0.05);
83
+ overflow: hidden;
84
+ box-shadow: 2px 0 10px rgba(0, 0, 0, 0.04); /* Subtler shadow */
83
85
  }
84
86
 
85
87
  /* Dark mode overrides */
@@ -94,7 +96,7 @@
94
96
  }
95
97
 
96
98
  .dbviewer-sidebar-header {
97
- padding: 1.2rem 1.25rem;
99
+ padding: 0.8rem 1rem; /* Reduced padding for more compact header */
98
100
  font-weight: 600;
99
101
  align-items: center;
100
102
  justify-content: space-between;
@@ -157,7 +159,7 @@
157
159
  .dbviewer-sidebar-content {
158
160
  flex: 1;
159
161
  overflow-y: auto;
160
- padding: 0.5rem 0;
162
+ padding: 0.25rem 0; /* Reduced padding */
161
163
  height: 100%;
162
164
  /* Improved scrollbar */
163
165
  scrollbar-width: thin;
@@ -183,9 +185,9 @@
183
185
 
184
186
  .dbviewer-main {
185
187
  flex: 1;
186
- margin-left: 260px;
187
- padding: 2rem 2.5rem;
188
- padding-top: 1.5rem; /* Adjusted for fixed header */
188
+ margin-left: 240px; /* Reduced sidebar width */
189
+ padding: 1.2rem 1.5rem; /* Reduced padding for more compact look */
190
+ padding-top: 0.8rem; /* Adjusted for fixed header */
189
191
  min-width: 0;
190
192
  animation: fadeIn 0.5s ease-in-out;
191
193
  transition: all 0.3s ease;
@@ -281,19 +283,20 @@
281
283
  }
282
284
  }
283
285
 
284
- /* Extra small screens */
286
+ /* Extra small screens - more compact for small devices */
285
287
  @media (max-width: 575.98px) {
286
- .dbviewer-main { padding: 0.75rem; }
288
+ .dbviewer-main { padding: 0.6rem; }
287
289
  h1, .h1 { font-size: 1.6rem; }
288
290
  h2, .h2 { font-size: 1.4rem; }
289
291
  h3, .h3 { font-size: 1.2rem; }
290
292
 
291
293
  .btn-sm {
292
- font-size: 0.8rem;
294
+ font-size: 0.75rem;
295
+ padding: 0.2rem 0.5rem;
293
296
  }
294
297
 
295
298
  .card-body {
296
- padding: 1rem;
299
+ padding: 0.75rem;
297
300
  }
298
301
  }
299
302
 
@@ -343,30 +346,31 @@
343
346
  border-color: rgba(134, 183, 254, 0.7);
344
347
  }
345
348
 
346
- /* Table structure and visualization components */
349
+ /* Table structure and visualization components - Grafana-inspired */
347
350
  .dbviewer-card {
348
- border-radius: 0.5rem;
351
+ border-radius: 3px; /* Smaller border radius for Grafana look */
349
352
  transition: all 0.2s ease;
350
353
  overflow: hidden;
351
- box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06), 0 1px 4px rgba(0, 0, 0, 0.08);
354
+ box-shadow: 0 1px 5px rgba(0, 0, 0, 0.05); /* Subtler shadow */
352
355
  height: 100%;
353
356
  }
354
357
 
355
358
  .dbviewer-card:hover {
356
- box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08), 0 1px 6px rgba(0, 0, 0, 0.1);
357
- transform: translateY(-2px);
359
+ box-shadow: 0 3px 10px rgba(0, 0, 0, 0.07), 0 1px 3px rgba(0, 0, 0, 0.06);
360
+ transform: translateY(-1px); /* Subtler hover effect */
358
361
  }
359
362
 
360
- /* Improved card headers */
363
+ /* Improved card headers - more compact */
361
364
  .dbviewer-card .card-header {
362
365
  font-weight: 600;
363
- padding: 1rem 1.25rem;
366
+ padding: 0.7rem 1rem; /* Reduced padding */
364
367
  border-bottom-width: 1px;
368
+ font-size: 0.95rem; /* Slightly smaller font */
365
369
  }
366
370
 
367
- /* Card body padding */
371
+ /* Card body padding - more compact */
368
372
  .dbviewer-card .card-body {
369
- padding: 1.25rem;
373
+ padding: 0.9rem 1rem; /* Reduced padding */
370
374
  }
371
375
 
372
376
  [data-bs-theme="light"] .dbviewer-card {
@@ -483,7 +487,7 @@
483
487
  /* List group styling for dark mode */
484
488
  [data-bs-theme="dark"] .list-group-item {
485
489
  background-color: var(--bs-dark);
486
- border-color: rgba(255, 255, 255, 0.15);
490
+ border-color: rgba(255, 255, 255, 0.08); /* Subtler border */
487
491
  color: var(--bs-light);
488
492
  }
489
493
 
@@ -494,10 +498,10 @@
494
498
  z-index: 1;
495
499
  }
496
500
 
497
- /* Equal height for timeline and structure cards */
501
+ /* Equal height for timeline and structure cards - Grafana-inspired compact layout */
498
502
  .two-column-layout .card { height: 100%; display: flex; flex-direction: column; }
499
- .two-column-layout .card-body { flex: 1; display: flex; flex-direction: column; }
500
- .two-column-layout .chart-container { flex: 1; min-height: 250px; }
503
+ .two-column-layout .card-body { flex: 1; display: flex; flex-direction: column; padding: 0.75rem; } /* Reduced padding */
504
+ .two-column-layout .chart-container { flex: 1; min-height: 220px; } /* Reduced min-height */
501
505
  .two-column-layout .structure-container { padding: 0; }
502
506
  .two-column-layout .tab-content { flex: 1; overflow: hidden; display: flex; flex-direction: column; }
503
507
  .two-column-layout .tab-pane { flex: 1; overflow: hidden; }
@@ -560,24 +564,28 @@
560
564
  font-size: 1.2rem;
561
565
  }
562
566
 
563
- /* Header styles for a more professional look */
567
+ /* Header styles for a more professional Grafana-like look */
564
568
  .navbar {
565
569
  transition: all 0.3s ease;
566
- padding: 0.5rem 1rem;
567
- box-shadow: 0 2px 15px rgba(0, 0, 0, 0.08);
570
+ padding: 0 0.75rem; /* Reduced horizontal padding */
571
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05); /* Subtler shadow */
572
+ min-height: 48px; /* Fixed height */
568
573
  }
569
574
 
570
575
  .navbar-brand {
571
576
  font-weight: 600;
572
577
  letter-spacing: -0.01em;
578
+ font-size: 1.1rem; /* Smaller brand */
579
+ padding: 0.1rem 0; /* Reduced padding */
573
580
  }
574
581
 
575
582
  .nav-link {
576
583
  font-weight: 500;
577
- padding: 0.5rem 0.8rem !important;
578
- border-radius: 4px;
584
+ padding: 0.35rem 0.65rem !important; /* Reduced padding */
585
+ border-radius: 2px; /* Smaller radius for Grafana look */
579
586
  transition: all 0.2s ease;
580
- margin: 0 2px;
587
+ margin: 0 1px; /* Reduced margin */
588
+ font-size: 0.9rem; /* Smaller font */
581
589
  }
582
590
 
583
591
  .nav-link.active {
@@ -602,11 +610,11 @@
602
610
  border-radius: 0;
603
611
  border-left: 0;
604
612
  border-right: 0;
605
- padding: 0.75rem 1.25rem;
613
+ padding: 0.5rem 0.85rem; /* Reduced padding for compact look */
606
614
  transition: all 0.15s ease-in-out;
607
615
  position: relative;
608
616
  font-weight: 500;
609
- font-size: 0.9rem;
617
+ font-size: 0.85rem; /* Smaller font for Grafana-like appearance */
610
618
  }
611
619
 
612
620
  .list-group-item:first-child {
@@ -679,23 +687,23 @@
679
687
  color: #adb5bd;
680
688
  }
681
689
 
682
- /* Enhanced button styling */
690
+ /* Enhanced button styling - Grafana-inspired */
683
691
  .btn {
684
692
  font-weight: 500;
685
- padding: 0.5rem 1rem;
686
- border-radius: 0.375rem;
693
+ padding: 0.4rem 0.85rem; /* Reduced padding */
694
+ border-radius: 2px; /* Smaller radius for Grafana look */
687
695
  transition: all 0.2s ease;
688
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
696
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
689
697
  }
690
698
 
691
699
  .btn-sm {
692
- padding: 0.35rem 0.75rem;
693
- font-size: 0.85rem;
700
+ padding: 0.25rem 0.6rem; /* Reduced padding */
701
+ font-size: 0.8rem; /* Smaller font size */
694
702
  }
695
703
 
696
704
  .btn-lg {
697
- padding: 0.65rem 1.2rem;
698
- font-size: 1.05rem;
705
+ padding: 0.5rem 1rem; /* Reduced padding */
706
+ font-size: 0.95rem; /* Smaller font size */
699
707
  }
700
708
 
701
709
  .btn:active {
@@ -760,23 +768,23 @@
760
768
  text-decoration: underline;
761
769
  }
762
770
 
763
- /* Enhanced code blocks and SQL query styling */
771
+ /* Enhanced code blocks and SQL query styling - Grafana-inspired */
764
772
  pre, code {
765
773
  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
766
- border-radius: 4px;
774
+ border-radius: 2px; /* Smaller radius */
767
775
  transition: all 0.2s ease;
768
776
  }
769
777
 
770
778
  pre {
771
- padding: 1rem;
772
- margin-bottom: 1rem;
773
- border-radius: 0.5rem;
774
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
779
+ padding: 0.75rem; /* Reduced padding */
780
+ margin-bottom: 0.75rem; /* Reduced margin */
781
+ border-radius: 2px; /* Smaller radius */
782
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.03);
775
783
  }
776
784
 
777
785
  code {
778
- font-size: 0.875em;
779
- padding: 0.2em 0.4em;
786
+ font-size: 0.825em; /* Smaller font */
787
+ padding: 0.15em 0.3em; /* Reduced padding */
780
788
  }
781
789
 
782
790
  /* SQL query code in tables */
@@ -868,7 +876,7 @@
868
876
  color: #ffffff;
869
877
  }
870
878
 
871
- /* Enhanced table styling */
879
+ /* Enhanced table styling - Grafana-like compact design */
872
880
  .table {
873
881
  margin-bottom: 0;
874
882
  width: 100%;
@@ -881,12 +889,12 @@
881
889
  }
882
890
 
883
891
  .table thead th {
884
- padding: 1rem;
892
+ padding: 0.65rem 0.75rem; /* Reduced padding */
885
893
  font-weight: 600;
886
894
  border-top: 0;
887
895
  vertical-align: middle;
888
896
  letter-spacing: 0.01em;
889
- font-size: 0.88rem;
897
+ font-size: 0.78rem; /* Smaller font */
890
898
  text-transform: uppercase;
891
899
  position: sticky;
892
900
  top: 0;
@@ -895,10 +903,10 @@
895
903
  }
896
904
 
897
905
  .table tbody td {
898
- padding: 0.85rem 1rem;
906
+ padding: 0.5rem 0.75rem; /* Reduced padding */
899
907
  vertical-align: middle;
900
908
  border-color: var(--bs-border-color);
901
- font-size: 0.92rem;
909
+ font-size: 0.85rem; /* Smaller font */
902
910
  }
903
911
 
904
912
  .table tbody tr:hover {
@@ -960,14 +968,21 @@
960
968
  color: #000 !important;
961
969
  }
962
970
 
963
- /* Enhanced alert styling */
971
+ /* Badge styling - More Grafana-like */
972
+ .badge {
973
+ padding: 0.3em 0.5em;
974
+ font-size: 0.75em;
975
+ border-radius: 2px;
976
+ }
977
+
978
+ /* Enhanced alert styling - Grafana-inspired */
964
979
  .alert {
965
- border-radius: 0.5rem;
980
+ border-radius: 2px; /* Smaller radius for Grafana look */
966
981
  border-width: 0;
967
- padding: 1rem 1.25rem;
968
- box-shadow: 0 3px 10px rgba(0, 0, 0, 0.08);
982
+ padding: 0.7rem 1rem; /* Reduced padding */
983
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
969
984
  position: relative;
970
- border-left: 4px solid transparent;
985
+ border-left: 3px solid transparent; /* Thinner border */
971
986
  }
972
987
 
973
988
  .alert-info {
@@ -1091,40 +1106,40 @@
1091
1106
  background-color: var(--bs-light);
1092
1107
  }
1093
1108
 
1094
- /* Enhanced stat cards and metric icons */
1109
+ /* Enhanced stat cards and metric icons - Grafana-inspired */
1095
1110
  .stat-card-bg {
1096
1111
  background: #ffffff;
1097
- border-radius: 0.75rem;
1098
- box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
1112
+ border-radius: 3px; /* Smaller radius for Grafana look */
1113
+ box-shadow: 0 1px 5px rgba(0, 0, 0, 0.03);
1099
1114
  transition: all 0.3s ease;
1100
1115
  border: none;
1101
1116
  }
1102
1117
 
1103
1118
  .stat-card-bg:hover {
1104
- transform: translateY(-3px);
1105
- box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
1119
+ transform: translateY(-1px); /* Subtler hover */
1120
+ box-shadow: 0 3px 8px rgba(0, 0, 0, 0.06);
1106
1121
  }
1107
1122
 
1108
1123
  [data-bs-theme="dark"] .stat-card-bg {
1109
1124
  background-color: #212529;
1110
- box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
1125
+ box-shadow: 0 1px 5px rgba(0, 0, 0, 0.08);
1111
1126
  }
1112
1127
 
1113
- /* Enhanced metric icon styling */
1128
+ /* Enhanced metric icon styling - Grafana-inspired */
1114
1129
  .metric-icon {
1115
1130
  display: flex;
1116
1131
  align-items: center;
1117
1132
  justify-content: center;
1118
- border-radius: 14px;
1119
- width: 65px;
1120
- height: 65px;
1121
- min-width: 65px;
1133
+ border-radius: 3px; /* Smaller radius */
1134
+ width: 50px; /* Smaller icon */
1135
+ height: 50px; /* Smaller icon */
1136
+ min-width: 50px; /* Smaller icon */
1122
1137
  text-align: center;
1123
- background: linear-gradient(135deg, rgba(var(--bs-primary-rgb), 0.2) 0%, rgba(var(--bs-primary-rgb), 0.1) 100%);
1138
+ background: linear-gradient(135deg, rgba(var(--bs-primary-rgb), 0.15) 0%, rgba(var(--bs-primary-rgb), 0.08) 100%);
1124
1139
  color: var(--bs-primary);
1125
- font-size: 1.6rem;
1140
+ font-size: 1.4rem; /* Smaller icon */
1126
1141
  transition: all 0.3s ease;
1127
- box-shadow: 0 3px 10px rgba(var(--bs-primary-rgb), 0.1);
1142
+ box-shadow: 0 1px 5px rgba(var(--bs-primary-rgb), 0.08);
1128
1143
  }
1129
1144
 
1130
1145
  .stat-card-bg:hover .metric-icon {
@@ -1181,17 +1196,28 @@
1181
1196
  transition: all 0.2s ease;
1182
1197
  }
1183
1198
 
1184
- /* Improved table hover effect */
1199
+ /* Improved table hover effect - Grafana-like */
1185
1200
  .table-hover > tbody > tr:hover {
1186
1201
  transition: all 0.15s ease;
1187
1202
  }
1188
1203
 
1189
1204
  [data-bs-theme="light"] .table-hover > tbody > tr:hover {
1190
- background-color: rgba(13, 110, 253, 0.04);
1205
+ background-color: rgba(13, 110, 253, 0.03); /* Subtler hover */
1191
1206
  }
1192
1207
 
1193
1208
  [data-bs-theme="dark"] .table-hover > tbody > tr:hover {
1194
- background-color: rgba(13, 110, 253, 0.07);
1209
+ background-color: rgba(13, 110, 253, 0.05); /* Subtler hover */
1210
+ }
1211
+
1212
+ /* Grafana-inspired grid layout adjustments */
1213
+ .row {
1214
+ margin-right: -0.5rem;
1215
+ margin-left: -0.5rem;
1216
+ }
1217
+
1218
+ .row > [class^="col-"] {
1219
+ padding-right: 0.5rem;
1220
+ padding-left: 0.5rem;
1195
1221
  }
1196
1222
 
1197
1223
  /* Button press effect */
@@ -1228,6 +1254,80 @@
1228
1254
  [data-bs-theme="dark"] html::-webkit-scrollbar-thumb {
1229
1255
  background-color: rgba(255, 255, 255, 0.2);
1230
1256
  }
1257
+
1258
+ /* Grafana-like panel enhancements */
1259
+ body {
1260
+ color: #464c54; /* More subdued text color for light theme */
1261
+ background-color: #f5f6f9; /* Subtle gray background */
1262
+ }
1263
+
1264
+ [data-bs-theme="dark"] body {
1265
+ background-color: #161719; /* Darker background for dark theme */
1266
+ color: #d8d9da; /* Softer text color for dark theme */
1267
+ }
1268
+
1269
+ /* Make font sizes consistently smaller for more compact look */
1270
+ body {
1271
+ font-size: 0.875rem;
1272
+ }
1273
+
1274
+ h1, .h1 { font-size: 1.6rem; }
1275
+ h2, .h2 { font-size: 1.4rem; }
1276
+ h3, .h3 { font-size: 1.2rem; }
1277
+ h4, .h4 { font-size: 1.1rem; }
1278
+ h5, .h5 { font-size: 1rem; }
1279
+
1280
+ /* Unify panel appearance */
1281
+ .card, .list-group {
1282
+ box-shadow: 0 0 4px rgba(0, 0, 0, 0.06);
1283
+ border: none;
1284
+ border-radius: 2px;
1285
+ }
1286
+
1287
+ [data-bs-theme="dark"] .card,
1288
+ [data-bs-theme="dark"] .list-group {
1289
+ box-shadow: 0 0 4px rgba(0, 0, 0, 0.15);
1290
+ background-color: #212124;
1291
+ }
1292
+
1293
+ /* Improved tab styling */
1294
+ .nav-tabs {
1295
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1);
1296
+ }
1297
+
1298
+ .nav-tabs .nav-link {
1299
+ border: none;
1300
+ border-bottom: 2px solid transparent;
1301
+ background-color: transparent;
1302
+ padding: 0.5rem 0.75rem;
1303
+ margin-bottom: -1px;
1304
+ font-size: 0.9rem;
1305
+ }
1306
+
1307
+ .nav-tabs .nav-link.active {
1308
+ border-bottom-color: var(--bs-primary);
1309
+ color: var(--bs-primary);
1310
+ }
1311
+
1312
+ [data-bs-theme="dark"] .nav-tabs {
1313
+ border-color: rgba(255, 255, 255, 0.1);
1314
+ }
1315
+
1316
+ /* Remove excessive margins between elements */
1317
+ .row + .row,
1318
+ .card + .card {
1319
+ margin-top: 0.75rem;
1320
+ }
1321
+
1322
+ /* Elegant form controls */
1323
+ .form-control, .form-select {
1324
+ padding: 0.4rem 0.6rem;
1325
+ font-size: 0.875rem;
1326
+ height: auto;
1327
+ border-radius: 2px;
1328
+ }
1329
+
1330
+ /* Add this right above the style closing tag */
1231
1331
  </style>
1232
1332
  </head>
1233
1333
  <body>
@@ -1,6 +1,5 @@
1
1
  <div class="dbviewer-sidebar-top">
2
2
  <div class="dbviewer-table-filter-container p-1 mb-0">
3
- <i class="bi bi-search dbviewer-table-filter-icon"></i>
4
3
  <input type="text" class="form-control form-control-sm dbviewer-table-filter mb-0"
5
4
  id="tableSearch" placeholder="Filter tables..." aria-label="Filter tables">
6
5
  </div>
data/config/routes.rb CHANGED
@@ -19,13 +19,24 @@ Dbviewer::Engine.routes.draw do
19
19
  # Homepage and API endpoints
20
20
  get "dashboard", to: "home#index", as: :dashboard
21
21
 
22
- # Analytics API endpoints
23
- get "api/analytics", to: "home#analytics" # Legacy/combined endpoint
24
- get "api/records", to: "home#records"
25
- get "api/tables", to: "home#tables_count"
26
- get "api/relationships", to: "home#relationships_count"
27
- get "api/database_size", to: "home#database_size"
28
- get "api/recent_queries", to: "home#recent_queries"
22
+ namespace :api do
23
+ resources :tables, only: [ :index ] do
24
+ collection do
25
+ get "records"
26
+ get "relationships_count"
27
+ end
28
+ end
29
+
30
+ resource :database, only: [], controller: "database" do
31
+ get "size"
32
+ end
33
+
34
+ resources :queries, only: [] do
35
+ collection do
36
+ get "recent"
37
+ end
38
+ end
39
+ end
29
40
 
30
41
  root to: "home#index"
31
42
  end
@@ -180,8 +180,48 @@ module Dbviewer
180
180
  @cache_manager.clear_all
181
181
  end
182
182
 
183
+ # Calculate the total size of the database schema
184
+ # @return [Integer, nil] Database size in bytes or nil if unsupported
185
+ def fetch_schema_size
186
+ case adapter_name
187
+ when /mysql/
188
+ fetch_mysql_size
189
+ when /postgres/
190
+ fetch_postgres_size
191
+ when /sqlite/
192
+ fetch_sqlite_size
193
+ else
194
+ nil # Unsupported database type for size calculation
195
+ end
196
+ end
197
+
183
198
  private
184
199
 
200
+ def fetch_mysql_size
201
+ query = "SELECT SUM(data_length + index_length) AS size FROM information_schema.TABLES WHERE table_schema = DATABASE()"
202
+ fetch_size_from_query(query)
203
+ end
204
+
205
+ def fetch_postgres_size
206
+ query = "SELECT pg_database_size(current_database()) AS size"
207
+ fetch_size_from_query(query)
208
+ end
209
+
210
+ def fetch_sqlite_size
211
+ page_count = fetch_sqlite_pragma_value("page_count")
212
+ page_size = fetch_sqlite_pragma_value("page_size")
213
+ page_count * page_size
214
+ end
215
+
216
+ def fetch_sqlite_pragma_value(pragma_name)
217
+ execute_sqlite_pragma(pragma_name).first.values.first.to_i
218
+ end
219
+
220
+ def fetch_size_from_query(query)
221
+ result = execute_query(query).first
222
+ result ? result["size"].to_i : nil
223
+ end
224
+
185
225
  # Ensure we have a valid database connection
186
226
  # @return [ActiveRecord::ConnectionAdapters::AbstractAdapter] The database connection
187
227
  def ensure_connection
@@ -20,8 +20,23 @@ module Dbviewer
20
20
  initializer "dbviewer.notifications" do
21
21
  ActiveSupport::Notifications.subscribe("sql.active_record") do |*args|
22
22
  event = ActiveSupport::Notifications::Event.new(*args)
23
+
24
+ next if skip_internal_query?(event)
25
+
23
26
  Logger.instance.add(event)
24
27
  end
25
28
  end
29
+
30
+ private
31
+
32
+ def skip_internal_query?(event)
33
+ caller_locations = caller_locations(1)
34
+ return false unless caller_locations
35
+
36
+ # Look for dbviewer in the call stack
37
+ caller_locations.any? { |l| l.path.include?("dbviewer") }
38
+ rescue
39
+ false
40
+ end
26
41
  end
27
42
  end
@@ -12,7 +12,6 @@ module Dbviewer
12
12
  def add(event)
13
13
  # Return early if query logging is disabled
14
14
  return unless Dbviewer.configuration.enable_query_logging
15
- return if QueryParser.should_skip_query?(event)
16
15
 
17
16
  current_time = Time.now
18
17
  @storage.add({
@@ -68,15 +68,5 @@ module Dbviewer
68
68
  rescue
69
69
  []
70
70
  end
71
-
72
- # Determine if a query should be skipped based on content
73
- def self.should_skip_query?(event)
74
- event.payload[:name] == "SCHEMA" ||
75
- event.payload[:sql].include?("SHOW TABLES") ||
76
- event.payload[:sql].include?("sqlite_master") ||
77
- event.payload[:sql].include?("information_schema") ||
78
- event.payload[:sql].include?("pg_catalog") ||
79
- from_dbviewer?(event)
80
- end
81
71
  end
82
72
  end
@@ -1,3 +1,3 @@
1
1
  module Dbviewer
2
- VERSION = "0.4.8"
2
+ VERSION = "0.5.1"
3
3
  end