8 ms·
From the article: > I’ve largely covered sqlc’s objective benefits and features, but more subjectively, it just feels good and fast to work with. Like Go itsel
by fprog 5y ago
From the article:
> I’ve largely covered sqlc’s objective benefits and features, but more subjectively, it just feels good and fast to work with. Like Go itself, the tool’s working for you instead of against you, and giving you an easy way to get work done without wrestling with the computer all day.
I've been meaning to write a blog post about sqlc myself, and when I get to it, I'll probably quote this line. sqlc is that rare tool that just "feels right". I think that feeling comes from a combination of things. It's fast. It uses an idiomatic Go approach (code generation, instead of e.g. reflection) to solve the problem at hand, so it feels at home in the Go ecosystem. As noted in the article, it allows you to check that your SQL is valid at compile-time, saving you from discovering errors at runtime, and eliminating the need for certain types of tests.
But perhaps most of all, sqlc lets you just write SQL. After using sqlc, using a more conventional ORM almost seemed like a crazy proposition. Why would someone author an ORM, painstakingly creating Go functions that just map to existing SQL features? Such a project is practically destined to be perpetually incomplete, and if one day it is no longer maintained, migration will be painful. And why add to your code a dependency on such a project, when you could use a tool like sqlc that is so drastically lighter, and brings nearly all the benefits?
sqlc embraces the idea that the right tool for talking to a relational database is the one we've had all along, the one which every engineer already knows: SQL. I look forward to using it in more projects.
- donio 5y agoA few years ago I had spent a year working with a Go project that made heavy use of one of the (then) popular Go ORMs. Learned my lesson, never again. Magic=Bad.
- noisem4ker 5y agoWhat ORM was that?
- Cthulhu_ 5y agoLikely Gorm, I'm using that at the moment and it's eeehhhh.
- noisem4ker 5y agoThat would've been GORM v1, then. Nowadays we're at v2. It's no Hibernate, but it has been solid in my experience.
- pstuart 5y agoHopefully they'll get SQLite working on it soon and I'll be all over it.
- LVB 5y agoI'm certainly eager to see official SQLite support as well. In the mean time, the overlap between postgres and SQLite syntax is enough that a lot of my "postgres" definitions in sqlc work just fine in SQLite. The recent addition of "RETURNING" (https://www.sqlite.org/lang_returning.html https://www.sqlite.org/lang_returning.html) to SQLite was a big help since that was a standard part of sql used for postgres with sqlc if you wanted the last insert ID.
- bitwize 5y ago> Why would someone author an ORM, painstakingly creating Go functions that just map to existing SQL features? The answer to this question lies in the assumption you make in this statement: > the one which every engineer already knows: SQL. Not every engineer knows, or wants to learn, SQL. I've met very competent engineers, SMEs over their particular system, who were flummoxed by SQL. And many more just want to work in their preferred language. I don't like ORMs either but, like, half the reason why they exist is so the programmer can talk to the RDBMS in Java, JavaScript, etc. and not touch SQL.
- shriek 5y ago> Not every engineer knows, or wants to learn, SQL. Which is bizarre cause you pretty much need some form of RDBs in most of the apps. And because of ANSI SQL, the syntax/concepts are relatively same on different databases too. No point in not making this investment.
- scrubs 5y agoAgree. This is the weird kid down the street who gets by on manyioise and saltines. To engage persistent storage is to engage sql for the first 75% of all work. Hey you gotta have some competence in the domain of work. I like Jordache (orm) but not Calvin Klein (sql) isn't wisdom; it's merely personal predilection.
- Fire-Dragon-DoL 5y agoIf you are using an ORM and need to write a query that will run on a SQL server you *need SQL knowledge and ORM knowledge*. If you are missing one the two, you probably have just wrote something with big performance penalties. This has been seen over and over in the Rails community.
- mohanmcgeek 5y agoExactly my experience too. The amount of SQL hatred from rails learning resources is unjustifiable. If you're dealing with a relational database with SQL as its primary interface, you'll end up learning SQL eventually because all abstractions leak!
- Sytten 5y agoWorking with SQL in X (any language) usually has a poor developer experience that is why ORM or query builders are popular. Things like proper syntax highlight or type safety (I remain to be convinced that sqlc can really check the validity at compile, usually it only works in specific basic cases). You just have to choose wisely your tools for sure, but most of the code you write needs to be rewritten anyway every X years.
- EB66 5y ago> Working with SQL in X (any language) usually has a poor developer experience that is why ORM or query builders are popular. At least when it comes to Postgres, I don't understand why more developers don't create their own user-defined functions with PL/pgSQL. It's very a robust and powerful procedural language. In my opinion, ORM's like SQLAlchemy add a completely unnecessary layer of abstraction. ORMs might be convenient for quick/simple queries, but when you're creating or troubleshooting a moderately complex query, it's far better to do it with native SQL than it is with a chained mess of ORM methods. At my company, we employ UDFs for every SQL query we make and every UDF returns a declared type. The end result is far easier to debug and maintain when compared with the ad hoc ORM query alternatives. Plus it has the side benefit of separating out application code from database code which allows our DBAs to more effectively code review SQL code written by developers. > You just have to choose wisely your tools for sure, but most of the code you write needs to be rewritten anyway every X years. Not if you stick with plain SQL and/or Pl/pgSQL :-)
- harikb 5y agoTwo problems 1. How do you handle versioning? Like if you want to try a development branch on a non-branch/shared db. Creating different version of stored procedures creates a recursive problem. A calls B, now A’ has to call B’ 2. Sometimes we still need to programmatically decide to include a table in the join or not or get creative on a filter. Pl/pgsql is less flexible in this regard. You get the benefit of syntax checking only when query is verbatim and not dynamically constructed.
- 5y ago
- bpodgursky 5y agoI get this, but personally I love using jOOQ because of how composable and dynamic query building is with a good query builder pattern. Adding optional filters, joins etc doesn't turn into a string-concatenation abomination; it's something. can do in native readable Java (and then translating back to generated Java objects is also great compared the alternative of unpacking some generic result set, casting to the right type, etc)
- arwineap 5y agosqlc definitely uses reflection But don't let that stop you, it looks like a nice solution and reflection isn't really all that bad anyway :)
- benhoyt 5y agoAre you sure? Well, it uses "reflection" in a general sense of introspecting your SQL code, but not in the Go sense of using using type information at runtime via the "reflect" package. sqlc compiles your SQL at build time to statically typed, non-reflect-using functions, as shown here: https://docs.sqlc.dev/en/stable/howto/select.html https://docs.sqlc.dev/en/stable/howto/select.html
- earthboundkid 5y agoTechnically, reflection is used by Go’s database Scanner interface, but it’s not what most people think of when they complain about reflection.
- benhoyt 5y agoGood point. I had assumed Rows.Scan() would have just used type switches for efficiency -- it looks like it does for common cases (https://github.com/golang/go/blob/d62866ef793872779c9011161e51b9c805fcb73d/src/database/sql/convert.go#L220 https://github.com/golang/go/blob/d62866ef793872779c9011161e...) but then falls back to reflect. I wonder why it doesn't just do all of that with type switches? Maybe there are just too many cases and it ends up slower than reflect for the rest of the cases. Scanner.Scan() is actually just called via a type assertion, though I guess implementations of Scan() might use reflection.
- arwineap 5y agoIt needs reflect in order to translate struct field names into column names at the very least
- benhoyt 5y ago
- throwdbaaway 5y agoNah, I love SQL, but if I have to choose between SQL and ORM, I will go with ... something in between, like the core layer of SQLAlchemy. Just take a look at that monstrosity of an UPDATE statement in the article. In my first job, I had to do something similar in SQL, but with a SELECT statement to allow users to search dynamically using any combination of the columns. I picked up SQLAlchemy in my second job, and have never looked back.
- deleted 5y ago[deleted]
- stubish 5y agoI've used similar tools (which I'm not going to recommend, as they have not aged well), and found it great to be able to rely on the compiler for checks. With ORMs or SQL I realized I would be better off working in Python, as without the compile time checks I got none of the benefits of Go and all the down sides. I haven't used sqlc, but do like that you just feed it queries. Other tools rely on using a templating language to generate the Go code from database schema introspection, and it is just awful to work with. Generics should do away with needing the templates, so maybe the database schema introspection approach will improve.
- otabdeveloper4 5y ago> code generation, instead of e.g. reflection "Hey man, we noticed there's not enough compiler in your compiler, so we made a second compiler for your compiler."
- JulianMorrison 5y ago"Your compiler compiles A, but you also want to compile B, so we added an extra compiler to help you compile it"
- Cthulhu_ 5y agoMakes sense, Go can't compile SQL and vice versa.
- y4mi 5y agoThe one thing that kept annoying me with compilation type orms like this is the chicken and egg situation. Your migrations will likely be run by your application, but your application won't compile until you've run your migrations.
- xorcist 5y agoIt does indeed look promising! Can it help with migrations? Seeing it has the field definitions right there it should at least be possible. Otherwise I can see how a system like this could become quite complex over time as the database structure changes.
- Cthulhu_ 5y agoBased on just this article, it looks like it needs a complete table definition to work with. Unless it queries the database for the definitive schema, but that would mean you need a database up and running at compile time.
- xorcist 5y agoI took for granted that sqlc could run all these CREATE TABLEs for you, perhaps that's not the case. It probably should, shouldn't it?