11@page " /"
22@using Microsoft .AspNetCore .Components .Web
3- @inject NavigationManager Navigation
3+ @using Lql
4+ @using Lql .Postgres
5+ @using Lql .SqlServer
6+ @using Results
47
58<PageTitle >Lambda Query Language (LQL) - Functional Data Querying</PageTitle >
69
1215
1316 <div class =" cta-buttons" >
1417 <a href =" #examples" class =" btn btn-primary" >See Examples</a >
15- <button @onclick = " NavigateToPlayground " class =" btn btn-secondary" >Try Playground</button >
18+ <a href = " #playground " class =" btn btn-secondary" >Try Playground</a >
1619 </div >
1720
1821 <div class =" hero-code" >
201204 </div >
202205</section >
203206
207+ <section id =" playground" class =" playground" >
208+ <div class =" container" >
209+ <div class =" section-header" >
210+ <h2 >LQL Playground</h2 >
211+ <p >Try Lambda Query Language and see how it transpiles to PostgreSQL or SQL Server</p >
212+ </div >
213+
214+ <div class =" playground-content" >
215+ <div class =" input-section" >
216+ <h3 class =" section-title" >LQL Input</h3 >
217+ <div class =" controls" >
218+ <select @bind =" selectedDialect" class =" dialect-selector" >
219+ <option value =" PostgreSQL" >PostgreSQL</option >
220+ <option value =" SqlServer" >SQL Server</option >
221+ </select >
222+ <button @onclick =" ConvertLql" class =" convert-btn" disabled =" @isConverting" >
223+ @if (isConverting )
224+ {
225+ <text >Converting .. .</text >
226+ }
227+ else
228+ {
229+ <text >Convert to SQL </text >
230+ }
231+ </button >
232+ </div >
233+ <textarea @bind =" lqlInput" @bind:event =" oninput" class =" lql-input"
234+ placeholder =" Enter your LQL query here...
235+
236+ Example:
237+ users |> select(users.id, users.name, users.email)" ></textarea >
238+ </div >
239+
240+ <div class =" output-section" >
241+ <h3 class =" section-title" >@selectedDialect Output</h3 >
242+ <div class =" sql-output" >@sqlOutput </div >
243+ @if (! string .IsNullOrEmpty (errorMessage ))
244+ {
245+ <div class =" error-message" >
246+ <strong >Error : </strong > @errorMessage
247+ </div >
248+ }
249+ </div >
250+ </div >
251+
252+ <div class =" examples-section" >
253+ <h3 class =" section-title" >Example Queries</h3 >
254+ <p style =" color : var (--text-secondary ); margin-bottom : 16px ;" >Click any example to load it into the editor:</p >
255+ <div class =" example-buttons" >
256+ <button @onclick =" () => LoadExample(simpleSelectExample)" class =" example-btn" >Simple Select</button >
257+ <button @onclick =" () => LoadExample(joinExample)" class =" example-btn" >Join Tables</button >
258+ <button @onclick =" () => LoadExample(filterExample)" class =" example-btn" >Filter Data</button >
259+ <button @onclick =" () => LoadExample(aggregateExample)" class =" example-btn" >Aggregation</button >
260+ <button @onclick =" () => LoadExample(complexExample)" class =" example-btn" >Complex Query</button >
261+ </div >
262+ </div >
263+ </div >
264+ </section >
265+
204266<footer >
205267 <div class =" container" >
206268 <div class =" footer-content" >
216278</footer >
217279
218280@code {
219- private void NavigateToPlayground ()
281+ private string lqlInput = " " ;
282+ private string sqlOutput = " Enter LQL code and click 'Convert to SQL' to see the result." ;
283+ private string errorMessage = " " ;
284+ private string selectedDialect = " PostgreSQL" ;
285+ private bool isConverting = false ;
286+
287+ // Example queries
288+ private readonly string simpleSelectExample = " users |> select(users.id, users.name, users.email)" ;
289+
290+ private readonly string joinExample = @" users
291+ |> join(orders, on = users.id = orders.user_id)
292+ |> select(users.name, orders.total, orders.status)" ;
293+
294+ private readonly string filterExample = @" employees
295+ |> select(employees.id, employees.name, employees.salary)
296+ |> filter(fn(row) => row.employees.salary > 50000 and row.employees.department = 'Engineering')" ;
297+
298+ private readonly string aggregateExample = @" orders
299+ |> group_by(orders.user_id)
300+ |> select(
301+ orders.user_id,
302+ count(*) as order_count,
303+ sum(orders.total) as total_amount,
304+ avg(orders.total) as avg_amount
305+ )
306+ |> having(fn(group) => count(*) > 2)
307+ |> order_by(total_amount desc)" ;
308+
309+ private readonly string complexExample = @" -- Complex analytics query
310+ let joined =
311+ users
312+ |> join(orders, on = users.id = orders.user_id)
313+ |> filter(fn(row) => row.orders.status = 'completed')
314+
315+ joined
316+ |> group_by(users.id)
317+ |> select(
318+ users.name,
319+ count(*) as total_orders,
320+ sum(orders.total) as revenue,
321+ avg(orders.total) as avg_order_value
322+ )
323+ |> filter(fn(row) => row.revenue > 1000)
324+ |> order_by(revenue desc)
325+ |> limit(10)" ;
326+
327+ private async Task ConvertLql ()
328+ {
329+ if (string .IsNullOrWhiteSpace (lqlInput ))
330+ {
331+ errorMessage = " Please enter some LQL code to convert." ;
332+ sqlOutput = " " ;
333+ return ;
334+ }
335+
336+ isConverting = true ;
337+ errorMessage = " " ;
338+ sqlOutput = " Converting..." ;
339+
340+ try
341+ {
342+ await Task .Delay (100 ); // Small delay to show loading state
343+
344+ // Parse the LQL code
345+ var statementResult = LqlStatementConverter .ToStatement (lqlInput );
346+
347+ if (statementResult is Result <LqlStatement , SqlError >.Failure parseFailure )
348+ {
349+ errorMessage = parseFailure .ErrorValue .DetailedMessage ?? parseFailure .ErrorValue .Message ;
350+ sqlOutput = " " ;
351+ return ;
352+ }
353+
354+ var statement = ((Result <LqlStatement , SqlError >.Success )statementResult ).Value ;
355+
356+ // Convert to the selected SQL dialect
357+ Result <string , SqlError > sqlResult = selectedDialect switch
358+ {
359+ " PostgreSQL" => statement .ToPostgreSql (),
360+ " SqlServer" => statement .ToSqlServer (),
361+ _ => new Result <string , SqlError >.Failure (new SqlError ($" Unsupported dialect: {selectedDialect }" ))
362+ };
363+
364+ if (sqlResult is Result <string , SqlError >.Failure sqlFailure )
365+ {
366+ errorMessage = sqlFailure .ErrorValue .DetailedMessage ?? sqlFailure .ErrorValue .Message ;
367+ sqlOutput = " " ;
368+ return ;
369+ }
370+
371+ var sql = ((Result <string , SqlError >.Success )sqlResult ).Value ;
372+ sqlOutput = sql ;
373+ errorMessage = " " ;
374+ }
375+ catch (Exception ex )
376+ {
377+ errorMessage = $" An unexpected error occurred: {ex }" ;
378+ sqlOutput = " " ;
379+ }
380+ finally
381+ {
382+ isConverting = false ;
383+ }
384+ }
385+
386+ private void LoadExample (string example )
387+ {
388+ lqlInput = example ;
389+ errorMessage = " " ;
390+ sqlOutput = " Click 'Convert to SQL' to see the result." ;
391+ }
392+
393+ protected override async Task OnInitializedAsync ()
220394 {
221- Navigation .NavigateTo (" /playground" );
395+ // Load a simple example by default
396+ lqlInput = simpleSelectExample ;
397+ await ConvertLql ();
222398 }
223399}
0 commit comments