0
# CLI Interface
1
2
Interactive command-line interface for executing SQL queries with Hive CLI compatibility. Provides a beeline/hive-style interactive shell for Spark SQL.
3
4
## Capabilities
5
6
### Main CLI Entry Point
7
8
Primary entry point for starting the interactive SQL command-line interface.
9
10
```scala { .api }
11
/**
12
* Entry point for interactive SQL CLI
13
* Provides Hive CLI compatible interface for Spark SQL
14
* @param args Command line arguments compatible with Hive CLI
15
*/
16
def main(args: Array[String]): Unit
17
```
18
19
**Usage Example:**
20
21
```scala
22
// Start interactive CLI
23
object MySQLCLI extends App {
24
SparkSQLCLIDriver.main(Array(
25
"-e", "SELECT * FROM my_table LIMIT 10", // Execute command and exit
26
"-f", "queries.sql", // Execute file and exit
27
"-i", "init.sql" // Run initialization script
28
))
29
}
30
```
31
32
**Supported Command Line Options:**
33
34
- `-e <sql>` - Execute SQL command and exit
35
- `-f <filename>` - Execute SQL commands from file
36
- `-i <filename>` - Execute initialization script before starting
37
- `-database <dbname>` - Set initial database
38
- `-silent` - Reduce output verbosity
39
- `-h <hostname>` - Connect to remote Hive server (limited support)
40
41
### Signal Handling
42
43
Installs interrupt handler for graceful cancellation of running operations.
44
45
```scala { .api }
46
/**
47
* Install interrupt callback to cancel all Spark jobs
48
* Enables Ctrl+C handling during query execution
49
*/
50
def installSignalHandler(): Unit
51
```
52
53
**Functionality:**
54
- Registers callback with Hive's interrupt handling system
55
- Cancels all running Spark jobs on Ctrl+C signal
56
- Handles both local and remote execution modes
57
- Provides clean termination of long-running queries
58
59
### CLI Driver Implementation
60
61
The private `SparkSQLCLIDriver` class extends Hive's `CliDriver` with Spark-specific command processing.
62
63
```scala { .api }
64
private[hive] class SparkSQLCLIDriver extends CliDriver {
65
/**
66
* Process SQL commands and CLI directives
67
* @param cmd Command string to execute
68
* @return Exit code (0 for success, non-zero for error)
69
*/
70
override def processCmd(cmd: String): Int
71
}
72
```
73
74
### Command Processing
75
76
The CLI supports both SQL commands and special CLI directives:
77
78
**SQL Commands:**
79
- Standard SQL queries (SELECT, INSERT, CREATE, etc.)
80
- DDL operations (CREATE TABLE, ALTER TABLE, etc.)
81
- DML operations (INSERT, UPDATE, DELETE)
82
- Spark SQL specific functions and syntax
83
84
**CLI Directives:**
85
- `quit` or `exit` - Exit the CLI
86
- `source <filename>` - Execute commands from file
87
- `!<shell_command>` - Execute shell command
88
- `list` - List available commands
89
90
### Interactive Session Management
91
92
The CLI provides an interactive session with:
93
94
**Command History:**
95
```scala
96
// History file location
97
val historyDirectory = System.getProperty("user.home")
98
val historyFile = historyDirectory + File.separator + ".hivehistory"
99
reader.setHistory(new FileHistory(new File(historyFile)))
100
```
101
102
**Command Completion:**
103
```scala
104
// Add Hive command completer
105
CliDriver.getCommandCompleter.foreach((e) => reader.addCompleter(e))
106
```
107
108
**Prompt Customization:**
109
```scala
110
val currentDB = ReflectionUtils.invokeStatic(classOf[CliDriver], "getFormattedDb",
111
classOf[HiveConf] -> conf, classOf[CliSessionState] -> sessionState)
112
113
def promptWithCurrentDB: String = s"$prompt$currentDB"
114
```
115
116
### SQL Execution Flow
117
118
The CLI processes commands through a specific flow:
119
120
1. **Command Parsing**: Tokenize and identify command type
121
2. **Context Selection**: Choose appropriate processor (Spark vs Hive)
122
3. **Execution**: Run command through SparkSQLDriver or native processor
123
4. **Result Handling**: Format and display results
124
5. **Timing**: Track and report execution time
125
126
```scala
127
val start: Long = System.currentTimeMillis()
128
val rc = driver.run(cmd)
129
val end = System.currentTimeMillis()
130
val timeTaken: Double = (end - start) / 1000.0
131
132
ret = rc.getResponseCode
133
if (ret != 0) {
134
rc.getException() match {
135
case e: AnalysisException =>
136
err.println(s"""Error in query: ${e.getMessage}""")
137
case _ => err.println(rc.getErrorMessage())
138
}
139
}
140
```
141
142
### Result Display
143
144
The CLI provides flexible result formatting:
145
146
**Header Display:**
147
```scala
148
if (HiveConf.getBoolVar(conf, HiveConf.ConfVars.HIVE_CLI_PRINT_HEADER)) {
149
// Print column names
150
Option(driver.getSchema.getFieldSchemas).foreach { fields =>
151
out.println(fields.asScala.map(_.getName).mkString("\t"))
152
}
153
}
154
```
155
156
**Result Streaming:**
157
```scala
158
val res = new JArrayList[String]()
159
var counter = 0
160
while (!out.checkError() && driver.getResults(res)) {
161
res.asScala.foreach { line =>
162
counter += 1
163
out.println(line)
164
}
165
res.clear()
166
}
167
```
168
169
**Execution Summary:**
170
```scala
171
var responseMsg = s"Time taken: $timeTaken seconds"
172
if (counter != 0) {
173
responseMsg += s", Fetched $counter row(s)"
174
}
175
console.printInfo(responseMsg, null)
176
```
177
178
### Environment Integration
179
180
The CLI integrates with SparkSQLEnv for context management:
181
182
```scala
183
// Initialize Spark SQL environment if not in remote mode
184
if (!isRemoteMode) {
185
SparkSQLEnv.init()
186
} else {
187
throw new RuntimeException("Remote operations not supported")
188
}
189
190
// Set initial database if specified
191
if (sessionState.database != null) {
192
SparkSQLEnv.hiveContext.runSqlHive(s"USE ${sessionState.database}")
193
}
194
```
195
196
### Error Handling
197
198
Comprehensive error handling for various scenarios:
199
200
**File Operations:**
201
```scala
202
try {
203
if (sessionState.fileName != null) {
204
System.exit(cli.processFile(sessionState.fileName))
205
}
206
} catch {
207
case e: FileNotFoundException =>
208
logError(s"Could not open input file for reading. (${e.getMessage})")
209
System.exit(3)
210
}
211
```
212
213
**Encoding Issues:**
214
```scala
215
try {
216
sessionState.out = new PrintStream(System.out, true, "UTF-8")
217
sessionState.info = new PrintStream(System.err, true, "UTF-8")
218
sessionState.err = new PrintStream(System.err, true, "UTF-8")
219
} catch {
220
case e: UnsupportedEncodingException => System.exit(3)
221
}
222
```
223
224
### Multi-line Command Support
225
226
The CLI supports multi-line SQL commands with continuation prompts:
227
228
```scala
229
var prefix = ""
230
var currentPrompt = promptWithCurrentDB
231
var line = reader.readLine(currentPrompt + "> ")
232
233
while (line != null) {
234
if (!line.startsWith("--")) { // Skip comments
235
if (prefix.nonEmpty) {
236
prefix += '\n'
237
}
238
239
if (line.trim().endsWith(";") && !line.trim().endsWith("\\;")) {
240
line = prefix + line
241
ret = cli.processLine(line, true)
242
prefix = ""
243
currentPrompt = promptWithCurrentDB
244
} else {
245
prefix = prefix + line
246
currentPrompt = continuedPromptWithDBSpaces
247
}
248
}
249
line = reader.readLine(currentPrompt + "> ")
250
}
251
```
252
253
This enables natural SQL authoring with commands spanning multiple lines, terminated by semicolons.