## Model

Model files are simple Go struct types used to combine and store result of SQL queries. They are 
autogenerated from database tables and enums. 

### Table model files

Following rules are applied to generate model types from database tables:

- for every table there is one Go file generated. File name is in snake case of the table name. 
- every model file contains one struct type. Type name is a camel case of table name. Package name
is always `model`.
- for every column of table there is a field in model struct type. Field name is camel case of column name. 
See below table for type mapping.
- fields are pointer types, if they relate to column that can be NULL. 
- fields corresponds to primary key columns are tagged with `sql:"primary_key"`.
_This tag is used during query execution to group row results into desired arbitrary structure. 
See more at [Execution](https://github.com/go-jet/jet/wiki/Execution)_  


##### Mappings of database types to Go types

| Database type(postgres)                         | Go type                                            |
| ----------------------------------------------- | -------------------------------------------------- |
| boolean                                         |  bool                                              |
| smallint                                        |  int16                                             |
| integer                                         |  int32                                             |
| bigint                                          |  int64                                             |
| real                                            |  float32                                           |
| numeric, decimal, double precision              |  float64                                           |
| date, timestamp, time(with or without timezone) |  time.Time                                         |
| bytea                                           |  []byte                                            |
| uuid                                            |  uuid.UUID                                         |
| enum                                            |  enum name                                         |
| text, character, character varying,             |                                                    |
| and all remaining types                         |  string                                            |

#### Example:

Sql table `address`:
```
CREATE TABLE dvds.address
(
    address_id serial NOT NULL DEFAULT,
    address character varying(50) NOT NULL,
    address2 character varying(50),
    district character varying(20) NOT NULL,
    city_id smallint NOT NULL,
    postal_code character varying(10),
    phone character varying(20) NOT NULL,
    last_update timestamp without time zone NOT NULL DEFAULT now(),
    CONSTRAINT address_pkey PRIMARY KEY (address_id)
)
```

Autogenerated model file `address.go`:

```
package model

import (
    "time"
)

type Address struct {
    AddressID  int32 `sql:"primary_key"`
    Address    string
    Address2   *string
    District   string
    CityID     int16
    PostalCode *string
    Phone      string
    LastUpdate time.Time
}
```

### Enum model files

Following rules are applied to generate model files from database enums:

- for every enum there is one Go file generated. File name is a snake case of enum name. 
- every file contains one renamed string type. Type name is a camel case of enum name.
Package name is always `model`.
Enum type has two helper methods to: 
    - initialize correctly from database query result
    - easily convert enum to string.
- for every enum value there is one constant defined. 
Name of the constant is in format `{CamelCase(enum_name)}_{CamelCase(enum_value_name)}`.

#### Example

Enum `mpaa_rating`:
```
CREATE TYPE dvds.mpaa_rating AS ENUM
    ('G', 'PG', 'PG-13', 'R', 'NC-17');
```

Autogenerated model file `mpaa_rating.go`

```
package model

import "errors"

type MpaaRating string

const (
	MpaaRating_G    MpaaRating = "G"
	MpaaRating_Pg   MpaaRating = "PG"
	MpaaRating_Pg13 MpaaRating = "PG-13"
	MpaaRating_R    MpaaRating = "R"
	MpaaRating_Nc17 MpaaRating = "NC-17"
)

func (e *MpaaRating) Scan(value interface{}) error {
	if v, ok := value.(string); !ok {
		return errors.New("jet: Invalid data for MpaaRating enum")
	} else {
		switch string(v) {
		case "G":
			*e = MpaaRating_G
		case "PG":
			*e = MpaaRating_Pg
		case "PG-13":
			*e = MpaaRating_Pg13
		case "R":
			*e = MpaaRating_R
		case "NC-17":
			*e = MpaaRating_Nc17
		default:
			return errors.New("Inavlid data " + string(v) + "for MpaaRating enum")
		}

		return nil
	}
}

func (e MpaaRating) String() string {
	return string(e)
}
```
