SOLR-8138: Simple UI for issuing SQL queries (#2381)

* Updated SOLR-8138 files for Solr 9.

This code was mostly written by Michael Suzuki,  i just tweaked it to load, and updated the version of ui-grid to the 4.10 version.

* unused file, we use the .min version.

* add an entry for the ui-grid project to license file.

Co-authored-by: epugh@opensourceconnections.com <>
This commit is contained in:
Eric Pugh 2021-02-18 17:21:21 -05:00 committed by GitHub
parent 5e834b39eb
commit f70a518f1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 388 additions and 2 deletions

View File

@ -207,6 +207,8 @@ class RatTask extends DefaultTask {
substringMatcher(licenseFamilyCategory: "MIT ", licenseFamilyName:"Modified BSD License") {
// ICU license
pattern(substring: "Permission is hereby granted, free of charge, to any person obtaining a copy")
// ui-grid
pattern(substring: " ; License: MIT")
}
// Apache

View File

@ -223,6 +223,7 @@ New Features
* SOLR-15150: New update.partial.requireInPlace=true option to prevent any partial document updates that can't be done In-Place (hossman)
* SOLR-8138: Simple UI for issuing SQL queries (Michael Suzuki via Eric Pugh)
Improvements
---------------------

View File

@ -596,3 +596,10 @@ Noggit is a fast streaming JSON parser for java. The code is included
into Solr codebase.
https://github.com/yonik/noggit
=========================================================================
== ui-grid notice ==
=========================================================================
This product includes the Angular UI UI Grid JavaScript library.
Copyright (c) 2015 the AngularUI Team, http://angular-ui.github.com

View File

@ -692,6 +692,7 @@ pre.syntax .tex .formula
#content .address-bar
{
margin-bottom: 10px;
margin-top: 10px;
background-image: url( ../../img/ico/ui-address-bar.png );
background-position: 5px 50%;
border: 1px solid #f0f0f0;

View File

@ -282,6 +282,7 @@ limitations under the License.
.sub-menu .overview a { background-image: url( ../../img/ico/home.png ); }
.sub-menu .query a { background-image: url( ../../img/ico/magnifier.png ); }
.sub-menu .sqlquery a { background-image: url( ../../img/ico/sql.png ); }
.sub-menu .stream a { background-image: url( ../../img/ico/node.png ); }
.sub-menu .analysis a { background-image: url( ../../img/ico/funnel.png ); }
.sub-menu .documents a { background-image: url( ../../img/ico/documents-stack.png ); }

View File

@ -0,0 +1,237 @@
/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#content #sqlquery
{
}
#content #sqlquery #form
{
float: top;
}
#content #sqlquery #form label
{
cursor: pointer;
display: inline;
margin-top: 5px;
}
#content #sqlquery #form input,
#content #sqlquery #form select,
#content #sqlquery #form textarea
{
margin-bottom: 2px;
width: 100%;
}
#content #sqlquery #form textarea
{
height: 125px;
}
#content #sqlquery #form #start
{
float: left;
width: 45%;
}
#content #sqlquery #form #rows
{
float: right;
width: 45%;
}
#content #sqlquery #form input[type=checkbox]
{
margin-bottom: 0;
margin-left: 5px;
margin-right: 0px;
width: 10px;
height: 10px;
display: inline;
}
#content #sqlquery #form fieldset
{
border: 1px solid #fff;
border-top: 1px solid #c0c0c0;
margin-bottom: 5px;
}
#content #sqlquery #form fieldset.common
{
margin-top: 10px;
}
#content #sqlquery #form fieldset legend
{
display: block;
margin-left: 10px;
padding: 0px 5px;
}
#content #sqlquery #form fieldset legend label
{
margin-top: 0;
}
#content #sqlquery #form button
{
margin-right: 10px;
}
#content #sqlquery #form fieldset .fieldset
{
border-bottom: 1px solid #f0f0f0;
margin-bottom: 5px;
padding-bottom: 10px;
}
#content #sqlquery #result
{
float: bottom;
}
#content #sqlquery #result #response
{
}
/************************/
#content #sqlquery #sql-response
{
border-top: 1px solid #f0f0f0;
border-bottom: 1px solid #f0f0f0;
margin-top:8px;
}
#content #sqlquery #result .loader
{
background-position: 0 50%;
padding-left: 21px;
}
#content #sqlquery #result #error
{
background-color: #f00;
background-image: url( ../../img/ico/construction.png );
background-position: 10px 12px;
color: #fff;
font-weight: bold;
margin-bottom: 20px;
padding: 10px;
padding-left: 35px;
}
#content #sqlquery #result #error .msg
{
font-style: italic;
font-weight: normal;
margin-top: 10px;
}
#content #sqlquery #result .content
{
padding-left: 0;
padding-right: 0;
}
#content #sqlquery #result .content.show
{
background-image: url( ../../img/div.gif );
background-repeat: repeat-y;
background-position: 31% 0;
}
#content #sqlquery #result #legend
{
border: 1px solid #f0f0f0;
padding: 10px;
/*position: absolute;
right: 0;
bottom: 0;*/
}
#content #sqlquery #result #explanation #legend li
{
padding-left: 15px;
position: relative;
-webkit-box-sizing: border-box;
}
#content #sqlquery #result #explanation #legend li svg
{
position: absolute;
left: 0;
top: 2px;
}
#content #sqlquery #result #explanation #explanation-content
{
min-height: 50px;
width: 100%
}
#content #sqlquery #result #explanation #explanation-content .node circle
{
color: #c48f00;
stroke: #c48f00;
fill: #c48f00;
}
#content #sqlquery #result #explanation #explanation-content .link
{
fill: none;
stroke: #e0e0e0;
stroke-width: 1.5px;
}
#content #sqlquery #result #explanation #legend .datastore circle,
#content #sqlquery #result #explanation #explanation-content .node.datastore circle
{
stroke: #3800c4;
fill: #3800c4;
}
#content #sqlquery #result #explanation #legend .sqlquery-source circle,
#content #sqlquery #result #explanation #explanation-content .node.sqlquery-source circle
{
stroke: #21a9ec;
fill: #21a9ec;
}
#content #sqlquery #result #explanation #legend .sqlquery-decorator circle,
#content #sqlquery #result #explanation #explanation-content .node.sqlquery-decorator circle
{
stroke: #cb21ec;
fill: #cb21ec;
}
#content #sqlquery #result #explanation #legend .graph-source circle,
#content #sqlquery #result #explanation #explanation-content .node.graph-source circle
{
stroke: #21eca9;
fill: #21eca9;
}
.gridStyle {
border: 1px solid rgb(212,212,212);
width: 400px;
height: 300px
}

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

View File

@ -46,6 +46,8 @@ limitations under the License.
<link rel="stylesheet" type="text/css" href="css/angular/threads.css?_=${version}">
<link rel="stylesheet" type="text/css" href="css/angular/chosen.css?_=${version}">
<link rel="stylesheet" type="text/css" href="css/angular/overview.css?_=${version}">
<link rel="stylesheet" type="text/css" href="css/angular/sqlquery.css?_=${version}">
<link rel="stylesheet" type="text/css" href="css/angular/ui-grid.min.css?_=${version}">
<link rel="stylesheet" type="text/css" href="css/angular/jquery-ui.min.css?_=${version}">
<link rel="stylesheet" type="text/css" href="css/angular/jquery-ui.structure.min.css?_=${version}">
<link rel="stylesheet" type="text/css" href="css/angular/jstree.style.min.css?_=${version}">
@ -62,6 +64,7 @@ limitations under the License.
<script src="libs/ngtimeago.js"></script>
<script src="libs/highlight.js"></script>
<script src="libs/d3.js"></script>
<script src="libs/ui-grid.min.js"></script>
<script src="libs/jquery-ui.min.js"></script>
<script src="libs/angular-utf8-base64.min.js"></script>
<script src="js/angular/app.js"></script>
@ -87,6 +90,7 @@ limitations under the License.
<script src="js/angular/controllers/schema.js"></script>
<script src="js/angular/controllers/segments.js"></script>
<script src="js/angular/controllers/unknown.js"></script>
<script src="js/angular/controllers/sqlquery.js"></script>
</head>
@ -195,6 +199,7 @@ limitations under the License.
<li class="files" ng-show="!isMultiDestAlias(currentCollection)" ng-class="{active:page=='files'}"><a href="#/{{currentCollection.name}}/files"><span>Files</span></a></li>
<li class="query" ng-class="{active:page=='query'}"><a href="#/{{currentCollection.name}}/query"><span>Query</span></a></li>
<li class="stream" ng-class="{active:page=='stream'}"><a href="#/{{currentCollection.name}}/stream"><span>Stream</span></a></li>
<li class="sqlquery" ng-class="{active:page=='sqlquery'}"><a href="#/{{currentCollection.name}}/sqlquery"><span>SQL</span></a></li>
<li class="schema" ng-show="!isMultiDestAlias(currentCollection)" ng-class="{active:page=='schema'}"><a href="#/{{currentCollection.name}}/schema"><span>Schema</span></a></li>
</ul>
</div>

View File

@ -20,7 +20,7 @@ if (!String.prototype.includes) {
String.prototype.includes = function(search, start) { 'use strict';
if (search instanceof RegExp) {
throw TypeError('first argument must not be a RegExp');
}
}
if (start === undefined) { start = 0; }
return this.indexOf(search, start) !== -1;
};
@ -52,7 +52,8 @@ var solrAdminApp = angular.module("solrAdminApp", [
"ngtimeago",
"solrAdminServices",
"localytics.directives",
"ab-base64"
"ab-base64",
"ui.grid"
]);
solrAdminApp.config([
@ -156,6 +157,10 @@ solrAdminApp.config([
templateUrl: 'partials/stream.html',
controller: 'StreamController'
}).
when('/:core/sqlquery', {
templateUrl: 'partials/sqlquery.html',
controller: 'SQLQueryController'
}).
when('/:core/replication', {
templateUrl: 'partials/replication.html',
controller: 'ReplicationController'

View File

@ -0,0 +1,81 @@
/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
solrAdminApp.controller('SQLQueryController',
function($scope, $routeParams, $location, Query, Constants) {
$scope.resetMenu("sqlquery", Constants.IS_COLLECTION_PAGE);
$scope.qt = "sql";
$scope.doExplanation = false
$scope.gridOptions = {
enableSorting: false,
enableRowHashing:false,
enableColumnMenus:false,
columnDefs:[],
data:[],
onRegisterApi: function(gridApi) {
$scope.gridApi = gridApi;
}
};
$scope.hostPortContext = $location.absUrl().substr(0,$location.absUrl().indexOf("#")); // For display only
$scope.doQuery = function() {
var params = {};
params.core = $routeParams.core;
params.handler = $scope.qt;
params.stmt = [$scope.stmt]
$scope.lang = "json";
$scope.response = null;
$scope.url = "";
$scope.gridOptions.data =[]
$scope.gridOptions.columnDefs = []
var url = Query.url(params);
Query.query(params, function(data) {
var jsonData = JSON.parse(data.toJSON().data);
$scope.lang = "json";
$scope.url = url;
$scope.sqlError = null;
$scope.sqlData = [];
if(jsonData != undefined){
var docs = jsonData['result-set'].docs
//get all docs
for (var i = 0; i < docs.length; i++) {
var doc = docs[i]
//get all the properties
if(doc.hasOwnProperty("EOF")){
if(doc.hasOwnProperty("EXCEPTION")){
$scope.sqlError = doc.EXCEPTION
}
} else {
$scope.gridOptions.data.push(doc);
}
}
}
//Build the columnFields from data
var fields = $scope.gridOptions.data[1];
for (var property in fields) {
if (fields.hasOwnProperty(property)) {
$scope.gridOptions.columnDefs.push({"name":property, "type":{}})
}
}
$scope.gridApi.core.notifyDataChange
});
};
}
);

7
solr/webapp/web/libs/ui-grid.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,35 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<div id="sqlquery" class="clearfix">
<div id="form">
<form>
<label for="sqlexpr" title="The SQL Query">
SQL Query Statement
</label>
<textarea name="stmt" ng-model="stmt" id="sqlexp"></textarea>
<button type="submit" ng-click="doQuery()">Execute</button>
<span><a href="https://lucene.apache.org/solr/guide/8_8/parallel-sql-interface.html" target="_out">syntax help</a></span>
</form>
</div>
<div id="sql-response">
<a ng-show="sqlData" id="url" class="address-bar" ng-href="{{url}}">{{hostPortContext}}{{url}}</a>
<div ng-show="sqlError"> {{sqlError}}</div>
<div ng-show="!sqlError" class="grid" ui-grid="gridOptions" id="sql-response"></div>
</div>
</div>