diff --git a/superset/__init__.py b/superset/__init__.py index 8ab8ded5e80db..b9cc6b0041e69 100644 --- a/superset/__init__.py +++ b/superset/__init__.py @@ -29,6 +29,7 @@ # In production mode, add log handler to sys.stderr. app.logger.addHandler(logging.StreamHandler()) app.logger.setLevel(logging.INFO) +logging.getLogger('pyhive.presto').setLevel(logging.INFO) db = SQLA(app) @@ -36,6 +37,8 @@ utils.pessimistic_connection_handling(db.engine.pool) cache = Cache(app, config=app.config.get('CACHE_CONFIG')) +tables_cache = Cache(app, config=app.config.get('TABLE_NAMES_CACHE_CONFIG')) + migrate = Migrate(app, db, directory=APP_DIR + "/migrations") diff --git a/superset/assets/javascripts/SqlLab/actions.js b/superset/assets/javascripts/SqlLab/actions.js index 0e72c209a3944..d7d20f49d3e1c 100644 --- a/superset/assets/javascripts/SqlLab/actions.js +++ b/superset/assets/javascripts/SqlLab/actions.js @@ -213,9 +213,9 @@ export function mergeTable(table, query) { return { type: MERGE_TABLE, table, query }; } -export function addTable(query, tableName) { +export function addTable(query, tableName, schemaName) { return function (dispatch) { - let url = `/superset/table/${query.dbId}/${tableName}/${query.schema}/`; + let url = `/superset/table/${query.dbId}/${tableName}/${schemaName}/`; $.get(url, (data) => { const dataPreviewQuery = { id: shortid.generate(), @@ -232,7 +232,7 @@ export function addTable(query, tableName) { Object.assign(data, { dbId: query.dbId, queryEditorId: query.id, - schema: query.schema, + schema: schemaName, expanded: true, }), dataPreviewQuery) ); @@ -248,12 +248,12 @@ export function addTable(query, tableName) { ); }); - url = `/superset/extra_table_metadata/${query.dbId}/${tableName}/${query.schema}/`; + url = `/superset/extra_table_metadata/${query.dbId}/${tableName}/${schemaName}/`; $.get(url, (data) => { const table = { dbId: query.dbId, queryEditorId: query.id, - schema: query.schema, + schema: schemaName, name: tableName, }; Object.assign(table, data); diff --git a/superset/assets/javascripts/SqlLab/components/SqlEditorLeftBar.jsx b/superset/assets/javascripts/SqlLab/components/SqlEditorLeftBar.jsx index 21d5f2bfceecc..c36d659ca6744 100644 --- a/superset/assets/javascripts/SqlLab/components/SqlEditorLeftBar.jsx +++ b/superset/assets/javascripts/SqlLab/components/SqlEditorLeftBar.jsx @@ -30,8 +30,8 @@ class SqlEditorLeftBar extends React.PureComponent { }; } componentWillMount() { - this.fetchSchemas(); - this.fetchTables(); + this.fetchSchemas(this.props.queryEditor.dbId); + this.fetchTables(this.props.queryEditor.dbId, this.props.queryEditor.schema); } onChange(db) { const val = (db) ? db.value : null; @@ -58,22 +58,51 @@ class SqlEditorLeftBar extends React.PureComponent { resetState() { this.props.actions.resetState(); } - fetchTables(dbId, schema) { - const actualDbId = dbId || this.props.queryEditor.dbId; - if (actualDbId) { - const actualSchema = schema || this.props.queryEditor.schema; - this.setState({ tableLoading: true }); - this.setState({ tableOptions: [] }); - const url = `/superset/tables/${actualDbId}/${actualSchema}`; + getTableNamesBySubStr(input) { + if (!this.props.queryEditor.dbId || !input) { + return Promise.resolve({ options: [] }); + } + const url = `/superset/tables/${this.props.queryEditor.dbId}/\ +${this.props.queryEditor.schema}/${input}`; + return $.get(url).then((data) => ({ options: data.options })); + } + // TODO: move fetching methods to the actions. + fetchTables(dbId, schema, substr) { + if (dbId) { + this.setState({ tableLoading: true, tableOptions: [] }); + const url = `/superset/tables/${dbId}/${schema}/${substr}/`; $.get(url, (data) => { - let tableOptions = data.tables.map((s) => ({ value: s, label: s })); - const views = data.views.map((s) => ({ value: s, label: '[view] ' + s })); - tableOptions = [...tableOptions, ...views]; - this.setState({ tableOptions }); - this.setState({ tableLoading: false }); + this.setState({ + tableLoading: false, + tableOptions: data.options, + tableLength: data.tableLength, + }); }); } } + changeTable(tableOpt) { + if (!tableOpt) { + this.setState({ tableName: '' }); + return; + } + const namePieces = tableOpt.value.split('.'); + let tableName = namePieces[0]; + let schemaName = this.props.queryEditor.schema; + if (namePieces.length === 1) { + this.setState({ tableName }); + } else { + schemaName = namePieces[0]; + tableName = namePieces[1]; + this.setState({ tableName }); + this.props.actions.queryEditorSetSchema(this.props.queryEditor, schemaName); + this.fetchTables(this.props.queryEditor.dbId, schemaName); + } + this.setState({ tableLoading: true }); + // TODO: handle setting the tableLoading state depending on success or + // failure of the addTable async call in the action. + this.props.actions.addTable(this.props.queryEditor, tableName, schemaName); + this.setState({ tableLoading: false }); + } changeSchema(schemaOpt) { const schema = (schemaOpt) ? schemaOpt.value : null; this.props.actions.queryEditorSetSchema(this.props.queryEditor, schema); @@ -95,14 +124,6 @@ class SqlEditorLeftBar extends React.PureComponent { closePopover(ref) { this.refs[ref].hide(); } - changeTable(tableOpt) { - const tableName = tableOpt.value; - const qe = this.props.queryEditor; - - this.setState({ tableLoading: true }); - this.props.actions.addTable(qe, tableName); - this.setState({ tableLoading: false }); - } render() { let networkAlert = null; if (!this.props.networkOn) { @@ -118,6 +139,8 @@ class SqlEditorLeftBar extends React.PureComponent { dataEndpoint="/databaseasync/api/read?_flt_0_expose_in_sqllab=1" onChange={this.onChange.bind(this)} value={this.props.queryEditor.dbId} + databaseId={this.props.queryEditor.dbId} + actions={this.props.actions} valueRenderer={(o) => (
Database: {o.label} @@ -126,8 +149,6 @@ class SqlEditorLeftBar extends React.PureComponent { mutator={this.dbMutator.bind(this)} placeholder="Select a database" /> -
-
+ {this.props.queryEditor.schema && +