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

Add subqueries, attribute modifiers & interactive mode #27

Merged
merged 42 commits into from
Jun 4, 2017
Merged

Conversation

kashav
Copy link
Owner

@kashav kashav commented Jun 4, 2017

Addresses #4, #17 (#3, #15).

This PR introduces 3 main features:

Also includes a slight refactor to the project structure. I've included a little before/after highlighting package changes below.

  • Before:

    . (main)
    ├── compare
    ├── query
    
  • Now:

    . (fsql)
    ├── cmd
    │   └── fsql (main)
    ├── parser
    ├── prompt
    ├── query
    ├── tokenizer
    └── transform
    

Additionally adds a Travis build step with some unit tests.

kashav and others added 30 commits May 17, 2017 03:53
The currently solution requires us to track both the tokenizer's "previous"
Token as well as each Token's preceding Token.

When we reach an opening paren, we check if it's preceding token is IN, and if
so, the next block is read as a Subquery.
This is just a string representing another input, so it'll be tokenized,
parsed, and evalulated as an individual query.

If the subquery includes parens, this method of reading breaks, since we stop
reading as soon as we reach a closing paren. So, we'll have to count opening
parens and only exit when the count is down to 0.
Addresses FIXMEs for parsing parens in subqueries and quotes/backticks.
Subqueries were missing an identifier; resolved by adding the final "word"
to the query string before breaking (in Tokenizer.readQuery).
Subquery implementation
=======================

  - Evaluates subqueries as individual queries on parse step. Currently
    lets you do something like:

    SELECT
      all
    FROM
      ~/Desktop
    WHERE
      name IN (
        SELECT
          name
        FROM
          $GOPATH/src
        WHERE
          name = %.go) AND
      size > 2mb

    Some points for discussion:

      - No support for SELECTing and comparing more than one attribute in a
        subquery yet, I'm not really sure _how_ to implement this (or even
        if it's necessary).

  - Also implemented boilerplate for superquery/subquery references (as
    discussed in #4#issuecomment-302104954). Currently runs **terribly**
    though, not really sure if there's a way to improve performance. Also,
    haven't added support for substituting directory/file names yet.

IN operator (non-subquery)
==========================

  - Haven't decided if I'm going to keep this. Currently only works for `name`.
    Accepts a comma-separated list of strings and checks if filename is in list.

  - Example:

    SELECT
      all
    FROM
      .
    WHERE
      name IN [main.go, query.go]

Project layout changes
======================

  - Introduce individual packages for tokenizer and parser;
  - Move compare package to query.

Unit tests
==========

  - Adds tests for tokenizer and compare functions.
  - Some tokenizer tests are currently failing (reflect.DeepEqual is saying
    identical strings don't match, might be a type issue (interface{} vs.
    string)).

Bug fixes
=========

  - Minor: Fix less-than-equal raw text (was >= before, doesn't really change
    anything, since we're not using the raw text for anything).
- Rename Transformation -> Modifier.
- Update PerformTransformations (renamed to ApplyModifiers) to run on all
  attributes at once.
- Each modifier function receives access to the key as well as path and
  os.FileInfo, so we're able to run our operation based on the key instead of
  type (i.e. format(time, ...) vs format(size, ...) shouldn't be a problem
  anymore).

Note that nothing here is final. I plan to merge these changes with the updated
parser structure, which means we'll a large portion of this will have to be
rewritten to fit the new structure.
* Adds excluder interface that can be used to determine file paths to exclude from output
* Implements excluder in regexExclude to detect if a filepath should be excluded
Further simplify Exlcuder.buildRegex, make test cases more concise
* feature/subquery:
  Minor clean-up
  Use regex to detect exclusions instead of string.Contains (#21)
  Fix failing tests; track tokens with slice instead of linked list
  Add prelim. implementation of subqueries; update package structure
  Fix bug with missing ending identifier in parsed subqueries
  Replace stack implementation with Lane (oleiade/lane)
  Minor tokenizer refactor
  Add subquery tokenizer
Currently supports 'iso' and 'unix' modes.
- Add support for attribute modifiers in WHERE clause. The Condition struct
  holds any and all attribute modifiers used in that condition.
- Offset all "transformation" work to transform package. This package is split
  into two parts: format and parse. Parse is use to parse input values (i.e.
  WHERE clause attributes) and format is used to format output values (i.e.
  SELECT clause attributes).
- Currently support modifiers: FORMAT for time (iso/unix), size (kb/mb/gb),
  UPPER and LOWER (for name), and FULLPATH (also for name).
- Note that attribute modifiers are not fully implemented for subqueries (both
  evaluated and unevaluated).
Use filepath.Clean on user given paths before processing
Now supports the following cases:

  1) SELECT all FROM . WHERE UPPER(name) IN (SELECT name FROM foo)
  2) SELECT all FROM . WHERE LOWER(name) IN [foo, BAR, BaZ]

Decided to make the parsers for these as abstract as possible; ended up using
reflect _quite_ heavily (mainly for working with "interfaced" slices/maps).
From my brief testing, it's working as it should, but this is probably
slightly unsafe.

Also removed tokenizer.readList in favour of parsing everything related
to conditions/attributes in parser.parseNextCond.

Note: Still no support for queries with super/sub-relationships (even without
attribute modifiers). Going to try to get this squashed next.
- Rename Condition.Comparator -> Condition.Operator.
- Change type of ConditionNode.Type to *TokenType (was TokenType).
- Clean directory filepaths when parsing source list instead of during
  traversal (exclusions are normalized as well now).
- Handle aliased exclusions (throws error, since it'd make no sense to give
  excluded directories an alias).
- Also removes a ton of dead code (notably size parsing, which was moved to
  the transform package).
Removes `go vet` cmd from Travis pre-script, since was getting a different
result locally, will take a look into this.
Recursive modifiers (e.g. `FULLPATH(UPPER(name))`) weren't being applied since
we were passing c.Value each time instead of the previously-altered value (so
only the innermost modifier was having an effect).
kashav added 12 commits May 29, 2017 04:08
- Invoked with -interactive.
- No arrow key support yet (for moving fwd/back in query, accessing previous
  queries, etc). Not sure how to go about implementing this right now.
- Slight change in structure: flag/input parsing moved to cmd/fsql, while
  top-level package (fsql) handles running the query and printing output.
- Adds new package with channel-based shell prompt. Allows for quote-less
  AND escape-less queries. End queries with single semicolon.
Layout must be set according to 2006-01-02T15:04:05.999999-07:00, some sample
queries:

  $ fsql SELECT all FROM . WHERE format(time, 2006-01-02) > 2017-05-29
  $ fsql SELECT name, format(time, "2016-01-02 15:04:05") FROM .
Subqueries, attribute modifiers & interactive mode!
* master:
  Add Homebrew installation instructions
  Bump version
  Add note for selecting from dirs that begin with hypen
- Add Travis badge to README
- Organize .gitignore
- Bump version to 0.2.0
@kashav kashav merged commit 09ea293 into master Jun 4, 2017
This was referenced Jun 4, 2017
@kashav kashav deleted the develop branch June 4, 2017 20:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants