Skip to content

Commit

Permalink
[SQL Lab] Adding DB options for SQL LAb
Browse files Browse the repository at this point in the history
each db can be exposed or not in SQL Lab
CTAS is an option
target_schema placeholder (not hooked yet, but would force the CTAS to
target a specific schema)
  • Loading branch information
mistercrunch committed Sep 1, 2016
1 parent 1667d15 commit 029957f
Show file tree
Hide file tree
Showing 16 changed files with 166 additions and 65 deletions.
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,
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';
$.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

0 comments on commit 029957f

Please sign in to comment.