Re: Introducing Norm: a Nim ORM

2020-03-12 Thread moigagoo
I'm proud to announce the first release of **Norman** , the migration manager 
for Norm: 
[https://moigagoo.github.io/norman/norman.html](https://moigagoo.github.io/norman/norman.html)

With Norman, you can keep your DB config separate from the models in a project 
config and generate, apply and undo migrations.

There are no tests at the moment, but they're on the way. Feel free to add 
Norman to your existing projects that use Norm, it should improve your 
developer experience.


Re: Introducing Norm: a Nim ORM

2020-02-02 Thread Dankrad
I've always searched for ORM's in Nim they are likely sequelize in nodejs (used 
sequelize years ago). Your project comes closest to sequelize, I like your 
approach. Nice work!


Re: Introducing Norm: a Nim ORM

2020-02-01 Thread JPLRouge
'''You mean connection pool? There's an open issue for it, but I'm not planning 
on taking on it any time soon. I plan to focus on the migration manager for 
Norm.''' yes


Re: Introducing Norm: a Nim ORM

2020-01-31 Thread moigagoo
> Did you think, open several connections > so if yes you can have a 
> transactional connection and a logical connection only for reading ...

You can connect to several DBs with [withDb and 
withCustomDb](https://moigagoo.github.io/norm/norm.html#reference-guide-connection),
 which allows you to use one connection for reading and another for writing.

> Did you think, open several connections

You mean connection pool? There's an [open 
issue](https://github.com/moigagoo/norm/issues/50) for it, but I'm not planning 
on taking on it any time soon. I plan to focus on the migration manager for 
Norm.


Re: Introducing Norm: a Nim ORM

2020-01-30 Thread JPLRouge
Bonjour, Hello

887/5000

I am passionate about DB ...
Did you think, open several connections

so if yes you can have a transactional connection and a logical connection only 
for reading ...

I work this way it allows me a lot of flexibility.

I worked on a wrapper (which works in C ++) based on Postgresql libpq.

I also did one with ECPG ... History of making a lib for each table containing 
access allowing to make the management a very functional test and a correct 
speed, this table in lib ... finally it was the materialization of fields and 
functional records identical to the AS400 DB2

I had thought of translating everything into nim, I stumbled on ECPG which 
demands absolutely "c" then converted to its sauce ... So I did not find it 
very nice for someone who uses nim 

Bon voyage in your adventure


Re: Introducing Norm: a Nim ORM

2020-01-30 Thread zetashift
This is awesome and lovely work! Thank you.


Re: Introducing Norm: a Nim ORM

2020-01-30 Thread moigagoo
It is my great pleasure to announce Norm version 1.1.0 release: 
[https://moigagoo.github.io/norm/changelog.html](https://moigagoo.github.io/norm/changelog.html)

The biggest change addition are the procs to write migrations. With those in 
place, I can focus on writing a migration manager that will make Norm even more 
useful for real life usage.


Re: Introducing Norm: a Nim ORM

2019-10-06 Thread moigagoo
I just want to clarify that there's no problem with plain Datetime, m just init 
it explicitly like I do in tests and norm-sample-webapp. It's none Datetime 
that is the real issue.


Re: Introducing Norm: a Nim ORM

2019-10-05 Thread JohnAD
... checked the range. `Time` is good to the year 292277026596 and presumably 
backwards that far.

So, you will have to worry about the Y292277026K problem.


Re: Introducing Norm: a Nim ORM

2019-10-05 Thread JohnAD
In the expansion of `norm` to support mongodb that I'm developing, I've 
defaulted to only supporting `Time`. The `DateTime` type breaks things on so 
many levels, mostly because `DateTime()` generates a runtime error.

Fortunately, the `Time` function, though based on the traditional Unix 
timestamp (seconds from Jan 1, 1970), is signed and 64 bit. So, the actual time 
range is massive and includes time before 1970.


Re: Introducing Norm: a Nim ORM

2019-10-05 Thread r3c
Right, i had DateTime field in the User type. Commented it out, and there are 
no errors :)


Re: Introducing Norm: a Nim ORM

2019-10-05 Thread moigagoo
What are the types of your model fields? I'm getting these warnings when using 
Option[Datetime] because Datetime doesn't have a default value. To make things 
worse, you can't solve it even with manual initialization: `none Datetime` 
still doesn't initialize a Datetime object which throws the warning.


Re: Introducing Norm: a Nim ORM

2019-10-05 Thread r3c
With nim 0.20.2 or newer theres an error:

template/generic instantiation from the withDb macro and getOne/getMany procs

It compiles, but its very frustrating because nimsuggest marks them as errors.


Re: Introducing Norm: a Nim ORM

2019-09-06 Thread moigagoo
In Norm 1.0.15 (released just now), you can split DC schema definition across 
multiple modules.

In order to do that. wrap the type section you want to use in schema in 
`dbTypes`` macro and use ``dbFromTypes`` instead of ``db`. See example in the 
docs (scroll down to “Alternatively to defining...”): 
[https://moigagoo.github.io/norm/norm.html](https://moigagoo.github.io/norm/norm.html)


Re: Introducing Norm: a Nim ORM

2019-09-04 Thread moigagoo
Here's a PR I'm developing this feature in: 
[https://github.com/moigagoo/norm/pull/26](https://github.com/moigagoo/norm/pull/26)

Feel free to comment.


Re: Introducing Norm: a Nim ORM

2019-09-01 Thread moigagoo
Sorry, I don't think I follow your point. Could you please try to illustrate it 
with some examples? Or we could connect directly and chat about it in Russian 
if you want.


Re: Introducing Norm: a Nim ORM

2019-09-01 Thread dponyatov
Did you try to work directly with objects by implementing the 
_[object](https://forum.nim-lang.org/postActivity.xml#object) database? ORMs 
looks for me like the dog's fifth leg -- factically _most times we need 
persistent object 
[storage](https://forum.nim-lang.org/postActivity.xml#storage), but again and 
again, we are trying to push object model into storage does not follow this 
model but designed to storing huge bunches of absolutely structured data.

As an example, let's look at any XML-packed data structure. It consists of 
arbitrary fields, all of them is optional from the viewpoint of the data 
storage format. Every time we are trying to put it in RDBMS we must use sparse 
tables with most fields nullable.


Re: Introducing Norm: a Nim ORM

2019-09-01 Thread moigagoo
It turned out to be trickier than I thought. The thing is, we're injecting id 
field into every type definition under db macro. This is necessary so that we 
can safely rely on objects having ids, which is necessary for getOne.

If we're allowing to define types separately from db macro, we can't just 
inject id field somewhere in another module.

The solution I'm leaning towards is:

  * allow to create db schema from types defined elsewhere only if those types 
have id field, which is also int and readonly
  * add db pragma to help people with the previous step: types with db pragma 
will be injected with id
  * disallow mixing the two approaches: you either define the schema as body 
for db macro, or you pass a list of db-annotated types to a different macro 
(e.g. dbFromTypes).




Re: Introducing Norm: a Nim ORM

2019-08-29 Thread moigagoo
There's an open PR that implements dbAddObject proc that allows to add type 
definitions from different module to the global model definition. This may be 
the thing that could help you: define types in modules as you'd normally do, 
then glue them together in models.nim module.

I'll try to implement this proc for SQLite and PostgreSQL backends tomorrow.


Re: Introducing Norm: a Nim ORM

2019-08-29 Thread Xena
Do you have an example for using Norm across multiple modules? I'd like to have 
my Users and Posts in separate .nim files, but I can't figure out an easy way 
to do that.


Re: Introducing Norm: a Nim ORM

2019-08-21 Thread moigagoo
Keeping you updated on Norm progress.

  * bool fields can be stored without custom parser or formatter. In SQLite, 
they are stored as 1 and 0, in PostgreSQL native BOOLEAN type is used.
  * times.DateTime fields are now also supported out of the box! In SQLite, 
they are stored as epoch timestamps, and in PostgreSQL native TIMESTAMP WITH 
TIME ZONE is used.



Changelog: 
[https://github.com/moigagoo/norm/blob/develop/changelog.md](https://github.com/moigagoo/norm/blob/develop/changelog.md)

As before, you are free to use a custom parser and formatter for any type. 
These are just sane defaults.

Also, one breaking change was introduced in formatIt pragma for SQLite backend: 
the expression in the pragma must explicitly evaluate to DbValue, implicit 
conversion has been removed.

Thanks everybody who helped by opening issues, sharing feedback, and 
contributing code to the project.

The next big milestone is supporting NULL values in PostgreSQL, which is 
unfortunately blocked by ndb progress.


Re: Introducing Norm: a Nim ORM

2019-06-15 Thread moigagoo
I have some great news: Norm 1.0.11 supports inserting and retrieving NULL 
values for SQLite databases.

This was made possible thanks to the great 
[ndb](https://github.com/xzfc/ndb.nim) module. The transition from std 
db_sqlite to ndb/sqlite was really smooth. I can't wait to see ndb replace all 
db_* modules in stdlib.

As soon as ndb supports PostreSQL, we'll be able to port norm/postgres to it as 
well, which will make NULL support universal.


Re: Introducing Norm: a Nim ORM

2019-05-10 Thread johnconway
@moigagoo Thanks for this, I've been using Norm in developing a little 
microblogging thing, and I like it's simplicity.


Re: Introducing Norm: a Nim ORM

2019-05-10 Thread moigagoo
A quick update about the project.

Thanks to [alaviss](https://github.com/alaviss), SQLite backend supports 
onUpdate and onDelete pragmas, foreign key handling now works (even with 
multiple FKs).

getOne can retrieve a record not only by ID, but also by condition.

getMany and getOne procs now support safe value substitution when constructing 
queries, so you can safely pass user-provided data to it.

There's a breaking change: instead of `where` and `orderBy`, we now have a 
single `cond` arg.

Feel free to use, report issues, and contribute: 
[https://github.com/moigagoo/norm](https://github.com/moigagoo/norm)


Re: Introducing Norm: a Nim ORM

2019-03-06 Thread moigagoo
Thanks for the idea! Sounds easy to implement. How do I store NULLs in an 
object though? Maybe, allow fields to be nil besides their own type?


Re: Introducing Norm: a Nim ORM

2019-03-06 Thread Araq
> I don't know what the right solution here is. Wrapping all values in Option 
> seems like an overkill. Returning 0 when NULL is returned where an int is 
> expected sound incorrect. Any ideas?

Ormin doesn't use the `seq[string]` idea at all, side-stepping the problem. But 
here's a different idea: Instead of `seq[Option[string]]` a row could be 
`tuple[data: seq[string], missing: seq[bool]]`. Then you can easily ignore the 
2nd tuple component when you know there are no NULLs in your schema (and there 
shouldn't be NULLs!).


Re: Introducing Norm: a Nim ORM

2019-03-05 Thread mikra
Hi all, regarding the discussion last year @ThomasTJdev mentioned I came up 
with my own solution of a rdbms-backend. It´s preminilary but stable for 
sqlite3 : [https://github.com/mikra01/nimdb](https://github.com/mikra01/nimdb) 
. Suggestions and PR´s welcome - I hope it´s intuitive. Sqlite's incremental 
blob api and rowid-handling (for inserts) is missing. I planned further 
examples with the chinook database. At the moment I am working at the odbc-part 
so it could be possible that I have to change the API a little bit..


Re: Introducing Norm: a Nim ORM

2019-03-04 Thread moigagoo
Thanks for the links! I didn't know about nim_sqlbuilder, I may switch to it 
instead of using my own `rowutils` module.


Re: Introducing Norm: a Nim ORM

2019-03-04 Thread ThomasTJdev
Hi @moigagoo

I've also had some trouble with NULL values. My question can be found in this 
thread: [4320](https://forum.nim-lang.org/t/4320)

I ended using the library here 
[nim_sqlbuilder](https://github.com/ThomasTJdev/nim_sqlbuilder), which 
substitute a type with `= NULL`.

@mashingan also provided a [good 
solution](https://forum.nim-lang.org/t/4320#26937) using options in the forum 
thread.

There's also a [github issue](https://github.com/nim-lang/Nim/issues/9453) 
about the missing API to precompile the query and the bind the data later, 
which @mikra01 is working on.


Re: Introducing Norm: a Nim ORM

2019-03-04 Thread moigagoo
I just want to make it clear that Norm is my first attempt to ORM and that 
decisions I've made may be wrong. Any advice from seasoned developers is highly 
appreciated.

Also, I'd be happy to see Norm evolve into a usable tool, so input from its 
potential users is vital.


Re: Introducing Norm: a Nim ORM

2019-03-04 Thread moigagoo
> Are all the incoming types from the database strings?

I'm not sure I understand the question. Row a.k.a. `seq[string]` is converted 
into an object based on the types of the object's fields. If the fields are 
int, float, and string, then a row `@["123", "123.321", "foo"]` is converted 
into 123, 123.123, "foo".

AFAIK Nim db modules' rows are always sequences of string regardless of the 
underlying DB types. So I'm relying on the target object's types. You can see 
the code that does the conversions in 
[rowutils](https://github.com/moigagoo/norm/blob/develop/src/norm/rowutils.nim) 
module.

> How does this handle NULL?

I haven't tested it with NULL values bth. I should though. How it's handled 
depends on how Nim's db modules handle NULL. I think it's returned as an empty 
string.


Re: Introducing Norm: a Nim ORM

2019-03-04 Thread Varriount
Are all the incoming types from the database strings? How does this handle NULL?


Re: Introducing Norm: a Nim ORM

2019-03-04 Thread moigagoo
> You can probably use custom pragmas: > > {.pragma: dbTime, dbType: "INTEGER", 
> parseIt: timeparser, formatIt: timeformatter.}

You sure can, thanks for the tip!

Just a little sidenote: `parseIt` pragma is used to set an `it` expression 
whereas `parser` is used to set a parser proc. So the correct code sample would 
be: `{.pragma: dbTime, dbType: "INTEGER", parser: timeparser, formatter: 
timeformatter.}`.


Re: Introducing Norm: a Nim ORM

2019-03-04 Thread moigagoo
Thanks for the positive comment! It means a lot to me, for real.

Currently, there's no way to shorten or reuse field definition, and `DateTime` 
is considered a special case, so _right now_ , unfortunately, it's `birthDate 
{.dbType: "INTEGER", parseIt: it.parseInt().fromUnix().local(), formatIt: 
$it.toTime().toUnix().}: DateTime` repeated multiple times in your DB schema. 
It's the only place you'll have to have this ugly code repetition though.

However, I've been thinking a lot about adding default parser and formatter for 
`DateTime` type. In SQLite, they'd be stored as `INTEGER` and in PostgreSQL as 
`TIMESTAMP`. Sounds like reasonable defaults.

DateTime is a common type and I can imagine developers rewriting the same 
parsers and formatters over and over. Do you think it's a good idea?


Re: Introducing Norm: a Nim ORM

2019-03-04 Thread mratsim
You can probably use custom pragmas:

`{.pragma: dbTime, dbType: "INTEGER", parseIt: timeparser, formatIt: 
timeformatter.}`


Re: Introducing Norm: a Nim ORM

2019-03-04 Thread PMunch
This looks pretty neat! Is it possible though to define a conversion and apply 
it to multiple fields? Say I had a lot of dates in my database it could get 
tedious fast to write {.dbType: "INTEGER", parseIt: timeparser, formatIt: 
timeformatter.}.


Re: Introducing Norm: a Nim ORM

2019-03-04 Thread moigagoo
Here's an example of a DB schema definition (from 
[https://github.com/moigagoo/norm-sample-webapp/blob/develop/src/models.nim)](https://github.com/moigagoo/norm-sample-webapp/blob/develop/src/models.nim\)):


db("app.db", "", "", ""):
  type
Owner* = object
  firstName*: string
  lastName*: string
  birthDate* {.
dbType: "INTEGER",
parseIt: it.parseInt().fromUnix().utc(),
formatIt: $it.toTime().toUnix()
  .}: DateTime
  
  proc getOwnerById(id: string): Owner =
result = Owner(birthDate: now())
withDb:
  result.getOne parseInt(id)
  
  type
Pet* = object
  name*: string
  birthDate* {.
dbType: "INTEGER",
parseIt: it.parseInt().fromUnix().utc(),
formatIt: $it.toTime().toUnix()
  .}: DateTime
  owner* {.
dbCol: "ownerId",
dbType: "INTEGER",
fk: Owner
parser: getOwnerById,
formatIt: $it.id
  .}: Owner


Run