本文整理汇总了Golang中github.com/youtube/vitess/go/sqltypes.BuildValue函数的典型用法代码示例。如果您正苦于以下问题:Golang BuildValue函数的具体用法?Golang BuildValue怎么用?Golang BuildValue使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了BuildValue函数的20个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的Golang代码示例。
示例1: TestCodexBuildSecondaryList
func TestCodexBuildSecondaryList(t *testing.T) {
pk1 := "pk1"
pk2 := "pk2"
tableInfo := createTableInfo("Table",
[]string{"pk1", "pk2", "col1"},
[]string{"int", "varbinary(128)", "int"},
[]string{pk1, pk2})
// set pk2 = 'xyz' where pk1=1 and pk2 = 'abc'
bindVars := map[string]interface{}{}
pk1Val, _ := sqltypes.BuildValue(1)
pk2Val, _ := sqltypes.BuildValue("abc")
pkValues := []interface{}{pk1Val, pk2Val}
pkList, _ := buildValueList(&tableInfo, pkValues, bindVars)
pk2SecVal, _ := sqltypes.BuildValue("xyz")
secondaryPKValues := []interface{}{nil, pk2SecVal}
// want [[1 xyz]]
want := [][]sqltypes.Value{
[]sqltypes.Value{pk1Val, pk2SecVal}}
got, _ := buildSecondaryList(&tableInfo, pkList, secondaryPKValues, bindVars)
if !reflect.DeepEqual(got, want) {
t.Fatalf("case 1 failed, got %v, want %v", got, want)
}
secondaryPKValues = []interface{}{"invalid_type", 1}
_, err := buildSecondaryList(&tableInfo, pkList, secondaryPKValues, bindVars)
if err == nil {
t.Fatalf("should get an error, column 0 is int type, but secondary list provides a string")
}
}
开发者ID:pranjal5215,项目名称:vitess,代码行数:30,代码来源:codex_test.go
示例2: TestSplitQueryFractionalColumn
func TestSplitQueryFractionalColumn(t *testing.T) {
schemaInfo := getSchemaInfo()
query := &proto.BoundQuery{
Sql: "select * from test_table where count > :count",
}
splitter := NewQuerySplitter(query, "", 3, schemaInfo)
splitter.validateQuery()
min, _ := sqltypes.BuildValue(10.5)
max, _ := sqltypes.BuildValue(490.5)
minField := &pbq.Field{
Name: "min",
Type: sqltypes.Float32,
}
maxField := &pbq.Field{
Name: "max",
Type: sqltypes.Float32,
}
fields := []*pbq.Field{minField, maxField}
pkMinMax := &sqltypes.Result{
Fields: fields,
Rows: [][]sqltypes.Value{[]sqltypes.Value{min, max}},
}
splits, err := splitter.split(sqltypes.Float32, pkMinMax)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
got := []proto.BoundQuery{}
for _, split := range splits {
if split.RowCount != 160 {
t.Errorf("wrong RowCount, got: %v, want: %v", split.RowCount, 160)
}
got = append(got, split.Query)
}
want := []proto.BoundQuery{
{
Sql: "select * from test_table where (count > :count) and (id < :" + endBindVarName + ")",
BindVariables: map[string]interface{}{endBindVarName: 170.5},
},
{
Sql: fmt.Sprintf("select * from test_table where (count > :count) and (id >= :%s and id < :%s)", startBindVarName, endBindVarName),
BindVariables: map[string]interface{}{
startBindVarName: 170.5,
endBindVarName: 330.5,
},
},
{
Sql: "select * from test_table where (count > :count) and (id >= :" + startBindVarName + ")",
BindVariables: map[string]interface{}{startBindVarName: 330.5},
},
}
if !reflect.DeepEqual(got, want) {
t.Errorf("wrong splits, got: %v, want: %v", got, want)
}
}
开发者ID:c3p0hz,项目名称:vitess,代码行数:55,代码来源:query_splitter_test.go
示例3: splitBoundariesIntColumn
func (qs *QuerySplitter) splitBoundariesIntColumn(pkMinMax *mproto.QueryResult) ([]sqltypes.Value, error) {
boundaries := []sqltypes.Value{}
if pkMinMax == nil || len(pkMinMax.Rows) != 1 || pkMinMax.Rows[0][0].IsNull() || pkMinMax.Rows[0][1].IsNull() {
return boundaries, nil
}
minNumeric := sqltypes.MakeNumeric(pkMinMax.Rows[0][0].Raw())
maxNumeric := sqltypes.MakeNumeric(pkMinMax.Rows[0][1].Raw())
if pkMinMax.Rows[0][0].Raw()[0] == '-' {
// signed values, use int64
min, err := minNumeric.ParseInt64()
if err != nil {
return nil, err
}
max, err := maxNumeric.ParseInt64()
if err != nil {
return nil, err
}
interval := (max - min) / int64(qs.splitCount)
if interval == 0 {
return nil, err
}
qs.rowCount = interval
for i := int64(1); i < int64(qs.splitCount); i++ {
v, err := sqltypes.BuildValue(min + interval*i)
if err != nil {
return nil, err
}
boundaries = append(boundaries, v)
}
return boundaries, nil
}
// unsigned values, use uint64
min, err := minNumeric.ParseUint64()
if err != nil {
return nil, err
}
max, err := maxNumeric.ParseUint64()
if err != nil {
return nil, err
}
interval := (max - min) / uint64(qs.splitCount)
if interval == 0 {
return nil, err
}
qs.rowCount = int64(interval)
for i := uint64(1); i < uint64(qs.splitCount); i++ {
v, err := sqltypes.BuildValue(min + interval*i)
if err != nil {
return nil, err
}
boundaries = append(boundaries, v)
}
return boundaries, nil
}
开发者ID:hadmagic,项目名称:vitess,代码行数:54,代码来源:query_splitter.go
示例4: toChunk
func toChunk(start, end interface{}, number, total int) (chunk, error) {
startValue, err := sqltypes.BuildValue(start)
if err != nil {
return chunk{}, fmt.Errorf("Failed to convert calculated start value (%v) into internal sqltypes.Value: %v", start, err)
}
endValue, err := sqltypes.BuildValue(end)
if err != nil {
return chunk{}, fmt.Errorf("Failed to convert calculated end value (%v) into internal sqltypes.Value: %v", end, err)
}
return chunk{startValue, endValue, number, total}, nil
}
开发者ID:erzel,项目名称:vitess,代码行数:11,代码来源:chunk.go
示例5: populateLocalMetadata
// populateLocalMetadata creates and fills the _vt.local_metadata table,
// which is a per-tablet table that is never replicated. This allows queries
// against local_metadata to return different values on different tablets,
// which is used for communicating between Vitess and MySQL-level tools like
// Orchestrator (http://github.com/outbrain/orchestrator).
func populateLocalMetadata(mysqld MysqlDaemon, localMetadata map[string]string) error {
log.Infof("Populating _vt.local_metadata table...")
// Get a non-pooled DBA connection.
conn, err := mysqld.GetDbaConnection()
if err != nil {
return err
}
defer conn.Close()
// Disable replication on this session. We close the connection after using
// it, so there's no need to re-enable replication when we're done.
if _, err := conn.ExecuteFetch("SET @@session.sql_log_bin = 0", 0, false); err != nil {
return err
}
// Create the database and table if necessary.
if _, err := conn.ExecuteFetch("CREATE DATABASE IF NOT EXISTS _vt", 0, false); err != nil {
return err
}
if _, err := conn.ExecuteFetch(sqlCreateLocalMetadataTable, 0, false); err != nil {
return err
}
if _, err := conn.ExecuteFetch("BEGIN", 0, false); err != nil {
return err
}
for name, val := range localMetadata {
nameValue, err := sqltypes.BuildValue(name)
if err != nil {
return err
}
valValue, err := sqltypes.BuildValue(val)
if err != nil {
return err
}
queryBuf := bytes.Buffer{}
queryBuf.WriteString("INSERT INTO _vt.local_metadata (name,value) VALUES (")
nameValue.EncodeSQL(&queryBuf)
queryBuf.WriteByte(',')
valValue.EncodeSQL(&queryBuf)
queryBuf.WriteString(") ON DUPLICATE KEY UPDATE value = ")
valValue.EncodeSQL(&queryBuf)
if _, err := conn.ExecuteFetch(queryBuf.String(), 0, false); err != nil {
return err
}
}
_, err = conn.ExecuteFetch("COMMIT", 0, false)
return err
}
开发者ID:jmptrader,项目名称:vitess,代码行数:57,代码来源:local_metadata.go
示例6: createRowMultiPk
func createRowMultiPk(id int) []sqltypes.Value {
// Map id from the one dimensional space to a two-dimensional space.
// Examples: 0, 1, 2, 3, 4 => (0, 0), (0, 1), (1, 0), (1, 1), (2, 0)
newID := id / 2
subID := id % 2
idValue, _ := sqltypes.BuildValue(int32(newID))
subIDValue, _ := sqltypes.BuildValue(int32(subID))
return []sqltypes.Value{
idValue,
subIDValue,
sqltypes.MakeString([]byte(fmt.Sprintf("msg %d", id))),
}
}
开发者ID:CowLeo,项目名称:vitess,代码行数:13,代码来源:result_merger_test.go
示例7: TestSplitQuery
func TestSplitQuery(t *testing.T) {
schemaInfo := getSchemaInfo()
query := &proto.BoundQuery{
Sql: "select * from test_table where count > :count",
}
splitter := NewQuerySplitter(query, "", 3, schemaInfo)
splitter.validateQuery()
min, _ := sqltypes.BuildValue(0)
max, _ := sqltypes.BuildValue(300)
minField := mproto.Field{
Name: "min",
Type: mproto.VT_LONGLONG,
}
maxField := mproto.Field{
Name: "min",
Type: mproto.VT_LONGLONG,
}
fields := []mproto.Field{minField, maxField}
pkMinMax := &mproto.QueryResult{
Fields: fields,
}
// Ensure that empty min max does not cause panic or return any error
splits, err := splitter.split(pkMinMax)
if err != nil {
t.Errorf("unexpected error while splitting on empty pkMinMax, %s", err)
}
pkMinMax.Rows = [][]sqltypes.Value{[]sqltypes.Value{min, max}}
splits, err = splitter.split(pkMinMax)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
got := []string{}
for _, split := range splits {
if split.RowCount != 100 {
t.Errorf("wrong RowCount, got: %v, want: %v", split.RowCount, 100)
}
got = append(got, split.Query.Sql)
}
want := []string{
"select * from test_table where count > :count and id < 100",
"select * from test_table where count > :count and id >= 100 and id < 200",
"select * from test_table where count > :count and id >= 200",
}
if !reflect.DeepEqual(got, want) {
t.Errorf("wrong splits, got: %v, want: %v", got, want)
}
}
开发者ID:pranjal5215,项目名称:vitess,代码行数:49,代码来源:query_splitter_test.go
示例8: handleDMLEvent
func (rci *RowcacheInvalidator) handleDMLEvent(event *blproto.StreamEvent) {
invalidations := int64(0)
tableInfo := rci.qe.schemaInfo.GetTable(event.TableName)
if tableInfo == nil {
panic(NewTabletError(ErrFail, "Table %s not found", event.TableName))
}
if tableInfo.CacheType == schema.CACHE_NONE {
return
}
sqlTypeKeys := make([]sqltypes.Value, 0, len(event.PKColNames))
for _, pkTuple := range event.PKValues {
sqlTypeKeys = sqlTypeKeys[:0]
for _, pkVal := range pkTuple {
key, err := sqltypes.BuildValue(pkVal)
if err != nil {
log.Errorf("Error building invalidation key for %#v: '%v'", event, err)
rci.qe.queryServiceStats.InternalErrors.Add("Invalidation", 1)
return
}
sqlTypeKeys = append(sqlTypeKeys, key)
}
newKey := validateKey(tableInfo, buildKey(sqlTypeKeys), rci.qe.queryServiceStats)
if newKey == "" {
continue
}
tableInfo.Cache.Delete(context.Background(), newKey)
invalidations++
}
tableInfo.invalidations.Add(invalidations)
}
开发者ID:pranjal5215,项目名称:vitess,代码行数:31,代码来源:rowcache_invalidator.go
示例9: EncodeValue
func EncodeValue(buf *bytes.Buffer, value interface{}) error {
switch bindVal := value.(type) {
case nil:
buf.WriteString("null")
case []sqltypes.Value:
for i := 0; i < len(bindVal); i++ {
if i != 0 {
buf.WriteString(", ")
}
if err := EncodeValue(buf, bindVal[i]); err != nil {
return err
}
}
case [][]sqltypes.Value:
for i := 0; i < len(bindVal); i++ {
if i != 0 {
buf.WriteString(", ")
}
buf.WriteByte('(')
if err := EncodeValue(buf, bindVal[i]); err != nil {
return err
}
buf.WriteByte(')')
}
default:
v, err := sqltypes.BuildValue(bindVal)
if err != nil {
return err
}
v.EncodeSql(buf)
}
return nil
}
开发者ID:CERN-Stage-3,项目名称:vitess,代码行数:33,代码来源:parsed_query.go
示例10: resolveValue
func resolveValue(col *schema.TableColumn, value interface{}, bindVars map[string]interface{}) (result sqltypes.Value, err error) {
switch v := value.(type) {
case string:
lookup, ok := bindVars[v[1:]]
if !ok {
return result, NewTabletError(FAIL, "missing bind var %s", v)
}
if sqlval, err := sqltypes.BuildValue(lookup); err != nil {
return result, NewTabletError(FAIL, err.Error())
} else {
result = sqlval
}
case sqltypes.Value:
result = v
case nil:
// no op
default:
panic(fmt.Sprintf("incompatible value type %v", v))
}
if err = validateValue(col, result); err != nil {
return result, err
}
return result, nil
}
开发者ID:miffa,项目名称:vitess,代码行数:25,代码来源:codex.go
示例11: addGeneratedRows
// addGeneratedRows will add from-to generated rows. The rows (their primary
// key) will be in the range [from, to).
func (sq *testQueryService) addGeneratedRows(from, to int) {
var rows [][]sqltypes.Value
// ksids has keyspace ids which are covered by the shard key ranges -40 and 40-80.
ksids := []uint64{0x2000000000000000, 0x6000000000000000}
for id := from; id < to; id++ {
// Only return the rows which are covered by this shard.
shardIndex := id % 2
if sq.shardCount == 1 || shardIndex == sq.shardIndex {
idValue, _ := sqltypes.BuildValue(int64(id))
row := []sqltypes.Value{
idValue,
sqltypes.MakeString([]byte(fmt.Sprintf("Text for %v", id))),
}
if !sq.omitKeyspaceID {
row = append(row, sqltypes.MakeString([]byte(fmt.Sprintf("%v", ksids[shardIndex]))))
}
rows = append(rows, row)
}
}
if sq.rows == nil {
sq.rows = rows
} else {
sq.rows = append(sq.rows, rows...)
}
}
开发者ID:dumbunny,项目名称:vitess,代码行数:30,代码来源:split_clone_test.go
示例12: splitBoundariesUintColumn
func (qs *QuerySplitter) splitBoundariesUintColumn(pkMinMax *sqltypes.Result) ([]sqltypes.Value, error) {
boundaries := []sqltypes.Value{}
if pkMinMax == nil || len(pkMinMax.Rows) != 1 || pkMinMax.Rows[0][0].IsNull() || pkMinMax.Rows[0][1].IsNull() {
return boundaries, nil
}
minNumeric := pkMinMax.Rows[0][0]
maxNumeric := pkMinMax.Rows[0][1]
min, err := minNumeric.ParseUint64()
if err != nil {
return nil, err
}
max, err := maxNumeric.ParseUint64()
if err != nil {
return nil, err
}
interval := (max - min) / uint64(qs.splitCount)
if interval == 0 {
return nil, err
}
qs.rowCount = int64(interval)
for i := uint64(1); i < uint64(qs.splitCount); i++ {
v, err := sqltypes.BuildValue(min + interval*i)
if err != nil {
return nil, err
}
boundaries = append(boundaries, v)
}
return boundaries, nil
}
开发者ID:littleyang,项目名称:vitess,代码行数:29,代码来源:query_splitter.go
示例13: createRowSinglePk
func createRowSinglePk(id int) []sqltypes.Value {
idValue, _ := sqltypes.BuildValue(int32(id))
return []sqltypes.Value{
idValue,
sqltypes.MakeString([]byte(fmt.Sprintf("msg %d", id))),
}
}
开发者ID:CowLeo,项目名称:vitess,代码行数:7,代码来源:result_merger_test.go
示例14: splitBoundariesFloatColumn
func (qs *QuerySplitter) splitBoundariesFloatColumn(pkMinMax *sqltypes.Result) ([]sqltypes.Value, error) {
boundaries := []sqltypes.Value{}
if pkMinMax == nil || len(pkMinMax.Rows) != 1 || pkMinMax.Rows[0][0].IsNull() || pkMinMax.Rows[0][1].IsNull() {
return boundaries, nil
}
min, err := strconv.ParseFloat(pkMinMax.Rows[0][0].String(), 64)
if err != nil {
return nil, err
}
max, err := strconv.ParseFloat(pkMinMax.Rows[0][1].String(), 64)
if err != nil {
return nil, err
}
interval := (max - min) / float64(qs.splitCount)
if interval == 0 {
return nil, err
}
qs.rowCount = int64(interval)
for i := 1; i < int(qs.splitCount); i++ {
boundary := min + interval*float64(i)
v, err := sqltypes.BuildValue(boundary)
if err != nil {
return nil, err
}
boundaries = append(boundaries, v)
}
return boundaries, nil
}
开发者ID:littleyang,项目名称:vitess,代码行数:28,代码来源:query_splitter.go
示例15: buildDmlData
func (rowCache *InvalidationProcessor) buildDmlData(event *mysqlctl.UpdateResponse) (*proto.DmlType, error) {
if !isDmlEvent(event.SqlType) {
rowCache.updateErrCounters(NewInvalidationError(INVALID_EVENT, fmt.Sprintf("Bad Dml type, '%v'", event.SqlType), event.BinlogPosition.String()))
return nil, nil
}
dml := new(proto.DmlType)
dml.Table = event.TableName
dml.Keys = make([]interface{}, 0, len(event.PkValues))
sqlTypeKeys := make([]sqltypes.Value, 0, len(event.PkColNames))
for _, pkTuple := range event.PkValues {
sqlTypeKeys = sqlTypeKeys[:0]
if len(pkTuple) == 0 {
continue
}
for _, pkVal := range pkTuple {
key, err := sqltypes.BuildValue(pkVal)
if err != nil {
rowCache.updateErrCounters(NewInvalidationError(INVALID_EVENT, fmt.Sprintf("Error building invalidation key '%v'", err), event.BinlogPosition.String()))
return nil, nil
}
sqlTypeKeys = append(sqlTypeKeys, key)
}
invalidateKey := buildKey(sqlTypeKeys)
if invalidateKey != "" {
dml.Keys = append(dml.Keys, invalidateKey)
}
}
return dml, nil
}
开发者ID:shrutip,项目名称:vitess,代码行数:29,代码来源:rowcache_invalidator.go
示例16: Literal
// Returns an escaped literal string
func Literal(v interface{}) Expression {
value, err := sqltypes.BuildValue(v)
if err != nil {
panic("sqlbuilder: invalid literal value: " + err.Error())
}
return &literalExpression{value: value}
}
开发者ID:jzelinskie,项目名称:godropbox,代码行数:8,代码来源:expression.go
示例17: writeStartedSwap
// writeStartedSwap registers in the _vt.shard_metadata table in the database the information
// about the new schema swap process being started.
func (shardSwap *shardSchemaSwap) writeStartedSwap(sql string) error {
tablet, err := shardSwap.getMasterTablet()
if err != nil {
return err
}
query := fmt.Sprintf(
"INSERT INTO _vt.shard_metadata (name, value) VALUES ('%s', '%d') ON DUPLICATE KEY UPDATE value = '%d'",
lastStartedMetadataName, shardSwap.parent.swapID, shardSwap.parent.swapID)
_, err = shardSwap.executeAdminQuery(tablet, query, 0 /* maxRows */)
if err != nil {
return err
}
queryBuf := bytes.Buffer{}
queryBuf.WriteString("INSERT INTO _vt.shard_metadata (name, value) VALUES ('")
queryBuf.WriteString(currentSQLMetadataName)
queryBuf.WriteString("',")
sqlValue, err := sqltypes.BuildValue(sql)
if err != nil {
return err
}
sqlValue.EncodeSQL(&queryBuf)
queryBuf.WriteString(") ON DUPLICATE KEY UPDATE value = ")
sqlValue.EncodeSQL(&queryBuf)
_, err = shardSwap.executeAdminQuery(tablet, queryBuf.String(), 0 /* maxRows */)
return err
}
开发者ID:dumbunny,项目名称:vitess,代码行数:28,代码来源:schema_swap.go
示例18: getSchemaInfo
func getSchemaInfo() *SchemaInfo {
table := &schema.Table{
Name: "test_table",
}
zero, _ := sqltypes.BuildValue(0)
table.AddColumn("id", sqltypes.Int64, zero, "")
table.AddColumn("id2", sqltypes.Int64, zero, "")
table.AddColumn("count", sqltypes.Int64, zero, "")
table.PKColumns = []int{0}
primaryIndex := table.AddIndex("PRIMARY")
primaryIndex.AddColumn("id", 12345)
id2Index := table.AddIndex("idx_id2")
id2Index.AddColumn("id2", 1234)
tables := make(map[string]*TableInfo, 1)
tables["test_table"] = &TableInfo{Table: table}
tableNoPK := &schema.Table{
Name: "test_table_no_pk",
}
tableNoPK.AddColumn("id", sqltypes.Int64, zero, "")
tableNoPK.PKColumns = []int{}
tables["test_table_no_pk"] = &TableInfo{Table: tableNoPK}
return &SchemaInfo{tables: tables}
}
开发者ID:c3p0hz,项目名称:vitess,代码行数:27,代码来源:query_splitter_test.go
示例19: parseFloat
func (qs *QuerySplitter) parseFloat(pkMinMax *mproto.QueryResult) ([]sqltypes.Value, error) {
boundaries := []sqltypes.Value{}
min, err := strconv.ParseFloat(pkMinMax.Rows[0][0].String(), 64)
if err != nil {
return nil, err
}
max, err := strconv.ParseFloat(pkMinMax.Rows[0][1].String(), 64)
if err != nil {
return nil, err
}
interval := (max - min) / float64(qs.splitCount)
if interval == 0 {
return nil, err
}
qs.rowCount = int64(interval)
for i := 1; i < qs.splitCount; i++ {
boundary := min + interval*float64(i)
v, err := sqltypes.BuildValue(boundary)
if err != nil {
return nil, err
}
boundaries = append(boundaries, v)
}
return boundaries, nil
}
开发者ID:pranjal5215,项目名称:vitess,代码行数:25,代码来源:query_splitter.go
示例20: TestSplitQuery
func TestSplitQuery(t *testing.T) {
schemaInfo := getSchemaInfo()
query := &proto.BoundQuery{
Sql: "select * from test_table where count > :count",
}
splitter := NewQuerySplitter(query, 3, schemaInfo)
splitter.validateQuery()
min, _ := sqltypes.BuildValue(0)
max, _ := sqltypes.BuildValue(300)
minField := mproto.Field{
Name: "min",
Type: mproto.VT_LONGLONG,
}
maxField := mproto.Field{
Name: "min",
Type: mproto.VT_LONGLONG,
}
fields := []mproto.Field{minField, maxField}
row := []sqltypes.Value{min, max}
rows := [][]sqltypes.Value{row}
pkMinMax := &mproto.QueryResult{
Rows: rows,
Fields: fields,
}
splits := splitter.split(pkMinMax)
got := []string{}
for _, split := range splits {
if split.RowCount != 100 {
t.Errorf("wrong RowCount, got: %v, want: %v", split.RowCount, 100)
}
got = append(got, split.Query.Sql)
}
want := []string{
"select * from test_table where count > :count and id < 100",
"select * from test_table where count > :count and id >= 100 and id < 200",
"select * from test_table where count > :count and id >= 200",
}
if !reflect.DeepEqual(got, want) {
t.Errorf("wrong splits, got: %v, want: %v", got, want)
}
}
开发者ID:nangong92t,项目名称:go_src,代码行数:41,代码来源:query_splitter_test.go
注:本文中的github.com/youtube/vitess/go/sqltypes.BuildValue函数示例由纯净天空整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。 |
请发表评论