Why use sql tags in struct in some go libs like gorm? - sql

Well I know the necessity of tags in struct in golang and how is it accessed by reflect in golang. But I have searched and could not find a reliable answer to the question of why I should use sql tags in struct while writing struct for sql results. I have explored many sample code and people are using sql:"index" in the struct and sql:"primary_key" in the struct.
Now I have done indexing in the database layer, isn’t it enough? Should I have to use sql:"index" too get the best results? Like so I have defined primary key attribute in the database should I have to specify sql:"primary_key" as well?
My code seems to work fine without those. Just want to know their benefit and usages.

I think you are referring to an ORM library like gorm
In that case, metadata like sql:"primary_key" or sql:"index" will just tell the ORM to create an index while trying to setup the tables or maybe migrate them.
A couple of examples in gorm could be: indexes, primary keys, foreign keys, many2many relations or when trying to adapt an exiting schema into your gorm models, setting the type explicitly, like for example:
type Address struct {
ID int
Address1 string `sql:"not null;unique"` // Set field as not nullable and unique
Address2 string `sql:"type:varchar(100);unique"`
Post sql.NullString `sql:"not null"`
}

Depends on the package you are using and your use-case. Is it enough for CRUD? Almost always, unless the package says so which is often rare but possible. Few packages sometime do under the hood magic which may give rise to bugs. If you are aware of these behaviours, or are quite explicit in your code, you'll probably avoid it.
Indexing tags mostly allows you to use package's migration tools translating your model declaration into sql queries (CREATE statements). So if you always want to do this by yourself, then you probably needn't bother adding such tags.
But you may find yourself a bug if your package requires a tag. For example, in case of gorm, the Model method takes a struct pointer as an input. If this struct has a field named ID it uses it as a primary key, that is, say ID has a value of "4", it will add a WHERE id=4 automatically. In case your struct has ID, you needn't even add a primary_key tag and it will still be treated as one. This behaviour may cause issues when you have both a "non-primary-key" ID field, and another field which you are actually using as the primary key. Another example for gorm is this. A possible behaviour can also be checking for nullable property and throwing an error if an INSERT statement involves a NOT NULL field getting a NULL value.
On a different note, adding tags to your structs can be considered good practice since it gives context of its properties in the DB.

Related

Nullablity of DB generated attributes

I'm working in a Kotlin based project and It force me to deal with any attribute that possibly can hold null. It's nice to find out somewhere nulls are possible while they are not welcome; but I see so much of ?.s and .!!s for attributes that DB generates, e.g. IDs. Maybe I'm abusing that operators?
Is there any convention to mark attribute as not nullable but still have DB generated values here? If I lookup an object It's safe to assume DB generated values are not null anymore. Can VM be made known to this? Maybe by framework or some annotations that language provide?
If your id is generated by the database it is nullable since the JVM/compiler/IDE has no way to know if your entity is already persisted or not.
What you could do though is implement additional methods that are guaranteed to return non-null values by throwing an exception otherwise.

IndexedDB - Do I need an "id" field?

After reading several tutorials I still have problems understanding IndexedDB completely...
I already build a "playground-app" with it, but I have a question before continuing....
Is it recommended to have a distinct "id" field in the ObjectStores?
What happens if object at index 42 (without id-field) needs to be updated? [From what I know IndexedDB doesn't have an update command.] How would you exchange/update this object in-place without breaking the references to this objects?
When you have a id-field - How to find a unused id-value when you add a new object to an ObjectStore? Is there a clever way to do it?
I couldn't find a discussion about this on SO or somewhere else...
cheers!
Using an id is not required but is recommended because it simplifies writing your program. This advice applies to traditional relational databases (SQL) and indexedDB (NoSQL).
Using a simple integer counter is helpful and recommended, even when you have another property or group of properties (a composite/compound primary key) that uniquely identifies each object in a store.
indexedDB provides a way to generate 'unused' id values. Use the autoincrement flag when calling createObjectStore and setting the key path.
See the MDB documentation to learn more. Specifically, review the section on object store keys.
In regards to the 42 question, you can open a cursor, then advance the cursor by 42, and then retrieve the value, change its properties, and then, if the underlying transaction is in readwrite mode, you can call cursor.update to replace the object at the cursor's position. Using this technique is not recommended primarily because it is not practical and can be confusing. It is preferable to use a simple auto-incremented integer id, especially when you are just learning.
It does not matter what the name of the property that represents the key is, so long as it conforms to normal JavaScript object property naming rules, and you access it consistently.

How to fix my m..n relationship in nosql (mongodb)?

At first I'm trying to make a rally (you know cars with drivers...) database. I have two collections: drivers { name, address, sex, ... } and then another one tournaments { name, location, price, ... }
I try to keep it simple. In a tournament there should be drivers (because a tournament without drivers...well its not nice ^^). And there is my problem, in a normal sql database I could select two primary keys (lets say name in drivers and name in tournaments - just to keep it simple, I know name as primary key is not nice). And because its an m..n relationship (is it right?) I would make a 3. Table with the two primary keys. OK that would be easy. But how should I solve this problem in mongodb. I thought something like: tournaments { name, location, price, ... drivers { driver_1, ..., driver_n } } , but im not sure. I'm using Java so I could make some special Classes which one is handling this relationship problem? I don't understand the other mongodb tutorials. Any ideas? Thank you for any help!
There are a few ways to do this:
As #Gianluca describes you can perform this linking manually by adding a driver's _id ObjectId or another identifying property (probably one you have a unique index on) to a "drivers" array in a tournament document. e.g. tournament : { ... drivers : ["6019235867192384", "73510945093", ...]}
Another option specifically built for this referencing is the DBRef specification which provides a more formal method probably more similar to what you're familiar in the SQL world. DBRef is supported by the java driver and allows you to scope your reference to a collection (basically saying where this reference comes from). I wouldn't be surprised if in the future versions of MongoDB cross-collection queries will be supported, although they are not currently.
More information here.
Also if you aren't using a DAO framework I would suggest Morphia which supports DBRef with a nice #Reference annotation.
I solved the problem using the _id field that every document had and is unique.
So in you case you just need to create a collection that has the ObjectId of the torunaments and some ObjectId from the collection drivers. Or you can just put the ObejctId of the driver directly in the torunaments collection. Probably not the best solution, but it work
Gianluca
Add an array field drivers in the trournaments type and put the _ids of the drivers in there.
To add/remove drivers, just update the field. There is no need for an intermediary N:M mapping table unless the array gets really huge.
If it gets huge, the usual solution is to cut the array into several smaller ones and save them in several documents that you can look up quickly by using the id_ of the container (the tournament). Removing and sorting is then a pain, of course.

SQL: Advantages of an ENUM vs. a one-to-many relationship?

I very rarely see ENUM datatypes used in the wild; a developer almost always just uses a secondary table that looks like this:
CREATE TABLE officer_ranks (
id int PRIMARY KEY
,title varchar NOT NULL UNIQUE);
INSERT INTO officer_ranks VALUES (1,'2LT'),(2,'1LT'),(3,'CPT'),(4,'MAJ'),(5,'LTC'),(6,'COL'),(7,'BG'),(8,'MG'),(9,'LTG'),(10,'GEN');
CREATE TABLE officers (
solider_name varchar NOT NULL
,rank int NOT NULL REFERENCES officer_ranks(id) ON DELETE RESTRICT
,serial_num varchar PRIMARY KEY);
But the same thing can also be shown using a user-defined type / ENUM:
CREATE TYPE officer_rank AS ENUM ('2LT', '1LT','CPT','MAJ','LTC','COL','BG','MG','LTG','GEN');
CREATE TABLE officers (
solider_name varchar NOT NULL
,rank officer_rank NOT NULL
,serial_num varchar PRIMARY KEY);
(Example shown using PostgreSQL, but other RDBMS's have similar syntax)
The biggest disadvantage I see to using an ENUM is that it's more difficult to update from within an application. And it might also confuse an inexperienced developer who's used to using a SQL DB simply as a bit bucket.
Assuming that the information is mostly static (weekday names, month names, US Army ranks, etc) is there any advantage to using a ENUM?
Example shown using PostgreSQL, but other RDBMS's have similar syntax
That's incorrect. It is not an ISO/IEC/ANSI SQL requirement, so the commercial databases do not provide it (you are supposed to provide Lookup tables). The small end of town implement various "extras", but do not implement the stricter requirements, or the grunt, of the big end of town.
We do not have ENUMs as part of a DataType either, that is absurd.
The first disadvantage of ENUMs is that is it non-standard and therefore not portable.
The second big disadvantage of ENUMs is, that the database is Closed. The hundreds of Report Tools that can be used on a database (independent of the app), cannot find them, and therefore cannot project the names/meanings. If you had a normal Standard SQL Lookup table, that problem is eliminated.
The third is, when you change the values, you have to change DDL. In a Normal Standard SQL database, you simply Insert/Update/Delete a row in the Lookup table.
Last, you cannot easily get a list of the content of the ENUM; you can with a Lookup table. More important, you have a vector to perform any Dimension-Fact queries with, eliminating the need for selecting from the large Fact table and GROUP BY.
I don't see any advantage in using ENUMS.
They are harder to maintain and don't offer anything that a regular lookup table with proper foreign keys wouldn't allow you to do.
A disadvantage of using something like an ENUM is that you can't get a list of all the available values if they don't happen to exist in your data table, unless you hard-code the list of available values somewhere. For example, if in your OFFICERS table you don't happen to have an MG on post there's no way to know the rank exists. Thus, when BG Blowhard is relieved by MG Marjorie-Banks you'll have no way to enter the new officer's rank - which is a shame, as he is the very model of a modern Major General. :-) And what happens when a General of the Army (five-star general) shows up?
For simple types which will not change I've used domains successfully. For example, in one of my databases I've got a yes_no_domain defined as follows:
CREATE DOMAIN yes_no_dom
AS character(1)
DEFAULT 'N'::bpchar
NOT NULL
CONSTRAINT yes_no_dom_check
CHECK ((VALUE = ANY (ARRAY['Y'::bpchar, 'N'::bpchar])));
Share and enjoy.
ENUMS are very-very-very useful! You just have to know how to use them:
An ENUM uses only 2 Bytes of storage.
No need for additional constraint (as replacement for FK).
Cheaper changes of Values compared to natural values in FKs.
No need for additional JOIN
ENUMs are ordered, ex you can compare if Monday < Friday, or January is < June or Project Initiation is < Payroll.
Thus if you have a fixed list of string values, which you want to use, an ENUM is a better solution compared to a lookup table. Let's say you need to List Amino-Acids in your products, with their respective weight. Today there are ~20 Amino Acids. If you would store their full names, you'd need much more space each time then 2 Bytes. The other option is to use artificial keys and to link to a foreign table. But how would the foreign Table look like? Would it have 2 columns: ID and Amino Acid Name? And you would join that table every time? What if your main table has >40 such fields? Querying that table would involve >40 Joins.
If your database hosts 1600 Tables, 400 of which are lookup tables which just replace ENUMs, your devs will waste lots of time navigating through them (in addition to the JOINs). Yes, you can work with prefixes, schemas and such.... but why not just kick those tables out?
ENUMS are Enumerated lists / ordered. That means that if you have values which are ordered, you are actually saving the hassle of maintaining a 3 columns lookup table.
The question is rather: why do I need lookup tables then?
Well, the answer is easy:
When your values are changing often
When you need to store more additional attributes --> The lookup table corresponds to a full fledged data object, and not a lookup list.
When you need it quick and dirty
And now the funny thing:
Lookup Tables and ENUMS are not complete replacements for each other!!!!
If you have a list, where the PK is single-column natural key. The list can grow or the values can change their names (for some reason), then you could define an ENUM and use it for both: PK in lookup and FK in main tables!
Example benefit:
you have to change the name of a lookup key. Without using the ENUM the DBMS will have to cascade the changes to all tables, where you use this value and not just your lookup table. If you are using ENUM, then you just change the value of ENUM, and there are no changes to the data.
A small advantage may lie in the fact, that you have a sort of UDT when creating an ENUM. A user defined type can be reused formally in many other database objects, e.g. in views, other tables, other types, stored procedures (in other RDBMS), etc.
Another advantage is for documentation of the allowed values of a field. Examples:
A yes/no field
A male/female field
A mr/mrs/ms/dr field
Probably a matter of taste. I prefer ENUMs for these kinds of fields, rather than foreign keys to lookup tables for such simple concepts.
Yet another advantage may be that when you use code generation or ORMs like jOOQ in Java, you can use that ENUM to generate a Java enum class from it, instead of joining the lookup table, or working with the ENUM literal's ID
It's a fact, though, that only few RDBMS support a formal ENUM type. I only know of Postgres and MySQL. Oracle or DB2 don't have it.
Advantages:
Type safety for stored procedures: will raise a type error if argument can not be coerced into the type. Like: select court_martial('3LT') would raise a type error automatically.
Custom coalition order: In your example, officers could be sorted without a ranking id.
Generally speaking, enum is better for things that don't change much, and it uses slightly fewer resources, since there's no FK checks or anything like to execute on insert etc.
Using a lookup table is more elegant and or traditional and it's much easier to add and remove options than an enum. It's also easier to mass change the values than an enum.
Well, you don't see, because usually developers are using enums in programming languages such as Java, and the don't have their counterparts in database design.
In database such enums are usually text or integer fields, with no constraints. Database enums will not be translated into Java/C#/etc. enums, so the developers see no gain in this.
There are very many very good database features which are rarely used because most ORM tools are too primitive to support them.
Another benefit of enums over a lookup table is that when you write SQL functions you get type checking.

Hibernate and IDs

Is it possible in hibernate to have an entity where some IDs are assigned and some are generated?
For instance:
Some objects have an ID between 1-10000 that are generated outside of the database; while some entities come in with no ID and need an ID generated by the database.
You could use 'assigned' as the Id generation strategy, but you would have to give the entity its id before you saved it to the database. Alternately you could build your own implementation of org.hibernate.id.IdentifierGenerator to provide the Id in the manner you've suggested.
I have to agree w/ Cade Roux though, and doing so seems like it be much more difficult than using built in increment, uuid, or other form of id generation.
I would avoid this and simply have an auxiliary column for the information about the source of the object and a column for the external identifier (assuming the external identifier was an important value you wanted to keep track of).
It's generally a bad idea to use columns for mixed purposes - in this case to infer from the nature of a surrogate key the source of an object.
Use any generator you like, make sure it can start at an offset (when you use a sequence, you can initialize it accordingly).
For all other entities, call setId() before you insert them. Hibernate will only generate an id if the id property is 0. Note that you should first insert objects with ids into the db and then work with them. There is a lot of code in Hibernate which expects the object to be in the DB when id != 0.
Another solution is to use negative ids for entities which come with an id. This will also make sure that there are no collisions when you insert an new object.