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

[SQL Lab] Adding DB options for SQL LAb #1054

Merged
merged 2 commits into from
Sep 1, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .codeclimate.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
engines:
csslint:
enabled: false
duplication:
enabled: false
eslint:
enabled: true
config:
Expand Down
6 changes: 5 additions & 1 deletion caravel/assets/javascripts/SqlLab/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const QUERY_EDITOR_SET_SCHEMA = 'QUERY_EDITOR_SET_SCHEMA';
export const QUERY_EDITOR_SET_TITLE = 'QUERY_EDITOR_SET_TITLE';
export const QUERY_EDITOR_SET_AUTORUN = 'QUERY_EDITOR_SET_AUTORUN';
export const QUERY_EDITOR_SET_SQL = 'QUERY_EDITOR_SET_SQL';
export const SET_WORKSPACE_DB = 'SET_WORKSPACE_DB';
export const SET_DATABASES = 'SET_DATABASES';
export const ADD_WORKSPACE_QUERY = 'ADD_WORKSPACE_QUERY';
export const REMOVE_WORKSPACE_QUERY = 'REMOVE_WORKSPACE_QUERY';
export const SET_ACTIVE_QUERY_EDITOR = 'SET_ACTIVE_QUERY_EDITOR';
Expand All @@ -28,6 +28,10 @@ export function resetState() {
return { type: RESET_STATE };
}

export function setDatabases(databases) {
return { type: SET_DATABASES, databases };
}

export function addQueryEditor(queryEditor) {
return { type: ADD_QUERY_EDITOR, queryEditor };
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class QueryAutoRefresh extends React.Component {
}
startTimer() {
if (!(this.timer)) {
this.timer = setInterval(this.stopwatch.bind(this), 5000);
this.timer = setInterval(this.stopwatch.bind(this), 1000);
}
}
stopTimer() {
Expand Down
22 changes: 12 additions & 10 deletions caravel/assets/javascripts/SqlLab/components/SouthPane.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,18 @@ const SouthPane = function (props) {
results = <Alert bsStyle="info">Run a query to display results here</Alert>;
}
return (
<Tabs bsStyle="tabs">
<Tab title="Results" eventKey={1}>
<div style={{ overflow: 'auto' }}>
{results}
</div>
</Tab>
<Tab title="Query History" eventKey={2}>
<QueryHistory />
</Tab>
</Tabs>
<div className="SouthPane">
<Tabs bsStyle="tabs">
<Tab title="Results" eventKey={1}>
<div style={{ overflow: 'auto' }}>
{results}
</div>
</Tab>
<Tab title="Query History" eventKey={2}>
<QueryHistory />
</Tab>
</Tabs>
</div>
);
};

Expand Down
49 changes: 28 additions & 21 deletions caravel/assets/javascripts/SqlLab/components/SqlEditor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -207,31 +207,37 @@ class SqlEditor extends React.Component {
</OverlayTrigger>
);
}
let ctasControls;
if (this.props.database && this.props.database.allow_ctas) {
ctasControls = (
<FormGroup>
<InputGroup>
<FormControl
type="text"
bsSize="small"
className="input-sm"
placeholder="new table name"
onChange={this.ctasChanged.bind(this)}
/>
<InputGroup.Button>
<Button
bsSize="small"
disabled={this.state.ctas.length === 0}
onClick={this.createTableAs.bind(this)}
>
<i className="fa fa-table" /> CTAS
</Button>
</InputGroup.Button>
</InputGroup>
</FormGroup>
);
}
const editorBottomBar = (
<div className="sql-toolbar clearfix">
<div className="pull-left">
<Form inline>
{runButtons}
<FormGroup>
<InputGroup>
<FormControl
type="text"
bsSize="small"
className="input-sm"
placeholder="new table name"
onChange={this.ctasChanged.bind(this)}
/>
<InputGroup.Button>
<Button
bsSize="small"
disabled={this.state.ctas.length === 0}
onClick={this.createTableAs.bind(this)}
>
<i className="fa fa-table" /> CTAS
</Button>
</InputGroup.Button>
</InputGroup>
</FormGroup>
{ctasControls}
</Form>
</div>
<div className="pull-right">
Expand Down Expand Up @@ -276,9 +282,10 @@ class SqlEditor extends React.Component {
}

SqlEditor.propTypes = {
queryEditor: React.PropTypes.object,
actions: React.PropTypes.object,
database: React.PropTypes.object,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you please add a comment specifying the schema of the object ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's define where we store schemas (maybe as functions that return objects)

latestQuery: React.PropTypes.object,
queryEditor: React.PropTypes.object,
};

SqlEditor.defaultProps = {
Expand Down
21 changes: 17 additions & 4 deletions caravel/assets/javascripts/SqlLab/components/SqlEditorLeft.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { connect } from 'react-redux';
import * as Actions from '../actions';
import shortid from 'shortid';
import Select from 'react-select';
import { Button } from 'react-bootstrap';
import TableElement from './TableElement';


Expand All @@ -26,6 +27,9 @@ class SqlEditorTopToolbar extends React.Component {
this.fetchSchemas();
this.fetchTables();
}
resetState() {
this.props.actions.resetState();
}
fetchTables(dbId, schema) {
const actualDbId = dbId || this.props.queryEditor.dbId;
if (actualDbId) {
Expand Down Expand Up @@ -73,11 +77,17 @@ class SqlEditorTopToolbar extends React.Component {
}
fetchDatabaseOptions() {
this.setState({ databaseLoading: true });
const url = '/databaseasync/api/read';
const url = '/databaseasync/api/read?_flt_0_expose_in_sqllab=1';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't find the _flt_0_expose_in_sqllab arg, could you please explain it in the comment ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's part of the FAB rest mini language, not sure if we need to explain it in this context (and all other contexes where it's used)

$.get(url, (data) => {
const options = data.result.map((db) => ({ value: db.id, label: db.database_name }));
this.props.actions.setDatabases(data.result);
this.setState({ databaseOptions: options });
this.setState({ databaseLoading: false });

// Auto select if only one option
if (options.length === 1) {
this.changeDb(options[0]);
}
});
}
closePopover(ref) {
Expand Down Expand Up @@ -112,7 +122,7 @@ class SqlEditorTopToolbar extends React.Component {
<div>
<Select
name="select-db"
placeholder="[Database]"
placeholder={`Select a database (${this.state.databaseOptions.length})`}
options={this.state.databaseOptions}
value={this.props.queryEditor.dbId}
isLoading={this.state.databaseLoading}
Expand All @@ -123,7 +133,7 @@ class SqlEditorTopToolbar extends React.Component {
<div className="m-t-5">
<Select
name="select-schema"
placeholder="[Schema]"
placeholder={`Select a schema (${this.state.schemaOptions.length})`}
options={this.state.schemaOptions}
value={this.props.queryEditor.schema}
isLoading={this.state.schemaLoading}
Expand All @@ -136,7 +146,7 @@ class SqlEditorTopToolbar extends React.Component {
name="select-table"
ref="selectTable"
isLoading={this.state.tableLoading}
placeholder="Add a table"
placeholder={`Add a table (${this.state.tableOptions.length})`}
autosize={false}
value={this.state.tableName}
onChange={this.changeTable.bind(this)}
Expand All @@ -149,6 +159,9 @@ class SqlEditorTopToolbar extends React.Component {
<TableElement table={table} queryEditor={this.props.queryEditor} />
))}
</div>
<Button bsSize="small" bsStyle="danger" onClick={this.resetState.bind(this)}>
<i className="fa fa-bomb" /> Reset State
</Button>
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ class QueryEditors extends React.Component {
render() {
const editors = this.props.queryEditors.map((qe, i) => {
let latestQuery = this.props.queries[qe.latestQueryId];
const database = this.props.databases[qe.dbId];

const state = (latestQuery) ? latestQuery.state : '';
const tabTitle = (
<div>
Expand Down Expand Up @@ -76,6 +78,7 @@ class QueryEditors extends React.Component {
<SqlEditor
queryEditor={qe}
latestQuery={latestQuery}
database={database}
/>
</div>
</div>
Expand All @@ -95,6 +98,7 @@ class QueryEditors extends React.Component {
}
QueryEditors.propTypes = {
actions: React.PropTypes.object,
databases: React.PropTypes.object,
queries: React.PropTypes.object,
queryEditors: React.PropTypes.array,
tabHistory: React.PropTypes.array,
Expand All @@ -106,6 +110,7 @@ QueryEditors.defaultProps = {

function mapStateToProps(state) {
return {
databases: state.databases,
queryEditors: state.queryEditors,
queries: state.queries,
tabHistory: state.tabHistory,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class TableElement extends React.Component {
{this.props.table.columns.map((col) => (
<div className="clearfix">
<span className="pull-left m-l-5">{col.name}</span>
<span className="pull-right">{col.type}</span>
<span className="pull-right text-muted">{col.type}</span>
</div>
))}
<hr />
Expand Down
4 changes: 4 additions & 0 deletions caravel/assets/javascripts/SqlLab/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -246,3 +246,7 @@ div.tablePopover:hover {
opacity: 1;
transition: visibility 0s, opacity 0.3s linear;
}

.SouthPane .tab-content {
padding-top: 10px;
}
8 changes: 8 additions & 0 deletions caravel/assets/javascripts/SqlLab/reducers.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const defaultQueryEditor = {
export const initialState = {
alerts: [],
queries: {},
databases: {},
queryEditors: [defaultQueryEditor],
tabHistory: [defaultQueryEditor.id],
tables: [],
Expand Down Expand Up @@ -166,6 +167,13 @@ export const sqlLabReducer = function (state, action) {
[actions.ADD_ALERT]() {
return addToArr(state, 'alerts', action.alert);
},
[actions.SET_DATABASES]() {
const databases = {};
action.databases.forEach((db) => {
databases[db.id] = db;
});
return Object.assign({}, state, { databases });
},
[actions.REMOVE_ALERT]() {
return removeFromArr(state, 'alerts', action.alert);
},
Expand Down
27 changes: 8 additions & 19 deletions caravel/data/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import pandas as pd
from sqlalchemy import String, DateTime, Date, Float, BigInteger

import caravel
from caravel import app, db, models, utils

# Shortcuts
Expand All @@ -27,18 +28,6 @@
DATA_FOLDER = os.path.join(config.get("BASE_DIR"), 'data')


def get_or_create_db(session):
print("Creating database reference")
dbobj = session.query(DB).filter_by(database_name='main').first()
if not dbobj:
dbobj = DB(database_name="main")
print(config.get("SQLALCHEMY_DATABASE_URI"))
dbobj.sqlalchemy_uri = config.get("SQLALCHEMY_DATABASE_URI")
session.add(dbobj)
session.commit()
return dbobj


def merge_slice(slc):
o = db.session.query(Slice).filter_by(slice_name=slc.slice_name).first()
if o:
Expand Down Expand Up @@ -76,7 +65,7 @@ def load_energy():
tbl = TBL(table_name=tbl_name)
tbl.description = "Energy consumption"
tbl.is_featured = True
tbl.database = get_or_create_db(db.session)
tbl.database = utils.get_or_create_db(caravel)
db.session.merge(tbl)
db.session.commit()
tbl.fetch_metadata()
Expand Down Expand Up @@ -202,7 +191,7 @@ def load_world_bank_health_n_pop():
tbl.description = utils.readfile(os.path.join(DATA_FOLDER, 'countries.md'))
tbl.main_dttm_col = 'year'
tbl.is_featured = True
tbl.database = get_or_create_db(db.session)
tbl.database = utils.get_or_create_db(caravel)
db.session.merge(tbl)
db.session.commit()
tbl.fetch_metadata()
Expand Down Expand Up @@ -593,7 +582,7 @@ def load_birth_names():
if not obj:
obj = TBL(table_name='birth_names')
obj.main_dttm_col = 'ds'
obj.database = get_or_create_db(db.session)
obj.database = utils.get_or_create_db(caravel)
obj.is_featured = True
db.session.merge(obj)
db.session.commit()
Expand Down Expand Up @@ -841,7 +830,7 @@ def load_unicode_test_data():
if not obj:
obj = TBL(table_name='unicode_test')
obj.main_dttm_col = 'date'
obj.database = get_or_create_db(db.session)
obj.database = utils.get_or_create_db(caravel)
obj.is_featured = False
db.session.merge(obj)
db.session.commit()
Expand Down Expand Up @@ -920,7 +909,7 @@ def load_random_time_series_data():
if not obj:
obj = TBL(table_name='random_time_series')
obj.main_dttm_col = 'ds'
obj.database = get_or_create_db(db.session)
obj.database = utils.get_or_create_db(caravel)
obj.is_featured = False
db.session.merge(obj)
db.session.commit()
Expand Down Expand Up @@ -988,7 +977,7 @@ def load_long_lat_data():
if not obj:
obj = TBL(table_name='long_lat')
obj.main_dttm_col = 'date'
obj.database = get_or_create_db(db.session)
obj.database = utils.get_or_create_db(caravel)
obj.is_featured = False
db.session.merge(obj)
db.session.commit()
Expand Down Expand Up @@ -1052,7 +1041,7 @@ def load_multiformat_time_series_data():
if not obj:
obj = TBL(table_name='multiformat_time_series')
obj.main_dttm_col = 'ds'
obj.database = get_or_create_db(db.session)
obj.database = utils.get_or_create_db(caravel)
obj.is_featured = False
dttm_and_expr_dict = {
'ds': [None, None],
Expand Down
Loading