
Show HN: Godb is a simple Go ORM for PostgreSQL, MySQL, SQLite and SQL Server - samonzeweb
https://github.com/samonzeweb/godb
======
masklinn
That's more of a query builder than an ORM: it doesn't actually use objects
and only allows for expressing SQL queries in Go.

In that it is similar to LINQ or HQL or SQLAlchemy Core — at an even lower
level really since things like conditions are provided as parameterised
strings.

~~~
samonzeweb
I agree, it’s a simple tool. As mentioned in the README, it’s not a full-
featured ORM, but it does more than building queries as it maps Go structs
with databases content (on this point I disagree as it use objects).

The purpose is to be more productive than doing all this job manually.

Many things can be improved, it's sill a young project. This project is
initially a learning one : doing stuff to improve my skill, on my spare time.
I tried to build something clean, and used it on some real data. Perhaps it
could be useful for somebody else. Nothing more ;)

~~~
masklinn
> on this point I disagree as it use objects

That's a technicality, it just loads query data into objects which is what
more or less every query builder does, the objects aren't involved in any of
the logic. By the benchmark you use psycopg is an ORM (it really isn't, it
isn't even a query builder).

Don't misunderstand, I'm not saying a query builder is bad, I'm just saying
this is not an ORM, and shouldn't be sold as such: it's going to disappoint
people looking for ORMs like Django's or Rails's and it's going to turn off
people who object to ORMs[0] but would have been interested in a query
builder.

Not to mention a good query builder is an excellent basis for a full-fledged
ORM.

[0] and there are many people who think ORMs are a terrible idea

~~~
Hannan
>> [0] and there are many people who think ORMs are a terrible idea

Do you have any links perchance? Because I can't shake the feeling that I'm a
pariah among the developer community for thinking this way.

~~~
sarabob
[https://blog.codinghorror.com/object-relational-mapping-
is-t...](https://blog.codinghorror.com/object-relational-mapping-is-the-
vietnam-of-computer-science/) for example :-)

~~~
Hannan
Excellent, thank you!

------
peterkieltyka
Also, for others looking for a Go data layer / ORM`ish package, have a look at
[https://github.com/upper/db](https://github.com/upper/db)

it's been in development for years, its used in production by many companies,
and theres been a lot of work to keep it lean and powerful through lots of
iteration.

~~~
chisleu
Also [https://github.com/jinzhu/gorm](https://github.com/jinzhu/gorm) and
[https://goa.design/](https://goa.design/)

~~~
0xCMP
I've had issues with gorm. I find it has quirks that bother enough for me to
move away from it. I have yet to find something I'll like more than just pure
sql.

Goa is just for generating apis. Not for databases?

------
aarondl0
I'm the author of a code-generation ORM in Go (real orm, does relationships
fairly robustly)
[https://github.com/vattle/sqlboiler](https://github.com/vattle/sqlboiler) and
I'm curious why you needed to make another one despite something like this
existing? Granted we don't support sqlite/mssql yet, but surely a PR to
support it is easier than writing your own :(

~~~
samonzeweb
The projet started as a learning one. I made some independent and experimental
component from time to time, and then glued them together, rewriting some
parts, ...

Why this kind of project ? Because I used Active Record (Rails), Entity
Framework, played with Django ORM, ... and regretted that nothing similar
exist in Go world. Instead of complaining I choose to do something, not
building a full ORM by myself, but at least build something allowing me to
have a better comprehension of the constraints (except of the classic "no
generic").

I didn't choose to build another Go library thinking I'll build something
better than others. I learned, and I got a library ;)

~~~
aarondl0
Well, now that you're done learning I hope you'll become an sqlboiler user and
maybe contribute to it to fit your use case too. Fragmentation in the sql
world in Go is pretty bad right now, hence my reaction to seeing your lib,
sorry for that :)

~~~
assafmo
Why do you think "Fragmentation" is bad?

~~~
aarondl0
I want to see the Go community and it's libraries flourish. But having
libraries like this around which provide extra confusing and probably poorly
maintained choices for users is detrimental to it's overall health. There's
already great examples of maintenance rot found even amongst the very popular
libraries like go-yaml and httprouter.

One thing you can say about Go is it has 1000 Micro-frameworks, ORMs, Routers,
and Logging libraries. Most of them are within a percent of giving the exact
same feature set with the exact same approach and and ever so slightly
different API. Lots of them share the same mistakes as they are a user's first
project or a learning arena (though routing has been a pretty benchmarked area
so that's been better than the others).

As someone who has open source libraries, and who uses Go in their day job and
at home my personal opinion is that Go needs fewer, stronger libraries. Well
supported, well maintained pieces rather than this illusion of choice that's
presented today. I'm sorry if I came off as crass in my reply to the OP but
that's simply the state I see in the community today.

Ideally there'd be 2-4 ORMs in Go that would be the goto. And half would use a
code-generation approach, half would use the reflection based approach.

[https://github.com/astaxie/beego/tree/master/orm](https://github.com/astaxie/beego/tree/master/orm)
[https://github.com/cosiner/gomodel](https://github.com/cosiner/gomodel)
[https://github.com/jinzhu/gorm](https://github.com/jinzhu/gorm)
[https://github.com/go-gorp/gorp](https://github.com/go-gorp/gorp)
[https://github.com/coocood/qbs](https://github.com/coocood/qbs)
[https://github.com/go-reform/reform](https://github.com/go-reform/reform)
[https://github.com/vattle/sqlboiler](https://github.com/vattle/sqlboiler)
[https://github.com/upper/db](https://github.com/upper/db)
[https://github.com/astaxie/beedb](https://github.com/astaxie/beedb)
[https://github.com/naoina/genmai](https://github.com/naoina/genmai)
[https://github.com/monochromegane/argen](https://github.com/monochromegane/argen)
[https://github.com/square/squalor](https://github.com/square/squalor)
[https://github.com/theduke/go-dukedb](https://github.com/theduke/go-dukedb)
[https://github.com/dropbox/godropbox/tree/master/database/sq...](https://github.com/dropbox/godropbox/tree/master/database/sqlbuilder)
(...and more) And now:
[https://github.com/samonzeweb/godb](https://github.com/samonzeweb/godb)

Do we truly need this? This one in particular feels a lot like upperdb. And if
it's for learning only, don't publish it to things like hackers news which
makes people seem like it's something you should use as opposed to the more
mature libraries out there. This is what I meant by fragmentation, it's an
illusion of choice. There are actually very few logging/routing/orm/micro-
framework libraries you should really use if you're serious about a project.

~~~
jasonwatkinspdx
Kindly: you are not the gatekeeper of other's efforts, contributions, and
submissions. Saying "you shouldn't have written this, open sourced it, or
submitted it to hnews because I think my library is much better" is obnoxious
behavior that I think is far more damaging to a community than fragmentation.
People will consolidate choice of libraries with time. We shouldn't be
shutting down new contributions reflexively, and it's much more distasteful
when it's because you're advocating for your alternative.

~~~
aarondl0
An incredibly rude post in reply to something I think is reasonable. My
opinion is as I stated, NOT as you very loosely interpreted thank you very
much. I don't think of myself of a gatekeeper of others, just my own things.

I have a very high bar for open source personally and I tend to view it "more
hardcore". I think that if you're putting open source out there to a wide
audience such as this that you have a contract with the people you're putting
it out to that you're going to maintain what's there and ensure it's of high
quality. And if you're going to go to that level of effort why not contribute
to something that's already mountains of work ahead of you and effectively the
same code anyway (upperdb/gorp/gorm/xorm in this case)?

I have many Go repositories on my Github account that I've used for learning -
but I've never put any of them out there to wide audiences that were solved by
a more popular project in the same way - the approach has always been
radically different. When I couldn't find logging libraries I liked I tried
using others and contributed to them. I've also never put anything out there
that I don't intend on maintaining basically forever. So my behavior is
consistent with my viewpoint for whatever that's worth.

My colleague suggests that other people use open source for different reasons
and view it much differently than me, and that's possibly the misunderstanding
here. I shouldn't try to reflect my opinion in that sense on others and I do
apologize for that. I suppose "if it were me" I wouldn't have done what he
has, and I was commenting as if people knew and understood that as a
commonality - which isn't probably true.

Also - I think you hugely overstated my bias for my own library. I'd be just
as happy if he had not posted this and worked on gorp instead. /shrug.

Also I've been waiting for a long time for Go's libraries to be converged on -
hasn't happened yet :)

~~~
jasonwatkinspdx
I don't believe I was rude but I'm happy to apologize if others concur.

~~~
mentat
No, you're right on. If others want to work on something, that's up to them.
Tell them they're doing it wrong is toxic.

------
mdasen
One of the features listed is "Mapping with nested structs", but there's no
example of this. Given that this would be a feature setting your project apart
from many of the Go "ORMs" out there, it would be nice to have an example.

Maybe something with two tables: an "authors" table and a "books" table. Then
an example of getting authors each struct of which has a `[]Book` of books.

~~~
samonzeweb
Nested structs are shown in the documentation :
[https://godoc.org/github.com/samonzeweb/godb#hdr-
Structs_map...](https://godoc.org/github.com/samonzeweb/godb#hdr-
Structs_mapping)

It's composition tool, not a relational one. Sorry.

~~~
chrisan
> It's composition tool, not a relational one. Sorry.

Isn't the R in ORM for relational?

~~~
samonzeweb
> > It's composition tool, not a relational one. Sorry.

> Isn't the R in ORM for relational?

I spoke about the nested structs. You can have nested structs for something
else than relational mapping.

As I replied to masklinn , I was not sure how to qualify godb, and I admit
that ORM is not a perfect qualifier.

~~~
camus2
Your library is a query builder, not an ORM.

------
samonzeweb
As it was stated, godb isn't really an ORM. The README and documentation was
updated.

Now godb is just "a Go query builder and struct mapper".

Thanks for all comments :)

------
sdfjkl
Took me a moment to parse the name correctly. Perhaps GoDB would've been a
better choice, although I assume naming conventions prevented that and so the
second letter of the alphabet was declared a deity instead.

~~~
ademarre
Coincidentally, something called "GodBolt" [0] is on the front page at the
same time. At first glance I almost thought they were related posts.

[0]
[https://news.ycombinator.com/item?id=13182726](https://news.ycombinator.com/item?id=13182726)

------
the_duke
The annoying thing about ORMs in Go is that since there are no macros /
annotations you either have to use code generation or reflection.

Reflection is a real drag on performance.

~~~
aleksi
But code generation doesn't have to be painful. Consider
[https://gopkg.in/reform.v1](https://gopkg.in/reform.v1), for example. It
generates methods for your data types and uses then to cover 80% of typical
usage and also does help you when you want to use SQL.

(disclosure: I'm the author)

~~~
camus2
Code generation is always painful. It's yet another compiler add-on one has to
add to a pipeline. Because now If I use your executable I have to manage your
tool and its versions,it becomes yet another dependency. At least real/reified
macros (that go lacks) need no third party executable . Code generation with
third party tools means language fragmentation. Suddenly people add their own
DSL on top of Go in form of a manifest. Suddenly Go executes instructions in
comments and other horrors ...

~~~
cyri
Yes that sucks. So I have written / am writing my own code generation tool
which runs only once and does not rely on any fancy instructions in comments.
Ah yes ... maybe `go generate`. I hate a slow compiler.

------
xupybd
I've not really understood the gain you get out of using ORMs or query
builders. Doesn't it just add a learning curve to a problem already solved by
SQL?

I know these are meant to decouple you from the db implementation, but don't
most projects of sufficient complexity end up getting tied to one db anyway?

~~~
zubi
I, as an author of such library, am a bit biased but still...

For one, you may get massive, massive developer productivity by eliminating
loads of queries. In a lot of ORMs you do things like myObject.save() instead
of generating a insert/update query for the particular state of myObject
without taking into consideration which fields of the object is currently set.
This reason alone enough for me to use them.

Second, bunch of additional functionality usually come out of the box with
ORMs, such as JSON or arbitrary (de)serialization of columns, caching, logging
etc which you would have to spend time on custom implementations of these
otherwise.

Third, like you mentioned, some allow very easy change of database vendor.

Fourth, mental abstraction from the underlying data storage (you stay in your
language's domain) which again contributes to the productivity.

Some other benefits include not seeing large SQL strings in your code which
make it more difficult to read and maintain, security and ability to easily
reason about what the code intends to do.

I don't want to sound arrogant (not my intention at all) but I believe those
who don't understand or downright rejects the benefits of a decent ORM system
are either the ones that never used one to see the productivity benefit or
those who work on projects that need to squeeze the last bit of optimization.
In a large enough project it is seriously pain and time consuming writing all
those queries which could be elegantly avoided.

------
tkyjonathan
How hard is it to just learn SQL?

~~~
chongli
Answer: not very! I don't know why people have such an aversion to it. SQL is
a powerful, flexible, fun, and highly rewarding language to learn!

The only substitute I'd accept is a quasiquoter that checked my SQL syntax for
me at compile time.

~~~
jerf
Powerful sorta, fun debateably, highly rewarding probably, flexible,
absolutely not. By far one of the biggest reasons to use something other than
raw SQL is because of SQL's near total lack of composability. Show me a valid
SQL fragment that represents "the 'permission' field of the given table is set
to true OR the joined-in user has the superuser flag", where the join is
represented in the fragment itself such that any query I apply it to will have
the requisite join added in if necessary. Then show me a fragment that
represents "this email and all of its attachments". Then show me how to
compose those fragments into a full query. You can't; if you're using raw SQL
you have to manually interleave those things into every query you want to use
them in. SQL basically _mandates_ copy and paste as the only abstraction
available, and it isn't even all that great at that since there's no such
thing as scopes within a query making it easy for your copy & pasted fragments
to stomp on each other's names.

Some of the additional query languages might be able to do it (they could
certainly do chunks of what I said), but they'd still be pretty klunky about
it since they bodge it on the side, and still don't compose anywhere near as
well as they could or should.

Mind you, I'm not sure this library can do it either; SQL is also quite
difficult to wrap around because of its structural deficiencies. Trying to
hack away foundational issues at higher levels is always messy, error-prone,
and still filled with the quirks that shine through.

~~~
pg314
You can use VIEWs [1] as an abstraction mechanism. It's not perfect, but it
can abstract certain things away. I think it would work for your first
example.

Something like:

    
    
      CREATE VIEW permitted_X AS
      SELECT X.*
      FROM X, user
      WHERE X.user_id = user.user_id
            AND (X.permission OR user.is_super);
    

You second example doesn't have enough info for me to see if it can be
accomplished by a VIEW.

Other abstraction mechanisms are user-defined functions.

[1] [https://www.postgresql.org/docs/current/static/sql-
createvie...](https://www.postgresql.org/docs/current/static/sql-
createview.html)

~~~
jerf
With your view I still think I can't _pass a table in_ ; your X is not a
variable. That's my point. There's a lot of power in SQL and its associated
technologies, _but_ there's also a _loooooot_ of places where in a modern
system we'd have a variable or some other composition mechanism, but there's
no first-class existence of that mechanism in SQL. For instance, in systems
programming languages, "first-class functions" have won so thoroughly that
it's hardly even a "feature" anymore, it's just part of the baseline for any
new language, or it better have a _darned_ good reason they aren't present.
SQL has not even remotely had that revolution.

Some of these things are fixed up by the product-specific languages, but only
some of these things.

Here's another example; using your product-specific language, can you create a
table for me with a variable number and types of columns based on the
parameters passed in? I don't know them all, but I bet it's hard in most or
all of them. No credit if your product-specific language lets you bash a
string together and then somehow execute it; I'm calling for everything to be
done via first-class mechanisms. (Also, I'm not asking for whether this is a
good idea; it is obviously a tricky thing of dubious use. But that should be a
software engineering determination, not a language restriction.)

~~~
tkyjonathan
If you want the table as a variable, you would need to use a prepared
statement:

PREPARE stmt1 FROM 'SELECT X.* FROM ? X, user WHERE X.user_id = user.user_id
AND (X.permission OR user.is_super)';

EXECUTE stmt1 USING 'yourtable';

------
VexorLoophole
As someone who is writing in go for some time (still deciding if i should
learn something like C or JVM-based to get better at understanding big
programms), i also want to get into Databases (never really learned to code.
Everything is self tought). Do i need to approach a not-language specific way
to really learn the SQL concept, and if yes, where do i start? In Chatroom i
always read super complex stuff about databases and meanwhile i was never able
to handle a SQL Database right, because i wasnt able to wrap my head around
the documentation, and used something simple like bolt (in go) for my db
needs.

~~~
sethammons
I would recommend getting familiar with using your db from the command line.
If you are in MySQL or Postgres, learn the basics. selects, inserts, updates,
deletes, and joins. After you have a bead on those, get used to subqueries.
Learn what denormalization is (might want to do that so you can play with
joins). Learn what transactions are. At this point, you are probably better
than most. After that, start digging into deeper parts by going through public
docs and seeing what neat functions they provide.

After you know the above, you can use that SQL knowledge in any language you
want when accessing the db. No need to learn a new ORM per language or
anything.

Also, at this point, you are likely to start understanding more about scaling
systems which involve intelligently choosing indexes, replication, and
sharding. Now you are on your way to Jr. DBA status :)

That was my path at least. There are likely better ways.

------
jcoffland
ORMs are almost always a bad idea. They add an unnecessary layer of complexity
which will result in both speed and space inefficiencies. If your project is
small just use SQL, it will be easier. If your project is large you will end
up writing a lot of customized SQL anyway, so just use SQL. If your project is
in the middle, will never become large, you won't have to support it later and
you already know the ORM tool then you may benefit from ORM.

~~~
sirclueless
If your project cares at all about security you should at least be using some
form of query builder. The bare minimum is a system that binds parameters of a
query to user data without manual escaping.

From there the distinction between ORMs and query builders gets fuzzy, it's
more of a spectrum than a bright line. I particularly like SQLAlchemy's model
of a core SQL-building library with an ORM you can use piecemeal around it.

~~~
jcoffland
Probably every modern SQL API supports safe query construction with out a
third-party query builder. Building queries with simple string concatination
is a bad idea but that's not a justification for the complexity of ORM.

------
mci
I cannot see how to build nested SELECTs with Godb.

~~~
samonzeweb
It's not really implemented yet.

You can build nested queries, doing some extra work, but it's not elegant and
will not work for any cases (especially with PostgreSQL) :
[https://gist.github.com/samonzeweb/b1ae3e2d1f3203ee1722ac4bd...](https://gist.github.com/samonzeweb/b1ae3e2d1f3203ee1722ac4bd2cb95e9)

Some work to do to add proper nested queries into godb, but for a so simple
example it doesn't seem to be extremely hard.

------
knz42
Do you plan to make it work with CockroachDB?

~~~
0xCMP
I think that's more up to CockroachDB. They offer a postgres compatible
interface so this _should be_ usable with CockroachDB already.

------
LukeB42
Is there anything like this or sqlx but in C?

------
wangii
Isn't CQRS the future?

