func (this *Handler) ShowBlank(id string) {
	base := new(models.ModelManager)
	blanks := base.Blanks()

	columns := blanks.Select(map[string]interface{}{"contest_id": id}, "columns")
	cl := columns[0].(map[string]interface{})
	colNames := blanks.Select(map[string]interface{}{"contest_id": id}, "colnames")
	cln := colNames[0].(map[string]interface{})
	types := blanks.Select(map[string]interface{}{"contest_id": id}, "types")
	t := types[0].(map[string]interface{})

	caption := blanks.Select(map[string]interface{}{"contest_id": id}, "name")[0].(map[string]interface{})["name"].(string)

	tmp, err := template.ParseFiles(
		"../uas/view/show_blank.html",
		"../uas/view/header.html",
		"../uas/view/footer.html")
	utils.HandleErr("[Handler.BlankShow] template.ParseFiles: ", err)
	err = tmp.ExecuteTemplate(this.Response, "show_blank", Model{
		Id:       id,
		Caption:  caption,
		Columns:  utils.ArrayStringToInterface(strings.Split(cl["columns"].(string), ",")),
		ColNames: utils.ArrayStringToInterface(strings.Split(cln["colnames"].(string), ",")),
		Types:    utils.ArrayStringToInterface(strings.Split(t["types"].(string), ","))})
	utils.HandleErr("[Handler.BlankShow] tmp.Execute: ", err)
}
func (this *Handler) HandleRegister(login string, password string) string {
	result := map[string]string{"result": "ok"}
	salt := time.Now().Unix()
	fmt.Println("register salt: ", salt)
	hash := GetMD5Hash(password + strconv.Itoa(int(salt)))
	passHasInvalidChars := false
	for i := 0; i < len(password); i++ {
		if strconv.IsPrint(rune(password[i])) == false {
			passHasInvalidChars = true
			break
		}
	}
	isExist, _, _, _ := IsExist(login)
	if isExist == true {
		result["result"] = "loginExists"
	} else if !MatchRegexp("^[a-zA-Z0-9]{2,36}$", login) {
		result["result"] = "badLogin"
	} else if !MatchRegexp("^.{6,36}$", password) && !passHasInvalidChars {
		result["result"] = "badPassword"
	} else {
		db := connect.DBConnect()
		query := connect.DBInsert("users", []string{"login", "password", "salt"})
		stmt, err := db.Prepare(query)
		utils.HandleErr("[HandleRegister] Prepare error :", err)
		defer stmt.Close()
		_, err = stmt.Exec(login, hash, salt)
		utils.HandleErr("[HandleRegister] Query error :", err)
	}
	response, err := json.Marshal(result)
	utils.HandleErr("[HandleRegister] json.Marshal: ", err)
	return string(response)
}
func (this *IndexController) Index() {
	this.Response.Header().Set("Content-Type", "text/html; charset=utf-8")
	tmp, err := template.ParseFiles("view/index.html", "view/header.html", "view/footer.html")
	utils.HandleErr("[IndexController] ParseFiles: ", err)
	err = tmp.ExecuteTemplate(this.Response, "index", nil)
	utils.HandleErr("[IndexController] ExecuteTemplate: ", err)
}
func (this Entity) Insert(fields []string, params []interface{}) {
	db := connect.DBConnect()
	query := connect.DBInsert(this.TableName, fields)
	stmt, err := db.Prepare(query)
	utils.HandleErr("[Entity.Insert] Prepare: ", err)
	defer connect.DBClose(db, stmt)
	_, err = stmt.Exec(params...)
	utils.HandleErr("[Entity.Insert] Exec: ", err)
}
func (this Entity) Update(fields []string, params []interface{}, where string) {
	db := connect.DBConnect()
	query := connect.DBUpdate(this.TableName, fields, where)
	fmt.Println("Update: ", query)
	stmt, err := db.Prepare(query)
	utils.HandleErr("[Entity.Update] Prepare: ", err)
	defer connect.DBClose(db, stmt)
	_, err = stmt.Exec(params...)
	utils.HandleErr("[Entity.Update] Exec: ", err)
}
func DBGetLastInsertedId(tableName string) string {
	db := DBConnect()
	defer DBClose(db)
	var id string
	query := "SELECT last_value FROM " + tableName + "_id_seq"
	stmt, err := db.Prepare(query)
	utils.HandleErr("[Connect.GetLastInsertedId] Prepare: ", err)
	err = stmt.QueryRow().Scan(&id)
	utils.HandleErr("[Connect.GetLastInsertedId] Query: ", err)
	return id
}
func DBGetColumnNames(tableName string) []string {
	db := DBConnect()
	defer DBClose(db)
	var columns []string
	query := "SELECT * FROM " + tableName
	stmt, err := db.Prepare(query)
	utils.HandleErr("[Connect.DBGetColumnNames] Prepare: ", err)
	rows, err := stmt.Query()
	utils.HandleErr("[Connect.DBGetColumnNames] Query: ", err)
	columns, err = rows.Columns()
	utils.HandleErr("[Connect.DBGetColumnNames] Columns: ", err)
	fmt.Println("column names: ", columns)
	return columns
}
func (this *Handler) HandleLogout() string {
	result := map[string]string{"result": "ok"}
	this.Session.SessionDestroy(this.Response, this.Request)
	response, err := json.Marshal(result)
	utils.HandleErr("[HandleLogout] json.Marshal: ", err)
	return string(response)
}
func CreateBlank(id string) {
	db := connect.DBConnect()
	defer connect.DBClose(db)
	base := new(ModelManager)
	model := base.Users()
	n := len(model.UserColumns)
	query := "CREATE TABLE IF NOT EXISTS blank_" + id + "("
	for i := 0; i < n; i++ {
		query += model.UserColumns[i] + " " + model.Fields[model.UserColumns[i]].Type + ", "
	}
	query = query[0:len(query)-2] + ");"
	fmt.Println("[DBCreateBlank]: Create table", query)
	_, err := db.Exec(query)
	utils.HandleErr("[Connect.DBCreateBlank]: Exec", err)

	contests := base.Contests()
	name := contests.Select(map[string]interface{}{"id": id}, "name")

	blanks := base.Blanks()
	blanks.Insert(
		blanks.Columns[1:],
		[]interface{}{
			name[0].(map[string]interface{})["name"].(string),
			id,
			"{" + strings.Join(model.UserColumns[1:], ",") + "}",
			"{" + strings.Join(model.UserColNames[1:], ",") + "}",
			"{" + strings.Join(model.UserTypes[1:], ",") + "}"})
}
func (this *Handler) Select(tableName string) {
	sess := this.Session.SessionStart(this.Response, this.Request)
	createTime := sess.Get("createTime")
	life := this.Session.Maxlifetime
	if createTime == nil || createTime.(int64)+life < time.Now().Unix() {
		this.Session.SessionDestroy(this.Response, this.Request)
		fmt.Println("Select - Destroy")
		tmp, err := template.ParseFiles(
			"view/index.html",
			"view/header.html",
			"view/footer.html")
		utils.HandleErr("[handler.select] ParseFiles: ", err)
		err = tmp.ExecuteTemplate(this.Response, "index", nil)
		utils.HandleErr("[handler.select] ExecuteTemplate: ", err)
		return
	}
	sess.Set("createTime", time.Now().Unix())
	base := new(models.ModelManager)
	var model models.Entity
	switch tableName {
	case "Users":
		model = base.Users().Entity
		break
	case "Contests":
		model = base.Contests().Entity
		break
	case "Blanks":
		model = base.Blanks().Entity
		break
	}
	answer := model.Select(nil, model.Columns...)
	tmp, err := template.ParseFiles(
		"../uas/view/table.html",
		"../uas/view/header.html",
		"../uas/view/footer.html")
	utils.HandleErr("[Handler.Select] template.ParseFiles: ", err)
	err = tmp.ExecuteTemplate(this.Response, "edit", Model{
		Table:     answer,
		TableName: model.TableName,
		ColNames:  utils.ArrayStringToInterface(model.ColNames),
		Columns:   utils.ArrayStringToInterface(model.Columns),
		Caption:   model.Caption})
	utils.HandleErr("[Handler.Select] tmp.Execute: ", err)
}
func IsExist(login string) (bool, string, string, string) {
	db := connect.DBConnect()
	var id, hash, salt string
	query := connect.DBSelect("users", []string{"login"}, "id", "password", "salt")
	stmt, err := db.Prepare(query)
	utils.HandleErr("[IsExist] Prepare: ", err)
	defer connect.DBClose(db, stmt)
	err = stmt.QueryRow(login).Scan(&id, &hash, &salt)
	return err != sql.ErrNoRows, id, hash, salt
}
func (this *Handler) SelectById(tableName string) {
	sess := this.Session.SessionStart(this.Response, this.Request)
	createTime := sess.Get("createTime")
	life := this.Session.Maxlifetime
	if createTime == nil || createTime.(int64)+life < time.Now().Unix() {
		this.Session.SessionDestroy(this.Response, this.Request)
		fmt.Println("SelectById - Destroy")
		tmp, err := template.ParseFiles(
			"view/index.html",
			"view/header.html",
			"view/footer.html")
		utils.HandleErr("[handler.select] ParseFiles: ", err)
		err = tmp.ExecuteTemplate(this.Response, "index", nil)
		utils.HandleErr("[handler.select] ExecuteTemplate: ", err)
		return
	}
	sess.Set("createTime", time.Now().Unix())
	id := sess.Get("id")
	base := new(models.ModelManager)
	var answer []interface{}
	switch tableName {
	case "Users":
		model := base.Users()
		answer = model.Select(map[string]interface{}{"id": id}, model.UserColumns...)
		tmp, err := template.ParseFiles(
			"../uas/view/card.html",
			"../uas/view/header.html",
			"../uas/view/footer.html")
		utils.HandleErr("[Handler.SelectById] template.ParseFiles: ", err)
		err = tmp.ExecuteTemplate(this.Response, "card", Model{
			Table:    answer,
			ColNames: utils.ArrayStringToInterface(model.UserColNames),
			Columns:  utils.ArrayStringToInterface(model.UserColumns)})
		utils.HandleErr("[Handler.SelectById] tmp.Execute: ", err)
		break
	}
}
func (this *Handler) HandleLogin(login, password string) string {
	result := map[string]interface{}{"result": "invalidCredentials"}
	isExist, id, hash, salt := IsExist(login)
	if isExist && hash == GetMD5Hash(password+salt) {
		sess := this.Session.SessionStart(this.Response, this.Request)
		sess.Set("createTime", time.Now().Unix())
		sess.Set("login", login)
		sess.Set("id", id)
		result["id"] = id
		result["result"] = "ok"
	}
	response, err := json.Marshal(result)
	utils.HandleErr("[HandleLogin] json.Marshal: ", err)
	return string(response)
}
func (this *Handler) Index() {
    var (
        request  interface{}
        response = ""
    )
    this.Response.Header().Set("Access-Control-Allow-Origin", "*")
    this.Response.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
    this.Response.Header().Set("Content-type", "application/json")

    decoder := json.NewDecoder(this.Request.Body)
    err := decoder.Decode(&request)
    utils.HandleErr("[Handler] Decode :", err)
    data := request.(map[string]interface{})

    switch data["action"] {
    case "register":
        login, password := data["login"].(string), data["password"].(string)
        response = this.HandleRegister(login, password)
        fmt.Fprintf(this.Response, "%s", response)
        break

    case "login":
        login, password := data["login"].(string), data["password"].(string)
        response = this.HandleLogin(login, password)
        fmt.Fprintf(this.Response, "%s", response)
        break

    case "logout":
        response = this.HandleLogout()
        fmt.Fprintf(this.Response, "%s", response)
        break

    case "getId":
        sess := this.Session.SessionStart(this.Response, this.Request)
        ans := map[string]interface{}{"id": sess.Get("id")}
        res, err := json.Marshal(ans)
        utils.HandleErr("[Handle.Index] json.Marshal: ", err)
        fmt.Fprintf(this.Response, "%s", string(res))
        break

    case "select":
        tableName := data["table"].(string)
        fields := data["fields"].([]interface{})
        base := new(models.ModelManager)

        var model models.Entity
        var length int

        switch tableName {
        case "Users":
            length = len(base.Users().UserColumns)
            model = base.Users().Entity
            break
        case "Contests":
            length = len(base.Contests().Columns)
            model = base.Contests().Entity
            break
        }
        p := make([]string, length)
        j := 0
        for i, v := range fields {
            if v != nil {
                p[i] = v.(string)
                j++
            }
        }
        pp := make([]string, j)
        copy(pp[:], p[:j])
        answer := model.Select(nil, pp...)
        response, err := json.Marshal(answer)
        utils.HandleErr("[HandleLogin] json.Marshal: ", err)
        fmt.Fprintf(this.Response, "%s", response)

    case "update":
        tableName := data["table"].(string)
        base := new(models.ModelManager)

        var model models.Entity
        var length int

        switch tableName {
        case "Users":
            length = len(base.Users().UserColumns)
            model = base.Users().Entity
            break
        case "Contests":
            length = len(base.Contests().Columns)
            model = base.Contests().Entity
            break
        }

        d := data["data"].(map[string](interface{}))
        fields := utils.ArrayInterfaceToString(d["fields"].([]interface{}), length-1)
        values := d["userData"].([]interface{})

        model.Update(fields, values, fmt.Sprintf("id=%s", data["id"]))

        response, err := json.Marshal(map[string]interface{}{"result": "ok"})
        utils.HandleErr("[HandleLogin] json.Marshal: ", err)
        fmt.Fprintf(this.Response, "%s", response)
        break

    case "editBlanks":
        id := data["id"].(string)
        inf := data["data"].([]interface{})

        columns := connect.DBGetColumnNames("blank_" + id)
        fmt.Println(columns)

        used := make(map[string][]int, len(columns))
        for i, v := range columns {
            used[v] = make([]int, 2)
            used[v][0] = 0
            used[v][1] = i
        }
        used["id"][0] = 1

        n := len(columns)

        db := connect.DBConnect()
        defer connect.DBClose(db)

        base := new(models.ModelManager)
        blanks := base.Blanks()

        for i := 0; i < len(inf); i = i + 4 {
            colNameObj := inf[i].(map[string]interface{})
            colNameDBObj := inf[i+1].(map[string]interface{})
            colTypeObj := inf[i+2].(map[string]interface{})
            colLenObj := inf[i+3].(map[string]interface{})

            var type_ string
            switch colTypeObj["value"].(string) {
            case "input":
                type_ = "varchar(" + colLenObj["value"].(string) + ")"
                break
            case "select":
                type_ = "varchar(" + colLenObj["value"].(string) + ")[]"
                break
            case "date":
                type_ = colLenObj["value"].(string)
                break
            }

            if utils.IsExist(columns, colNameDBObj["value"].(string)) == false {
                query := "ALTER TABLE blank_" + id + " ADD COLUMN " + colNameDBObj["value"].(string) + " " + type_
                stmt, err := db.Prepare(query)
                defer connect.DBClose(stmt)
                utils.HandleErr("[Handler.Index->editBlank] Prepare: ", err)
                _, err = stmt.Exec()
                utils.HandleErr("[Handler.Index->editBlank] Exec: ", err)

                blanks.Update([]string{"columns[" + strconv.Itoa(n) + "]"}, []interface{}{colNameDBObj["value"].(string)}, fmt.Sprintf("contest_id=%s", id))
                blanks.Update([]string{"colNames[" + strconv.Itoa(n) + "]"}, []interface{}{colNameObj["value"].(string)}, fmt.Sprintf("contest_id=%s", id))
                blanks.Update([]string{"types[" + strconv.Itoa(n) + "]"}, []interface{}{type_}, fmt.Sprintf("contest_id=%s", id))
                n++
            } else {
                used[colNameDBObj["value"].(string)][0] = 1
                query := "ALTER TABLE blank_" + id + " ALTER COLUMN " + colNameDBObj["value"].(string) + " TYPE " + type_
                stmt, err := db.Prepare(query)
                defer connect.DBClose(stmt)
                utils.HandleErr("[Handler.Index->editBlank] Prepare: ", err)
                _, err = stmt.Exec()
                utils.HandleErr("[Handler.Index->editBlank] Exec: ", err)
                blanks.Update([]string{"types[" + strconv.Itoa(used[colNameDBObj["value"].(string)][1]) + "]"}, []interface{}{type_}, fmt.Sprintf("contest_id=%s", id))
            }
        }

        for i, v := range used {
            if v[0] == 0 {
                query := "UPDATE blanks SET columns = "
                query += "(SELECT del_elem_by_index ("
                query += "(SELECT columns FROM blanks WHERE contest_id =" + id + "),"
                query += strconv.Itoa(v[1]) + "))"
                query += "WHERE contest_id =" + id

                stmt, err := db.Prepare(query)
                defer connect.DBClose(stmt)
                utils.HandleErr("[Handler.Index->editBlank] Prepare: ", err)
                _, err = stmt.Exec()
                utils.HandleErr("[Handler.Index->editBlank] Exec: ", err)

                query = "UPDATE blanks SET colnames = "
                query += "(SELECT del_elem_by_index ("
                query += "(SELECT colnames FROM blanks WHERE contest_id =" + id + "),"
                query += strconv.Itoa(v[1]) + "))"
                query += "WHERE contest_id =" + id

                stmt, err = db.Prepare(query)
                defer connect.DBClose(stmt)
                utils.HandleErr("[Handler.Index->editBlank] Prepare: ", err)
                _, err = stmt.Exec()
                utils.HandleErr("[Handler.Index->editBlank] Exec: ", err)

                query = "UPDATE blanks SET types = "
                query += "(SELECT del_elem_by_index ("
                query += "(SELECT types FROM blanks WHERE contest_id =" + id + "),"
                query += strconv.Itoa(v[1]) + "))"
                query += "WHERE contest_id =" + id

                stmt, err = db.Prepare(query)
                defer connect.DBClose(stmt)
                utils.HandleErr("[Handler.Index->editBlank] Prepare: ", err)
                _, err = stmt.Exec()
                utils.HandleErr("[Handler.Index->editBlank] Exec: ", err)

                query = "ALTER TABLE blank_" + id + " DROP COLUMN IF EXISTS " + i
                stmt, err = db.Prepare(query)
                defer connect.DBClose(stmt)
                utils.HandleErr("[Handler.Index->editBlank] Prepare: ", err)
                _, err = stmt.Exec()
                utils.HandleErr("[Handler.Index->editBlank] Exec: ", err)
            }
        }

        query := "UPDATE blanks SET columns = "
        query += "(SELECT del_null_from_arr ("
        query += "(SELECT columns FROM blanks WHERE contest_id =" + id + ")))"
        query += "WHERE contest_id =" + id

        stmt, err := db.Prepare(query)
        defer connect.DBClose(stmt)
        utils.HandleErr("[Handler.Index->editBlank] Prepare: ", err)
        _, err = stmt.Exec()
        utils.HandleErr("[Handler.Index->editBlank] Exec: ", err)

        query = "UPDATE blanks SET colnames = "
        query += "(SELECT del_null_from_arr ("
        query += "(SELECT colnames FROM blanks WHERE contest_id =" + id + ")))"
        query += "WHERE contest_id =" + id

        stmt, err = db.Prepare(query)
        defer connect.DBClose(stmt)
        utils.HandleErr("[Handler.Index->editBlank] Prepare: ", err)
        _, err = stmt.Exec()
        utils.HandleErr("[Handler.Index->editBlank] Exec: ", err)

        query = "UPDATE blanks SET types = "
        query += "(SELECT del_null_from_arr ("
        query += "(SELECT types FROM blanks WHERE contest_id =" + id + ")))"
        query += "WHERE contest_id =" + id

        stmt, err = db.Prepare(query)
        defer connect.DBClose(stmt)
        utils.HandleErr("[Handler.Index->editBlank] Prepare: ", err)
        _, err = stmt.Exec()
        utils.HandleErr("[Handler.Index->editBlank] Exec: ", err)
        break

    case "addBlank":
        id := data["id"].(string)
        inf := data["data"].([]interface{})
        fmt.Println("inf: ", inf)

        columns := connect.DBGetColumnNames("blank_" + id)
        var fields []interface{}

        for i := 0; i < len(inf); i++ {
            field := inf[i].(map[string]interface{})
            fields = append(fields, field["value"].(string))
        }

        query := connect.DBInsert("blank_"+id, columns[1:])
        db := connect.DBConnect()
        stmt, err := db.Prepare(query)
        defer connect.DBClose(db, stmt)
        utils.HandleErr("[addBlank] Prepare: ", err)
        _, err = stmt.Exec(fields...)
        utils.HandleErr("[addBlank] Exec: ", err)

        ans := map[string]interface{}{"response": "ok"}
        res, err := json.Marshal(ans)
        utils.HandleErr("[Handle.Index] json.Marshal: ", err)
        fmt.Fprintf(this.Response, "%s", string(res))
    }
}
func DBConnect() *sql.DB {
	db, err := sql.Open("postgres", "host=localhost user="******" dbname="+dbname+" password="******" sslmode=disable")
	utils.HandleErr("Coonect DB: ", err)
	return db
}
func (this Entity) Select(where map[string]interface{}, fields ...string) []interface{} {
	keys := make([]string, len(where))
	vals := make([]interface{}, len(where))
	j := 0
	for i, v := range where {
		keys[j] = i
		vals[j] = v
		j++
	}
	db := connect.DBConnect()
	query := connect.DBSelect(this.TableName, keys, fields...)
	stmt, err := db.Prepare(query)
	utils.HandleErr("[Entity.Select] Prepare: ", err)
	defer connect.DBClose(db, stmt)

	rows, err := stmt.Query(vals...)
	utils.HandleErr("[Entity.Select] Query: ", err)

	rowsInf, err := stmt.Exec(vals...)
	utils.HandleErr("[Entity.Select] Exec: ", err)

	columns, err := rows.Columns()
	utils.HandleErr("[Entity.Select] Columns: ", err)

	row := make([]interface{}, len(columns))
	values := make([]interface{}, len(columns))
	for i, _ := range row {
		row[i] = &values[i]
	}

	l, err := rowsInf.RowsAffected()
	utils.HandleErr("[Entity.Select] RowsAffected: ", err)
	answer := make([]interface{}, l)
	j = 0

	for rows.Next() {
		rows.Scan(row...)
		answer[j] = make(map[string]interface{}, len(values))
		record := make(map[string]interface{}, len(values))
		for i, col := range values {
			if col != nil {
				fmt.Printf("\n%s: type= %s\n", columns[i], reflect.TypeOf(col))
				switch col.(type) {
				default:
					utils.HandleErr("Entity.Select: Unexpected type.", nil)
				case bool:
					record[columns[i]] = col.(bool)
				case int:
					record[columns[i]] = col.(int)
				case int64:
					record[columns[i]] = col.(int64)
				case float64:
					record[columns[i]] = col.(float64)
				case string:
					record[columns[i]] = col.(string)
				case []byte:
					record[columns[i]] = string(col.([]byte))
				case []int8:
					record[columns[i]] = col.([]string)
				case time.Time:
					record[columns[i]] = col
				}
			}
			answer[j] = record
		}
		j++
	}
	return answer
}
func DBInitSchema() {
	db := DBConnect()
	defer DBClose(db)
	query := `CREATE TABLE IF NOT EXISTS users (
                    id       serial       NOT NULL PRIMARY KEY,
                    login    varchar(32)  NOT NULL UNIQUE,
                    password varchar(128) NOT NULL,
                    salt     varchar(64)  NOT NULL,
                    sid      varchar(40)  NOT NULL DEFAULT '',
                
                    fname    varchar(32)  NOT NULL DEFAULT '',
                    lname    varchar(32)  NOT NULL DEFAULT '',
                    pname    varchar(32)  NOT NULL DEFAULT '',
                    email    varchar(32)  NOT NULL DEFAULT '',
                    phone    varchar(32)  NOT NULL DEFAULT '',
                
                    region   varchar(32)  NOT NULL DEFAULT '',
                    district varchar(32)  NOT NULL DEFAULT '',
                    city     varchar(32)  NOT NULL DEFAULT '',
                    street   varchar(32)  NOT NULL DEFAULT '',
                    building varchar(32)  NOT NULL DEFAULT ''
                );`
	_, err := db.Exec(query)
	utils.HandleErr("[Connect.InitSchema.Users]: ", err)
	query = `CREATE TABLE IF NOT EXISTS contests (
                    id       serial       NOT NULL PRIMARY KEY,
                    name     varchar(128) NOT NULL UNIQUE,
                    date     date         NOT NULL
                );`
	_, err = db.Exec(query)
	utils.HandleErr("[Connect.InitSchema.Contests]: ", err)
	query = `CREATE TABLE IF NOT EXISTS blanks (
                    id          serial        NOT NULL PRIMARY KEY,
                    name        varchar(128)  NOT NULL UNIQUE,
                    contest_id  int           NOT NULL REFERENCES contests (id) ON DELETE CASCADE,
                    columns     varchar(32)[],
                    colNames    varchar(32)[],
                    types       varchar(32)[]
                );`
	_, err = db.Exec(query)
	utils.HandleErr("[Connect.InitSchema.Contests]: ", err)
	query = `CREATE OR REPLACE FUNCTION del_elem_by_index(anyarray, integer)
              RETURNS anyarray AS
            $BODY$ 
                declare 
                    arr_ $1%type;
                    idx_ $2%type;
                begin
                    for idx_ in array_lower($1, 1)..array_upper($1, 1) loop
                        if not idx_ = $2 then 
                            arr_ = array_append(arr_, $1[idx_]);
                        else 
                            arr_ = array_append(arr_, NULL);
                        end if;
                    end loop;
                    return arr_;
                end;
            $BODY$
              LANGUAGE plpgsql VOLATILE
            COST 100;
            ALTER FUNCTION del_elem_by_index(anyarray, integer)
            OWNER TO admin;`
	_, err = db.Exec(query)
	utils.HandleErr("[Connect.InitSchema.del_elem_by_index]: ", err)

	query = `CREATE OR REPLACE FUNCTION del_null_from_arr(anyarray)
              RETURNS anyarray AS
            $BODY$ 
                declare
                    arr_ $1%type;
                    idx_ int;
                begin
                    for idx_ in array_lower($1, 1)..array_upper($1, 1) loop
                        if not $1[idx_] = '' then
                            arr_ = array_append(arr_, $1[idx_]);
                        end if;
                    end loop;
                    return arr_;
                end;
            $BODY$
              LANGUAGE plpgsql VOLATILE
                COST 100;
            ALTER FUNCTION del_null_from_arr(anyarray)
                  OWNER TO admin;`
	_, err = db.Exec(query)
	utils.HandleErr("[Connect.InitSchema.del_null_from_arr]: ", err)
}
func (this *Handler) Edit(tableName string) {
	sess := this.Session.SessionStart(this.Response, this.Request)
	createTime := sess.Get("createTime")
	life := this.Session.Maxlifetime
	if createTime.(int64)+life < time.Now().Unix() {
		this.Session.SessionDestroy(this.Response, this.Request)
		fmt.Println("Edit - Destroy")
		tmp, err := template.ParseFiles(
			"view/index.html",
			"view/header.html",
			"view/footer.html")
		utils.HandleErr("[handler.select] ParseFiles: ", err)
		err = tmp.ExecuteTemplate(this.Response, "index", nil)
		utils.HandleErr("[handler.select] ExecuteTemplate: ", err)
		return
	}
	sess.Set("createTime", time.Now().Unix())
	oper := this.Request.FormValue("oper")
	base := new(models.ModelManager)
	var model models.Entity
	switch tableName {
	case "Users":
		model = base.Users().Entity
		break
	case "Contests":
		model = base.Contests().Entity
		break
	case "Blanks":
		model = base.Blanks().Entity
		break
	}

	params := make([]interface{}, len(model.Columns)-1)
	for i := 0; i < len(model.Columns)-1 && this.Request.FormValue(model.Columns[i+1]) != ""; i++ {
		if model.Columns[i+1] == "date" {
			params[i] = this.Request.FormValue(model.Columns[i+1])[0:10]
		} else {
			params[i] = this.Request.FormValue(model.Columns[i+1])
		}
	}

	switch oper {
	case "edit":
		model.Update(model.Columns[1:], params, fmt.Sprintf("id=%s", this.Request.FormValue("id")))
		break
	case "add":
		model.Insert(model.Columns[1:], params)
		if tableName == "Contests" {
			id := connect.DBGetLastInsertedId(tableName)
			models.CreateBlank(id)
			fmt.Println("last inserted id: ", id)
		}
		break
	case "del":
		ids := strings.Split(this.Request.FormValue("id"), ",")
		p := make([]interface{}, len(ids))
		for i, v := range ids {
			p[i] = interface{}(v)
		}
		model.Delete("id", p)
		break
	}
}