climc:allow disable term line width

This commit is contained in:
root
2020-06-05 11:03:15 +08:00
committed by lvyangyang
parent db91628f0b
commit 0a0af5cfa2
15 changed files with 392 additions and 221 deletions

8
go.mod
View File

@@ -127,13 +127,13 @@ require (
k8s.io/cluster-bootstrap v0.17.3
k8s.io/kubernetes v1.16.0
yunion.io/x/executor v0.0.0-20200227030256-a18417815e74
yunion.io/x/jsonutils v0.0.0-20200415132054-2bf8a5e94501
yunion.io/x/jsonutils v0.0.0-20200601015434-d61aefddfe79
yunion.io/x/log v0.0.0-20200313080802-57a4ce5966b3
yunion.io/x/ovsdb v0.0.0-20200526071744-27bf0940cbc7
yunion.io/x/pkg v0.0.0-20200516092703-0a53bc9270aa
yunion.io/x/pkg v0.0.0-20200603123312-ad58e621aec0
yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e
yunion.io/x/sqlchemy v0.0.0-20200312002602-1177cd8fbc57
yunion.io/x/structarg v0.0.0-20200423163001-168d0687be7e
yunion.io/x/sqlchemy v0.0.0-20200603015906-56eda65f53e4
yunion.io/x/structarg v0.0.0-20200603035440-0690e9bc7655
)
replace (

22
go.sum
View File

@@ -769,8 +769,6 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yousong/ovsdb v0.0.0-20200526055947-05168ba66aaf h1:MfwaIeKiVUqeWZSKyO5GwOccti0O/ENZDdqOkB3OPnU=
github.com/yousong/ovsdb v0.0.0-20200526055947-05168ba66aaf/go.mod h1:0vLkNEhlmA64HViPBAnSTUMrx5QP1CLsxXmxDKQ80tc=
github.com/yunionio/go-ceph v0.0.0-20190912101231-6f05a06b3859 h1:wu596gn6sV3j5wy+GDfiG8nwtzIDpalJihfmC/TjoYc=
github.com/yunionio/go-ceph v0.0.0-20190912101231-6f05a06b3859/go.mod h1:8XuBae5AzsgotLArJSewMruYVaQs8AlfsK5jBCG8T9Y=
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
@@ -1110,27 +1108,23 @@ vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc/go.mod h1:so/NYdZXCz+E3ZpW0uAoCj
yunion.io/x/executor v0.0.0-20200227030256-a18417815e74 h1:A15C6VdVRWvmQ9pAJHrUs9yan5qKlYH7uaRxHg1kRbk=
yunion.io/x/executor v0.0.0-20200227030256-a18417815e74/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
yunion.io/x/jsonutils v0.0.0-20200415132054-2bf8a5e94501 h1:i1r9XvbdxH3FgTCLmTaRi3MzQqhiQimXJRlUOPgrxnU=
yunion.io/x/jsonutils v0.0.0-20200415132054-2bf8a5e94501/go.mod h1:T7kxQJR13+t7z0TuT+Wzd7MTxBOk2H9c0pO1ONQSv90=
yunion.io/x/jsonutils v0.0.0-20200601015434-d61aefddfe79 h1:MP8wgqdmGbg8Tb1O2/HQlyeKMrEPsq3R0pClQFMJmlg=
yunion.io/x/jsonutils v0.0.0-20200601015434-d61aefddfe79/go.mod h1:T7kxQJR13+t7z0TuT+Wzd7MTxBOk2H9c0pO1ONQSv90=
yunion.io/x/log v0.0.0-20190514041436-04ce53b17c6b/go.mod h1:+gauLs73omeJAPlsXcevLsJLKixV+sR/E7WSYTSx1fE=
yunion.io/x/log v0.0.0-20190629062853-9f6483a7103d h1:59zrDL7Ft+hDukguJRmLr/Gdu/9V75x+yX99ovZwfaA=
yunion.io/x/log v0.0.0-20190629062853-9f6483a7103d/go.mod h1:LC6f/4FozL0iaAbnFt2eDX9jlsyo3WiOUPm03d7+U4U=
yunion.io/x/log v0.0.0-20200313080802-57a4ce5966b3 h1:5Wc5hkB8PtMudmHuzCyok960RuOa9I55imIGrigSdjs=
yunion.io/x/log v0.0.0-20200313080802-57a4ce5966b3/go.mod h1:LC6f/4FozL0iaAbnFt2eDX9jlsyo3WiOUPm03d7+U4U=
yunion.io/x/ovsdb v0.0.0-20200512112253-a3601d1ee987 h1:BlHpXbNhqG1rZ57io0+XI4L9ckWunn7LHR2JQikGqQg=
yunion.io/x/ovsdb v0.0.0-20200512112253-a3601d1ee987/go.mod h1:0vLkNEhlmA64HViPBAnSTUMrx5QP1CLsxXmxDKQ80tc=
yunion.io/x/ovsdb v0.0.0-20200526062315-c921cb58f76e h1:v5AnakAKVOvYoYEtsTkntcr4MIgawTAI106/5mmaMAs=
yunion.io/x/ovsdb v0.0.0-20200526062315-c921cb58f76e/go.mod h1:0vLkNEhlmA64HViPBAnSTUMrx5QP1CLsxXmxDKQ80tc=
yunion.io/x/ovsdb v0.0.0-20200526071744-27bf0940cbc7 h1:gjqNa2uQzIEXyySsbvVz0UltTEbGsnFFlvnzOpCfHdo=
yunion.io/x/ovsdb v0.0.0-20200526071744-27bf0940cbc7/go.mod h1:0vLkNEhlmA64HViPBAnSTUMrx5QP1CLsxXmxDKQ80tc=
yunion.io/x/pkg v0.0.0-20190620104149-945c25821dbf/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/pkg v0.0.0-20190628082551-f4033ba2ea30/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/pkg v0.0.0-20200302034534-fdf44d54b070/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/pkg v0.0.0-20200516092703-0a53bc9270aa h1:VizPfW8+mLFEE7W/97zxQJbfdxchi2dn1M/Y7YBwTTc=
yunion.io/x/pkg v0.0.0-20200516092703-0a53bc9270aa/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/pkg v0.0.0-20200603123312-ad58e621aec0 h1:i2AghhUX3Xr/iri9yRJ5spsE6OX+akutGwZ2XVcE02U=
yunion.io/x/pkg v0.0.0-20200603123312-ad58e621aec0/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e h1:v+EzIadodSwkdZ/7bremd7J8J50Cise/HCylsOJngmo=
yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e/go.mod h1:0iFKpOs1y4lbCxeOmq3Xx/0AcQoewVPwj62eRluioEo=
yunion.io/x/sqlchemy v0.0.0-20200312002602-1177cd8fbc57 h1:KtQAuLJ00RSUVqkiRmJ1DiDABiw0U3xxXnzD3lGavaY=
yunion.io/x/sqlchemy v0.0.0-20200312002602-1177cd8fbc57/go.mod h1:FTdwPdGhMgh4E+UFXc9klI1Ok34fMuybTT+jLhOaIjI=
yunion.io/x/structarg v0.0.0-20200423163001-168d0687be7e h1:pctCe/EPel3F1B83pJ2q9b34Umd1NdbLW1Yd+Lzur2s=
yunion.io/x/structarg v0.0.0-20200423163001-168d0687be7e/go.mod h1:EP6NSv2C0zzqBDTKumv8hPWLb3XvgMZDHQRfyuOrQng=
yunion.io/x/sqlchemy v0.0.0-20200603015906-56eda65f53e4 h1:y6lrMWPt/xd8f6B1E0s+iL7xx/Y8ui4S6h9UJBzUDk4=
yunion.io/x/sqlchemy v0.0.0-20200603015906-56eda65f53e4/go.mod h1:FTdwPdGhMgh4E+UFXc9klI1Ok34fMuybTT+jLhOaIjI=
yunion.io/x/structarg v0.0.0-20200603035440-0690e9bc7655 h1:Y01W3976TSUm3S9QDbZS4ZgHKoP79PgE+1IF/iPu5bc=
yunion.io/x/structarg v0.0.0-20200603035440-0690e9bc7655/go.mod h1:EP6NSv2C0zzqBDTKumv8hPWLb3XvgMZDHQRfyuOrQng=

View File

@@ -16,6 +16,7 @@ package printutils
import (
"fmt"
"os"
"sort"
"yunion.io/x/jsonutils"
@@ -57,7 +58,12 @@ func PrintJSONList(list *modulebase.ListResult, columns []string) {
}
}
}
pt := prettytable.NewPrettyTable(colsWithData)
osTryTermWidth := os.Getenv("OS_TRY_TERM_WIDTH")
tryTermWidth := true
if osTryTermWidth == "false" {
tryTermWidth = false
}
pt := prettytable.NewPrettyTableWithTryTermWidth(colsWithData, tryTermWidth)
rows := make([][]string, 0)
for _, obj := range list.Data {
row := make([]string, 0)

8
vendor/modules.txt vendored
View File

@@ -991,7 +991,7 @@ sigs.k8s.io/yaml
yunion.io/x/executor/apis
yunion.io/x/executor/client
yunion.io/x/executor/server
# yunion.io/x/jsonutils v0.0.0-20200415132054-2bf8a5e94501
# yunion.io/x/jsonutils v0.0.0-20200601015434-d61aefddfe79
yunion.io/x/jsonutils
# yunion.io/x/log v0.0.0-20200313080802-57a4ce5966b3
yunion.io/x/log
@@ -1000,7 +1000,7 @@ yunion.io/x/log/hooks
yunion.io/x/ovsdb/cli_util
yunion.io/x/ovsdb/schema/ovn_nb
yunion.io/x/ovsdb/types
# yunion.io/x/pkg v0.0.0-20200516092703-0a53bc9270aa
# yunion.io/x/pkg v0.0.0-20200603123312-ad58e621aec0
yunion.io/x/pkg/errors
yunion.io/x/pkg/gotypes
yunion.io/x/pkg/prettytable
@@ -1032,7 +1032,7 @@ yunion.io/x/pkg/util/workqueue
yunion.io/x/pkg/utils
# yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e
yunion.io/x/s3cli
# yunion.io/x/sqlchemy v0.0.0-20200312002602-1177cd8fbc57
# yunion.io/x/sqlchemy v0.0.0-20200603015906-56eda65f53e4
yunion.io/x/sqlchemy
# yunion.io/x/structarg v0.0.0-20200423163001-168d0687be7e
# yunion.io/x/structarg v0.0.0-20200603035440-0690e9bc7655
yunion.io/x/structarg

View File

@@ -17,6 +17,7 @@ package jsonutils
import (
"fmt"
"strings"
"yunion.io/x/pkg/util/regutils"
)

View File

@@ -337,19 +337,30 @@ func (this *JSONString) unmarshalValue(val reflect.Value) error {
}
}
switch val.Kind() {
case reflect.Int, reflect.Uint, reflect.Int8, reflect.Uint8,
reflect.Int16, reflect.Uint16, reflect.Int32, reflect.Uint32, reflect.Int64, reflect.Uint64:
intVal, err := strconv.ParseInt(this.data, 10, 64)
if err != nil {
return err
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
if len(this.data) > 0 {
intVal, err := strconv.ParseInt(normalizeCurrencyString(this.data), 10, 64)
if err != nil {
return err
}
val.SetInt(intVal)
}
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
if len(this.data) > 0 {
intVal, err := strconv.ParseUint(normalizeCurrencyString(this.data), 10, 64)
if err != nil {
return err
}
val.SetUint(intVal)
}
val.SetInt(intVal)
case reflect.Float32, reflect.Float64:
floatVal, err := strconv.ParseFloat(normalizeCurrencyString(this.data), 64)
if err != nil {
return err
if len(this.data) > 0 {
floatVal, err := strconv.ParseFloat(normalizeCurrencyString(this.data), 64)
if err != nil {
return err
}
val.SetFloat(floatVal)
}
val.SetFloat(floatVal)
case reflect.Bool:
val.SetBool(utils.ToBool(this.data))
case reflect.String:
@@ -557,14 +568,20 @@ func setStructFieldAt(key string, v JSONObject, fieldValues reflectutils.SStruct
func (this *JSONDict) unmarshalStruct(val reflect.Value) error {
fieldValues := reflectutils.FetchStructFieldValueSetForWrite(val)
keyIndexMap := fieldValues.GetStructFieldIndexesMap()
errs := make([]error, 0)
for k, v := range this.data {
err := setStructFieldAt(k, v, fieldValues, keyIndexMap, nil)
if err != nil {
return errors.Wrapf(err, "setStructFieldAt %s: %s", k, v)
// store error, not interrupt the process
errs = append(errs, errors.Wrapf(err, "setStructFieldAt %s: %s", k, v))
}
}
callStructAfterUnmarshal(val)
return nil
if len(errs) > 0 {
return errors.NewAggregate(errs)
} else {
return nil
}
}
func callStructAfterUnmarshal(val reflect.Value) {

View File

@@ -134,7 +134,9 @@ func ParseValue(val string, tp reflect.Type) (reflect.Value, error) {
return reflect.ValueOf(val_float), err
}
case reflect.String:
return reflect.ValueOf(val), nil
v := reflect.New(tp).Elem()
v.SetString(val)
return v, nil
case reflect.Ptr:
tpElem := tp.Elem()
rv, err := ParseValue(val, tpElem)
@@ -229,10 +231,10 @@ func SliceBaseType(tp reflect.Type) reflect.Type {
}
func AppendValue(value reflect.Value, val string) error {
tp := SliceBaseType(value.Type())
if tp == nil {
if value.Kind() != reflect.Slice {
return fmt.Errorf("Cannot append to non-slice type")
}
tp := value.Type().Elem()
val_raw, e := ParseValue(val, tp)
if e != nil {
return e

View File

@@ -53,6 +53,12 @@ func NewPrettyTable(fields []string) *PrettyTable {
return &pt
}
func NewPrettyTableWithTryTermWidth(fields []string, tryTermWidth bool) *PrettyTable {
pt := NewPrettyTable(fields)
pt.tryTermWidth = tryTermWidth
return pt
}
func rowLine(buf *bytes.Buffer, widths []int) {
buf.WriteByte('+')
for _, w := range widths {

View File

@@ -138,11 +138,19 @@ type SStructFieldValue struct {
type SStructFieldValueSet []SStructFieldValue
func FetchStructFieldValueSet(dataValue reflect.Value) SStructFieldValueSet {
return expandAmbiguousPrefix(fetchStructFieldValueSet(dataValue, false, nil))
return expandAmbiguousPrefix(fetchStructFieldValueSet(dataValue, false))
}
func FetchStructFieldValueSetForWrite(dataValue reflect.Value) SStructFieldValueSet {
return expandAmbiguousPrefix(fetchStructFieldValueSet(dataValue, true, nil))
return expandAmbiguousPrefix(fetchStructFieldValueSet(dataValue, true))
}
func FetchAllStructFieldValueSet(dataValue reflect.Value) SStructFieldValueSet {
return expandAmbiguousPrefix(fetchStructFieldValueSet2(dataValue, false, nil, true))
}
func FetchAllStructFieldValueSetForWrite(dataValue reflect.Value) SStructFieldValueSet {
return expandAmbiguousPrefix(fetchStructFieldValueSet2(dataValue, true, nil, true))
}
type sStructFieldInfoMap map[string]SStructFieldInfo
@@ -186,7 +194,11 @@ func fetchStructFieldInfos(dataType reflect.Type) sStructFieldInfoMap {
return smap
}
func fetchStructFieldValueSet(dataValue reflect.Value, allocatePtr bool, tags map[string]string) SStructFieldValueSet {
func fetchStructFieldValueSet(dataValue reflect.Value, allocatePtr bool) SStructFieldValueSet {
return fetchStructFieldValueSet2(dataValue, allocatePtr, nil, false)
}
func fetchStructFieldValueSet2(dataValue reflect.Value, allocatePtr bool, tags map[string]string, includeIgnore bool) SStructFieldValueSet {
fields := SStructFieldValueSet{}
dataType := dataValue.Type()
fieldInfos := fetchCacheStructFieldInfos(dataType)
@@ -223,13 +235,13 @@ func fetchStructFieldValueSet(dataValue reflect.Value, allocatePtr bool, tags ma
// field of interface type.
if fv.Kind() == reflect.Struct && sf.Type != gotypes.TimeType {
anonymousTags := utils.TagMap(sf.Tag)
subfields := fetchStructFieldValueSet(fv, allocatePtr, anonymousTags)
subfields := fetchStructFieldValueSet2(fv, allocatePtr, anonymousTags, includeIgnore)
fields = append(fields, subfields...)
continue
}
}
fieldInfo := fieldInfos[sf.Name].deepCopy()
if !fieldInfo.Ignore {
if !fieldInfo.Ignore || includeIgnore {
fields = append(fields, SStructFieldValue{
Info: fieldInfo,
Value: fv,

View File

@@ -387,6 +387,8 @@ type SIntegerColumn struct {
IsAutoIncrement bool
IsAutoVersion bool
IsUnsigned bool
AutoIncrementOffset int64
}
func (c *SIntegerColumn) IsNumeric() bool {
@@ -426,9 +428,16 @@ func (c *SIntegerColumn) ColType() string {
func NewIntegerColumn(name string, sqltype string, unsigned bool, tagmap map[string]string, isPointer bool) SIntegerColumn {
autoinc := false
autoincBase := int64(0)
tagmap, v, ok := utils.TagPop(tagmap, TAG_AUTOINCREMENT)
if ok {
autoinc = utils.ToBool(v)
base, err := strconv.ParseInt(v, 10, 64)
if err == nil && base > 0 {
autoinc = true
autoincBase = base
} else {
autoinc = utils.ToBool(v)
}
}
autover := false
tagmap, v, ok = utils.TagPop(tagmap, TAG_AUTOVERSION)
@@ -436,10 +445,11 @@ func NewIntegerColumn(name string, sqltype string, unsigned bool, tagmap map[str
autover = utils.ToBool(v)
}
c := SIntegerColumn{
SBaseWidthColumn: NewBaseWidthColumn(name, sqltype, tagmap, isPointer),
IsAutoIncrement: autoinc,
IsAutoVersion: autover,
IsUnsigned: unsigned,
SBaseWidthColumn: NewBaseWidthColumn(name, sqltype, tagmap, isPointer),
IsAutoIncrement: autoinc,
AutoIncrementOffset: autoincBase,
IsAutoVersion: autover,
IsUnsigned: unsigned,
}
if autoinc {
c.isPrimary = true // autoincrement column must be primary key
@@ -585,11 +595,9 @@ func (c *STextColumn) DefinitionString() string {
func (c *STextColumn) IsZero(val interface{}) bool {
if c.isPointer {
bval := val.(*string)
return bval == nil
return gotypes.IsNil(val)
} else {
bVal := val.(string)
return len(bVal) == 0
return reflect.ValueOf(val).Len() == 0
}
}

View File

@@ -225,6 +225,32 @@ func IsFalse(f IQueryField) ICondition {
return &c
}
type SNoLaterThanCondition struct {
SSingleCondition
}
func (c *SNoLaterThanCondition) WhereClause() string {
return fmt.Sprintf("%s >= NOW()", c.field.Reference())
}
func NoLaterThan(f IQueryField) ICondition {
c := SNoLaterThanCondition{NewSingleCondition(f)}
return &c
}
type SNoEarlierThanCondition struct {
SSingleCondition
}
func (c *SNoEarlierThanCondition) WhereClause() string {
return fmt.Sprintf("%s <= NOW()", c.field.Reference())
}
func NoEarlierThan(f IQueryField) ICondition {
c := SNoEarlierThanCondition{NewSingleCondition(f)}
return &c
}
type STupleCondition struct {
left IQueryField
right interface{}

103
vendor/yunion.io/x/sqlchemy/parser.go generated vendored
View File

@@ -15,6 +15,7 @@
package sqlchemy
import (
"fmt"
"reflect"
"yunion.io/x/pkg/gotypes"
@@ -41,50 +42,55 @@ func structField2ColumnSpec(field *reflectutils.SStructFieldValue) IColumnSpec {
func getFiledTypeCol(fieldType reflect.Type, fieldname string, tagmap map[string]string, isPointer bool) IColumnSpec {
switch fieldType {
case gotypes.StringType:
col := NewTextColumn(fieldname, tagmap, isPointer)
return &col
case gotypes.IntType, gotypes.Int32Type:
tagmap[TAG_WIDTH] = "11"
col := NewIntegerColumn(fieldname, "INT", false, tagmap, isPointer)
return &col
case gotypes.Int8Type:
tagmap[TAG_WIDTH] = "4"
col := NewIntegerColumn(fieldname, "TINYINT", false, tagmap, isPointer)
return &col
case gotypes.Int16Type:
tagmap[TAG_WIDTH] = "6"
col := NewIntegerColumn(fieldname, "SMALLINT", false, tagmap, isPointer)
return &col
case gotypes.Int64Type:
tagmap[TAG_WIDTH] = "20"
col := NewIntegerColumn(fieldname, "BIGINT", false, tagmap, isPointer)
return &col
case gotypes.UintType, gotypes.Uint32Type:
tagmap[TAG_WIDTH] = "11"
col := NewIntegerColumn(fieldname, "INT", true, tagmap, isPointer)
return &col
case gotypes.Uint8Type:
tagmap[TAG_WIDTH] = "4"
col := NewIntegerColumn(fieldname, "TINYINT", true, tagmap, isPointer)
return &col
case gotypes.Uint16Type:
tagmap[TAG_WIDTH] = "6"
col := NewIntegerColumn(fieldname, "SMALLINT", true, tagmap, isPointer)
return &col
case gotypes.Uint64Type:
tagmap[TAG_WIDTH] = "20"
col := NewIntegerColumn(fieldname, "BIGINT", true, tagmap, isPointer)
return &col
case gotypes.BoolType:
tagmap[TAG_WIDTH] = "1"
col := NewBooleanColumn(fieldname, tagmap, isPointer)
return &col
case tristate.TriStateType:
tagmap[TAG_WIDTH] = "1"
col := NewTristateColumn(fieldname, tagmap, isPointer)
return &col
case gotypes.Float32Type, gotypes.Float64Type:
case gotypes.TimeType:
col := NewDateTimeColumn(fieldname, tagmap, isPointer)
return &col
}
switch fieldType.Kind() {
case reflect.String:
col := NewTextColumn(fieldname, tagmap, isPointer)
return &col
case reflect.Int, reflect.Int32:
tagmap[TAG_WIDTH] = "11"
col := NewIntegerColumn(fieldname, "INT", false, tagmap, isPointer)
return &col
case reflect.Int8:
tagmap[TAG_WIDTH] = "4"
col := NewIntegerColumn(fieldname, "TINYINT", false, tagmap, isPointer)
return &col
case reflect.Int16:
tagmap[TAG_WIDTH] = "6"
col := NewIntegerColumn(fieldname, "SMALLINT", false, tagmap, isPointer)
return &col
case reflect.Int64:
tagmap[TAG_WIDTH] = "20"
col := NewIntegerColumn(fieldname, "BIGINT", false, tagmap, isPointer)
return &col
case reflect.Uint, reflect.Uint32:
tagmap[TAG_WIDTH] = "11"
col := NewIntegerColumn(fieldname, "INT", true, tagmap, isPointer)
return &col
case reflect.Uint8:
tagmap[TAG_WIDTH] = "4"
col := NewIntegerColumn(fieldname, "TINYINT", true, tagmap, isPointer)
return &col
case reflect.Uint16:
tagmap[TAG_WIDTH] = "6"
col := NewIntegerColumn(fieldname, "SMALLINT", true, tagmap, isPointer)
return &col
case reflect.Uint64:
tagmap[TAG_WIDTH] = "20"
col := NewIntegerColumn(fieldname, "BIGINT", true, tagmap, isPointer)
return &col
case reflect.Bool:
tagmap[TAG_WIDTH] = "1"
col := NewBooleanColumn(fieldname, tagmap, isPointer)
return &col
case reflect.Float32, reflect.Float64:
if _, ok := tagmap[TAG_WIDTH]; ok {
col := NewDecimalColumn(fieldname, tagmap, isPointer)
return &col
@@ -96,23 +102,26 @@ func getFiledTypeCol(fieldType reflect.Type, fieldname string, tagmap map[string
col := NewFloatColumn(fieldname, colType, tagmap, isPointer)
return &col
}
case gotypes.TimeType:
col := NewDateTimeColumn(fieldname, tagmap, isPointer)
}
if fieldType.Implements(gotypes.ISerializableType) {
col := NewCompoundColumn(fieldname, tagmap, isPointer)
return &col
default:
if fieldType.Implements(gotypes.ISerializableType) {
col := NewCompoundColumn(fieldname, tagmap, isPointer)
return &col
}
}
return nil
}
func struct2TableSpec(sv reflect.Value, table *STableSpec) {
fields := reflectutils.FetchStructFieldValueSet(sv)
autoIncCnt := 0
for i := 0; i < len(fields); i += 1 {
column := structField2ColumnSpec(&fields[i])
if column != nil {
if intC, ok := column.(*SIntegerColumn); ok && intC.IsAutoIncrement {
autoIncCnt += 1
if autoIncCnt > 1 {
panic(fmt.Sprintf("Table %s contains multiple autoincremental columns!!", table.name))
}
}
if column.IsIndex() {
table.AddIndex(column.IsUnique(), column.Name())
}

View File

@@ -20,9 +20,9 @@ import (
"strconv"
"time"
"yunion.io/x/pkg/errors"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/gotypes"
"yunion.io/x/pkg/tristate"
"yunion.io/x/pkg/util/timeutils"
@@ -31,22 +31,10 @@ import (
func getStringValue(dat interface{}) string {
value := reflect.ValueOf(dat)
switch value.Type() {
case gotypes.BoolType:
if value.Bool() {
return "true"
} else {
return "false"
}
case gotypes.IntType, gotypes.Int8Type, gotypes.Int16Type, gotypes.Int32Type, gotypes.Int64Type:
return fmt.Sprintf("%d", value.Int())
case gotypes.UintType, gotypes.Uint8Type, gotypes.Uint16Type, gotypes.Uint32Type, gotypes.Uint64Type:
return fmt.Sprintf("%d", value.Uint())
case gotypes.Float32Type, gotypes.Float64Type:
return fmt.Sprintf("%f", value.Float())
case gotypes.StringType:
return value.String()
case tristate.TriStateType:
return dat.(tristate.TriState).String()
case gotypes.TimeType:
tm, ok := value.Interface().(time.Time)
tm, ok := dat.(time.Time)
if !ok {
log.Errorf("Fail to convert to time.Time %s", value)
} else {
@@ -67,14 +55,28 @@ func getStringValue(dat interface{}) string {
} else {
return string(rawBytes)
}
default:
serializable, ok := value.Interface().(gotypes.ISerializable)
if !ok {
log.Errorf("cannot convert %v to string", value)
return ""
}
switch value.Kind() {
case reflect.Bool:
if value.Bool() {
return "true"
} else {
return "false"
}
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return fmt.Sprintf("%d", value.Int())
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return fmt.Sprintf("%d", value.Uint())
case reflect.Float32, reflect.Float64:
return fmt.Sprintf("%f", value.Float())
case reflect.String:
return value.String()
}
serializable, ok := value.Interface().(gotypes.ISerializable)
if ok {
return serializable.String()
}
log.Errorf("cannot convert %v to string", value)
return ""
}
@@ -83,12 +85,6 @@ func setValueBySQLString(value reflect.Value, val string) error {
return errors.Wrap(ErrReadOnly, "value is not settable")
}
switch value.Type() {
case gotypes.BoolType:
if val == "0" {
value.SetBool(false)
} else {
value.SetBool(true)
}
case tristate.TriStateType:
if val == "0" {
value.Set(tristate.TriStateFalseValue)
@@ -97,63 +93,71 @@ func setValueBySQLString(value reflect.Value, val string) error {
} else {
value.Set(tristate.TriStateNoneValue)
}
case gotypes.IntType, gotypes.Int8Type, gotypes.Int16Type, gotypes.Int32Type, gotypes.Int64Type:
valInt, err := strconv.ParseInt(val, 10, 64)
if err != nil {
return err
}
value.SetInt(valInt)
case gotypes.UintType, gotypes.Uint8Type, gotypes.Uint16Type, gotypes.Uint32Type, gotypes.Uint64Type:
valUint, err := strconv.ParseUint(val, 10, 64)
if err != nil {
return err
}
value.SetUint(valUint)
case gotypes.Float32Type, gotypes.Float64Type:
valFloat, err := strconv.ParseFloat(val, 64)
if err != nil {
return err
}
value.SetFloat(valFloat)
case gotypes.StringType:
value.SetString(val)
return nil
case gotypes.TimeType:
if val != "0000-00-00 00:00:00" {
tm, err := timeutils.ParseTimeStr(val)
if err != nil {
return err
return errors.Wrap(err, "ParseTimeStr")
}
value.Set(reflect.ValueOf(tm))
}
/*case jsonutils.JSONDictType, jsonutils.JSONArrayType, jsonutils.JSONStringType, jsonutils.JSONIntType,
jsonutils.JSONFloatType, jsonutils.JSONBoolType, jsonutils.JSONObjectType:
log.Debugf("Decode JSON value: $%s$", val)
json, err := jsonutils.ParseString(val)
if err != nil {
return err
return nil
}
value.Set(reflect.ValueOf(json))*/
case gotypes.BoolSliceType, gotypes.IntSliceType, gotypes.Int8SliceType, gotypes.Int16SliceType,
gotypes.Int32SliceType, gotypes.Int64SliceType, gotypes.UintSliceType, gotypes.Uint8SliceType,
gotypes.Uint16SliceType, gotypes.Uint32SliceType, gotypes.Uint64SliceType,
gotypes.Float32SliceType, gotypes.Float64SliceType, gotypes.StringSliceType:
reflect.Append(value, reflect.ValueOf(val))
default:
valueType := value.Type()
if valueType.Implements(gotypes.ISerializableType) {
serializable, err := jsonutils.JSONDeserialize(valueType, val)
if err != nil {
return err
}
value.Set(reflect.ValueOf(serializable))
return nil
} else if value.Kind() == reflect.Ptr {
if value.IsNil() {
value.Set(reflect.New(value.Type().Elem()))
}
return setValueBySQLString(value.Elem(), val)
switch value.Kind() {
case reflect.Bool:
if val == "0" {
value.SetBool(false)
} else {
value.SetBool(true)
}
return errors.Wrapf(ErrNotSupported, "not supported type: %s", valueType)
return nil
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
valInt, err := strconv.ParseInt(val, 10, 64)
if err != nil {
return errors.Wrap(err, "ParseInt")
}
value.SetInt(valInt)
return nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
valUint, err := strconv.ParseUint(val, 10, 64)
if err != nil {
return errors.Wrap(err, "ParseUint")
}
value.SetUint(valUint)
return nil
case reflect.Float32, reflect.Float64:
valFloat, err := strconv.ParseFloat(val, 64)
if err != nil {
return errors.Wrap(err, "ParseFloat")
}
value.SetFloat(valFloat)
return nil
case reflect.String:
value.SetString(val)
return nil
case reflect.Slice:
elemValue := reflect.New(value.Type().Elem()).Elem()
err := setValueBySQLString(elemValue, val)
if err != nil {
return errors.Wrap(err, "reflect.Slice")
}
value.Set(reflect.Append(value, elemValue))
return nil
case reflect.Ptr:
if value.IsNil() {
value.Set(reflect.New(value.Type().Elem()))
}
return setValueBySQLString(value.Elem(), val)
}
return nil
valueType := value.Type()
if valueType.Implements(gotypes.ISerializableType) {
serializable, err := jsonutils.JSONDeserialize(valueType, val)
if err != nil {
return errors.Wrap(err, "jsonutils.JSONDeserialize")
}
value.Set(reflect.ValueOf(serializable))
return nil
}
return errors.Wrapf(ErrNotSupported, "not supported type: %s", valueType)
}

View File

@@ -83,10 +83,14 @@ func (ts *STableSpec) CreateSQL() string {
cols := make([]string, 0)
primaries := make([]string, 0)
indexes := make([]string, 0)
autoInc := ""
for _, c := range ts.columns {
cols = append(cols, c.DefinitionString())
if c.IsPrimary() {
primaries = append(primaries, fmt.Sprintf("`%s`", c.Name()))
if intC, ok := c.(*SIntegerColumn); ok && intC.AutoIncrementOffset > 1 {
autoInc = fmt.Sprintf(" AUTO_INCREMENT=%d", intC.AutoIncrementOffset)
}
}
if c.IsIndex() {
indexes = append(indexes, fmt.Sprintf("KEY `ix_%s_%s` (`%s`)", ts.name, c.Name(), c.Name()))
@@ -98,7 +102,7 @@ func (ts *STableSpec) CreateSQL() string {
if len(indexes) > 0 {
cols = append(cols, indexes...)
}
return fmt.Sprintf("CREATE TABLE IF NOT EXISTS `%s` (\n%s\n) ENGINE=InnoDB DEFAULT CHARSET=utf8", ts.name, strings.Join(cols, ",\n"))
return fmt.Sprintf("CREATE TABLE IF NOT EXISTS `%s` (\n%s\n) ENGINE=InnoDB DEFAULT CHARSET=utf8%s", ts.name, strings.Join(cols, ",\n"), autoInc)
}
func (ts *STableSpec) Instance() *STable {

View File

@@ -27,6 +27,7 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/gotypes"
"yunion.io/x/pkg/util/reflectutils"
"yunion.io/x/pkg/utils"
@@ -44,6 +45,7 @@ type Argument interface {
Token() string
AliasToken() string
ShortToken() string
NegativeToken() string
MetaVar() string
IsPositional() bool
IsRequired() bool
@@ -53,7 +55,7 @@ type Argument interface {
String() string
SetValue(val string) error
Reset()
DoAction() error
DoAction(nega bool) error
Validate() error
SetDefault()
IsSet() bool
@@ -63,6 +65,7 @@ type SingleArgument struct {
token string
aliasToken string
shortToken string
negaToken string
metavar string
positional bool
required bool
@@ -104,9 +107,12 @@ type ArgumentParser struct {
func NewArgumentParser(target interface{}, prog, desc, epilog string) (*ArgumentParser, error) {
parser := ArgumentParser{prog: prog, description: desc,
epilog: epilog, target: target}
target_type := reflect.TypeOf(target).Elem()
target_value := reflect.ValueOf(target).Elem()
e := parser.addStructArgument("", target_type, target_value)
targetValue := reflect.ValueOf(target)
if targetValue.Kind() != reflect.Ptr {
return nil, fmt.Errorf("target must be a pointer")
}
targetValue = targetValue.Elem()
e := parser.addStructArgument("", targetValue)
if e != nil {
return nil, e
}
@@ -182,37 +188,46 @@ const (
Alias name of argument
*/
TAG_ALIAS = "alias"
/*
Token for negative value, applicable to boolean values
*/
TAG_NEGATIVE_TOKEN = "negative"
)
func (this *ArgumentParser) addStructArgument(prefix string, tp reflect.Type, val reflect.Value) error {
for i := 0; i < tp.NumField(); i++ {
v := val.Field(i)
if !v.CanSet() {
continue
}
f := tp.Field(i)
if f.Type.Kind() == reflect.Struct {
p := prefix
if !f.Anonymous {
p += f.Name + "-"
func (this *ArgumentParser) addStructArgument(prefix string, tpVal reflect.Value) error {
sets := reflectutils.FetchAllStructFieldValueSetForWrite(tpVal)
for i := range sets {
if sets[i].Value.Kind() == reflect.Struct && sets[i].Value.Type() != gotypes.TimeType {
tagMap := sets[i].Info.Tags
if _, ok := tagMap[reflectutils.TAG_DEPRECATED_BY]; ok {
// deprecated field, ignore
return nil
}
e := this.addStructArgument(p, f.Type, v)
if e != nil {
return e
token, ok := tagMap[TAG_TOKEN]
if !ok {
token = sets[i].Info.MarshalName()
}
token = prefix + token + "-"
err := this.addStructArgument(token, sets[i].Value)
if err != nil {
return errors.Wrap(err, "addStructArgument")
}
} else {
e := this.addArgument(prefix, f, v)
if e != nil {
return e
err := this.addArgument(prefix, sets[i].Value, sets[i].Info)
if err != nil {
return errors.Wrap(err, "addArgument")
}
}
}
return nil
}
func (this *ArgumentParser) addArgument(prefix string, f reflect.StructField, v reflect.Value) error {
info := reflectutils.ParseStructFieldJsonInfo(f)
func (this *ArgumentParser) addArgument(prefix string, fv reflect.Value, info *reflectutils.SStructFieldInfo) error {
tagMap := info.Tags
if _, ok := tagMap[reflectutils.TAG_DEPRECATED_BY]; ok {
// deprecated field, ignore
return nil
}
help := tagMap[TAG_HELP]
token, ok := tagMap[TAG_TOKEN]
if !ok {
@@ -221,6 +236,7 @@ func (this *ArgumentParser) addArgument(prefix string, f reflect.StructField, v
token = prefix + token
shorttoken := tagMap[TAG_SHORT_TOKEN]
alias := tagMap[TAG_ALIAS]
negative := tagMap[TAG_NEGATIVE_TOKEN]
metavar := tagMap[TAG_METAVAR]
defval := tagMap[TAG_DEFAULT]
if len(defval) > 0 {
@@ -234,6 +250,9 @@ func (this *ArgumentParser) addArgument(prefix string, f reflect.StructField, v
}
}
}
if len(negative) > 0 && !valueIsBool(fv) {
return fmt.Errorf("negative token is applicable to boolean option ONLY")
}
use_default := true
if len(defval) == 0 {
use_default = false
@@ -249,7 +268,7 @@ func (this *ArgumentParser) addArgument(prefix string, f reflect.StructField, v
}
// heuristic guessing "positional"
var positional bool
if f.Name == strings.ToUpper(f.Name) {
if info.FieldName == strings.ToUpper(info.FieldName) {
positional = true
} else {
positional = false
@@ -292,7 +311,7 @@ func (this *ArgumentParser) addArgument(prefix string, f reflect.StructField, v
}
var defval_t reflect.Value
if use_default {
defval_t, err = gotypes.ParseValue(defval, f.Type)
defval_t, err = gotypes.ParseValue(defval, fv.Type())
if err != nil {
return err
}
@@ -301,20 +320,21 @@ func (this *ArgumentParser) addArgument(prefix string, f reflect.StructField, v
positional = true
}
var arg Argument = nil
ovalue := reflect.New(v.Type()).Elem()
ovalue.Set(v)
ovalue := reflect.New(fv.Type()).Elem()
ovalue.Set(fv)
sarg := SingleArgument{
token: token,
shortToken: shorttoken,
aliasToken: alias,
negaToken: negative,
positional: positional,
required: required,
metavar: metavar,
help: help,
choices: choices,
useDefault: use_default,
aliasToken: alias,
defValue: defval_t,
value: v,
value: fv,
ovalue: ovalue,
parser: this,
}
@@ -322,7 +342,7 @@ func (this *ArgumentParser) addArgument(prefix string, f reflect.StructField, v
if subcommand {
arg = &SubcommandArgument{SingleArgument: sarg,
subcommands: make(map[string]SubcommandArgumentData)}
} else if f.Type.Kind() == reflect.Array || f.Type.Kind() == reflect.Slice {
} else if fv.Kind() == reflect.Array || fv.Kind() == reflect.Slice || fv.Kind() == reflect.Map {
var min, max int64
var err error
nargs := tagMap[TAG_NARGS]
@@ -413,8 +433,7 @@ func (this *ArgumentParser) Options() interface{} {
return this.target
}
func (this *SingleArgument) valueIsBool() bool {
rv := this.value
func valueIsBool(rv reflect.Value) bool {
if rv.Kind() == reflect.Bool {
return true
}
@@ -425,6 +444,13 @@ func (this *SingleArgument) valueIsBool() bool {
return false
}
func valueIsMap(rv reflect.Value) bool {
if rv.Kind() == reflect.Map {
return true
}
return false
}
func (this *SingleArgument) defaultBoolValue() bool {
rv := this.defValue
if rv.Kind() == reflect.Bool {
@@ -438,7 +464,7 @@ func (this *SingleArgument) defaultBoolValue() bool {
}
func (this *SingleArgument) NeedData() bool {
if this.valueIsBool() {
if valueIsBool(this.value) {
return false
} else {
return true
@@ -467,6 +493,9 @@ func (this *SingleArgument) AllToken() string {
if len(this.ShortToken()) != 0 {
ret = fmt.Sprintf("%s|-%s", ret, this.ShortToken())
}
if len(this.NegativeToken()) != 0 {
ret = fmt.Sprintf("%s/--%s", ret, this.NegativeToken())
}
return ret
}
@@ -482,6 +511,10 @@ func (this *SingleArgument) ShortToken() string {
return this.shortToken
}
func (this *SingleArgument) NegativeToken() string {
return this.negaToken
}
func (this *SingleArgument) String() string {
var start, end byte
if this.IsRequired() {
@@ -570,11 +603,13 @@ func (this *SingleArgument) Reset() {
this.isSet = false
}
func (this *SingleArgument) DoAction() error {
if this.valueIsBool() {
func (this *SingleArgument) DoAction(nega bool) error {
if valueIsBool(this.value) {
var v bool
if this.useDefault {
v = !this.defaultBoolValue()
} else if nega {
v = false
} else {
v = true
}
@@ -605,7 +640,37 @@ func (this *MultiArgument) IsMulti() bool {
return true
}
func (this *MultiArgument) setKeyValue(val string) error {
pos := strings.IndexByte(val, '=')
var key, value string
if pos >= 0 {
key = val[:pos]
value = val[pos+1:]
} else {
key = val
}
keyType := this.value.Type().Key()
keyValue, err := gotypes.ParseValue(key, keyType)
if err != nil {
return errors.Wrapf(err, "ParseValue for key %s", key)
}
valType := this.value.Type().Elem()
valValue, err := gotypes.ParseValue(value, valType)
if err != nil {
return errors.Wrapf(err, "ParseValue for value %s", value)
}
if this.value.Len() == 0 {
this.value.Set(reflect.MakeMap(this.value.Type()))
}
this.value.SetMapIndex(keyValue, valValue)
this.isSet = true
return nil
}
func (this *MultiArgument) SetValue(val string) error {
if valueIsMap(this.value) {
return this.setKeyValue(val)
}
if !this.InChoices(val) {
return this.choicesErr(val)
}
@@ -777,28 +842,38 @@ func tokenMatch(argToken, input string, exactMatch bool) bool {
}
}
func (this *ArgumentParser) findOptionalArgument(token string, exactMatch bool) Argument {
func (this *ArgumentParser) findOptionalArgument(token string, exactMatch bool) (Argument, bool) {
var match_arg Argument = nil
match_len := -1
negative := false
for _, arg := range this.optArgs {
if tokenMatch(arg.Token(), token, exactMatch) {
if match_len < 0 || match_len > len(arg.Token()) {
match_len = len(arg.Token())
match_arg = arg
negative = false
}
} else if tokenMatch(arg.ShortToken(), token, exactMatch) {
if match_len < 0 || match_len > len(arg.ShortToken()) {
match_len = len(arg.ShortToken())
match_arg = arg
negative = false
}
} else if tokenMatch(arg.AliasToken(), token, exactMatch) {
if match_len < 0 || match_len > len(arg.AliasToken()) {
match_len = len(arg.AliasToken())
match_arg = arg
negative = false
}
} else if tokenMatch(arg.NegativeToken(), token, exactMatch) {
if match_len < 0 || match_len > len(arg.AliasToken()) {
match_len = len(arg.AliasToken())
match_arg = arg
negative = true
}
}
}
return match_arg
return match_arg, negative
}
func validateArgs(args []Argument) error {
@@ -838,9 +913,8 @@ func (this *ArgumentParser) ParseArgs(args []string, ignore_unknown bool) error
}
func (this *ArgumentParser) ParseArgs2(args []string, ignore_unknown bool, setDefaults bool) error {
var pos_idx int = 0
var arg Argument = nil
var err error = nil
var pos_idx int
var err error
var argStr string
this.reset()
@@ -848,7 +922,7 @@ func (this *ArgumentParser) ParseArgs2(args []string, ignore_unknown bool, setDe
for i := 0; i < len(args) && err == nil; i++ {
argStr = args[i]
if strings.HasPrefix(argStr, "-") {
arg = this.findOptionalArgument(strings.TrimLeft(argStr, "-"), false)
arg, nega := this.findOptionalArgument(strings.TrimLeft(argStr, "-"), false)
if arg != nil {
if arg.NeedData() {
if i+1 < len(args) {
@@ -862,7 +936,7 @@ func (this *ArgumentParser) ParseArgs2(args []string, ignore_unknown bool, setDe
break
}
} else {
err = arg.DoAction()
err = arg.DoAction(nega)
if err != nil {
break
}
@@ -886,7 +960,7 @@ func (this *ArgumentParser) ParseArgs2(args []string, ignore_unknown bool, setDe
break
}
} else {
arg = this.posArgs[pos_idx]
arg := this.posArgs[pos_idx]
pos_idx += 1
err = arg.SetValue(argStr)
if err != nil {
@@ -922,8 +996,12 @@ func isQuoted(str string) bool {
}
func (this *ArgumentParser) parseKeyValue(key, value string) error {
arg := this.findOptionalArgument(key, true)
arg, nega := this.findOptionalArgument(key, true)
if arg != nil {
if nega {
log.Warningf("Ignore negative token when parse %s=%v", key, value)
return nil
}
if arg.IsSet() {
return nil
}
@@ -1019,11 +1097,15 @@ func keyToToken(key string) string {
func (this *ArgumentParser) parseJSONKeyValue(key string, obj jsonutils.JSONObject) error {
token := keyToToken(key)
arg := this.findOptionalArgument(token, true)
arg, nega := this.findOptionalArgument(token, true)
if arg == nil {
log.Warningf("Cannot find argument %s", token)
return nil
}
if nega {
log.Warningf("Ignore negative token when parse JSONKeyValue %s", token)
return nil
}
if arg.IsSet() {
return nil
}