Skip to content

Commit

Permalink
Replaces CLI to use Pico CLI
Browse files Browse the repository at this point in the history
  • Loading branch information
johnedquinn committed Dec 22, 2022
1 parent 7d9c7f6 commit 683830e
Show file tree
Hide file tree
Showing 22 changed files with 390 additions and 462 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

### Changed
- Updates the CLI to use Pico CLI

### Deprecated

Expand Down
4 changes: 2 additions & 2 deletions buildSrc/src/main/kotlin/partiql.versions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ object Versions {
const val jline = "3.21.0"
const val jmh = "0.5.3"
const val joda = "2.12.1"
const val jopt = "5.0"
const val picoCli = "4.7.0"
const val ktlint = "10.2.1"
const val pig = "0.6.1"
//---Testing
Expand Down Expand Up @@ -66,7 +66,7 @@ object Deps {
val jansi = "org.fusesource.jansi:jansi:${Versions.jansi}"
val jline = "org.jline:jline:${Versions.jline}"
val joda = "joda-time:joda-time:${Versions.joda}"
val jopt = "net.sf.jopt-simple:jopt-simple:${Versions.jopt}"
const val picoCli = "info.picocli:picocli:${Versions.picoCli}"
val pig = "org.partiql:partiql-ir-generator:${Versions.pig}"
val pigRuntime = "org.partiql:partiql-ir-generator-runtime:${Versions.pig}"
//---Testing
Expand Down
67 changes: 18 additions & 49 deletions docs/tutorials/Command Line Tutorial.md
Original file line number Diff line number Diff line change
@@ -1,74 +1,43 @@
# PartiQL CLI

```
PartiQL CLI
Command line interface for executing PartiQL queries. Can be run in an interactive (REPL) mode or non-interactive.
Examples:
To run in REPL mode simply execute the executable without any arguments:
partiql
In non-interactive mode we use Ion as the format for input data which is bound to a global variable
named "input_data", in the example below /logs/log.ion is bound to "input_data":
partiql --query="SELECT * FROM input_data" --input=/logs/log.ion
The cli can output using PartiQL syntax or Ion using the --output-format option, e.g. to output binary ion:
partiql --query="SELECT * FROM input_data" --output-format=ION_BINARY --input=/logs/log.ion
## Build and Run the CLI

To pipe input data in via stdin:
cat /logs/log.ion | partiql --query="SELECT * FROM input_data" --format=ION_BINARY > output.10n
The following command will build and run the CLI:

Option Description
------ -----------
-e, --environment <File> initial global environment (optional)
-h, --help prints this help
-i, --input <File> input file, requires the query option (optional)
-if, --input-format <InputFormat> input format, requires the query option (default: ION) [ION, PARTIQL]
-w, --wrap-ion wraps Ion input file values in a bag, requires the input format to be ION, requires the query option
-m, --monochrome removes syntax highlighting for the REPL
-o, --output <File> output file, requires the query option (default: stdout)
-of, --output-format <OutputFormat> output format, requires the query option (default: PARTIQL) [PARTIQL, PARTIQL_PRETTY, ION_TEXT, ION_BINARY]
-p, --permissive run the PartiQL query in PERMISSIVE typing mode
-q, --query <String> PartiQL query, triggers non interactive mode
```

## Building the CLI
```shell
# To build and run
./partiql-app/partiql-cli/shell.sh

The root Gradle build also builds the CLI. To build the CLI separately, execute:
# To build (only)
./gradlew :partiql-app:partiql-cli:install

```shell
./gradlew :cli:build
# To Run (only)
./partiql-app/partiql-cli/build/install/partiql-cli/bin/partiql
```

After building, distributable jars are located in the `cli/build/distributions` directory (relative to the
After building the entire project, distributable jars are located in the `cli/build/distributions` directory (relative to the
project root).

Be sure to include the correct relative path to `gradlew` if you are not in the project root.

## Using the CLI
## CLI Commands

The following command will build any dependencies before starting the CLI.
To view all commands available, run the CLI with the `--help` option.

```shell
./gradlew :cli:run -q --args="<command line arguments>"
```
## Shell

The CLI can be run in two manners, non-interactive and interactive (REPL).

## REPL

To start an interactive read, eval, print loop (REPL) execute:
To start an interactive shell, execute:

> Note that running directly with Gradle will eat arrow keys and control sequences due to the Gradle daemon.
```shell
./partiql-app/partiql-cli/shell.sh
./partiql-app/partiql-cli/shell.sh shell
```

You will see a prompt that looks as follows:

```shell
Welcome to the PartiQL REPL!
Welcome to the PartiQL Shell!
PartiQL>
```

Expand Down Expand Up @@ -173,15 +142,15 @@ The variables `animals` and `types` can both be bound to the execution environme
To bind the environment file to the execution environment, start the REPL with the following command:
```shell
$ ./gradlew :cli:run -q --console=plain --args='-e config.env'
$ ./partiql-app/partiql-cli/shell.sh shell -e config.env
```
**Note**: Shell expansions such as `~` do not work within the value of the `args` argument.
Or, if you have extracted one of the compressed archives:
```shell
$ ./bin/partiql -e config.env
$ ./bin/partiql shell -e config.env
```
Expressions can then use the environment defined by `config.env`:
Expand Down
94 changes: 10 additions & 84 deletions docs/tutorials/Tutorial.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Getting Started

PartiQL provides an interactive shell, or Read Evaluate Print Loop (REPL),
that allows users to write and evaluate PartiQL queries.
PartiQL provides an interactive shell that allows users to write and evaluate PartiQL queries.

## Prerequisites

Expand All @@ -14,9 +13,9 @@ You can obtain the *latest* version of the Java Runtime from either
[Follow the instructions on how to set](https://docs.oracle.com/cd/E19182-01/820-7851/inst_cli_jdk_javahome_t/)
`JAVA_HOME` to the path where your Java Runtime is installed.

## Download the PartiQL REPL
## Download the PartiQL CLI

Each release of PartiQL comes with an archive that contains the PartiQL REPL as a
Each release of PartiQL comes with an archive that contains the PartiQL CLI as a
zip file.

1. [Download](https://github.com/partiql/partiql-lang-kotlin/releases).
Expand Down Expand Up @@ -58,20 +57,20 @@ The root folder `partiql-cli` contains a `README.md` file and 3 subfolders
1. Sample query output files with the extension `.output`. These files
contain sample output from running the tutorial queries on the
appropriate data.
1. Alternatively, you can use the online [CLI Tutorial](https://github.com/partiql/partiql-lang-kotlin/wiki/Command-Line-Tutorial).




## Running the PartiQL REPL
## Running the PartiQL CLI

### Windows

Run (double click on) `partiql.bat`. This should open a command-line
prompt and start the PartiQL REPL which displays:
prompt and start the PartiQL CLI which displays:

```shell
Welcome to the PartiQL REPL!
PartiQL>
Welcome to the PartiQL CLI!
```

### macOS (Mac) and Unix
Expand All @@ -82,85 +81,12 @@ PartiQL>
The folder name will have the PartiQL version as a suffix, i.e., `partiql-cli-0.1.0`.

```shell
Welcome to the PartiQL REPL!
PartiQL>
Welcome to the PartiQL CLI!
```

## Testing the PartiQL REPL

Let's write a simple query to verify that our PartiQL REPL is working. At the `PartiQL>` prompt type:

```shell
PartiQL> SELECT * FROM [1,2,3]
```

and press `ENTER` *twice*. The output should look similar to:

```partiql
<<
{
'_1': 1
},
{
'_1': 2
},
{
'_1': 3
}
>>
```

Congratulations! You successfully installed and run the PartiQL REPL.
The PartiQL REPL is now waiting for more input.

To exit the PartiQL REPL, press:

* `Control+D` in macOS or Unix
* `Control+C` on Windows

or close the terminal/command prompt window.


## Loading data from a file

An easy way to load the necessary data into the REPL
is use the `-e` switch when starting the REPL
and provide the name of a file that contains your data.

```shell
./bin/partiql -e Tutorial/code/q1.env
```

You can then see what is loaded in the REPL's global environment using
the **special** REPL command `!global_env`, i.e.,

```shell
PartiQL> !global_env;
```
```partiql
{
'hr': {
'employees': <<
{
'id': 3,
'name': 'Bob Smith',
'title': NULL
},
{
'id': 4,
'name': 'Susan Smith',
'title': 'Dev Mgr'
},
{
'id': 6,
'name': 'Jane Smith',
'title': 'Software Eng 2'
}
>>
}
}
```
### Command Line Tutorial

To get a deeper understanding of PartiQL, check out the [CLI Tutorial](https://github.com/partiql/partiql-lang-kotlin/wiki/Command-Line-Tutorial).

# Introduction

Expand Down
4 changes: 2 additions & 2 deletions partiql-app/partiql-cli/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ dependencies {
implementation(Deps.jansi)
implementation(Deps.jline)
implementation(Deps.joda)
implementation(Deps.jopt)
implementation(Deps.picoCli)
implementation(Deps.kotlinReflect)
}

application {
applicationName = "partiql"
mainClass.set("org.partiql.cli.Main")
mainClass.set("org.partiql.Main")
}

distributions {
Expand Down
2 changes: 1 addition & 1 deletion partiql-app/partiql-cli/shell.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ cli_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )

cd "$cli_path"
../../gradlew :partiql-app:partiql-cli:install
../partiql-cli/build/install/partiql-cli/bin/partiql
../partiql-cli/build/install/partiql-cli/bin/partiql "$@"
39 changes: 39 additions & 0 deletions partiql-app/partiql-cli/src/main/kotlin/org/partiql/Main.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright 2019 Amazon.com, Inc. or its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at:
*
* http://aws.amazon.com/apache2.0/
*
* or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
* language governing permissions and limitations under the License.
*/
@file:JvmName("Main")

@file:Suppress("DEPRECATION")

package org.partiql

import com.amazon.ion.system.IonSystemBuilder
import org.partiql.lang.eval.ExprValueFactory
import org.partiql.pico.CommandPartiQL
import org.partiql.pico.CommandQuery
import org.partiql.pico.CommandShell
import picocli.CommandLine
import kotlin.system.exitProcess

/**
* Runs the PartiQL CLI.
*/
fun main(args: Array<String>) {
val ion = IonSystemBuilder.standard().build()
val valueFactory = ExprValueFactory.standard(ion)
val command = CommandLine(CommandPartiQL())
.addSubcommand(CommandQuery(valueFactory))
.addSubcommand(CommandShell(valueFactory))
val exitCode = command.execute(*args)
exitProcess(exitCode)
}
25 changes: 13 additions & 12 deletions partiql-app/partiql-cli/src/main/kotlin/org/partiql/cli/Cli.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import org.partiql.lang.eval.PartiQLResult
import org.partiql.lang.eval.delegate
import org.partiql.lang.eval.toIonValue
import org.partiql.lang.util.ConfigurableExprValueFormatter
import org.partiql.pico.CommandQuery
import org.partiql.pipeline.AbstractPipeline
import java.io.InputStream
import java.io.OutputStream
Expand All @@ -34,20 +35,20 @@ import java.io.OutputStreamWriter
internal class Cli(
private val valueFactory: ExprValueFactory,
private val input: InputStream,
private val inputFormat: InputFormat,
private val inputFormat: CommandQuery.InputFormat,
private val output: OutputStream,
private val outputFormat: OutputFormat,
private val outputFormat: CommandQuery.OutputFormat,
private val compilerPipeline: AbstractPipeline,
private val globals: Bindings<ExprValue>,
private val query: String,
private val wrapIon: Boolean
) : PartiQLCommand {
) {

private val ion = IonSystemBuilder.standard().build()

init {
if (wrapIon && inputFormat != InputFormat.ION) {
throw IllegalArgumentException("Specifying --wrap-ion requires that the input format be ${InputFormat.ION}.")
if (wrapIon && inputFormat != CommandQuery.InputFormat.ION) {
throw IllegalArgumentException("Specifying --wrap-ion requires that the input format be ${CommandQuery.InputFormat.ION}.")
}
}

Expand All @@ -56,10 +57,10 @@ internal class Cli(
.withWriteTopLevelValuesOnNewLines(true)
}

override fun run() {
internal fun run() {
when (inputFormat) {
InputFormat.ION -> runWithIonInput()
InputFormat.PARTIQL -> runWithPartiQLInput()
CommandQuery.InputFormat.ION -> runWithIonInput()
CommandQuery.InputFormat.PARTIQL -> runWithPartiQLInput()
}
}

Expand Down Expand Up @@ -118,10 +119,10 @@ internal class Cli(

private fun outputResult(result: ExprValue) {
when (outputFormat) {
OutputFormat.ION_TEXT -> ionTextWriterBuilder.build(output).use { result.toIonValue(ion).writeTo(it) }
OutputFormat.ION_BINARY -> valueFactory.ion.newBinaryWriter(output).use { result.toIonValue(ion).writeTo(it) }
OutputFormat.PARTIQL -> OutputStreamWriter(output).use { it.write(result.toString()) }
OutputFormat.PARTIQL_PRETTY -> OutputStreamWriter(output).use {
CommandQuery.OutputFormat.ION_TEXT -> ionTextWriterBuilder.build(output).use { result.toIonValue(ion).writeTo(it) }
CommandQuery.OutputFormat.ION_BINARY -> valueFactory.ion.newBinaryWriter(output).use { result.toIonValue(ion).writeTo(it) }
CommandQuery.OutputFormat.PARTIQL -> OutputStreamWriter(output).use { it.write(result.toString()) }
CommandQuery.OutputFormat.PARTIQL_PRETTY -> OutputStreamWriter(output).use {
ConfigurableExprValueFormatter.pretty.formatTo(result, it)
}
}
Expand Down
Loading

0 comments on commit 683830e

Please sign in to comment.