<commit_before>package cqlb

import (
	"fmt"
	"reflect"
	"strings"

	"github.com/gocql/gocql"
	"github.com/jinzhu/inflection"
	"github.com/relops/cqlr"
)

const (
	insertQueryTemplate = "insert into %s (%s) values(%s);"
	whereQueryTemplate  = "select %s from %s where %s %s %s;"
)

type fieldTag struct {
	Name      string
	OmitEmpty bool
}

type Session struct {
	s         *gocql.Session
	query     interface{}
	args      []interface{}
	sel       []string
	limit     int
	value     reflect.Value
	indirect  reflect.Value
	tableName string
}

func SetSession(s *gocql.Session) *Session {
	return &Session{s: s}
}

func (s *Session) Find(slice interface{}) error {
	// var fields map[string]interface{}
	// var fieldsToScan []interface{}
	// value := reflect.ValueOf(slice)
	// k := value.Kind()
	// if k != reflect.Slice {
	// 	return errors.New("value should be a slice.")
	// }
	// v := value.Index(0)
	// indirect := reflect.Indirect(v)
	// s.setModel(v)
	// query := s.query
	// vq := reflect.ValueOf(query)
	// kindQuery := vq.Kind()
	// switch kindQuery {
	// case reflect.Map:
	// 	fields = whereFieldsFromMap(query)
	// }
	// iter := s.s.Query(s.whereQuery(fields), values).Iter()
	// cols := iter.Columns()
	// values := make([]interface{}, len(cols))
	// names := f["names"].([]string)
	// for i, col := range cols {
	// 	values[i] = f["strategies"].(map[string]interface{})[col.Name]
	// }
	return nil
}

func (s *Session) Insert(v interface{}) error {
	f := fields(v)
	stmt := insertQuery(f)
	return s.s.Query(stmt, f["values"].([]interface{})...).Exec()
}

func (s *Session) Where(query interface{}, args ...interface{}) *Session {
	ns := s.clone()
	ns.query = query
	ns.args = args
	return ns
}

func (s *Session) Limit(limit int) *Session {
	c := s.clone()
	c.limit = limit
	return c
}

func (s *Session) Model(value interface{}) *Session {
	v := reflect.ValueOf(value)
	ns := s.clone()
	ns.setModel(v)
	return ns
}

func (s *Session) Scan(value interface{}) bool {
	var fields map[string]interface{}
	v := reflect.ValueOf(value)
	s.setModel(v)
	query := s.query
	vq := reflect.ValueOf(query)
	kindQuery := vq.Kind()
	switch kindQuery {
	case reflect.Map:
		fields = whereFieldsFromMap(query)
	}
	values := fields["values"].([]interface{})
	q := s.s.Query(s.whereQuery(fields), values...)
	b := cqlr.BindQuery(q)
	return b.Scan(value)
}

func (s *Session) Select(sel ...string) *Session {
	c := s.clone()
	c.sel = sel
	return c
}

func (s *Session) limitString() string {
	if limit := s.limit; limit > 0 {
		return fmt.Sprintf("LIMIT %v", limit)
	}
	return ""
}

func (s *Session) selectString() string {
	if sel := s.sel; len(sel) > 0 {
		return strings.Join(sel, ",")
	}
	return "*"
}

func (s *Session) setModel(v reflect.Value) {
	indirect := reflect.Indirect(v)
	t := indirect.Type()
	s.value = v
	s.indirect = indirect
	s.tableName = inflection.Plural(strings.ToLower(t.Name()))
}

func (s *Session) clone() *Session {
	ns := *s
	return &ns
}

func (s *Session) whereQuery(f map[string]interface{}) string {
	sel := s.selectString()
	limit := s.limitString()
	query := fmt.Sprintf(whereQueryTemplate, sel, s.tableName, f["conditions"], limit, "")
	return query
}

func insertQuery(f map[string]interface{}) string {
	query := fmt.Sprintf(insertQueryTemplate, f["table_name"], f["names"], f["slots"])
	return query
}

func compile(v interface{}, cols []gocql.ColumnInfo) error {

	return nil
}

func tag(f reflect.StructField) *fieldTag {
	ft := &fieldTag{}
	tag := f.Tag.Get("cql")
	opts := strings.Split(tag, ",")<commit_msg>It is possible to modify consistency and the table name.<commit_after>package cqlb

import (
	"fmt"
	"reflect"
	"strings"

	"github.com/gocql/gocql"
	"github.com/jinzhu/inflection"
	"github.com/relops/cqlr"
)

const (
	insertQueryTemplate = "insert into %s (%s) values(%s);"
	whereQueryTemplate  = "select %s from %s where %s %s %s;"
)

type fieldTag struct {
	Name      string
	OmitEmpty bool
}

type Session struct {
	s           *gocql.Session
	query       interface{}
	args        []interface{}
	sel         []string
	limit       int
	consistency gocql.Consistency
	value       reflect.Value
	indirect    reflect.Value
	tableName   string
}

func SetSession(s *gocql.Session) *Session {
	return &Session{s: s}
}

func (s *Session) Consistency(consistency gocql.Consistency) *Session {
	c := s.clone()
	c.consistency = consistency
	return c
}

func (s *Session) Find(slice interface{}) error {
	// var fields map[string]interface{}
	// var fieldsToScan []interface{}
	// value := reflect.ValueOf(slice)
	// k := value.Kind()
	// if k != reflect.Slice {
	// 	return errors.New("value should be a slice.")
	// }
	// v := value.Index(0)
	// indirect := reflect.Indirect(v)
	// s.setModel(v)
	// query := s.query
	// vq := reflect.ValueOf(query)
	// kindQuery := vq.Kind()
	// switch kindQuery {
	// case reflect.Map:
	// 	fields = whereFieldsFromMap(query)
	// }
	// iter := s.s.Query(s.whereQuery(fields), values).Iter()
	// cols := iter.Columns()
	// values := make([]interface{}, len(cols))
	// names := f["names"].([]string)
	// for i, col := range cols {
	// 	values[i] = f["strategies"].(map[string]interface{})[col.Name]
	// }
	return nil
}

func (s *Session) Insert(v interface{}) error {
	f := fields(v)
	stmt := insertQuery(f)
	return s.s.Query(stmt, f["values"].([]interface{})...).Exec()
}

func (s *Session) Where(query interface{}, args ...interface{}) *Session {
	ns := s.clone()
	ns.query = query
	ns.args = args
	return ns
}

func (s *Session) Limit(limit int) *Session {
	c := s.clone()
	c.limit = limit
	return c
}

func (s *Session) Model(value interface{}) *Session {
	v := reflect.ValueOf(value)
	ns := s.clone()
	ns.setModel(v)
	return ns
}

func (s *Session) Scan(value interface{}) bool {
	var fields map[string]interface{}
	v := reflect.ValueOf(value)
	s.setModel(v)
	query := s.query
	vq := reflect.ValueOf(query)
	kindQuery := vq.Kind()
	switch kindQuery {
	case reflect.Map:
		fields = whereFieldsFromMap(query)
	}
	values := fields["values"].([]interface{})
	q := s.s.Query(s.whereQuery(fields), values...)
	if consistency := s.consistency; consistency > 0 {
		q = q.Consistency(consistency)
	}
	b := cqlr.BindQuery(q)
	return b.Scan(value)
}

func (s *Session) Select(sel ...string) *Session {
	c := s.clone()
	c.sel = sel
	return c
}

func (s *Session) Table(name string) *Session {
	c := s.clone()
	c.tableName = name
	return c
}

func (s *Session) limitString() string {
	if limit := s.limit; limit > 0 {
		return fmt.Sprintf("LIMIT %v", limit)
	}
	return ""
}

func (s *Session) selectString() string {
	if sel := s.sel; len(sel) > 0 {
		return strings.Join(sel, ",")
	}
	return "*"
}

func (s *Session) setModel(v reflect.Value) {
	indirect := reflect.Indirect(v)
	t := indirect.Type()
	s.value = v
	s.indirect = indirect
	if s.tableName == "" {
		s.tableName = inflection.Plural(strings.ToLower(t.Name()))
	}
}

func (s *Session) clone() *Session {
	ns := *s
	return &ns
}

func (s *Session) whereQuery(f map[string]interface{}) string {
	sel := s.selectString()
	limit := s.limitString()
	query := fmt.Sprintf(whereQueryTemplate, sel, s.tableName, f["conditions"], limit, "")
	return query
}

func insertQuery(f map[string]interface{}) string {
	query := fmt.Sprintf(insertQueryTemplate, f["table_name"], f["names"], f["slots"])
	return query
}

func compile(v interface{}, cols []gocql.ColumnInfo) error {

	return nil
}

func tag(f reflect.StructField) *fieldTag {
	ft := &fieldTag{}
	tag := f.Tag.Get("cql")
	opts := strings.Split(tag, ",")
{'fraction_non_alphanumeric': 0.17890822154336566, 'fraction_numerical': 0.0009297383450657458, 'mean_word_length': 3.65389369592089, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1898291', 'n_tokens_mistral': 2780, 'n_tokens_neox': 2754, 'n_words': 678}