diff --git a/client/driver.go b/client/driver.go index 83f33dc43..a5314818a 100644 --- a/client/driver.go +++ b/client/driver.go @@ -100,9 +100,19 @@ func (d *covenantSQLDriver) Open(dsn string) (conn driver.Conn, err error) { // ResourceMeta defines new database resources requirement descriptions. type ResourceMeta struct { - types.ResourceMeta - GasPrice uint64 - AdvancePayment uint64 + // copied fields from types.ResourceMeta + TargetMiners []proto.AccountAddress `json:"target-miners,omitempty"` // designated miners + Node uint16 `json:"node,omitempty"` // reserved node count + Space uint64 `json:"space,omitempty"` // reserved storage space in bytes + Memory uint64 `json:"memory",omitempty` // reserved memory in bytes + LoadAvgPerCPU float64 `json:"load-avg-per-cpu",omitempty` // max loadAvg15 per CPU + EncryptionKey string `json:"encrypt-key,omitempty"` // encryption key for database instance + UseEventualConsistency bool `json:"eventual-consistency,omitempty"` // use eventual consistency replication if enabled + ConsistencyLevel float64 `json:"consistency-level,omitempty"` // customized strong consistency level + IsolationLevel int `json:"isolation-level,omitempty"` // customized isolation level + + GasPrice uint64 `json:"gas-price"` // customized gas price + AdvancePayment uint64 `json:"advance-payment"` // customized advance payment } func defaultInit() (err error) { @@ -186,8 +196,18 @@ func Create(meta ResourceMeta) (txHash hash.Hash, dsn string, err error) { req.TTL = 1 req.Tx = types.NewCreateDatabase(&types.CreateDatabaseHeader{ - Owner: clientAddr, - ResourceMeta: meta.ResourceMeta, + Owner: clientAddr, + ResourceMeta: types.ResourceMeta{ + TargetMiners: meta.TargetMiners, + Node: meta.Node, + Space: meta.Space, + Memory: meta.Memory, + LoadAvgPerCPU: meta.LoadAvgPerCPU, + EncryptionKey: meta.EncryptionKey, + UseEventualConsistency: meta.UseEventualConsistency, + ConsistencyLevel: meta.ConsistencyLevel, + IsolationLevel: meta.IsolationLevel, + }, GasPrice: meta.GasPrice, AdvancePayment: meta.AdvancePayment, TokenType: types.Particle, diff --git a/cmd/cql-minerd/integration_test.go b/cmd/cql-minerd/integration_test.go index 6aee862bd..c21f1ee6e 100644 --- a/cmd/cql-minerd/integration_test.go +++ b/cmd/cql-minerd/integration_test.go @@ -410,11 +410,9 @@ func TestFullProcess(t *testing.T) { // client send create database transaction meta := client.ResourceMeta{ - ResourceMeta: types.ResourceMeta{ - TargetMiners: minersAddrs, - Node: uint16(len(minersAddrs)), - IsolationLevel: int(sql.LevelReadUncommitted), - }, + TargetMiners: minersAddrs, + Node: uint16(len(minersAddrs)), + IsolationLevel: int(sql.LevelReadUncommitted), GasPrice: testGasPrice, AdvancePayment: testAdvancePayment, } @@ -844,11 +842,9 @@ func benchMiner(b *testing.B, minerCount uint16) { if minerCount > 0 { // create meta := client.ResourceMeta{ - ResourceMeta: types.ResourceMeta{ - Node: minerCount, - UseEventualConsistency: benchEventualConsistency, - IsolationLevel: int(sql.LevelReadUncommitted), - }, + Node: minerCount, + UseEventualConsistency: benchEventualConsistency, + IsolationLevel: int(sql.LevelReadUncommitted), } // wait for chain service var ctx1, cancel1 = context.WithTimeout(context.Background(), 1*time.Minute) @@ -962,13 +958,11 @@ func benchOutsideMinerWithTargetMinerList( if minerCount > 0 { // create meta := client.ResourceMeta{ - ResourceMeta: types.ResourceMeta{ - TargetMiners: targetMiners, - Node: minerCount, - UseEventualConsistency: benchEventualConsistency, - IsolationLevel: int(sql.LevelReadUncommitted), - }, - AdvancePayment: 1000000000, + TargetMiners: targetMiners, + Node: minerCount, + UseEventualConsistency: benchEventualConsistency, + IsolationLevel: int(sql.LevelReadUncommitted), + AdvancePayment: 1000000000, } // wait for chain service var ctx1, cancel1 = context.WithTimeout(context.Background(), 1*time.Minute) diff --git a/cmd/cql/internal/adapter.go b/cmd/cql/internal/adapter.go index 644bd76a0..03c7abab0 100644 --- a/cmd/cql/internal/adapter.go +++ b/cmd/cql/internal/adapter.go @@ -31,10 +31,10 @@ var ( // CmdAdapter is cql adapter command entity. var CmdAdapter = &Command{ - UsageLine: "cql adapter [-config file] [-tmp-path path] [-bg-log-level level] [-mirror addr] listen_address", - Short: "start a SQLChain adapter", + UsageLine: "cql adapter [common params] [-tmp-path path] [-bg-log-level level] [-mirror addr] listen_address", + Short: "start a SQLChain adapter server", Long: ` -Adapter command serves a SQLChain adapter +Adapter serves a SQLChain adapter. e.g. cql adapter 127.0.0.1:7784 `, diff --git a/cmd/cql/internal/base.go b/cmd/cql/internal/base.go index 7ccf52fd7..4112be57f 100644 --- a/cmd/cql/internal/base.go +++ b/cmd/cql/internal/base.go @@ -39,6 +39,10 @@ var ( func init() { ConsoleLog = logrus.New() + ConsoleLog.SetFormatter(&logrus.TextFormatter{ + DisableTimestamp: true, + DisableLevelTruncation: true, + }) } // A Command is an implementation of a cql command @@ -85,8 +89,8 @@ func (c *Command) Name() string { // Usage print base usage help info. func (c *Command) Usage() { - fmt.Fprintf(os.Stderr, "usage: %s\n", c.UsageLine) - fmt.Fprintf(os.Stderr, "Run 'cql help %s' for details.\n", c.LongName()) + fmt.Fprintf(os.Stdout, "usage: %s\n", c.UsageLine) + fmt.Fprintf(os.Stdout, "Run 'cql help %s' for details.\n", c.LongName()) os.Exit(2) } diff --git a/cmd/cql/internal/cfg.go b/cmd/cql/internal/cfg.go index 9a6c8f2a6..f4f0f15c2 100644 --- a/cmd/cql/internal/cfg.go +++ b/cmd/cql/internal/cfg.go @@ -56,7 +56,7 @@ func addCommonFlags(cmd *Command) { "Config file for covenantsql (Usually no need to set, default is enough.)") // debugging flags. - cmd.Flag.StringVar(&consoleLogLevel, "log-level", "error", + cmd.Flag.StringVar(&consoleLogLevel, "log-level", "info", "Console log level: trace debug info warning error fatal panic") cmd.Flag.StringVar(&password, "password", "", "Master key password for covenantsql (NOT SAFE, for debug or script only)") @@ -69,15 +69,15 @@ func addCommonFlags(cmd *Command) { func configInit(cmd *Command) { if help { - _, _ = fmt.Fprintf(os.Stderr, "usage: %s\n", cmd.UsageLine) - _, _ = fmt.Fprintf(os.Stderr, cmd.Long) - _, _ = fmt.Fprintf(os.Stderr, "\nParams:\n") + _, _ = fmt.Fprintf(os.Stdout, "usage: %s\n", cmd.UsageLine) + _, _ = fmt.Fprintf(os.Stdout, cmd.Long) + _, _ = fmt.Fprintf(os.Stdout, "\nParams:\n") cmd.Flag.PrintDefaults() Exit() } if lvl, err := logrus.ParseLevel(consoleLogLevel); err != nil { - ConsoleLog.SetLevel(logrus.ErrorLevel) + ConsoleLog.SetLevel(log.InfoLevel) } else { ConsoleLog.SetLevel(lvl) } diff --git a/cmd/cql/internal/console.go b/cmd/cql/internal/console.go index a154ba518..a14443f2d 100644 --- a/cmd/cql/internal/console.go +++ b/cmd/cql/internal/console.go @@ -46,17 +46,17 @@ import ( // CmdConsole is cql console command entity. var CmdConsole = &Command{ - UsageLine: "cql console [-config file] [-dsn dsn_string] [-command sqlcommand] [-file filename] [-out outputfile] [-no-rc true/false] [-single-transaction] [-variable variables] [-explorer explorer_addr] [-adapter adapter_addr]", + UsageLine: "cql console [common params] [-dsn dsn_string] [-command sqlcommand] [-file filename] [-out outputfile] [-no-rc true/false] [-single-transaction] [-variable variables] [-explorer explorer_addr] [-adapter adapter_addr]", Short: "run a console for interactive sql operation", Long: ` -Console command can run a interactive SQL console for CovenantSQL +Console runs an interactive SQL console for CovenantSQL. e.g. - cql console -dsn covenantsql://the_dsn_of_your_database + cql console -dsn covenantsql://4119ef997dedc585bfbcfae00ab6b87b8486fab323a8e107ea1fd4fc4f7eba5c There is also a -command param for SQL script, and a -file param for reading SQL in a file. If those params are set, it will run SQL script and exit without staying console mode. e.g. - cql console -dsn covenantsql://the_dsn_of_your_database -command "create table test1(test2 int);" + cql console -dsn covenantsql://4119ef997dedc585bfbcfae00ab6b87b8486fab323a8e107ea1fd4fc4f7eba5c -command "create table test1(test2 int);" `, } diff --git a/cmd/cql/internal/create.go b/cmd/cql/internal/create.go index f7b3bfa42..6d41d7ef1 100644 --- a/cmd/cql/internal/create.go +++ b/cmd/cql/internal/create.go @@ -26,16 +26,30 @@ import ( // CmdCreate is cql create command entity. var CmdCreate = &Command{ - UsageLine: "cql create [-config file] [-wait-tx-confirm] db_meta_json", + UsageLine: "cql create [common params] [-wait-tx-confirm] db_meta_json", Short: "create a database", Long: ` -Create CovenantSQL database by database meta info JSON string, meta info must include node count. +Create creates a CovenantSQL database by database meta info JSON string. The meta info must include +node count. e.g. - cql create '{"node":2}' + cql create '{"node": 2}' -Since CovenantSQL is blockchain database, you may want get confirm of creation. +A complete introduction of db_meta_json fields: + + target-miners []string // List of target miner addresses + node int // Target node number + space int // Minimum disk space requirement, 0 for none + memory int // Minimum memory requirement, 0 for none + load-avg-per-cpu float // Minimum idle CPU requirement, 0 for none + encrypt-key string // Encryption key for persistence data + eventual-consistency bool // Use eventual consistency to sync among miner nodes + consistency-level float // Consistency level, node*consistency_level is the node number to perform strong consistency + isolation-level int // Isolation level in a single node + +Since CovenantSQL is built on top of blockchains, you may want to wait for the transaction +confirmation before the creation takes effect. e.g. - cql create -wait-tx-confirm '{"node":2}' + cql create -wait-tx-confirm '{"node": 2}' `, } diff --git a/cmd/cql/internal/drop.go b/cmd/cql/internal/drop.go index 5bc0a0583..38c5d903a 100644 --- a/cmd/cql/internal/drop.go +++ b/cmd/cql/internal/drop.go @@ -22,16 +22,17 @@ import ( // CmdDrop is cql drop command entity. var CmdDrop = &Command{ - UsageLine: "cql drop [-config file] [-wait-tx-confirm] dsn", + UsageLine: "cql drop [common params] [-wait-tx-confirm] dsn", Short: "drop a database by dsn or database id", Long: ` -Drop command can drop a database by DSN or database id +Drop drops a CovenantSQL database by DSN or database ID. e.g. - cql drop covenantsql://the_dsn_of_your_database + cql drop covenantsql://4119ef997dedc585bfbcfae00ab6b87b8486fab323a8e107ea1fd4fc4f7eba5c -Since CovenantSQL is blockchain database, you may want get confirm of drop operation. +Since CovenantSQL is built on top of blockchains, you may want to wait for the transaction +confirmation before the drop operation takes effect. e.g. - cql drop -wait-tx-confirm covenantsql://the_dsn_of_your_database + cql drop -wait-tx-confirm covenantsql://4119ef997dedc585bfbcfae00ab6b87b8486fab323a8e107ea1fd4fc4f7eba5c `, } diff --git a/cmd/cql/internal/explorer.go b/cmd/cql/internal/explorer.go index a1a9cc9be..8ec1f4a9f 100644 --- a/cmd/cql/internal/explorer.go +++ b/cmd/cql/internal/explorer.go @@ -32,10 +32,10 @@ var ( // CmdExplorer is cql explorer command. var CmdExplorer = &Command{ - UsageLine: "cql explorer [-config file] [-tmp-path path] [-bg-log-level level] listen_address", - Short: "start a SQLChain explorer explorer", + UsageLine: "cql explorer [common params] [-tmp-path path] [-bg-log-level level] listen_address", + Short: "start a SQLChain explorer server", Long: ` -Explorer command serves a SQLChain web explorer. +Explorer serves a SQLChain web explorer. e.g. cql explorer 127.0.0.1:8546 `, diff --git a/cmd/cql/internal/generate.go b/cmd/cql/internal/generate.go index 0870bb633..89c8254ba 100644 --- a/cmd/cql/internal/generate.go +++ b/cmd/cql/internal/generate.go @@ -36,10 +36,10 @@ import ( // CmdGenerate is cql generate command entity. var CmdGenerate = &Command{ - UsageLine: "cql generate [-config file] config/public", + UsageLine: "cql generate [common params] config | public", Short: "generate config related file or keys", Long: ` -Generate command can generate private.key and config.yaml for CovenantSQL. +Generate generates private.key and config.yaml for CovenantSQL. e.g. cql generate config `, diff --git a/cmd/cql/internal/grant.go b/cmd/cql/internal/grant.go index a608771d8..3a3eaabf3 100644 --- a/cmd/cql/internal/grant.go +++ b/cmd/cql/internal/grant.go @@ -26,16 +26,17 @@ import ( // CmdGrant is cql grant command entity. var CmdGrant = &Command{ - UsageLine: "cql grant [-config file] [-wait-tx-confirm] permission_meta_json", + UsageLine: "cql grant [common params] [-wait-tx-confirm] permission_meta_json", Short: "grant a user's permissions on specific sqlchain", Long: ` -Grant command can give a user some specific permissions on your database +Grant grants specific permissions for the target user. e.g. - cql grant '{"chain":"your_chain_addr","user":"user_addr","perm":"perm_struct"}' + cql grant '{"chain": "your_chain_addr", "user": "user_addr", "perm": "perm_struct"}' -Since CovenantSQL is blockchain database, you may want get confirm of permission update. +Since CovenantSQL is built on top of blockchains, you may want to wait for the transaction +confirmation before the permission takes effect. e.g. - cql grant -wait-tx-confirm '{"chain":"your_chain_addr","user":"user_addr","perm":"perm_struct"}' + cql grant -wait-tx-confirm '{"chain": "your_chain_addr", "user": "user_addr", "perm": "perm_struct"}' `, } diff --git a/cmd/cql/internal/help.go b/cmd/cql/internal/help.go index a9ad89fa4..15ae4c7ab 100644 --- a/cmd/cql/internal/help.go +++ b/cmd/cql/internal/help.go @@ -17,6 +17,7 @@ package internal import ( + "bytes" "fmt" "os" "runtime" @@ -58,7 +59,7 @@ func PrintVersion(printLog bool) string { name, Version, runtime.GOOS, runtime.GOARCH, runtime.Version()) if printLog { - ConsoleLog.Infof("cql build: %s\n", version) + ConsoleLog.Debugf("cql build: %s\n", version) } return version @@ -69,7 +70,11 @@ func runVersion(cmd *Command, args []string) { } func runHelp(cmd *Command, args []string) { - if len(args) != 1 { + if l := len(args); l != 1 { + if l > 1 { + // Don't support multiple commands + SetExitStatus(2) + } MainUsage() } @@ -78,9 +83,10 @@ func runHelp(cmd *Command, args []string) { if cmd.Name() != cmdName { continue } - fmt.Fprintf(os.Stderr, "usage: %s\n", cmd.UsageLine) - fmt.Fprintf(os.Stderr, cmd.Long) - fmt.Fprintf(os.Stderr, "\nParams:\n") + fmt.Fprintf(os.Stdout, "usage: %s\n", cmd.UsageLine) + fmt.Fprintf(os.Stdout, cmd.Long) + fmt.Fprintf(os.Stdout, "\nParams:\n") + cmd.Flag.SetOutput(os.Stdout) cmd.Flag.PrintDefaults() return } @@ -96,28 +102,35 @@ func MainUsage() { Usage: - cql [-params] [arguments] + cql [params] [arguments] The commands are: ` + helpCommon := ` +The common params for commands (except help and version) are: + +` + helpTail := ` Use "cql help " for more information about a command. ` - helpMsg := helpHead + output := bytes.NewBuffer(nil) + output.WriteString(helpHead) for _, cmd := range CqlCommands { if cmd.Name() == "help" { continue } - cmdName := cmd.Name() - for len(cmdName) < 10 { - cmdName += " " - } - helpMsg += "\t" + cmdName + "\t" + cmd.Short + "\n" + fmt.Fprintf(output, "\t%-10s\t%s\n", cmd.Name(), cmd.Short) } - helpMsg += helpTail - fmt.Fprintf(os.Stderr, helpMsg) + addCommonFlags(CmdHelp) + fmt.Fprint(output, helpCommon) + CmdHelp.Flag.SetOutput(output) + CmdHelp.Flag.PrintDefaults() + + fmt.Fprint(output, helpTail) + fmt.Fprintf(os.Stdout, output.String()) Exit() } diff --git a/cmd/cql/internal/idminer.go b/cmd/cql/internal/idminer.go index 230501dc4..6a3969361 100644 --- a/cmd/cql/internal/idminer.go +++ b/cmd/cql/internal/idminer.go @@ -39,10 +39,11 @@ var ( // CmdIDMiner is cql idminer command entity. var CmdIDMiner = &Command{ - UsageLine: "cql idminer [-config file] [-difficulty number] [-loop false]", + UsageLine: "cql idminer [common params] [-difficulty number] [-loop [true]]", Short: "calculate nonce and node id for config.yaml file", Long: ` -IDMiner command can calculate legal node id and it's nonce. Default 24 difficulty and no endless loop. +IDMiner calculates legal node id and it's nonce. Default parameters are difficulty of 24 and +no endless loop. e.g. cql idminer -difficulty 24 diff --git a/cmd/cql/internal/mirror.go b/cmd/cql/internal/mirror.go index 1b7e76050..68804d7aa 100644 --- a/cmd/cql/internal/mirror.go +++ b/cmd/cql/internal/mirror.go @@ -31,10 +31,10 @@ var ( // CmdMirror is cql mirror command. var CmdMirror = &Command{ - UsageLine: "cql mirror [-config file] [-tmp-path path] [-bg-log-level level] dsn listen_address", - Short: "start a SQLChain database mirror", + UsageLine: "cql mirror [common params] [-tmp-path path] [-bg-log-level level] dsn listen_address", + Short: "start a SQLChain database mirror server", Long: ` -Mirror command subscribes database updates and serves a read-only database mirror. +Mirror subscribes database updates and serves a read-only database mirror. e.g. cql mirror dsn 127.0.0.1:9389 `, diff --git a/cmd/cql/internal/rpc.go b/cmd/cql/internal/rpc.go index 7f2369f5d..8b6c4b4da 100644 --- a/cmd/cql/internal/rpc.go +++ b/cmd/cql/internal/rpc.go @@ -52,10 +52,10 @@ var ( // CmdRPC is cql rpc command entity. var CmdRPC = &Command{ - UsageLine: "cql rpc [-config file] [-wait-tx-confirm] -name rpc_name -endpoint rpc_endpoint -req rpc_request", + UsageLine: "cql rpc [common params] [-wait-tx-confirm] -name rpc_name -endpoint rpc_endpoint -req rpc_request", Short: "make a rpc request", Long: ` -Rpc command make a RPC request to server +RPC makes a RPC request to the target endpoint. e.g. cql rpc -name 'MCC.QuerySQLChainProfile' \ -endpoint 000000fd2c8f68d54d55d97d0ad06c6c0d91104e4e51a7247f3629cc2a0127cf \ diff --git a/cmd/cql/internal/transfer.go b/cmd/cql/internal/transfer.go index fa2f6f1d8..7bc8080c7 100644 --- a/cmd/cql/internal/transfer.go +++ b/cmd/cql/internal/transfer.go @@ -29,17 +29,18 @@ import ( // CmdTransfer is cql transfer command entity. var CmdTransfer = &Command{ - UsageLine: "cql transfer [-config file] [-wait-tx-confirm] meta_json", + UsageLine: "cql transfer [common params] [-wait-tx-confirm] meta_json", Short: "transfer token to target account", Long: ` -Transfer command can transfer your token to the target account. -Command argument is JSON meta info of a token transaction. +Transfer transfers your token to the target account. +The command argument is a token transaction in JSON format. e.g. - cql transfer '{"addr":"your_account_addr","amount":"100 Particle"}' + cql transfer '{"addr": "43602c17adcc96acf2f68964830bb6ebfbca6834961c0eca0915fcc5270e0b40", "amount": "100 Particle"}' -Since CovenantSQL is blockchain database, you may want get confirm of permission update. +Since CovenantSQL is built on top of blockchains, you may want to wait for the transaction +confirmation before the transfer takes effect. e.g. - cql transfer -wait-tx-confirm '{"addr":"your_account_addr","amount":"100 Particle"}' + cql transfer -wait-tx-confirm '{"addr": "43602c17adcc96acf2f68964830bb6ebfbca6834961c0eca0915fcc5270e0b40", "amount": "100 Particle"}' `, } diff --git a/cmd/cql/internal/wallet.go b/cmd/cql/internal/wallet.go index 110c22f33..d54fd403b 100644 --- a/cmd/cql/internal/wallet.go +++ b/cmd/cql/internal/wallet.go @@ -31,10 +31,10 @@ var ( // CmdWallet is cql wallet command entity. var CmdWallet = &Command{ - UsageLine: "cql wallet [-config file] [-balance token_name]", + UsageLine: "cql wallet [common params] [-balance type]", Short: "get the wallet address and the balance of current account", Long: ` -Wallet command can get CovenantSQL wallet address and the token balance of current account +Wallet gets the CovenantSQL wallet address and the token balances of the current account. e.g. cql wallet @@ -110,6 +110,6 @@ func runWallet(cmd *Command, args []string) { SetExitStatus(1) return } - ConsoleLog.Infof("%s balance is: %d", tokenType.String(), tokenBalance) + fmt.Printf("%s balance is: %d\n", tokenType, tokenBalance) } } diff --git a/test/compatibility/specific_old.sh b/test/compatibility/specific_old.sh index 594dd128d..85ab9a25e 100755 --- a/test/compatibility/specific_old.sh +++ b/test/compatibility/specific_old.sh @@ -51,7 +51,7 @@ sleep 20 ${CLIENTBIN} wallet -config node_c/config.yaml -balance all -no-password -${CLIENTBIN} create -config node_c/config.yaml -wait-tx-confirm -no-password '{"node":2}' | tee dsn.txt +${CLIENTBIN} create -config node_c/config.yaml -wait-tx-confirm -no-password '{"node":2}' | tail -n1 | tee dsn.txt #get dsn dsn=$(cat dsn.txt)