Skip to content

Commit

Permalink
Added CURRENT_USER, 'USER and SESSION_USER` system functions.
Browse files Browse the repository at this point in the history
  • Loading branch information
andreidan committed Jun 26, 2017
1 parent 7e94e19 commit abb059a
Show file tree
Hide file tree
Showing 21 changed files with 527 additions and 71 deletions.
6 changes: 6 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ the appropriate section of the docs.
Breaking Changes
================

- ``CURRENT_USER``, ``USER`` and ``SESSION_USER`` are now reserved words as we
introduced them as system functions. These terms will not be available to
be used as table, and column names and for already existing entities they
will have to be quoted when referenced (otherwise the terms will be treated
as function calls).

- ``SELECT`` statements without any ``FROM`` items are no longer executed
against the ``sys.cluster`` table, but against a virtual table with no
columns. Queries including ``sys.cluster`` columns but no explicit ``FROM``
Expand Down
42 changes: 21 additions & 21 deletions blackbox/docs/best_practice/data_import.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ Defining the Data Structure
Before starting the import you'll have to consider how your table structure
will look. Decisions made at this point will influence the import process later.

For this example we have a simple single ``user`` table with 6 columns of
For this example we have a simple single ``users`` table with 6 columns of
various types::

cr> CREATE TABLE user (
cr> CREATE TABLE users (
... id INT primary key,
... name STRING,
... day_joined TIMESTAMP,
Expand All @@ -40,7 +40,7 @@ various types::

.. hide:

cr> DROP TABLE user;
cr> DROP TABLE users;
DROP OK, 1 row affected (... sec)

There's nothing wrong with this method and it does the job, but it's not very
Expand Down Expand Up @@ -80,7 +80,7 @@ according to your availability requirements.

The ``CREATE TABLE`` statement now looks like::

cr> CREATE TABLE user (
cr> CREATE TABLE users(
... id INT primary key,
... name STRING,
... day_joined TIMESTAMP,
Expand All @@ -107,17 +107,17 @@ therefore also minimise the overhead during import.

::

cr> ALTER TABLE user SET (refresh_interval = 0);
cr> ALTER TABLE users SET (refresh_interval = 0);
ALTER OK, -1 rows affected (... sec)

.. hide:

cr> DROP TABLE user;
cr> DROP TABLE users;
DROP OK, 1 row affected (... sec)

It's possible to set the refresh interval in the ``CREATE TABLE`` statement::

cr> CREATE TABLE user (
cr> CREATE TABLE users (
... id INT primary key,
... name STRING,
... day_joined TIMESTAMP,
Expand All @@ -136,7 +136,7 @@ It's possible to set the refresh interval in the ``CREATE TABLE`` statement::
Once the import is finished you can set the refresh interval to a reasonable
value (time in ms)::

cr> ALTER TABLE user SET (refresh_interval = 1000);
cr> ALTER TABLE users SET (refresh_interval = 1000);
ALTER OK, -1 rows affected (... sec)

.. seealso::
Expand Down Expand Up @@ -212,18 +212,18 @@ will return successfully, reporting ``COPY OK, 0 rows affected (... sec)``.

::

cr> COPY user FROM '/tmp/best_practice_data/users.json';
cr> COPY users FROM '/tmp/best_practice_data/users.json';
COPY OK, 150 rows affected (... sec)

.. hide:

cr> REFRESH TABLE user;
cr> REFRESH TABLE users;
REFRESH OK, 1 row affected (... sec)

cr> delete from user;
cr> delete from users;
DELETE OK, 150 rows affected (... sec)

cr> REFRESH TABLE user;
cr> REFRESH TABLE users;
REFRESH OK, 1 row affected (... sec)

.. note::
Expand All @@ -242,19 +242,19 @@ defaults to 10 000 if not specified.

For example::

cr> COPY user FROM '/tmp/best_practice_data/users.json'
cr> COPY users FROM '/tmp/best_practice_data/users.json'
... WITH (bulk_size = 2000);
COPY OK, 150 rows affected (... sec)

.. hide:

cr> REFRESH TABLE user;
cr> REFRESH TABLE users;
REFRESH OK, 1 row affected (... sec)

cr> delete from user;
cr> delete from users;
DELETE OK, 150 rows affected (... sec)

cr> REFRESH TABLE user;
cr> REFRESH TABLE users;
REFRESH OK, 1 row affected (... sec)

In our example it will not make a difference, but if you have a more complex
Expand All @@ -274,13 +274,13 @@ CrateDB does not automatically detect compression, so you'll need to specify

For example::

cr> COPY user FROM '/tmp/best_practice_data/users.json.gz'
cr> COPY users FROM '/tmp/best_practice_data/users.json.gz'
... WITH (compression = 'gzip');
COPY OK, 150 rows affected (... sec)

.. hide:

cr> REFRESH TABLE user;
cr> REFRESH TABLE users;
REFRESH OK, 1 row affected (... sec)

Partitioned Tables
Expand All @@ -300,12 +300,12 @@ partition column.

.. hide:

cr> DROP TABLE user;
cr> DROP TABLE users;
DROP OK, 1 row affected (... sec)

::

cr> CREATE TABLE user (
cr> CREATE TABLE users (
... id INT primary key,
... name STRING,
... day_joined TIMESTAMP primary key,
Expand Down Expand Up @@ -333,7 +333,7 @@ For example: ``users_1408312800.json``
The value of the partition column must be defined in the ``COPY FROM``
statement using the ``PARTITION`` clause::

cr> COPY user PARTITION (day_joined=1408312800)
cr> COPY users PARTITION (day_joined=1408312800)
... FROM '/tmp/best_practice_data/users_1408312800.json';
COPY OK, 23 rows affected (... sec)

Expand Down
81 changes: 78 additions & 3 deletions blackbox/docs/sql/scalar.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1621,9 +1621,11 @@ The default schema can be set when using the `JDBC
<https://crate.io/docs/reference/protocols/http.html#default-schema>`_ such as
`CrateDB PDO`_.

The ``CURRENT_SCHEMA`` function has a special SQL syntax, meaning that it must
be called without trailing parenthesis (``()``). However, CrateDB also supports
the optional parenthesis.
.. note::

The ``CURRENT_SCHEMA`` function has a special SQL syntax, meaning that it
must be called without trailing parenthesis (``()``). However, CrateDB also
supports the optional parenthesis.

Synopsis::

Expand All @@ -1639,6 +1641,76 @@ Example::
+----------------+
SELECT 1 row in set (... sec)

``CURRENT_USER``
----------------

The ``CURRENT_USER`` system information function returns the name of the
current connected user.

Returns: ``string``

Synopsis::

CURRENT_USER

Example::

cr> select current_user;
+--------------+
| current_user |
+--------------+
| crate |
+--------------+
SELECT 1 row in set (... sec)

``USER``
--------

Equivalent to ``CURRENT_USER``.

Returns: ``string``

Synopsis::

USER

Example::

cr> select user;
+--------------+
| current_user |
+--------------+
| crate |
+--------------+
SELECT 1 row in set (... sec)

``SESSION_USER``
----------------
The ``SESSION_USER`` system information function returns the name of the
current connected user.

Returns: ``string``

Synopsis::

SESSION_USER

Example::

cr> select session_user;
+--------------+
| session_user |
+--------------+
| crate |
+--------------+
SELECT 1 row in set (... sec)

.. note::

The ``CURRENT_USER``, ``SESSION_USER`` and ``USER`` functions have a
a special SQL syntax, meaning that they must be called without trailing
parenthesis (``()``).

.. rubric:: Footnotes

.. [#MySQL-Docs] http://dev.mysql.com/doc/refman/5.6/en/date-and-time-functions.html#function_date-format
Expand All @@ -1647,4 +1719,7 @@ Example::
.. _Java Regular Expressions: http://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html
.. _`MySQL date_format`: http://dev.mysql.com/doc/refman/5.6/en/date-and-time-functions.html#function_date-format
.. _`Haversine formula`: https://en.wikipedia.org/wiki/Haversine_formula



.. _`CrateDB PDO`: https://crate.io/docs/reference/pdo/usage.html#dsn
6 changes: 5 additions & 1 deletion sql-parser/src/main/antlr/SqlBase.g4
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@ primaryExpression
| name=CURRENT_TIME ('(' precision=integerLiteral')')? #specialDateTimeFunction
| name=CURRENT_TIMESTAMP ('(' precision=integerLiteral')')? #specialDateTimeFunction
| CURRENT_SCHEMA ('(' ')')? #currentSchema
| (CURRENT_USER | USER) #currentUser
| SESSION_USER ('(' ')')? #sessionUser
| SUBSTRING '(' expr FROM expr (FOR expr)? ')' #substring
| EXTRACT '(' identExpr FROM expr ')' #extract
| CAST '(' expr AS dataType ')' #cast
Expand Down Expand Up @@ -565,7 +567,7 @@ nonReserved
| SHARDS | SHOW | STRICT | SYSTEM | TABLES | TABLESAMPLE | TEXT | TIME
| TIMESTAMP | TO | TOKENIZER | TOKEN_FILTERS | TYPE | VALUES | VIEW | YEAR
| REPOSITORY | SNAPSHOT | RESTORE | GENERATED | ALWAYS | BEGIN
| ISOLATION | TRANSACTION | LEVEL | LANGUAGE | OPEN | CLOSE | RENAME | USER
| ISOLATION | TRANSACTION | LEVEL | LANGUAGE | OPEN | CLOSE | RENAME
;

SELECT: 'SELECT';
Expand Down Expand Up @@ -615,6 +617,8 @@ CURRENT_DATE: 'CURRENT_DATE';
CURRENT_TIME: 'CURRENT_TIME';
CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP';
CURRENT_SCHEMA: 'CURRENT_SCHEMA';
CURRENT_USER: 'CURRENT_USER';
SESSION_USER: 'SESSION_USER';
EXTRACT: 'EXTRACT';
CASE: 'CASE';
WHEN: 'WHEN';
Expand Down
9 changes: 9 additions & 0 deletions sql-parser/src/main/java/io/crate/sql/parser/AstBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -1006,7 +1006,16 @@ public Node visitSubstring(SqlBaseParser.SubstringContext context) {
@Override
public Node visitCurrentSchema(SqlBaseParser.CurrentSchemaContext context) {
return new FunctionCall(QualifiedName.of("current_schema"), ImmutableList.of());
}

@Override
public Node visitCurrentUser(SqlBaseParser.CurrentUserContext ctx) {
return new FunctionCall(QualifiedName.of("current_user"), ImmutableList.of());
}

@Override
public Node visitSessionUser(SqlBaseParser.SessionUserContext ctx) {
return new FunctionCall(QualifiedName.of("session_user"), ImmutableList.of());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,11 +271,18 @@ public void testCurrentTimestamp()
}

@Test
public void testSpecialFunctions() throws Exception {
public void testCurrentSchemaFunction() throws Exception {
assertInstanceOf("CURRENT_SCHEMA", FunctionCall.class);
assertInstanceOf("CURRENT_SCHEMA()", FunctionCall.class);
}

@Test
public void testUserFunctions() {
assertInstanceOf("CURRENT_USER", FunctionCall.class);
assertInstanceOf("SESSION_USER", FunctionCall.class);
assertInstanceOf("USER", FunctionCall.class);
}

private void assertInstanceOf(String expr, Class<? extends Node> cls) {
Expression expression = SqlParser.createExpression(expr);
assertThat(expression, instanceOf(cls));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,10 @@ public void testSystemInformationFunctionsStmtBuilder() {
printStatement("select current_schema()");
printStatement("select * from information_schema.tables where table_schema = current_schema");
printStatement("select * from information_schema.tables where table_schema = current_schema()");

printStatement("select current_user");
printStatement("select user");
printStatement("select session_user");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,30 @@

package io.crate.operation.scalar;

import io.crate.metadata.FunctionResolver;
import io.crate.metadata.FunctionIdent;
import io.crate.metadata.FunctionImplementation;
import io.crate.metadata.FunctionResolver;
import io.crate.operation.scalar.arithmetic.*;
import io.crate.operation.scalar.cast.CastFunction;
import io.crate.operation.scalar.cast.TryCastScalarFunction;
import io.crate.operation.scalar.conditional.*;
import io.crate.operation.scalar.geo.*;
import io.crate.operation.scalar.conditional.CoalesceFunction;
import io.crate.operation.scalar.conditional.GreatestFunction;
import io.crate.operation.scalar.conditional.IfFunction;
import io.crate.operation.scalar.conditional.LeastFunction;
import io.crate.operation.scalar.conditional.NullIfFunction;
import io.crate.operation.scalar.geo.CoordinateFunction;
import io.crate.operation.scalar.geo.DistanceFunction;
import io.crate.operation.scalar.geo.GeoHashFunction;
import io.crate.operation.scalar.geo.IntersectsFunction;
import io.crate.operation.scalar.geo.WithinFunction;
import io.crate.operation.scalar.regex.MatchesFunction;
import io.crate.operation.scalar.regex.ReplaceFunction;
import io.crate.operation.scalar.string.HashFunctions;
import io.crate.operation.scalar.string.LengthFunction;
import io.crate.operation.scalar.string.StringCaseFunction;
import io.crate.operation.scalar.systeminformation.CurrentSchemaFunction;
import io.crate.operation.scalar.systeminformation.CurrentUserFunction;
import io.crate.operation.scalar.systeminformation.SessionUserFunction;
import io.crate.operation.scalar.timestamp.CurrentTimestampFunction;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.inject.multibindings.MapBinder;
Expand Down Expand Up @@ -114,6 +124,8 @@ protected void configure() {
IfFunction.register(this);

CurrentSchemaFunction.register(this);
CurrentUserFunction.register(this);
SessionUserFunction.register(this);

// bind all registered functions and resolver
// by doing it here instead of the register functions, plugins can also use the
Expand Down
Loading

0 comments on commit abb059a

Please sign in to comment.