0

I'm writing simple API in Go using MySQL but my MySQL code inserts data to row even the column is set to NOT NULL. Here is my code:

schema.sql

CREATE TABLE IF NOT EXISTS seller (
    seller_id int NOT NULL AUTO_INCREMENT,
    name varchar(255) NOT NULL UNIQUE,
    contact varchar(255) NOT NULL,
    street varchar(255) NOT NULL,
    city varchar(255) NOT NULL,
    nip varchar(255) NOT NULL UNIQUE,
    bank varchar(255) NOT NULL,
    account_number varchar(255) NOT NULL UNIQUE,
    PRIMARY KEY (seller_id)
);

database/mysql/invoice.go

func (r *invoiceRepository) CreateSeller(seller *invoice.Seller) error {
        query := "INSERT INTO seller (name, contact, street, city, nip, bank, account_number) VALUES (?, ?, ?, ?, ?, ?, ?)"
        stmt, err := r.db.Prepare(query)
        if err != nil {
                log.Errorf("Unable to create seller %s: %v", seller.SellerName, err)
                return err
        }

        res, err := stmt.Exec(&seller.SellerName, &seller.SellerContact, &seller.SellerStreet, &seller.SellerCity, &seller.SellerNIP, &seller.SellerBank, &seller.SellerAccountNumber)
        if err != nil {
                log.Errorf("Error while creating seller: %v", err)
                return err
        }

        newID, err := res.LastInsertId()
        if err != nil {
                log.Errorf("Error while getting inserted id: %v", err)
                return err
        }

        log.Infof("Created seller %s [id=%d]", seller.SellerName, newID)
        return nil
}

Now when I'm making a POST request (using httpie) with the only seller_name my code creates row even with null columns. It looks like this: http POST localhost:8000/api/seller/create seller_name=testt

Here is how my row looks in table:

+-----------+-------+---------+--------+------+-----+------+----------------+
| seller_id | name  | contact | street | city | nip | bank | account_number |
+-----------+-------+---------+--------+------+-----+------+----------------+
|         1 | testt |         |        |      |     |      |                |
+-----------+-------+---------+--------+------+-----+------+----------------+

I don't know where I've made a mistake.

EDIT (added model)

type Seller struct {
        SellerID            int64  `json:"seller_id"`
        SellerName          string `json:"seller_name"`
        SellerContact       string `json:"seller_contact"`
        SellerStreet        string `json:"seller_street"`
        SellerCity          string `json:"seller_city"`
        SellerNIP           string `json:"seller_nip"`
        SellerBank          string `json:"seller_bank"`
        SellerAccountNumber string `json:"seller_account_number"`
}
5
  • "I don't know where I've made a mistake." Execute SELECT @@sql_mode; ? and paste it here.. Commented May 1, 2019 at 17:43
  • 1
    As iám pretty sure your MySQL server seams to be running without SQL mode STRICT_TRANS_TABLES see without and with Commented May 1, 2019 at 17:48
  • You were expecting it to return an error? An error at the DB layer should be a worst-case scenario; something before that should be sanitizing and validating user inputs. I.e., if you don't want nulls/empties inserted into the DB, they should never make it to your CreateSeller function. Commented May 1, 2019 at 17:54
  • A couple of things: What does seller actually look like, are the fields populated (remember: empty strings are not nil/NULL values)? More over: you create a prepared statement, but that resource is never closed, after the error check on r.db.Prepare(), add a defer stmt.Close(), please. Commented May 1, 2019 at 18:09
  • @RaymondNijland +--------------------------------------------+ | @@sql_mode | +--------------------------------------------+ | NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION | +--------------------------------------------+ Commented May 1, 2019 at 19:44

2 Answers 2

4

Go isn't inserting nulls in your table, it is inserting empty strings. Your code is effectively doing this:

seller := Seller{}
seller.SellerName = "testt"

to create the seller that you're inserting. So all the fields in your seller except SellerName will have the zero value for their type; the fields causing you trouble are strings and the zero value of a string is "" (i.e an empty string) so the SQL ends up looking like:

INSERT INTO seller (name, contact, ...)
VALUES ('testt', '', ...)

and there isn't a NULL in sight.

You could validate the incoming data in Go so that empty strings are rejected, you could use NullString instead of string and let the database deal with NULLs (assuming MySQL is properly configured), or do both.

Sign up to request clarification or add additional context in comments.

1 Comment

It's working. You're right, Go wasn't inserting null but empty string. I changed string to sql.NullString in my model and now everything works correctly.
0

Yes, because when it comes to Mysql: emtpy string (e.g '') is NOT a null. It treats it like being a string (only empty).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.