Re: [racket-users] Why would a value produced by eval-ing code not satisfy its type predicate? (Particularly, a SQL statement from the sql package)

2019-02-04 Thread Philip McGrath
On Sat, Feb 2, 2019 at 11:34 PM hashim muqtadir 
wrote:

> > As long as you at least know the schema you're working with, you could
> even generate select statements for all possible sets of columns at compile
> time, and then just choose the right statement dynamically with a runtime
> function.
>
> That did occur to me, and was my other idea compared to eval, up until I'd
> figured out the INJECT thing, but I didn't do it as then there would be a
> huge amount of select statements. The idea was to basically take the column
> list, sort it, string-join, and then get the relevant select from a hash
> table. But there'd be way too many.
>
> …
>
> One of the problems we face is of moving too much data around. Mobile
> applications that have to mainly work offline and periodically sync, they
> have to move around lots of data on horrible connections. (We do gzip and
> all. Choosing a data format that's not json is an option I'll evaluate in
> the future.)
>
> So selecting a list of fields when getting data for different entites is
> something we provide in our APIs.
>

It occurred to me you could also consider a sort of middle option. The
`sql` library can already handle dynamically filling in the names and order
of the columns to select: the only restriction is that the *number* of
columns must be specified at compile-time (aside from with
`ScalarExpr:INJECT`). So, if you know your table has N columns, you could
generate select statements for 1 to N columns, with the names of the
columns to be filled in at runtime. That would do much less code generation
than compiling a select statement for every possible combination of columns
(or, worse, permutation), while also being less of a hack than
`ScalarExpr:INJECT` (which I still think is a reasonable workaround). You
could use a `case` expression or a vector of functions for dispatch.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Why would a value produced by eval-ing code not satisfy its type predicate? (Particularly, a SQL statement from the sql package)

2019-02-02 Thread hashim muqtadir
>  The issue you're encountering with namespaces is analogous, because each 
namespace gets its own instances of modules. This is a feature! Imagine, 
for example, that you are trying to run students' programs in a sandbox. If 
namespaces shared module instances, a malicious or buggy student program 
could alter mutable state and affect other students' programs or your 
outside-the-sandbox program. But this means that two different namespaces 
will have two distinct instances of the `sql` module that export two 
distinct `sql-statement?` predicates, each recognizing only its own version 
of the sql-statement struct type: this is effectively the same situation as 
calling `thing1?` on `a-thing2` in my example.

> For times when you really do want to share a module instance, Racket 
provides `namespace-attach-module`. Alternatively, you could just use 
`define-namespace-anchor` and `namespace-anchor->namespace`.

Thanks! That both explains and resolves the issue.

In my original example, if I replace the beginning part with:

#lang racket

(require db)
(require sql)

(define sql-namespace (make-base-empty-namespace))
(define src-namespace (current-namespace))
(parameterize ([current-namespace sql-namespace])
  (namespace-attach-module src-namespace 'sql)
  (namespace-require 'sql))

Then everything works as expected, and now I know why.

> But, as others have said, you really don't want to use `eval`. (If you 
aren't already familiar with the issues, see [...]

Point taken. At the time I just wanted the variable-columns thing working 
and I hadn't figured out how to make it work with a list. Additionally, 
escaping column names isn't going to be an issue, because most likely in 
the actual use case the user's required column list will pass through a 
whitelist. That part's solved, one way or another.

> As long as you at least know the schema you're working with, you could 
even generate select statements for all possible sets of columns at compile 
time, and then just choose the right statement dynamically with a runtime 
function.

That did occur to me, and was my other idea compared to eval, up until I'd 
figured out the INJECT thing, but I didn't do it as then there would be a 
huge amount of select statements. The idea was to basically take the column 
list, sort it, string-join, and then get the relevant select from a hash 
table. But there'd be way too many.

As to why I would like to do this, well, basically at my workplace we sort 
of make web applications, generally split into a separate server side 
application that's basically an HTTP API, that different browser and mobile 
applications talk to. I've previously always written the server side part 
in python. "Sort of" because have to work offline too.

One of the problems we face is of moving too much data around. Mobile 
applications that have to mainly work offline and periodically sync, they 
have to move around lots of data on horrible connections. (We do gzip and 
all. Choosing a data format that's not json is an option I'll evaluate in 
the future.)

So selecting a list of fields when getting data for different entites is 
something we provide in our APIs. In the beginning we did in fact return 
all of an entity's data. as writing different column sets for different 
clients, while do-able, is sort of bad in the sense that then when somebody 
asks for adding a column in a table in the mobile app, it required changes 
in two places, and needlessly adds code. The idea being that when we only 
write a different column set (and call it a different entity) on the same 
enttiy when it's a non trivial thing to do.

So anyway while most of this is solved for the current few projects we 
have, we're moving away from python. Racket's an experiment, partly chosen 
because we agree with the "many languages" approach. Things like python's 
django, sqlalchemy and javascript's vue aren't libraries, they're #langs. 
So now I have to write solutions/languages in Racket to make sure we're at 
least on par with what we have at the moment. Like in python we have our 
little filters language, which piggybacks on django ORM's column and 
relation lookup syntax, but we restrict some operations and add some 
others, nest them in and/or/not operators, and generically handle edge 
cases that django doesn't (like ensuring that joins don't increase row 
count). And no, writing SQL in the client application is not (yet) an 
option as we need to evaluate certain things first. Evaluated graphQL, a 
bit, tentatively, and alone, it doesn't to fit the use case. A hybrid 
approach seems do-able in the short term but a bad idea in the long term.

Anyway, thanks for the help. and I suppose I should mark this thread as 
solved (I don't know what that really does). I don't mind people asking 
things, but I suppose littering the list with specifics would be frowned 
upon.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To 

Re: [racket-users] Why would a value produced by eval-ing code not satisfy its type predicate? (Particularly, a SQL statement from the sql package)

2019-02-02 Thread George Neuner



On 2/1/2019 5:12 AM, hashim muqtadir wrote:

> No.  Look back at your code ... you defined the struct in your own
> unnamed module just before the definition of "select/f"

But the thing is, the error was that it failed to recognize 
sql-statement in the test, which is provided by sql, not me. The 
function otherwise worked correctly. The thing returned by the 
function wasn't recognized as an sql-statement. It had the same 
printed representation as a call to "select" done manually.


If I remember correctly, you said the error was that the result didn't 
satisfy "sql-statement?".  That would happen if the struct was not 
recognized.


George

--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Why would a value produced by eval-ing code not satisfy its type predicate? (Particularly, a SQL statement from the sql package)

2019-02-01 Thread Philip McGrath
On the original question: Racket's struct types are generative (except for
#:prefab structs), meaning that each time you evaluate a `struct` form (or,
at a lower level, each time you call `make-struct-type`), the you create a
fresh type distinct from all other types. That can be a bit confusing to
just think about in the abstract, so here's a little illustration that
doesn't involve namespaces or modules:
#lang racket
(require rackunit)
(define (generate)
  (struct thing ())
  (values (thing) thing?))
(define-values (a-thing1 thing1?)
  (generate))
(define-values (a-thing2 thing2?)
  (generate))
(check-false (thing2? a-thing1))
(check-false (thing1? a-thing2))

The issue you're encountering with namespaces is analogous, because each
namespace gets its own instances of modules. This is a feature! Imagine,
for example, that you are trying to run students' programs in a sandbox. If
namespaces shared module instances, a malicious or buggy student program
could alter mutable state and affect other students' programs or your
outside-the-sandbox program. But this means that two different namespaces
will have two distinct instances of the `sql` module that export two
distinct `sql-statement?` predicates, each recognizing only its own version
of the sql-statement struct type: this is effectively the same situation as
calling `thing1?` on `a-thing2` in my example.

For times when you really do want to share a module instance, Racket
provides `namespace-attach-module
`.
Alternatively, you could just use `define-namespace-anchor
`
and `namespace-anchor->namespace

`.

But, as others have said, you really don't want to use `eval`. (If you
aren't already familiar with the issues, see
https://blog.racket-lang.org/2011/10/on-eval-in-dynamic-languages-generally.html)
The only part of what you want that (AFAIK) you can't already do with the
`sql` library's dynamic facilities is selecting a dynamically-determined
number of columns. I think your work-around using `ScalarExpr:INJECT` is
reasonable, with the caveat that you need to be sure to understand the
quoting/case-folding rules for the specific database(s) you're targeting.

More broadly, it might help to know why you want to select a number of
columns to be determined dynamically at run-time. I can't immediately think
of a time when I've ever wanted to do that. If you can say a bit more,
there may be a solution to your ultimate problem that doesn't need this
functionality. For example, if you want to select a few different sets of
columns from the same base query, you could write the base query as one
select expression that selects all the columns, then re-use that as the
`#:from` table expression through dynamic composition in more select
statements that return only the particular sets of columns you're
interested in. As long as you at least know the schema you're working with,
you could even generate select statements for all possible sets of columns
at compile time, and then just choose the right statement dynamically with
a runtime function.

If it turns out that you really do need to determine the number of columns
dynamically, you certainly could make a feature request. (Ryan has been
kind enough to accept a few of my pull requests to add some features I've
needed, including additional dynamic statement composition hooks.) The main
thing would probably be to figure out a principled way to structure the
feature.

-Philip


On Fri, Feb 1, 2019 at 11:02 PM hashim muqtadir 
wrote:

> > Good news, limit and distinct are in scope for v0.2 - I'm working on it
> now :)
>
> That's good to hear, thanks! I'll be sure to check it out, and let you
> know if I have any ideas/requirements for features or if I can contribute.
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to racket-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Why would a value produced by eval-ing code not satisfy its type predicate? (Particularly, a SQL statement from the sql package)

2019-02-01 Thread hashim muqtadir
> Good news, limit and distinct are in scope for v0.2 - I'm working on it 
now :)

That's good to hear, thanks! I'll be sure to check it out, and let you know 
if I have any ideas/requirements for features or if I can contribute. 


-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Why would a value produced by eval-ing code not satisfy its type predicate? (Particularly, a SQL statement from the sql package)

2019-02-01 Thread Ryan Kramer

>
> PS There's also a racket package called plisqin which seemed closer to 
> what I was looking for. Maybe in a few months or so if it clicks I'll see 
> if I can add to that package everything I need (things like limit and 
> distinct) and it might work out.
>

Good news, limit and distinct are in scope for v0.2 - I'm working on it now 
:)

Right now, the scope for plisqin 0.2 is determined by
1) About 6k lines of SQL from my day job
2) Ecto's query API: https://hexdocs.pm/ecto/Ecto.Query.API.html#content

I figure that's a decent way to define a reasonable scope. But if you or 
anyone has a list of "must have" features, let me know and I'll certainly 
consider it.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Why would a value produced by eval-ing code not satisfy its type predicate? (Particularly, a SQL statement from the sql package)

2019-02-01 Thread David Storrs
Hey, neat.  I did not know that there was a sql package; I should have
thought to look.

Ryan, is there a way to use PostgreSQL's "RETURNING" feature or other
DB-specific items?  RETURNING is insanely useful and I'd be sad to
give it up.

On Fri, Feb 1, 2019 at 5:12 AM hashim muqtadir
 wrote:
>
> > No.  Look back at your code ... you defined the struct in your own
> > unnamed module just before the definition of  "select/f"
>
> But the thing is, the error was that it failed to recognize sql-statement in 
> the test, which is provided by sql, not me. The function otherwise worked 
> correctly. The thing returned by the function wasn't recognized as an 
> sql-statement. It had the same printed representation as a call to "select" 
> done manually.
>
> > This is a late stage debugging version with a lot
> > of visible output - cleaned up a bit, the final version is part of a
> > scheduler I wrote.  You are free to do with it whatever you like
>
> Thanks! Seems pretty neat.
>
> --
> You received this message because you are subscribed to the Google Groups 
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to racket-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Why would a value produced by eval-ing code not satisfy its type predicate? (Particularly, a SQL statement from the sql package)

2019-02-01 Thread hashim muqtadir
> No.  Look back at your code ... you defined the struct in your own 
> unnamed module just before the definition of  "select/f" 

But the thing is, the error was that it failed to recognize sql-statement 
in the test, which is provided by sql, not me. The function otherwise 
worked correctly. The thing returned by the function wasn't recognized as 
an sql-statement. It had the same printed representation as a call to 
"select" done manually.

> This is a late stage debugging version with a lot 
> of visible output - cleaned up a bit, the final version is part of a 
> scheduler I wrote.  You are free to do with it whatever you like

Thanks! Seems pretty neat.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Why would a value produced by eval-ing code not satisfy its type predicate? (Particularly, a SQL statement from the sql package)

2019-02-01 Thread George Neuner


On 2/1/2019 12:39 AM, hashim muqtadir wrote:

> If order to use a struct across namespaces, the module that
> defines the struct must be required into each namespace that uses the
> struct.

Yes, I suspect there's some weird interaction between namespaces too, 
hence the topic, but that's still pretty vague. After all, the thing 
defining the structs is the sql package, and my modules/namespaces are 
importing that.


No.  Look back at your code ... you defined the struct in your own 
unnamed module just before the definition of  "select/f"




> Eval almost always is the wrong answer.

I wanted to pass a list to select, but select is a macro, and I didn't 
get how to define a macro on top of that to do what I wanted, since 
the macro doesn't know that one of the things being passed into it 
evaluates to a list, so it can't splice that list into select, hence, 
eval.


Macros can construct calls to other macros or functions.  SQL is too 
complicated to give a representative example, but you can look at this 
AT-style time macro.  This is a late stage debugging version with a lot 
of visible output - cleaned up a bit, the final version is part of a 
scheduler I wrote.  You are free to do with it whatever you like.



> I recommend that you take a look at section 3.7 of the 
documentation, "Dynamic Statement Composition and SQL Injection”, 
which I believe does exactly what you want. Specifically, you want to 
dynamically construct a select statement.


I did look at that. And up until yesterday I thought "this isn't 
helping, I need to inject multiple select-expr's!".


And today, I had a look again and thought, hey, what if I use a string 
that has a comma in it, and, hey, that works!


i.e. the following works:

    #lang racket
    (require sql)
    (select (ScalarExpr:INJECT (unquote "mew, two")) #:from pokemon)

It gives me `(sql-statement "SELECT mew, two FROM pokemon")`

So now I know all I have to do is comma-join my list to form a string, 
and inject that.


What I do _not_ know if that's how INJECT was meant to be used, or 
whether I should build a separate inject macro that uses 
unquote-splice instead that comma-joins the list and does some form of 
escaping on the columns. My first guess is that properly verifying the 
items in the list to be single expressions is pretty difficult, so it 
sounds like a bad idea, and since one select-expr is allowed to yield 
multiple columns (because the "db" library that will actually get the 
results doesn't need any info from the query, I think), my approach 
should be fine.


I haven't looked at the SQL package  [didn't know about it until you 
mentioned it].



I use my own [really complex] macro for writing free form SQL.  It 
allows arbitrary Racket code (that produces a string) to be interspliced 
among the SQL, and the result all is reduced to a string to pass to the 
DB library.  It's not release material though:  it's good enough for me, 
but the error reporting is poor and the "language" it accepts is not 
quite SQL but rather a hybrid of SQL and Racket..


I've been meaning to go back to it.  I'd like to fix it so I can write 
standard SQL instead of the hybrid language  (SQL's meaning for single 
quotes, brackets, etc.) , but I never seem to get around to it.  If 
Ryan's SQL library is good enough, maybe I just retire my own code instead.


George


--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
#lang racket/base

(require
  (for-syntax racket/base
  racket/format
  )

  racket/base
  racket/match
  racket/list
  racket/format
  racket/dict
  racket/date

  )


;%%%
#|

allows free form date/time descriptions in
the style of the Unix "at" command. converts
the description into seconds since the Unix
epoch: 1970-01-01 at 00:00hrs.

the resulting seconds value may be converted
into a usable date structure, or passed to
an alarm event for scheduling.

special words:
  "now" = current date/time
  "today"  - at 00hrs
  "tomorrow"   - at 00hrs
  "this-month" - at 00hrs on the 1st
  "next-month" - at 00hrs on the 1st

dates must be entered in -mm-dd format.

times may be entered in 12hr or 24hr format.
minutes, seconds, and AM/PM are optional.
AM/PM is ignored if time is unambiguous.

"+  " adds a given offset
to the accumulated date/time value. units
may be seconds, minutes, hours, days, or weeks.

units and their typical abbreviations are
recognized in both singular and plural forms.

|#
;%%%


;==
;
;  macro interface - generates call to
;  parsing function at runtime
;
;==

(define-syntax (at stx)
  (let* [
 (input   (cdr 

Re: [racket-users] Why would a value produced by eval-ing code not satisfy its type predicate? (Particularly, a SQL statement from the sql package)

2019-01-31 Thread hashim muqtadir
> If order to use a struct across namespaces, the module that 
> defines the struct must be required into each namespace that uses the 
> struct. 

Yes, I suspect there's some weird interaction between namespaces too, hence 
the topic, but that's still pretty vague. After all, the thing defining the 
structs is the sql package, and my modules/namespaces are importing that.

> Eval almost always is the wrong answer.

I wanted to pass a list to select, but select is a macro, and I didn't get 
how to define a macro on top of that to do what I wanted, since the macro 
doesn't know that one of the things being passed into it evaluates to a 
list, so it can't splice that list into select, hence, eval.

> And thanks, Ryan, for racket-izing SQL! Maybe I can stop stapling 
together all of those long horrible strings now. 

Yes, I was quite pleasantly surprised at how comprehensive this library is! 
I was thinking "surely it wouldn't support arrays as they're not standard" 
but nope, they're covered too :)

> I recommend that you take a look at section 3.7 of the documentation, 
"Dynamic Statement Composition and SQL Injection”, which I believe does 
exactly what you want. Specifically, you want to dynamically construct a 
select statement. 

I did look at that. And up until yesterday I thought "this isn't helping, I 
need to inject multiple select-expr's!".

And today, I had a look again and thought, hey, what if I use a string that 
has a comma in it, and, hey, that works!

i.e. the following works:

#lang racket
(require sql)
(select (ScalarExpr:INJECT (unquote "mew, two")) #:from pokemon)

It gives me `(sql-statement "SELECT mew, two FROM pokemon")`

So now I know all I have to do is comma-join my list to form a string, and 
inject that.

What I do _not_ know if that's how INJECT was meant to be used, or whether 
I should build a separate inject macro that uses unquote-splice instead 
that comma-joins the list and does some form of escaping on the columns. My 
first guess is that properly verifying the items in the list to be single 
expressions is pretty difficult, so it sounds like a bad idea, and since 
one select-expr is allowed to yield multiple columns (because the "db" 
library that will actually get the results doesn't need any info from the 
query, I think), my approach should be fine.

As an aside, I really like python's sqlalchemy library. It makes composing 
sql really easy. But I think sqlalchemy would complain if a single 
expression yielded multiple results on the wire. Is that coupling between 
query and result a good thing or bad? It seems to have its pros and cons, 
but right now I'm depending on the lack of coupling, so that's cool on 
"sql"'s part. But anyway in sqlalchemy it's just all functions. In this 
one, it's all macros, and I'm a bit slow with Racket, trying to compose 
macros trips me up a bit.

So I guess my goal's reachable (I should now be able to insert a list of 
columns into a select using a function, without needing eval or 
namespaces). Thanks, all, for the input.

I do wish to find out how to get around the predicate thing and why it's 
throwing an error, in case anyone knows.

PS There's also a racket package called plisqin which seemed closer to what 
I was looking for. Maybe in a few months or so if it clicks I'll see if I 
can add to that package everything I need (things like limit and distinct) 
and it might work out.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Why would a value produced by eval-ing code not satisfy its type predicate? (Particularly, a SQL statement from the sql package)

2019-01-31 Thread George Neuner


On 1/31/2019 10:58 AM, hashim muqtadir wrote:


The test in my following code raises an error saying that when I call 
select/f, the result doesn't satisfy `sql-statement?`.


I've no idea why, the only vague idea I have is that it may have 
something to do with the fact that it was essentially eval'd in a 
separate namespace.


Any ideas?

    #lang racket

    (require db)

    (define sql-namespace (make-base-empty-namespace))
    (parameterize ([current-namespace sql-namespace])
  (namespace-require 'sql sql-namespace))

    (struct Select-spec
  (tbl  ;; symbol
   col-exprs  ;; listof symbols
   limit  ;; number
   order-by)) ;; listof select symbols

    (define (select/f sel-spec)
  (eval
   `(select ,@(Select-spec-col-exprs sel-spec)
    #:from ,(Select-spec-tbl sel-spec)
    ,@(let ([lim (Select-spec-limit sel-spec)]
    [order (Select-spec-order-by sel-spec)])
    (if lim
    `(#:limit ,lim #:order-by ,@order)
    '(
   sql-namespace))

    (module+ test
  (require sql)
  (require rackunit)
  (check-equal?
   (sql-statement->string
    (select/f
  (Select-spec
   'd
   '(a b c)
   10
   '(a b
   (sql-statement->string
    (select a b c
    #:from d #:order-by a b #:limit 10

    (provide select/f
 Select-spec)


My main reason for doing this was that the statement-producing macros 
provided by the sql package were, well, macros, so I couldn't pass in 
a list of columns and get a statement. What I want to do is have a 
struct like the one I made in this snippet, and use functions to 
include/exclude columns, before finally passing it off to a function 
that produces the statement.


I agree with John that you probably should not be using eval here. Eval 
almost always is the wrong answer.


But as to why your code is not working: there is a problem with structs 
and namespaces - I don't recall the technical specifics, but the gist is 
that simply copying a struct into a different namespace doesn't work - 
it results in a new, auto-created struct type - which isn't what you 
want.  If order to use a struct across namespaces, the module that 
defines the struct must be required into each namespace that uses the 
struct.


George

--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Why would a value produced by eval-ing code not satisfy its type predicate? (Particularly, a SQL statement from the sql package)

2019-01-31 Thread 'John Clements' via Racket Users
First off, many thanks for bringing to my attention the fact that Ryan has 
started racket-izing SQL! And thanks, Ryan, for racket-izing SQL! Maybe I can 
stop stapling together all of those long horrible strings now.

Next, to answer your question, I believe that eval is not necessary here, and 
is in fact the wrong approach.

I recommend that you take a look at section 3.7 of the documentation, "Dynamic 
Statement Composition and SQL Injection”, which I believe does exactly what you 
want. Specifically, you want to dynamically construct a select statement.

Also… I admit that I’m not *totally* sure that you get exactly the primitives 
you need, here. This might be a feature request.

John


> On Jan 31, 2019, at 7:58 AM, hashim muqtadir  
> wrote:
> 
> Hello,
> 
> The test in my following code raises an error saying that when I call 
> select/f, the result doesn't satisfy `sql-statement?`.
> 
> I've no idea why, the only vague idea I have is that it may have something to 
> do with the fact that it was essentially eval'd in a separate namespace.
> 
> Any ideas?
> 
> #lang racket
> 
> (require db)
> 
> (define sql-namespace (make-base-empty-namespace))
> (parameterize ([current-namespace sql-namespace])
>   (namespace-require 'sql sql-namespace))
> 
> (struct Select-spec
>   (tbl  ;; symbol
>col-exprs  ;; listof symbols
>limit  ;; number
>order-by)) ;; listof select symbols
> 
> (define (select/f sel-spec)
>   (eval
>`(select ,@(Select-spec-col-exprs sel-spec)
> #:from ,(Select-spec-tbl sel-spec)
> ,@(let ([lim (Select-spec-limit sel-spec)]
> [order (Select-spec-order-by sel-spec)])
> (if lim
> `(#:limit ,lim #:order-by ,@order)
> '(
>sql-namespace))
> 
> (module+ test
>   (require sql)
>   (require rackunit)
>   (check-equal?
>(sql-statement->string
> (select/f
>   (Select-spec
>'d
>'(a b c)
>10
>'(a b
>(sql-statement->string
> (select a b c
> #:from d #:order-by a b #:limit 10
> 
> (provide select/f
>  Select-spec)
> 
> 
> My main reason for doing this was that the statement-producing macros 
> provided by the sql package were, well, macros, so I couldn't pass in a list 
> of columns and get a statement. What I want to do is have a struct like the 
> one I made in this snippet, and use functions to include/exclude columns, 
> before finally passing it off to a function that produces the statement.
> 
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to racket-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.



-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[racket-users] Why would a value produced by eval-ing code not satisfy its type predicate? (Particularly, a SQL statement from the sql package)

2019-01-31 Thread hashim muqtadir
Hello,

The test in my following code raises an error saying that when I call 
select/f, the result doesn't satisfy `sql-statement?`.

I've no idea why, the only vague idea I have is that it may have something 
to do with the fact that it was essentially eval'd in a separate namespace.

Any ideas?

#lang racket

(require db)

(define sql-namespace (make-base-empty-namespace))
(parameterize ([current-namespace sql-namespace])
  (namespace-require 'sql sql-namespace))

(struct Select-spec
  (tbl  ;; symbol
   col-exprs  ;; listof symbols
   limit  ;; number
   order-by)) ;; listof select symbols

(define (select/f sel-spec)
  (eval
   `(select ,@(Select-spec-col-exprs sel-spec)
#:from ,(Select-spec-tbl sel-spec)
,@(let ([lim (Select-spec-limit sel-spec)]
[order (Select-spec-order-by sel-spec)])
(if lim
`(#:limit ,lim #:order-by ,@order)
'(
   sql-namespace))

(module+ test
  (require sql)
  (require rackunit)
  (check-equal?
   (sql-statement->string
(select/f
  (Select-spec
   'd
   '(a b c)
   10
   '(a b
   (sql-statement->string
(select a b c
#:from d #:order-by a b #:limit 10

(provide select/f
 Select-spec)


My main reason for doing this was that the statement-producing macros 
provided by the sql package were, well, macros, so I couldn't pass in a 
list of columns and get a statement. What I want to do is have a struct 
like the one I made in this snippet, and use functions to include/exclude 
columns, before finally passing it off to a function that produces the 
statement.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.