Skip to content

Commit

Permalink
Add cassandra and hive
Browse files Browse the repository at this point in the history
  • Loading branch information
minhduc140583 committed Oct 1, 2023
1 parent 6574dd1 commit 5c4d56d
Show file tree
Hide file tree
Showing 13 changed files with 1,411 additions and 17 deletions.
29 changes: 29 additions & 0 deletions cassandra/map.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package cassandra

import (
"context"
"reflect"
)

func MapModels(ctx context.Context, models interface{}, mp func(context.Context, interface{}) (interface{}, error)) (interface{}, error) {
vo := reflect.Indirect(reflect.ValueOf(models))
if vo.Kind() == reflect.Ptr {
vo = reflect.Indirect(vo)
}
if vo.Kind() == reflect.Slice {
le := vo.Len()
for i := 0; i < le; i++ {
x := vo.Index(i)
k := x.Kind()
if k == reflect.Struct {
y := x.Addr().Interface()
mp(ctx, y)
} else {
y := x.Interface()
mp(ctx, y)
}

}
}
return models, nil
}
File renamed without changes.
133 changes: 133 additions & 0 deletions cassandra/scan.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package cassandra

import (
"errors"
"github.com/gocql/gocql"
"reflect"
"strings"
)

func ScanIter(iter *gocql.Iter, results interface{}, options...map[string]int) error {
modelType := reflect.TypeOf(results).Elem().Elem()

tb, er2 := Scan(iter, modelType, options...)
if er2 != nil {
return er2
}
for _, element := range tb {
appendToArray(results, element)
}
return nil
}
func appendToArray(arr interface{}, item interface{}) interface{} {
arrValue := reflect.ValueOf(arr)
elemValue := reflect.Indirect(arrValue)

itemValue := reflect.ValueOf(item)
if itemValue.Kind() == reflect.Ptr {
itemValue = reflect.Indirect(itemValue)
}
elemValue.Set(reflect.Append(elemValue, itemValue))
return arr
}
func GetColumnIndexes(modelType reflect.Type) (map[string]int, error) {
ma := make(map[string]int, 0)
if modelType.Kind() != reflect.Struct {
return ma, errors.New("bad type")
}
for i := 0; i < modelType.NumField(); i++ {
field := modelType.Field(i)
ormTag := field.Tag.Get("gorm")
column, ok := FindTag(ormTag, "column")
column = strings.ToLower(column)
if ok {
ma[column] = i
}
}
return ma, nil
}
func FindTag(tag string, key string) (string, bool) {
if has := strings.Contains(tag, key); has {
str1 := strings.Split(tag, ";")
num := len(str1)
for i := 0; i < num; i++ {
str2 := strings.Split(str1[i], ":")
for j := 0; j < len(str2); j++ {
if str2[j] == key {
return str2[j+1], true
}
}
}
}
return "", false
}
func Scan(iter *gocql.Iter, modelType reflect.Type, options...map[string]int) (t []interface{}, err error) {
var fieldsIndex map[string]int
if len(options) > 0 && options[0] != nil {
fieldsIndex = options[0]
} else {
fieldsIndex, err = GetColumnIndexes(modelType)
}
if err != nil {
return
}
columns := GetColumns(iter.Columns())
for {
initModel := reflect.New(modelType).Interface()
r := StructScan(initModel, columns, fieldsIndex, -1)
if !iter.Scan(r...) {
return
} else {
t = append(t, initModel)
}
}
}
func StructScan(s interface{}, columns []string, fieldsIndex map[string]int, indexIgnore int) (r []interface{}) {
if s != nil {
modelType := reflect.TypeOf(s).Elem()
maps := reflect.Indirect(reflect.ValueOf(s))
if columns == nil {
for i := 0; i < maps.NumField(); i++ {
r = append(r, maps.Field(i).Addr().Interface())
}
return
}
for i, columnsName := range columns {
if i == indexIgnore {
continue
}
var index int
var ok bool
var valueField reflect.Value
if fieldsIndex == nil {
if _, ok = modelType.FieldByName(columnsName); !ok {
var t interface{}
r = append(r, &t)
continue
}
valueField = maps.FieldByName(columnsName)
} else {
if index, ok = fieldsIndex[columnsName]; !ok {
var t interface{}
r = append(r, &t)
continue
}
valueField = maps.Field(index)
}
x := valueField.Addr().Interface()
r = append(r, x)
}
}
return
}
func GetColumns(cols []gocql.ColumnInfo) []string {
c2 := make([]string, 0)
if cols == nil {
return c2
}
for _, c := range cols {
s := strings.ToLower(c.Name)
c2 = append(c2, s)
}
return c2
}
144 changes: 144 additions & 0 deletions cassandra/search_builder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package cassandra

import (
"context"
"encoding/hex"
"reflect"
"strings"

"github.com/gocql/gocql"
)

const (
desc = "desc"
asc = "asc"
)

type SearchBuilder struct {
DB *gocql.ClusterConfig
BuildQuery func(sm interface{}) (string, []interface{})
ModelType reflect.Type
Map func(ctx context.Context, model interface{}) (interface{}, error)
fieldsIndex map[string]int
}
func NewSearchQuery(db *gocql.ClusterConfig, modelType reflect.Type, buildQuery func(interface{}) (string, []interface{}), options ...func(context.Context, interface{}) (interface{}, error)) (*SearchBuilder, error) {
return NewSearchBuilder(db, modelType, buildQuery, options...)
}
func NewSearchBuilder(db *gocql.ClusterConfig, modelType reflect.Type, buildQuery func(interface{}) (string, []interface{}), options ...func(context.Context, interface{}) (interface{}, error)) (*SearchBuilder, error) {
var mp func(context.Context, interface{}) (interface{}, error)
if len(options) >= 1 {
mp = options[0]
}
fieldsIndex, err := GetColumnIndexes(modelType)
if err != nil {
return nil, err
}
builder := &SearchBuilder{DB: db, fieldsIndex: fieldsIndex, BuildQuery: buildQuery, ModelType: modelType, Map: mp}
return builder, nil
}

func (b *SearchBuilder) Search(ctx context.Context, m interface{}, results interface{}, limit int64, refId string) (string, error) {
sql, params := b.BuildQuery(m)
ses, err := b.DB.CreateSession()
defer ses.Close()

if err != nil {
return "", err
}
nextPageToken, er2 := QueryWithMap(ses, b.fieldsIndex, results, sql, params, limit, refId, b.Map)
return nextPageToken, er2
}
func QueryWithMap(ses *gocql.Session, fieldsIndex map[string]int, results interface{}, sql string, values []interface{}, max int64, refId string, options...func(context.Context, interface{}) (interface{}, error)) (string, error) {
var mp func(context.Context, interface{}) (interface{}, error)
if len(options) > 0 && options[0] != nil {
mp = options[0]
}
next, er0 := hex.DecodeString(refId)
if er0 != nil {
return "", er0
}
query := ses.Query(sql, values...).PageState(next).PageSize(int(max))
if query.Exec() != nil {
return "", query.Exec()
}
err := ScanIter(query.Iter(), results, fieldsIndex)
if err != nil {
return "", err
}
nextPageToken := hex.EncodeToString(query.Iter().PageState())
if mp != nil {
_, err := MapModels(context.Background(), results, mp)
return nextPageToken, err
}
return nextPageToken, nil
}
func GetSort(sortString string, modelType reflect.Type) string {
var sort = make([]string, 0)
sorts := strings.Split(sortString, ",")
for i := 0; i < len(sorts); i++ {
sortField := strings.TrimSpace(sorts[i])
fieldName := sortField
c := sortField[0:1]
if c == "-" || c == "+" {
fieldName = sortField[1:]
}
columnName := GetColumnNameForSearch(modelType, fieldName)
if len(columnName) > 0 {
sortType := GetSortType(c)
sort = append(sort, columnName+" "+sortType)
}
}
if len(sort) > 0 {
return strings.Join(sort, ",")
} else {
return ""
}
}
func BuildSort(sortString string, modelType reflect.Type) string {
sort := GetSort(sortString, modelType)
if len(sort) > 0 {
return ` order by ` + sort
} else {
return ""
}
}
func GetColumnNameForSearch(modelType reflect.Type, sortField string) string {
sortField = strings.TrimSpace(sortField)
i, _, column := GetFieldByJson(modelType, sortField)
if i > -1 {
return column
}
return ""
}
func GetSortType(sortType string) string {
if sortType == "-" {
return desc
} else {
return asc
}
}
func GetFieldByJson(modelType reflect.Type, jsonName string) (int, string, string) {
numField := modelType.NumField()
for i := 0; i < numField; i++ {
field := modelType.Field(i)
tag1, ok1 := field.Tag.Lookup("json")
if ok1 && strings.Split(tag1, ",")[0] == jsonName {
if tag2, ok2 := field.Tag.Lookup("gorm"); ok2 {
if has := strings.Contains(tag2, "column"); has {
str1 := strings.Split(tag2, ";")
num := len(str1)
for k := 0; k < num; k++ {
str2 := strings.Split(str1[k], ":")
for j := 0; j < len(str2); j++ {
if str2[j] == "column" {
return i, field.Name, str2[j+1]
}
}
}
}
}
return i, field.Name, ""
}
}
return -1, jsonName, jsonName
}
24 changes: 24 additions & 0 deletions firestore/connect.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package firestore

import (
"cloud.google.com/go/firestore"
"context"
firebase "firebase.google.com/go"
"google.golang.org/api/option"
"log"
)

func Connect(ctx context.Context, credentials []byte) (*firestore.Client, error) {
app, er1 := firebase.NewApp(ctx, nil, option.WithCredentialsJSON(credentials))
if er1 != nil {
log.Fatalf("Could not create admin client: %v", er1)
return nil, er1
}

client, er2 := app.Firestore(ctx)
if er2 != nil {
log.Fatalf("Could not create data operations client: %v", er2)
return nil, er2
}
return client, nil
}
17 changes: 0 additions & 17 deletions firestore/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,10 @@ package firestore

import (
"cloud.google.com/go/firestore"
"context"
firebase "firebase.google.com/go"
"google.golang.org/api/option"
"log"
"reflect"
"strings"
)
func Connect(ctx context.Context, credentials []byte) (*firestore.Client, error) {
app, er1 := firebase.NewApp(ctx, nil, option.WithCredentialsJSON(credentials))
if er1 != nil {
log.Fatalf("Could not create admin client: %v", er1)
return nil, er1
}

client, er2 := app.Firestore(ctx)
if er2 != nil {
log.Fatalf("Could not create data operations client: %v", er2)
return nil, er2
}
return client, nil
}
func BindCommonFields(result interface{}, doc *firestore.DocumentSnapshot, idIndex int, createdTimeIndex int, updatedTimeIndex int) {
rv := reflect.Indirect(reflect.ValueOf(result))
fv := rv.Field(idIndex)
Expand Down
6 changes: 6 additions & 0 deletions geo/geo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package geo

type JSON struct {
Type string `json:"type,omitempty" bson:"type,omitempty"`
Coordinates []float64 `json:"coordinates,omitempty" bson:"coordinates,omitempty"`
}
Loading

0 comments on commit 5c4d56d

Please sign in to comment.