Esempio n. 1
0
// addHistory persists a line of input to the readline history
// file.
func addHistory(line string) {
	// readline.AddHistory will push command into memory and try to
	// persist to disk (if readline.SetHistoryPath was called).  err can
	// be not nil only if it got a IO error while trying to persist.
	if err := readline.AddHistory(line); err != nil {
		log.Warningf("cannot save command-line history: %s", err)
		log.Info("command-line history will not be saved in this session")
		readline.SetHistoryPath("")
	}
}
Esempio n. 2
0
// runInteractive runs the SQL client interactively, presenting
// a prompt to the user for each statement.
func runInteractive(conn *sqlConn) (exitErr error) {
	fullPrompt, continuePrompt := preparePrompts(conn.url)

	if isatty.IsTerminal(os.Stdout.Fd()) {
		// We only enable history management when the terminal is actually
		// interactive. This saves on memory when e.g. piping a large SQL
		// script through the command-line client.
		userAcct, err := user.Current()
		if err != nil {
			if log.V(2) {
				log.Warningf("cannot retrieve user information: %s", err)
				log.Info("cannot load or save the command-line history")
			}
		} else {
			histFile := filepath.Join(userAcct.HomeDir, ".cockroachdb_history")
			readline.SetHistoryPath(histFile)
		}
	}

	fmt.Print(infoMessage)

	var stmt []string

	for {
		thisPrompt := fullPrompt
		if len(stmt) > 0 {
			thisPrompt = continuePrompt
		}
		l, err := readline.Line(thisPrompt)

		if err == readline.ErrInterrupt || err == io.EOF {
			break
		} else if err != nil {
			fmt.Fprintf(osStderr, "input error: %s\n", err)
			return err
		}

		tl := strings.TrimSpace(l)

		// Check if this is a request for help or a client-side command.
		// If so, process it directly and skip query processing below.
		status := handleInputLine(&stmt, tl)
		if status == cliNextLine {
			continue
		} else if status == cliExit {
			break
		}

		// We join the statements back together with newlines in case
		// there is a significant newline inside a string literal. However
		// we join with spaces for keeping history, because otherwise a
		// history recall will only pull one line from a multi-line
		// statement.
		fullStmt := strings.Join(stmt, "\n")

		// We save the history between each statement, This enables
		// reusing history in another SQL shell without closing the
		// current shell.
		//
		// AddHistory will push command into memory and try to persist
		// to disk (if readline.SetHistoryPath was called).
		// err can be not nil only if it got a IO error while
		// trying to persist.
		if err := readline.AddHistory(strings.Join(stmt, " ")); err != nil {
			log.Warningf("cannot save command-line history: %s", err)
			log.Info("command-line history will not be saved in this session")
			readline.SetHistoryPath("")
		}

		if exitErr = runPrettyQuery(conn, os.Stdout, makeQuery(fullStmt)); exitErr != nil {
			fmt.Fprintln(osStderr, exitErr)
		}

		// Clear the saved statement.
		stmt = stmt[:0]
	}

	return exitErr
}