Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update local command #121

Merged
merged 2 commits into from
Aug 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 14 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,27 +105,25 @@ docker> nebula-console -u <user> -p <password> --address=<graphd> --port=9669
```


## Export mode for Nebula Graph Console

When the export mode is enabled, Nebula Graph Console exports all the query results into a CSV file. When the export mode is disabled, the export stops. The syntax is as follows.
## Console side commands:

> **NOTE**: The following commands are case insensitive.

* Enable nebula-console export mode:
* Export the result of the following statement to a csv file:

```nGQL
nebula> :set CSV <your_file.csv>
nebula> :csv a.csv
```

* Disable nebula-console export mode:
* Export the execution plan in graphviz format to a dot file when profiling a statement with format "dot" or "dot:struct":

```nGQL
nebula> :unset CSV
nebula> :dot a.dot
nebula> PROFILE FORMAT="dot" GO FROM "Tony Parker" OVER like;
```
You can paste the content in the dot file to `https://dreampuf.github.io/GraphvizOnline/` to show the execution plan.

## Load nba dataset

To load the demonstration nba dataset, make sure that Console is connected to Nebula Graph.
* Load the demonstration nba dataset:

```ngql
nebula> :play nba
Expand All @@ -134,45 +132,19 @@ Start loading dataset nba...
Load dataset succeeded!
```

## Wait for heartbeat

```nGQL
nebula> :sleep 3
```

e.g.

```nGQL
cat >> nba.ngql << EOF
CREATE SPACE nba(VID_TYPE=FIXED_STRING(32));
:sleep 3

USE nba;
CREATE TAG IF NOT EXISTS player(name string, age int);
:sleep 3

INSERT VERTEX player(name, age) VALUES "Amar'e Stoudemire": ("Amar'e Stoudemire", 36)
EOF

nebula-console -addr 127.0.0.1 -port 9669 -u root -p nebula -f nba.ngql

```

## Export .dot file

To export the graviz text to a `.dot` format, run the following command:
* Repeat to execute a statement n times, the average execution time will also be printed:

```ngql
nebula> :set dot <filename>
nebula> :repeat 3
```

For example:
* Sleep for some seconds, it's just used in `:play nba`:

```ngql
nebula> TODO
```nGQL
nebula> :sleep 3
```

## Disconnect Nebula Graph Console from Nebula Graph
* Exit the console

You can use `:EXIT` or `:QUIT` to disconnect from Nebula Graph. For convenience, nebula-console supports using these commands in lower case without the colon (":"), such as `quit`.

Expand Down
93 changes: 38 additions & 55 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,13 @@ import (

// Console side commands
const (
Unknown = -1
Quit = 0
SetCsv = 1
UnsetCsv = 2
PlayData = 3
Sleep = 4
SetDot = 5
UnsetDot = 6
Repeat = 7
Unknown = -1
Quit = 0
PlayData = 1
Sleep = 2
ExportCsv = 3
ExportDot = 4
Repeat = 5
)

var dataSetPrinter = printer.NewDataSetPrinter()
Expand All @@ -45,8 +43,6 @@ in order to get the total and avearge execution time of the statement") */
var g_repeats = 1

func welcome(interactive bool) {
defer dataSetPrinter.UnsetOutCsv()
defer planDescPrinter.UnsetOutDot()
if !interactive {
return
}
Expand Down Expand Up @@ -99,6 +95,8 @@ func playData(data string) (string, error) {

// Console side cmd will not be sent to server
func isConsoleCmd(cmd string) (isLocal bool, localCmd int, args []string) {
isLocal = false
localCmd = Unknown
// Currently, command "exit" and "quit" can also exit the console
if cmd == "exit" || cmd == "quit" {
isLocal = true
Expand All @@ -112,63 +110,56 @@ func isConsoleCmd(cmd string) (isLocal bool, localCmd int, args []string) {
}

isLocal = true
localCmd = Unknown
if plain[len(plain)-1] == ';' {
plain = plain[:len(plain)-1]
}
words := strings.Fields(plain[1:])
switch len(words) {
case 1:
if words[0] == "exit" || words[0] == "quit" {
localCmd = Quit
}
case 2:
if words[0] == "unset" && words[1] == "csv" {
localCmd = UnsetCsv
} else if words[0] == "unset" && words[1] == "dot" {
localCmd = UnsetDot
} else if words[0] == "sleep" {
localCmdName := words[0]
switch localCmdName {
case "exit", "quit":
localCmd = Quit
case "sleep":
{
localCmd = Sleep
args = []string{words[1]}
} else if words[0] == "play" {
}
case "play":
{
localCmd = PlayData
args = []string{words[1]}
} else if words[0] == "repeat" {
}
case "repeat":
{
localCmd = Repeat
args = []string{words[1]}
}
case 3:
if words[0] == "set" && words[1] == "csv" {
localCmd = SetCsv
args = []string{words[2]}
} else if words[0] == "set" && words[1] == "dot" {
localCmd = SetDot
args = []string{words[2]}
case "csv":
{
localCmd = ExportCsv
args = []string{words[1]}
}
case "dot":
{
localCmd = ExportDot
args = []string{words[1]}
}
default:
localCmd = Unknown
}

return
}

func executeConsoleCmd(cmd int, args []string) (newSpace string) {
func executeConsoleCmd(c cli.Cli, cmd int, args []string) {
switch cmd {
case SetCsv:
dataSetPrinter.SetOutCsv(args[0])
case UnsetCsv:
dataSetPrinter.UnsetOutCsv()
case SetDot:
planDescPrinter.SetOutDot(args[0])
case UnsetDot:
planDescPrinter.UnsetOutDot()
case ExportCsv:
dataSetPrinter.ExportCsv(args[0])
case ExportDot:
planDescPrinter.ExportDot(args[0])
case PlayData:
var err error
newSpace, err = playData(args[0])
newSpace, err := playData(args[0])
if err != nil {
printConsoleResp("Error: load dataset failed, " + err.Error())
} else {
printConsoleResp("Load dataset succeeded!")
c.SetSpace(newSpace)
}
case Sleep:
i, err := strconv.Atoi(args[0])
Expand All @@ -187,7 +178,6 @@ func executeConsoleCmd(cmd int, args []string) (newSpace string) {
default:
printConsoleResp("Error: this local command not exists!")
}
return newSpace
}

func printResultSet(res *nebula.ResultSet, startTime time.Time) (duration time.Duration) {
Expand Down Expand Up @@ -254,14 +244,7 @@ func loop(c cli.Cli) error {
if cmd == Quit {
return nil
}
newSpace := executeConsoleCmd(cmd, args)
if newSpace != "" {
c.SetSpace(newSpace)
session.Execute(fmt.Sprintf("USE %s", newSpace))
if err != nil {
return err
}
}
executeConsoleCmd(c, cmd, args)
continue
}
// Server side command
Expand Down
24 changes: 7 additions & 17 deletions printer/dataset_printer.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,7 @@ func NewDataSetPrinter() DataSetPrinter {
}
}

func (p *DataSetPrinter) SetOutCsv(filename string) {
if p.fd != nil {
p.UnsetOutCsv()
}
func (p *DataSetPrinter) ExportCsv(filename string) {
fd, err := os.OpenFile(filename, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
if err != nil {
fmt.Printf("Open or Create file %s failed, %s", filename, err.Error())
Expand All @@ -42,17 +39,6 @@ func (p *DataSetPrinter) SetOutCsv(filename string) {
p.filename = filename
}

func (p *DataSetPrinter) UnsetOutCsv() {
if p.fd == nil {
return
}
if err := p.fd.Close(); err != nil {
fmt.Printf("Close file %s failed, %s", p.filename, err.Error())
}
p.fd = nil
p.filename = ""
}

func (p *DataSetPrinter) PrintDataSet(res *nebula.ResultSet) {
if res.GetColSize() == 0 {
return
Expand Down Expand Up @@ -86,10 +72,14 @@ func (p *DataSetPrinter) PrintDataSet(res *nebula.ResultSet) {
fmt.Println(p.writer.Render())
if p.fd != nil {
go func() {
p.fd.Truncate(0)
p.fd.Seek(0, 0)
s := strings.Replace(p.writer.RenderCSV(), "\\\"", "", -1)
fmt.Fprintln(p.fd, s)

if err := p.fd.Close(); err != nil {
fmt.Printf("Close file %s failed, %s", p.filename, err.Error())
}
p.fd = nil
p.filename = ""
}()
}
}
24 changes: 7 additions & 17 deletions printer/plan_desc_printer.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,7 @@ func NewPlanDescPrinter() PlanDescPrinter {
}
}

func (p *PlanDescPrinter) SetOutDot(filename string) {
if p.fd != nil {
p.UnsetOutDot()
}
func (p *PlanDescPrinter) ExportDot(filename string) {
fd, err := os.OpenFile(filename, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
if err != nil {
fmt.Printf("Open or Create file %s failed, %s", filename, err.Error())
Expand All @@ -51,17 +48,6 @@ func (p *PlanDescPrinter) SetOutDot(filename string) {
p.filename = filename
}

func (p *PlanDescPrinter) UnsetOutDot() {
if p.fd == nil {
return
}
if err := p.fd.Close(); err != nil {
fmt.Printf("Close file %s failed, %s", p.filename, err.Error())
}
p.fd = nil
p.filename = ""
}

func (p PlanDescPrinter) configWriterDotRenderStyle(renderByDot bool) {
if renderByDot {
p.writer.Style().Box.Left = " "
Expand Down Expand Up @@ -132,9 +118,13 @@ func (p *PlanDescPrinter) PrintPlanDesc(res *nebula.ResultSet) {

if p.fd != nil {
go func() {
p.fd.Truncate(0)
p.fd.Seek(0, 0)
fmt.Fprintln(p.fd, s)

if err := p.fd.Close(); err != nil {
fmt.Printf("Close file %s failed, %s", p.filename, err.Error())
}
p.fd = nil
p.filename = ""
}()
}
}