appquery 0.6.0 → 0.7.0.rc2
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/.yard/templates/default/fulldoc/html/css/dark.css +234 -0
- data/.yard/templates/default/fulldoc/html/setup.rb +5 -0
- data/.yard/templates/default/layout/html/setup.rb +5 -0
- data/.yardopts +2 -0
- data/CHANGELOG.md +9 -0
- data/LICENSE.txt +1 -1
- data/README.md +179 -276
- data/assets/banner-dark.svg +222 -0
- data/assets/banner-light.svg +222 -0
- data/lib/app_query/tokenizer.rb +12 -2
- data/lib/app_query/version.rb +1 -1
- metadata +6 -1
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 240">
|
|
2
|
+
<defs>
|
|
3
|
+
<!-- Main title gradient - vibrant for dark -->
|
|
4
|
+
<linearGradient id="title-grad-dark" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
5
|
+
<stop offset="0%" style="stop-color:#818CF8"/>
|
|
6
|
+
<stop offset="25%" style="stop-color:#A78BFA"/>
|
|
7
|
+
<stop offset="50%" style="stop-color:#F472B6"/>
|
|
8
|
+
<stop offset="75%" style="stop-color:#FBBF24"/>
|
|
9
|
+
<stop offset="100%" style="stop-color:#34D399"/>
|
|
10
|
+
</linearGradient>
|
|
11
|
+
|
|
12
|
+
<!-- Accent gradients -->
|
|
13
|
+
<linearGradient id="accent-left-dark" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
14
|
+
<stop offset="0%" style="stop-color:#818CF8"/>
|
|
15
|
+
<stop offset="100%" style="stop-color:#A78BFA"/>
|
|
16
|
+
</linearGradient>
|
|
17
|
+
<linearGradient id="accent-right-dark" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
18
|
+
<stop offset="0%" style="stop-color:#F472B6"/>
|
|
19
|
+
<stop offset="100%" style="stop-color:#FB7185"/>
|
|
20
|
+
</linearGradient>
|
|
21
|
+
<linearGradient id="rainbow-dark" x1="0%" y1="0%" x2="100%" y2="0%">
|
|
22
|
+
<stop offset="0%" style="stop-color:#818CF8"/>
|
|
23
|
+
<stop offset="50%" style="stop-color:#F472B6"/>
|
|
24
|
+
<stop offset="100%" style="stop-color:#FBBF24"/>
|
|
25
|
+
</linearGradient>
|
|
26
|
+
|
|
27
|
+
<!-- Background gradient -->
|
|
28
|
+
<radialGradient id="bg-radial-dark" cx="50%" cy="50%" r="70%">
|
|
29
|
+
<stop offset="0%" style="stop-color:#161B22"/>
|
|
30
|
+
<stop offset="100%" style="stop-color:#0D1117"/>
|
|
31
|
+
</radialGradient>
|
|
32
|
+
|
|
33
|
+
<!-- Glow filters - stronger for dark -->
|
|
34
|
+
<filter id="glow-dark" x="-50%" y="-50%" width="200%" height="200%">
|
|
35
|
+
<feGaussianBlur stdDeviation="5" result="coloredBlur"/>
|
|
36
|
+
<feMerge>
|
|
37
|
+
<feMergeNode in="coloredBlur"/>
|
|
38
|
+
<feMergeNode in="SourceGraphic"/>
|
|
39
|
+
</feMerge>
|
|
40
|
+
</filter>
|
|
41
|
+
<filter id="glow-strong-dark" x="-100%" y="-100%" width="300%" height="300%">
|
|
42
|
+
<feGaussianBlur stdDeviation="10" result="coloredBlur"/>
|
|
43
|
+
<feMerge>
|
|
44
|
+
<feMergeNode in="coloredBlur"/>
|
|
45
|
+
<feMergeNode in="SourceGraphic"/>
|
|
46
|
+
</feMerge>
|
|
47
|
+
</filter>
|
|
48
|
+
<filter id="shadow-dark" x="-20%" y="-20%" width="140%" height="140%">
|
|
49
|
+
<feDropShadow dx="0" dy="4" stdDeviation="8" flood-color="#818CF8" flood-opacity="0.4"/>
|
|
50
|
+
</filter>
|
|
51
|
+
|
|
52
|
+
<!-- Patterns -->
|
|
53
|
+
<pattern id="grid-dark" width="30" height="30" patternUnits="userSpaceOnUse">
|
|
54
|
+
<path d="M 30 0 L 0 0 0 30" fill="none" stroke="#21262D" stroke-width="0.5"/>
|
|
55
|
+
</pattern>
|
|
56
|
+
<pattern id="dots-dark" width="15" height="15" patternUnits="userSpaceOnUse">
|
|
57
|
+
<circle cx="7.5" cy="7.5" r="1" fill="#818CF8" opacity="0.1"/>
|
|
58
|
+
</pattern>
|
|
59
|
+
<pattern id="hexgrid-dark" width="28" height="49" patternUnits="userSpaceOnUse">
|
|
60
|
+
<path d="M14,0 L28,8 L28,24 L14,32 L0,24 L0,8 Z M14,33 L28,41 L28,49 M14,33 L0,41 L0,49" fill="none" stroke="#21262D" stroke-width="0.4"/>
|
|
61
|
+
</pattern>
|
|
62
|
+
|
|
63
|
+
<!-- Orb gradients - glowing for dark -->
|
|
64
|
+
<radialGradient id="orb-purple-dark" cx="30%" cy="30%">
|
|
65
|
+
<stop offset="0%" style="stop-color:#7C3AED"/>
|
|
66
|
+
<stop offset="100%" style="stop-color:#7C3AED;stop-opacity:0"/>
|
|
67
|
+
</radialGradient>
|
|
68
|
+
<radialGradient id="orb-pink-dark" cx="30%" cy="30%">
|
|
69
|
+
<stop offset="0%" style="stop-color:#EC4899"/>
|
|
70
|
+
<stop offset="100%" style="stop-color:#EC4899;stop-opacity:0"/>
|
|
71
|
+
</radialGradient>
|
|
72
|
+
<radialGradient id="orb-blue-dark" cx="30%" cy="30%">
|
|
73
|
+
<stop offset="0%" style="stop-color:#6366F1"/>
|
|
74
|
+
<stop offset="100%" style="stop-color:#6366F1;stop-opacity:0"/>
|
|
75
|
+
</radialGradient>
|
|
76
|
+
</defs>
|
|
77
|
+
|
|
78
|
+
<!-- Background layers -->
|
|
79
|
+
<rect width="800" height="240" fill="url(#bg-radial-dark)"/>
|
|
80
|
+
<rect width="800" height="240" fill="url(#hexgrid-dark)" opacity="0.6"/>
|
|
81
|
+
<rect width="800" height="240" fill="url(#dots-dark)" opacity="0.6"/>
|
|
82
|
+
|
|
83
|
+
<!-- Large glowing orbs - more visible in dark -->
|
|
84
|
+
<circle cx="80" cy="80" r="100" fill="url(#orb-purple-dark)" opacity="0.15"/>
|
|
85
|
+
<circle cx="720" cy="160" r="120" fill="url(#orb-pink-dark)" opacity="0.12"/>
|
|
86
|
+
<circle cx="400" cy="280" r="180" fill="url(#orb-blue-dark)" opacity="0.1"/>
|
|
87
|
+
<circle cx="650" cy="40" r="60" fill="url(#orb-purple-dark)" opacity="0.12"/>
|
|
88
|
+
<circle cx="150" cy="200" r="70" fill="url(#orb-pink-dark)" opacity="0.1"/>
|
|
89
|
+
|
|
90
|
+
<!-- Floating binary/code snippets -->
|
|
91
|
+
<g font-family="Monaco, monospace" font-size="8" fill="#818CF8" opacity="0.2">
|
|
92
|
+
<text x="20" y="30">SELECT * FROM</text>
|
|
93
|
+
<text x="700" y="25">WHERE id = :id</text>
|
|
94
|
+
<text x="50" y="220">ORDER BY created_at</text>
|
|
95
|
+
<text x="680" y="230">LIMIT 100</text>
|
|
96
|
+
<text x="300" y="20">WITH cte AS (...)</text>
|
|
97
|
+
<text x="500" y="235">GROUP BY category</text>
|
|
98
|
+
</g>
|
|
99
|
+
|
|
100
|
+
<!-- Data flow curves - brighter for dark -->
|
|
101
|
+
<g stroke-width="2" fill="none" opacity="0.25">
|
|
102
|
+
<path d="M 0 120 Q 100 80 200 100 T 350 90" stroke="url(#accent-left-dark)"/>
|
|
103
|
+
<path d="M 800 120 Q 700 80 600 100 T 450 90" stroke="url(#accent-right-dark)"/>
|
|
104
|
+
<path d="M 0 180 Q 150 160 250 170 T 380 150" stroke="url(#accent-left-dark)" stroke-dasharray="5 5"/>
|
|
105
|
+
<path d="M 800 180 Q 650 160 550 170 T 420 150" stroke="url(#accent-right-dark)" stroke-dasharray="5 5"/>
|
|
106
|
+
</g>
|
|
107
|
+
|
|
108
|
+
<!-- Sparkles and stars - brighter -->
|
|
109
|
+
<g fill="#FBBF24">
|
|
110
|
+
<polygon points="100,50 102,56 108,56 103,60 105,66 100,62 95,66 97,60 92,56 98,56" opacity="0.6"/>
|
|
111
|
+
<polygon points="700,45 701,48 704,48 702,50 703,53 700,51 697,53 698,50 696,48 699,48" opacity="0.5"/>
|
|
112
|
+
<polygon points="180,180 181,183 184,183 182,185 183,188 180,186 177,188 178,185 176,183 179,183" opacity="0.45"/>
|
|
113
|
+
</g>
|
|
114
|
+
<g fill="#F472B6">
|
|
115
|
+
<polygon points="620,180 621,183 624,183 622,185 623,188 620,186 617,188 618,185 616,183 619,183" opacity="0.5"/>
|
|
116
|
+
<polygon points="750,100 752,106 758,106 753,110 755,116 750,112 745,116 747,110 742,106 748,106" opacity="0.4"/>
|
|
117
|
+
</g>
|
|
118
|
+
<g fill="#818CF8">
|
|
119
|
+
<polygon points="50,140 51,143 54,143 52,145 53,148 50,146 47,148 48,145 46,143 49,143" opacity="0.6"/>
|
|
120
|
+
<polygon points="350,30 351,33 354,33 352,35 353,38 350,36 347,38 348,35 346,33 349,33" opacity="0.5"/>
|
|
121
|
+
</g>
|
|
122
|
+
|
|
123
|
+
<!-- Floating SQL keywords with glow -->
|
|
124
|
+
<g font-family="Monaco, 'Courier New', monospace">
|
|
125
|
+
<text x="45" y="65" font-size="14" fill="#818CF8" opacity="0.6" font-weight="700" filter="url(#glow-dark)">SELECT</text>
|
|
126
|
+
<text x="30" y="105" font-size="12" fill="#A78BFA" opacity="0.4">FROM</text>
|
|
127
|
+
<text x="55" y="145" font-size="13" fill="#818CF8" opacity="0.35" font-weight="600">WHERE</text>
|
|
128
|
+
<text x="25" y="185" font-size="11" fill="#F472B6" opacity="0.4">JOIN</text>
|
|
129
|
+
|
|
130
|
+
<text x="705" y="60" font-size="12" fill="#A78BFA" opacity="0.4">WITH</text>
|
|
131
|
+
<text x="725" y="100" font-size="14" fill="#818CF8" opacity="0.6" font-weight="700" filter="url(#glow-dark)">CTE</text>
|
|
132
|
+
<text x="670" y="140" font-size="11" fill="#F472B6" opacity="0.35">ORDER BY</text>
|
|
133
|
+
<text x="710" y="180" font-size="12" fill="#A78BFA" opacity="0.4">GROUP</text>
|
|
134
|
+
</g>
|
|
135
|
+
|
|
136
|
+
<!-- Database cylinders with glow -->
|
|
137
|
+
<g transform="translate(130, 85)" filter="url(#glow-dark)">
|
|
138
|
+
<g opacity="0.35">
|
|
139
|
+
<ellipse cx="0" cy="0" rx="25" ry="10" fill="#1E1B4B" stroke="#818CF8" stroke-width="2"/>
|
|
140
|
+
<path d="M-25,0 L-25,35 A25,10 0 0,0 25,35 L25,0" fill="#1E1B4B" stroke="#818CF8" stroke-width="2"/>
|
|
141
|
+
<ellipse cx="0" cy="17" rx="25" ry="10" fill="none" stroke="#818CF8" stroke-width="1" stroke-dasharray="4 3"/>
|
|
142
|
+
<ellipse cx="0" cy="35" rx="25" ry="10" fill="#1E1B4B" stroke="#818CF8" stroke-width="2"/>
|
|
143
|
+
</g>
|
|
144
|
+
</g>
|
|
145
|
+
<g transform="translate(670, 90)" filter="url(#glow-dark)">
|
|
146
|
+
<g opacity="0.35">
|
|
147
|
+
<ellipse cx="0" cy="0" rx="23" ry="9" fill="#4A1D3D" stroke="#F472B6" stroke-width="2"/>
|
|
148
|
+
<path d="M-23,0 L-23,32 A23,9 0 0,0 23,32 L23,0" fill="#4A1D3D" stroke="#F472B6" stroke-width="2"/>
|
|
149
|
+
<ellipse cx="0" cy="16" rx="23" ry="9" fill="none" stroke="#F472B6" stroke-width="1" stroke-dasharray="4 3"/>
|
|
150
|
+
<ellipse cx="0" cy="32" rx="23" ry="9" fill="#4A1D3D" stroke="#F472B6" stroke-width="2"/>
|
|
151
|
+
</g>
|
|
152
|
+
</g>
|
|
153
|
+
|
|
154
|
+
<!-- Table/grid icons -->
|
|
155
|
+
<g transform="translate(195, 165)" opacity="0.3">
|
|
156
|
+
<rect x="-18" y="-14" width="36" height="28" rx="3" fill="#1E1B4B" stroke="#818CF8" stroke-width="1.5"/>
|
|
157
|
+
<line x1="-18" y1="-4" x2="18" y2="-4" stroke="#818CF8" stroke-width="1"/>
|
|
158
|
+
<line x1="-18" y1="6" x2="18" y2="6" stroke="#818CF8" stroke-width="0.5" stroke-dasharray="2 2"/>
|
|
159
|
+
<line x1="-4" y1="-14" x2="-4" y2="14" stroke="#818CF8" stroke-width="1"/>
|
|
160
|
+
<line x1="8" y1="-14" x2="8" y2="14" stroke="#818CF8" stroke-width="0.5" stroke-dasharray="2 2"/>
|
|
161
|
+
</g>
|
|
162
|
+
<g transform="translate(605, 165)" opacity="0.3">
|
|
163
|
+
<rect x="-18" y="-14" width="36" height="28" rx="3" fill="#4A1D3D" stroke="#F472B6" stroke-width="1.5"/>
|
|
164
|
+
<line x1="-18" y1="-4" x2="18" y2="-4" stroke="#F472B6" stroke-width="1"/>
|
|
165
|
+
<line x1="-18" y1="6" x2="18" y2="6" stroke="#F472B6" stroke-width="0.5" stroke-dasharray="2 2"/>
|
|
166
|
+
<line x1="-4" y1="-14" x2="-4" y2="14" stroke="#F472B6" stroke-width="1"/>
|
|
167
|
+
</g>
|
|
168
|
+
|
|
169
|
+
<!-- Ruby gem - detailed with facets and glow -->
|
|
170
|
+
<g transform="translate(400, 42)" opacity="0.25">
|
|
171
|
+
<polygon points="0,-28 25,-10 15,22 -15,22 -25,-10" fill="#7F1D1D" stroke="#EF4444" stroke-width="2"/>
|
|
172
|
+
<polygon points="0,-28 25,-10 0,8 -25,-10" fill="#991B1B" stroke="#EF4444" stroke-width="1"/>
|
|
173
|
+
<polygon points="0,8 25,-10 15,22" fill="#B91C1C" stroke="#EF4444" stroke-width="1"/>
|
|
174
|
+
<polygon points="0,8 -25,-10 -15,22" fill="#B91C1C" stroke="#EF4444" stroke-width="1"/>
|
|
175
|
+
<line x1="0" y1="-28" x2="0" y2="22" stroke="#EF4444" stroke-width="1"/>
|
|
176
|
+
</g>
|
|
177
|
+
|
|
178
|
+
<!-- Connection dots/nodes - glowing -->
|
|
179
|
+
<g fill="#818CF8">
|
|
180
|
+
<circle cx="250" cy="100" r="4" opacity="0.4"/>
|
|
181
|
+
<circle cx="280" cy="120" r="3" opacity="0.3"/>
|
|
182
|
+
<circle cx="320" cy="105" r="5" opacity="0.35"/>
|
|
183
|
+
</g>
|
|
184
|
+
<g fill="#F472B6">
|
|
185
|
+
<circle cx="550" cy="100" r="4" opacity="0.4"/>
|
|
186
|
+
<circle cx="520" cy="120" r="3" opacity="0.3"/>
|
|
187
|
+
<circle cx="480" cy="105" r="5" opacity="0.35"/>
|
|
188
|
+
</g>
|
|
189
|
+
|
|
190
|
+
<!-- Main title with rainbow gradient and strong glow -->
|
|
191
|
+
<text x="400" y="115" font-family="system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif" font-size="62" font-weight="900" fill="url(#title-grad-dark)" text-anchor="middle" filter="url(#glow-strong-dark)">AppQuery</text>
|
|
192
|
+
|
|
193
|
+
<!-- Decorative underline -->
|
|
194
|
+
<g transform="translate(400, 128)">
|
|
195
|
+
<rect x="-120" y="0" width="240" height="4" rx="2" fill="url(#rainbow-dark)" opacity="0.7"/>
|
|
196
|
+
<rect x="-100" y="6" width="200" height="2" rx="1" fill="url(#rainbow-dark)" opacity="0.4"/>
|
|
197
|
+
</g>
|
|
198
|
+
|
|
199
|
+
<!-- Tagline -->
|
|
200
|
+
<text x="400" y="158" font-family="system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif" font-size="18" fill="#8B949E" text-anchor="middle" letter-spacing="2" font-weight="500">Raw SQL, ergonomically</text>
|
|
201
|
+
|
|
202
|
+
<!-- Terminal code block - fancy -->
|
|
203
|
+
<g transform="translate(400, 200)" filter="url(#shadow-dark)">
|
|
204
|
+
<rect x="-250" y="-18" width="500" height="36" rx="18" fill="#21262D" stroke="#30363D" stroke-width="1"/>
|
|
205
|
+
<!-- Window controls -->
|
|
206
|
+
<circle cx="-225" cy="0" r="6" fill="#F85149"/>
|
|
207
|
+
<circle cx="-206" cy="0" r="6" fill="#D29922"/>
|
|
208
|
+
<circle cx="-187" cy="0" r="6" fill="#3FB950"/>
|
|
209
|
+
<!-- Separator -->
|
|
210
|
+
<line x1="-170" y1="-10" x2="-170" y2="10" stroke="#30363D" stroke-width="1"/>
|
|
211
|
+
<!-- Code with syntax highlighting -->
|
|
212
|
+
<text x="-155" y="5" font-family="Monaco, 'Courier New', monospace" font-size="12">
|
|
213
|
+
<tspan fill="#A78BFA">AppQuery</tspan><tspan fill="#8B949E">[</tspan><tspan fill="#7EE787">:sales</tspan><tspan fill="#8B949E">].</tspan><tspan fill="#79C0FF">select_all</tspan><tspan fill="#8B949E">(</tspan><tspan fill="#FF7B72">binds:</tspan><tspan fill="#8B949E"> {</tspan><tspan fill="#7EE787">year:</tspan><tspan fill="#FFA657"> 2026</tspan><tspan fill="#8B949E">})</tspan>
|
|
214
|
+
</text>
|
|
215
|
+
</g>
|
|
216
|
+
|
|
217
|
+
<!-- Output arrow with results hint -->
|
|
218
|
+
<g transform="translate(400, 228)">
|
|
219
|
+
<path d="M-30,0 L0,10 L30,0" stroke="#3FB950" stroke-width="2.5" fill="none" opacity="0.6"/>
|
|
220
|
+
<text x="0" y="12" font-family="Monaco, monospace" font-size="8" fill="#3FB950" text-anchor="middle" opacity="0.6">[{revenue: 42000, ...}]</text>
|
|
221
|
+
</g>
|
|
222
|
+
</svg>
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 240">
|
|
2
|
+
<defs>
|
|
3
|
+
<!-- Main title gradient -->
|
|
4
|
+
<linearGradient id="title-grad" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
5
|
+
<stop offset="0%" style="stop-color:#4F46E5"/>
|
|
6
|
+
<stop offset="25%" style="stop-color:#7C3AED"/>
|
|
7
|
+
<stop offset="50%" style="stop-color:#DB2777"/>
|
|
8
|
+
<stop offset="75%" style="stop-color:#F59E0B"/>
|
|
9
|
+
<stop offset="100%" style="stop-color:#10B981"/>
|
|
10
|
+
</linearGradient>
|
|
11
|
+
|
|
12
|
+
<!-- Accent gradients -->
|
|
13
|
+
<linearGradient id="accent-left" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
14
|
+
<stop offset="0%" style="stop-color:#6366F1"/>
|
|
15
|
+
<stop offset="100%" style="stop-color:#8B5CF6"/>
|
|
16
|
+
</linearGradient>
|
|
17
|
+
<linearGradient id="accent-right" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
18
|
+
<stop offset="0%" style="stop-color:#EC4899"/>
|
|
19
|
+
<stop offset="100%" style="stop-color:#F43F5E"/>
|
|
20
|
+
</linearGradient>
|
|
21
|
+
<linearGradient id="rainbow" x1="0%" y1="0%" x2="100%" y2="0%">
|
|
22
|
+
<stop offset="0%" style="stop-color:#6366F1"/>
|
|
23
|
+
<stop offset="50%" style="stop-color:#EC4899"/>
|
|
24
|
+
<stop offset="100%" style="stop-color:#F59E0B"/>
|
|
25
|
+
</linearGradient>
|
|
26
|
+
|
|
27
|
+
<!-- Background gradient -->
|
|
28
|
+
<radialGradient id="bg-radial" cx="50%" cy="50%" r="70%">
|
|
29
|
+
<stop offset="0%" style="stop-color:#FFFFFF"/>
|
|
30
|
+
<stop offset="100%" style="stop-color:#F3F4F6"/>
|
|
31
|
+
</radialGradient>
|
|
32
|
+
|
|
33
|
+
<!-- Glow filters -->
|
|
34
|
+
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
|
|
35
|
+
<feGaussianBlur stdDeviation="4" result="coloredBlur"/>
|
|
36
|
+
<feMerge>
|
|
37
|
+
<feMergeNode in="coloredBlur"/>
|
|
38
|
+
<feMergeNode in="SourceGraphic"/>
|
|
39
|
+
</feMerge>
|
|
40
|
+
</filter>
|
|
41
|
+
<filter id="glow-strong" x="-100%" y="-100%" width="300%" height="300%">
|
|
42
|
+
<feGaussianBlur stdDeviation="8" result="coloredBlur"/>
|
|
43
|
+
<feMerge>
|
|
44
|
+
<feMergeNode in="coloredBlur"/>
|
|
45
|
+
<feMergeNode in="SourceGraphic"/>
|
|
46
|
+
</feMerge>
|
|
47
|
+
</filter>
|
|
48
|
+
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
|
|
49
|
+
<feDropShadow dx="0" dy="4" stdDeviation="6" flood-color="#6366F1" flood-opacity="0.2"/>
|
|
50
|
+
</filter>
|
|
51
|
+
|
|
52
|
+
<!-- Patterns -->
|
|
53
|
+
<pattern id="grid" width="30" height="30" patternUnits="userSpaceOnUse">
|
|
54
|
+
<path d="M 30 0 L 0 0 0 30" fill="none" stroke="#E5E7EB" stroke-width="0.5"/>
|
|
55
|
+
</pattern>
|
|
56
|
+
<pattern id="dots" width="15" height="15" patternUnits="userSpaceOnUse">
|
|
57
|
+
<circle cx="7.5" cy="7.5" r="1" fill="#6366F1" opacity="0.15"/>
|
|
58
|
+
</pattern>
|
|
59
|
+
<pattern id="hexgrid" width="28" height="49" patternUnits="userSpaceOnUse">
|
|
60
|
+
<path d="M14,0 L28,8 L28,24 L14,32 L0,24 L0,8 Z M14,33 L28,41 L28,49 M14,33 L0,41 L0,49" fill="none" stroke="#E5E7EB" stroke-width="0.3"/>
|
|
61
|
+
</pattern>
|
|
62
|
+
|
|
63
|
+
<!-- Orb gradient -->
|
|
64
|
+
<radialGradient id="orb-purple" cx="30%" cy="30%">
|
|
65
|
+
<stop offset="0%" style="stop-color:#C4B5FD"/>
|
|
66
|
+
<stop offset="100%" style="stop-color:#8B5CF6;stop-opacity:0"/>
|
|
67
|
+
</radialGradient>
|
|
68
|
+
<radialGradient id="orb-pink" cx="30%" cy="30%">
|
|
69
|
+
<stop offset="0%" style="stop-color:#FBCFE8"/>
|
|
70
|
+
<stop offset="100%" style="stop-color:#EC4899;stop-opacity:0"/>
|
|
71
|
+
</radialGradient>
|
|
72
|
+
<radialGradient id="orb-blue" cx="30%" cy="30%">
|
|
73
|
+
<stop offset="0%" style="stop-color:#A5B4FC"/>
|
|
74
|
+
<stop offset="100%" style="stop-color:#6366F1;stop-opacity:0"/>
|
|
75
|
+
</radialGradient>
|
|
76
|
+
</defs>
|
|
77
|
+
|
|
78
|
+
<!-- Background layers -->
|
|
79
|
+
<rect width="800" height="240" fill="url(#bg-radial)"/>
|
|
80
|
+
<rect width="800" height="240" fill="url(#hexgrid)" opacity="0.4"/>
|
|
81
|
+
<rect width="800" height="240" fill="url(#dots)" opacity="0.5"/>
|
|
82
|
+
|
|
83
|
+
<!-- Large glowing orbs -->
|
|
84
|
+
<circle cx="80" cy="80" r="100" fill="url(#orb-purple)" opacity="0.4"/>
|
|
85
|
+
<circle cx="720" cy="160" r="120" fill="url(#orb-pink)" opacity="0.3"/>
|
|
86
|
+
<circle cx="400" cy="280" r="180" fill="url(#orb-blue)" opacity="0.2"/>
|
|
87
|
+
<circle cx="650" cy="40" r="60" fill="url(#orb-purple)" opacity="0.25"/>
|
|
88
|
+
<circle cx="150" cy="200" r="70" fill="url(#orb-pink)" opacity="0.2"/>
|
|
89
|
+
|
|
90
|
+
<!-- Floating binary/code snippets -->
|
|
91
|
+
<g font-family="Monaco, monospace" font-size="8" fill="#6366F1" opacity="0.15">
|
|
92
|
+
<text x="20" y="30">SELECT * FROM</text>
|
|
93
|
+
<text x="700" y="25">WHERE id = :id</text>
|
|
94
|
+
<text x="50" y="220">ORDER BY created_at</text>
|
|
95
|
+
<text x="680" y="230">LIMIT 100</text>
|
|
96
|
+
<text x="300" y="20">WITH cte AS (...)</text>
|
|
97
|
+
<text x="500" y="235">GROUP BY category</text>
|
|
98
|
+
</g>
|
|
99
|
+
|
|
100
|
+
<!-- Data flow curves -->
|
|
101
|
+
<g stroke-width="2" fill="none" opacity="0.2">
|
|
102
|
+
<path d="M 0 120 Q 100 80 200 100 T 350 90" stroke="url(#accent-left)"/>
|
|
103
|
+
<path d="M 800 120 Q 700 80 600 100 T 450 90" stroke="url(#accent-right)"/>
|
|
104
|
+
<path d="M 0 180 Q 150 160 250 170 T 380 150" stroke="url(#accent-left)" stroke-dasharray="5 5"/>
|
|
105
|
+
<path d="M 800 180 Q 650 160 550 170 T 420 150" stroke="url(#accent-right)" stroke-dasharray="5 5"/>
|
|
106
|
+
</g>
|
|
107
|
+
|
|
108
|
+
<!-- Sparkles and stars -->
|
|
109
|
+
<g fill="#F59E0B">
|
|
110
|
+
<polygon points="100,50 102,56 108,56 103,60 105,66 100,62 95,66 97,60 92,56 98,56" opacity="0.5"/>
|
|
111
|
+
<polygon points="700,45 701,48 704,48 702,50 703,53 700,51 697,53 698,50 696,48 699,48" opacity="0.4"/>
|
|
112
|
+
<polygon points="180,180 181,183 184,183 182,185 183,188 180,186 177,188 178,185 176,183 179,183" opacity="0.35"/>
|
|
113
|
+
</g>
|
|
114
|
+
<g fill="#EC4899">
|
|
115
|
+
<polygon points="620,180 621,183 624,183 622,185 623,188 620,186 617,188 618,185 616,183 619,183" opacity="0.4"/>
|
|
116
|
+
<polygon points="750,100 752,106 758,106 753,110 755,116 750,112 745,116 747,110 742,106 748,106" opacity="0.3"/>
|
|
117
|
+
</g>
|
|
118
|
+
<g fill="#6366F1">
|
|
119
|
+
<polygon points="50,140 51,143 54,143 52,145 53,148 50,146 47,148 48,145 46,143 49,143" opacity="0.5"/>
|
|
120
|
+
<polygon points="350,30 351,33 354,33 352,35 353,38 350,36 347,38 348,35 346,33 349,33" opacity="0.4"/>
|
|
121
|
+
</g>
|
|
122
|
+
|
|
123
|
+
<!-- Floating SQL keywords with varied styling -->
|
|
124
|
+
<g font-family="Monaco, 'Courier New', monospace">
|
|
125
|
+
<text x="45" y="65" font-size="14" fill="#6366F1" opacity="0.7" font-weight="700" filter="url(#glow)">SELECT</text>
|
|
126
|
+
<text x="30" y="105" font-size="12" fill="#8B5CF6" opacity="0.5">FROM</text>
|
|
127
|
+
<text x="55" y="145" font-size="13" fill="#6366F1" opacity="0.4" font-weight="600">WHERE</text>
|
|
128
|
+
<text x="25" y="185" font-size="11" fill="#EC4899" opacity="0.5">JOIN</text>
|
|
129
|
+
|
|
130
|
+
<text x="705" y="60" font-size="12" fill="#8B5CF6" opacity="0.5">WITH</text>
|
|
131
|
+
<text x="725" y="100" font-size="14" fill="#6366F1" opacity="0.7" font-weight="700" filter="url(#glow)">CTE</text>
|
|
132
|
+
<text x="670" y="140" font-size="11" fill="#EC4899" opacity="0.4">ORDER BY</text>
|
|
133
|
+
<text x="710" y="180" font-size="12" fill="#8B5CF6" opacity="0.5">GROUP</text>
|
|
134
|
+
</g>
|
|
135
|
+
|
|
136
|
+
<!-- Database cylinders with glow -->
|
|
137
|
+
<g transform="translate(130, 85)" filter="url(#glow)">
|
|
138
|
+
<g opacity="0.3">
|
|
139
|
+
<ellipse cx="0" cy="0" rx="25" ry="10" fill="#EEF2FF" stroke="#6366F1" stroke-width="2"/>
|
|
140
|
+
<path d="M-25,0 L-25,35 A25,10 0 0,0 25,35 L25,0" fill="#EEF2FF" stroke="#6366F1" stroke-width="2"/>
|
|
141
|
+
<ellipse cx="0" cy="17" rx="25" ry="10" fill="none" stroke="#6366F1" stroke-width="1" stroke-dasharray="4 3"/>
|
|
142
|
+
<ellipse cx="0" cy="35" rx="25" ry="10" fill="#EEF2FF" stroke="#6366F1" stroke-width="2"/>
|
|
143
|
+
</g>
|
|
144
|
+
</g>
|
|
145
|
+
<g transform="translate(670, 90)" filter="url(#glow)">
|
|
146
|
+
<g opacity="0.3">
|
|
147
|
+
<ellipse cx="0" cy="0" rx="23" ry="9" fill="#FDF2F8" stroke="#EC4899" stroke-width="2"/>
|
|
148
|
+
<path d="M-23,0 L-23,32 A23,9 0 0,0 23,32 L23,0" fill="#FDF2F8" stroke="#EC4899" stroke-width="2"/>
|
|
149
|
+
<ellipse cx="0" cy="16" rx="23" ry="9" fill="none" stroke="#EC4899" stroke-width="1" stroke-dasharray="4 3"/>
|
|
150
|
+
<ellipse cx="0" cy="32" rx="23" ry="9" fill="#FDF2F8" stroke="#EC4899" stroke-width="2"/>
|
|
151
|
+
</g>
|
|
152
|
+
</g>
|
|
153
|
+
|
|
154
|
+
<!-- Table/grid icons -->
|
|
155
|
+
<g transform="translate(195, 165)" opacity="0.25">
|
|
156
|
+
<rect x="-18" y="-14" width="36" height="28" rx="3" fill="#EEF2FF" stroke="#6366F1" stroke-width="1.5"/>
|
|
157
|
+
<line x1="-18" y1="-4" x2="18" y2="-4" stroke="#6366F1" stroke-width="1"/>
|
|
158
|
+
<line x1="-18" y1="6" x2="18" y2="6" stroke="#6366F1" stroke-width="0.5" stroke-dasharray="2 2"/>
|
|
159
|
+
<line x1="-4" y1="-14" x2="-4" y2="14" stroke="#6366F1" stroke-width="1"/>
|
|
160
|
+
<line x1="8" y1="-14" x2="8" y2="14" stroke="#6366F1" stroke-width="0.5" stroke-dasharray="2 2"/>
|
|
161
|
+
</g>
|
|
162
|
+
<g transform="translate(605, 165)" opacity="0.25">
|
|
163
|
+
<rect x="-18" y="-14" width="36" height="28" rx="3" fill="#FDF2F8" stroke="#EC4899" stroke-width="1.5"/>
|
|
164
|
+
<line x1="-18" y1="-4" x2="18" y2="-4" stroke="#EC4899" stroke-width="1"/>
|
|
165
|
+
<line x1="-18" y1="6" x2="18" y2="6" stroke="#EC4899" stroke-width="0.5" stroke-dasharray="2 2"/>
|
|
166
|
+
<line x1="-4" y1="-14" x2="-4" y2="14" stroke="#EC4899" stroke-width="1"/>
|
|
167
|
+
</g>
|
|
168
|
+
|
|
169
|
+
<!-- Ruby gem - detailed with facets -->
|
|
170
|
+
<g transform="translate(400, 42)" opacity="0.2">
|
|
171
|
+
<polygon points="0,-28 25,-10 15,22 -15,22 -25,-10" fill="#FEE2E2" stroke="#DC2626" stroke-width="2"/>
|
|
172
|
+
<polygon points="0,-28 25,-10 0,8 -25,-10" fill="#FECACA" stroke="#DC2626" stroke-width="1"/>
|
|
173
|
+
<polygon points="0,8 25,-10 15,22" fill="#FCA5A5" stroke="#DC2626" stroke-width="1"/>
|
|
174
|
+
<polygon points="0,8 -25,-10 -15,22" fill="#FCA5A5" stroke="#DC2626" stroke-width="1"/>
|
|
175
|
+
<line x1="0" y1="-28" x2="0" y2="22" stroke="#DC2626" stroke-width="1"/>
|
|
176
|
+
</g>
|
|
177
|
+
|
|
178
|
+
<!-- Connection dots/nodes -->
|
|
179
|
+
<g fill="#6366F1">
|
|
180
|
+
<circle cx="250" cy="100" r="4" opacity="0.3"/>
|
|
181
|
+
<circle cx="280" cy="120" r="3" opacity="0.2"/>
|
|
182
|
+
<circle cx="320" cy="105" r="5" opacity="0.25"/>
|
|
183
|
+
</g>
|
|
184
|
+
<g fill="#EC4899">
|
|
185
|
+
<circle cx="550" cy="100" r="4" opacity="0.3"/>
|
|
186
|
+
<circle cx="520" cy="120" r="3" opacity="0.2"/>
|
|
187
|
+
<circle cx="480" cy="105" r="5" opacity="0.25"/>
|
|
188
|
+
</g>
|
|
189
|
+
|
|
190
|
+
<!-- Main title with rainbow gradient and strong glow -->
|
|
191
|
+
<text x="400" y="115" font-family="system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif" font-size="62" font-weight="900" fill="url(#title-grad)" text-anchor="middle" filter="url(#glow-strong)">AppQuery</text>
|
|
192
|
+
|
|
193
|
+
<!-- Decorative underline - animated look -->
|
|
194
|
+
<g transform="translate(400, 128)">
|
|
195
|
+
<rect x="-120" y="0" width="240" height="4" rx="2" fill="url(#rainbow)" opacity="0.6"/>
|
|
196
|
+
<rect x="-100" y="6" width="200" height="2" rx="1" fill="url(#rainbow)" opacity="0.3"/>
|
|
197
|
+
</g>
|
|
198
|
+
|
|
199
|
+
<!-- Tagline with subtle styling -->
|
|
200
|
+
<text x="400" y="158" font-family="system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif" font-size="18" fill="#6B7280" text-anchor="middle" letter-spacing="2" font-weight="500">Raw SQL, ergonomically</text>
|
|
201
|
+
|
|
202
|
+
<!-- Terminal code block - fancy -->
|
|
203
|
+
<g transform="translate(400, 200)" filter="url(#shadow)">
|
|
204
|
+
<rect x="-250" y="-18" width="500" height="36" rx="18" fill="#FFFFFF" stroke="#E5E7EB" stroke-width="1"/>
|
|
205
|
+
<!-- Window controls -->
|
|
206
|
+
<circle cx="-225" cy="0" r="6" fill="#EF4444"/>
|
|
207
|
+
<circle cx="-206" cy="0" r="6" fill="#F59E0B"/>
|
|
208
|
+
<circle cx="-187" cy="0" r="6" fill="#22C55E"/>
|
|
209
|
+
<!-- Separator -->
|
|
210
|
+
<line x1="-170" y1="-10" x2="-170" y2="10" stroke="#E5E7EB" stroke-width="1"/>
|
|
211
|
+
<!-- Code with syntax highlighting -->
|
|
212
|
+
<text x="-155" y="5" font-family="Monaco, 'Courier New', monospace" font-size="12">
|
|
213
|
+
<tspan fill="#8B5CF6">AppQuery</tspan><tspan fill="#6B7280">[</tspan><tspan fill="#059669">:sales</tspan><tspan fill="#6B7280">].</tspan><tspan fill="#2563EB">select_all</tspan><tspan fill="#6B7280">(</tspan><tspan fill="#DC2626">binds:</tspan><tspan fill="#6B7280"> {</tspan><tspan fill="#059669">year:</tspan><tspan fill="#D97706"> 2026</tspan><tspan fill="#6B7280">})</tspan>
|
|
214
|
+
</text>
|
|
215
|
+
</g>
|
|
216
|
+
|
|
217
|
+
<!-- Output arrow with results hint -->
|
|
218
|
+
<g transform="translate(400, 228)">
|
|
219
|
+
<path d="M-30,0 L0,10 L30,0" stroke="#22C55E" stroke-width="2.5" fill="none" opacity="0.5"/>
|
|
220
|
+
<text x="0" y="12" font-family="Monaco, monospace" font-size="8" fill="#22C55E" text-anchor="middle" opacity="0.5">[{revenue: 42000, ...}]</text>
|
|
221
|
+
</g>
|
|
222
|
+
</svg>
|
data/lib/app_query/tokenizer.rb
CHANGED
|
@@ -257,16 +257,26 @@ module AppQuery
|
|
|
257
257
|
|
|
258
258
|
level = 1
|
|
259
259
|
loop do
|
|
260
|
-
read_until(/\)|\(/)
|
|
260
|
+
read_until(/\)|\(|'/)
|
|
261
261
|
if eos?
|
|
262
262
|
err "CTE select ended prematurely"
|
|
263
|
+
elsif match?(/'/)
|
|
264
|
+
# Skip string literal (handle escaped quotes '')
|
|
265
|
+
read_char
|
|
266
|
+
loop do
|
|
267
|
+
read_until(/'/)
|
|
268
|
+
read_char
|
|
269
|
+
break unless match?(/'/) # '' is escaped quote, continue
|
|
270
|
+
read_char
|
|
271
|
+
end
|
|
263
272
|
elsif match?(/\(/)
|
|
264
273
|
level += 1
|
|
274
|
+
read_char
|
|
265
275
|
elsif match?(/\)/)
|
|
266
276
|
level -= 1
|
|
267
277
|
break if level.zero?
|
|
278
|
+
read_char
|
|
268
279
|
end
|
|
269
|
-
read_char
|
|
270
280
|
end
|
|
271
281
|
|
|
272
282
|
err "Expected non-empty CTE select, e.g. '(select 1)'" if chars_read.strip == "("
|
data/lib/app_query/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: appquery
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0.rc2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Gert Goet
|
|
@@ -43,12 +43,17 @@ files:
|
|
|
43
43
|
- ".irbrc"
|
|
44
44
|
- ".rspec"
|
|
45
45
|
- ".standard.yml"
|
|
46
|
+
- ".yard/templates/default/fulldoc/html/css/dark.css"
|
|
47
|
+
- ".yard/templates/default/fulldoc/html/setup.rb"
|
|
48
|
+
- ".yard/templates/default/layout/html/setup.rb"
|
|
46
49
|
- ".yardopts"
|
|
47
50
|
- Appraisals
|
|
48
51
|
- CHANGELOG.md
|
|
49
52
|
- LICENSE.txt
|
|
50
53
|
- README.md
|
|
51
54
|
- Rakefile
|
|
55
|
+
- assets/banner-dark.svg
|
|
56
|
+
- assets/banner-light.svg
|
|
52
57
|
- lib/app_query.rb
|
|
53
58
|
- lib/app_query/base.rb
|
|
54
59
|
- lib/app_query/base_query.rb
|