Anentropic
Anentropic

Reputation: 33833

Racket SQL: how to use variable value as table name in create-table?

https://docs.racket-lang.org/sql/ is a nice DSL for preparing SQL statements, which works with the db library.

The docs show an example like:

(require sql)

(create-table #:temporary the_numbers
  #:columns [n integer #:not-null] [d varchar])

In this code the_numbers is not an identifier, it's treated literally as the name of the table.

What I want to do is something like:

(require sql)

(define (my-create-table table-name)
  (create-table #:temporary table-name
    #:columns [n integer #:not-null] [d varchar]))

This gives an error because it treats table-name as the actual table name and it doesn't like the hyphen in it (I think it should be possible to use that as a table name but I guess I need to do something more to have the lib quote it properly...)

I am new to Racket and don't know many tricks. I tried using 'table-name but that doesn't work.

Upvotes: 4

Views: 132

Answers (2)

Ryan Culpepper
Ryan Culpepper

Reputation: 10653

The features you need are described in the Dynamic Statement Composition and SQL Injection of the docs. You can write the Ident for the table's name as (Ident:AST ,expr), where expr produces an Ident AST value.

> (define (my-create-table table-name)
    (create-table #:temporary (Ident:AST ,(make-ident-ast table-name))
      #:columns [n integer #:not-null] [d varchar]))
> (my-create-table 'the_numbers)
(sql-statement
 "CREATE TEMPORARY TABLE the_numbers (n integer NOT NULL, d varchar)")

Upvotes: 3

MLavrentyev
MLavrentyev

Reputation: 1969

Here's something that should work for you:

#lang racket

(require syntax/parse/define)
(require sql)

(define-simple-macro (my-create-table table-name:id)
  (create-table #:temporary table-name
                #:columns [n integer #:not-null] [d varchar]))

(my-create-table my_table_name)

This creates a macro called my-create-table. What that essentially does is it syntactically replaces (hygienically) the expression (my-create-table <some-id>), where <some-id> is any identifier, with the expression below (the create-table expression), replacing table-name with the id given in the original syntax.

Macros are cool.

Upvotes: 1

Related Questions