├── examples ├── chinook.db ├── dvdrental.tar ├── firebird.fdb ├── dbname │ └── example.ibd ├── rect_category_heatmap.vl.json ├── PostgreSQL.ipynb ├── Firebird.ipynb ├── MySQL.ipynb ├── XVega operations.ipynb └── SQLite.ipynb ├── xeus-sql-screencast.gif ├── share └── jupyter │ └── kernels │ └── xsql │ ├── logo-32x32.png │ ├── logo-64x64.png │ └── kernel.json.in ├── binder └── environment.yml ├── readthedocs.yml ├── docs ├── environment.yml ├── source │ ├── sql_magic.rst │ ├── DB2.rst │ ├── Oracle.rst │ ├── api.rst │ ├── SQLite3.rst │ ├── conf.py │ ├── index.rst │ ├── PostgreSQL.rst │ ├── MySQL.rst │ ├── Firebird.rst │ ├── ODBC.rst │ ├── installation.rst │ ├── quantstack-white.svg │ └── xvega_magic.rst ├── Doxyfile ├── Makefile └── make.bat ├── .gitignore ├── environment-dev.yml ├── test ├── main.cpp ├── test_db.cpp └── CMakeLists.txt ├── cmake ├── Findmysql.cmake └── FindSoci.cmake ├── LICENSE ├── include └── xeus-sql │ ├── xeus_sql_config.hpp │ ├── xeus_sql_interpreter.hpp │ └── soci_handler.hpp ├── CONTRIBUTING.md ├── xeus-sqlConfig.cmake.in ├── .github └── workflows │ └── main.yml ├── README.md ├── src ├── main.cpp └── xeus_sql_interpreter.cpp └── CMakeLists.txt /examples/chinook.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyter-xeus/xeus-sql/HEAD/examples/chinook.db -------------------------------------------------------------------------------- /examples/dvdrental.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyter-xeus/xeus-sql/HEAD/examples/dvdrental.tar -------------------------------------------------------------------------------- /examples/firebird.fdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyter-xeus/xeus-sql/HEAD/examples/firebird.fdb -------------------------------------------------------------------------------- /xeus-sql-screencast.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyter-xeus/xeus-sql/HEAD/xeus-sql-screencast.gif -------------------------------------------------------------------------------- /examples/dbname/example.ibd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyter-xeus/xeus-sql/HEAD/examples/dbname/example.ibd -------------------------------------------------------------------------------- /share/jupyter/kernels/xsql/logo-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyter-xeus/xeus-sql/HEAD/share/jupyter/kernels/xsql/logo-32x32.png -------------------------------------------------------------------------------- /share/jupyter/kernels/xsql/logo-64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyter-xeus/xeus-sql/HEAD/share/jupyter/kernels/xsql/logo-64x64.png -------------------------------------------------------------------------------- /binder/environment.yml: -------------------------------------------------------------------------------- 1 | name: xeus-sql 2 | channels: 3 | - conda-forge 4 | dependencies: 5 | - xeus-sql=0.0.8 6 | - soci-sqlite 7 | - soci-core 8 | -------------------------------------------------------------------------------- /readthedocs.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | build: 4 | os: "ubuntu-22.04" 5 | tools: 6 | python: "mambaforge-22.9" 7 | 8 | conda: 9 | environment: docs/environment.yml 10 | -------------------------------------------------------------------------------- /docs/environment.yml: -------------------------------------------------------------------------------- 1 | name: xeus-sql-docs 2 | 3 | channels: 4 | - conda-forge 5 | 6 | dependencies: 7 | - breathe 8 | - sphinx_rtd_theme 9 | - pip: 10 | - sphinx-tabs 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build directory 2 | build/ 3 | 4 | # generated kernel specs 5 | share/jupyter/kernels/xsql/kernel.json 6 | 7 | # Jupyter artefacts 8 | .ipynb_checkpoints/ 9 | 10 | # ccls 11 | .ccls-cache/ 12 | compile_commands.json -------------------------------------------------------------------------------- /share/jupyter/kernels/xsql/kernel.json.in: -------------------------------------------------------------------------------- 1 | { 2 | "display_name": "xsql", 3 | "argv": [ 4 | "@CMAKE_INSTALL_FULL_BINDIR@/xsql", 5 | "-f", 6 | "{connection_file}" 7 | ], 8 | "language": "sqlite" 9 | } 10 | -------------------------------------------------------------------------------- /docs/source/sql_magic.rst: -------------------------------------------------------------------------------- 1 | SQL magics 2 | ========== 3 | 4 | Magics that allow you to operate on the database. 5 | 6 | LOAD 7 | ~~~~ 8 | 9 | .. object:: %LOAD database_type name_of_database 10 | 11 | To see how to use this command in depth, please refer to the specific page of the database. -------------------------------------------------------------------------------- /docs/source/DB2.rst: -------------------------------------------------------------------------------- 1 | .. Copyright (c) 2020, Mariana Meireles 2 | 3 | Distributed under the terms of the BSD 3-Clause License. 4 | 5 | The full license is in the file LICENSE, distributed with this software. 6 | 7 | DB2 8 | === 9 | 10 | We're missing this part of the docs. If you've used ``xeus-sql`` in this context and would like to help, please feel free to open a PR! :) -------------------------------------------------------------------------------- /docs/Doxyfile: -------------------------------------------------------------------------------- 1 | PROJECT_NAME = "xeus-sql" 2 | XML_OUTPUT = xml 3 | INPUT = ../include 4 | GENERATE_LATEX = NO 5 | GENERATE_MAN = NO 6 | GENERATE_RTF = NO 7 | CASE_SENSE_NAMES = NO 8 | GENERATE_HTML = NO 9 | GENERATE_XML = YES 10 | RECURSIVE = YES 11 | QUIET = YES 12 | JAVADOC_AUTOBRIEF = YES 13 | WARN_IF_UNDOCUMENTED = NO 14 | -------------------------------------------------------------------------------- /docs/source/Oracle.rst: -------------------------------------------------------------------------------- 1 | .. Copyright (c) 2020, Mariana Meireles 2 | 3 | Distributed under the terms of the BSD 3-Clause License. 4 | 5 | The full license is in the file LICENSE, distributed with this software. 6 | 7 | Oracle 8 | ====== 9 | 10 | We're missing this part of the docs. If you've used ``xeus-sql`` in this context and would like to help, please feel free to open a PR! :) -------------------------------------------------------------------------------- /docs/source/api.rst: -------------------------------------------------------------------------------- 1 | API 2 | === 3 | 4 | This API refers to the magics implemented to execute operations that are not SQL code. There's a distinction between ``xvega`` magics that implements magics from the ``xvega`` library and allows the user to create graphic visualizations of ``xeus-sql`` outputs and the ``xeus-sql`` magics that allows file operations. 5 | 6 | .. toctree:: 7 | 8 | sql_magic 9 | 10 | xvega_magic 11 | -------------------------------------------------------------------------------- /environment-dev.yml: -------------------------------------------------------------------------------- 1 | name: xeus-sql 2 | channels: 3 | - conda-forge 4 | dependencies: 5 | # Build dependencies 6 | - cmake <4 7 | - cxx-compiler 8 | - ninja 9 | # host dependencies 10 | - cpp-tabulate>=1.5 11 | - cppzmq 12 | - nlohmann_json 13 | - soci-core 14 | - xeus-zmq>=3.1.1,<4 15 | - xproperty 16 | - xvega-bindings>=0.1.1 17 | - xvega>=0.1.3 18 | # Test dependencies 19 | - doctest >= 2.4.6 20 | -------------------------------------------------------------------------------- /examples/rect_category_heatmap.vl.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://vega.github.io/schema/vega-lite/v4.json", 3 | "data": {"url": "data/movies.json"}, 4 | "mark": "rect", 5 | "width": 600, 6 | "height": 400, 7 | "encoding": { 8 | "x": { 9 | "field": "Country", 10 | "type": "nominal" 11 | }, 12 | "y": { 13 | "field": "Genre", 14 | "type": "nominal" 15 | }, 16 | "color": { 17 | "type": "quantitative", 18 | "field": "c" 19 | } 20 | }, 21 | "config": { 22 | "view": { 23 | "stroke": "transparent" 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /docs/source/SQLite3.rst: -------------------------------------------------------------------------------- 1 | .. Copyright (c) 2020, Mariana Meireles 2 | 3 | Distributed under the terms of the BSD 3-Clause License. 4 | 5 | The full license is in the file LICENSE, distributed with this software. 6 | 7 | SQLite 8 | ====== 9 | 10 | To run the SQLite backend simply install it with: 11 | 12 | .. code:: 13 | 14 | mamba install soci-sqlite xeus-sql jupyterlab -c conda-forge 15 | 16 | Or any other method desired. 17 | 18 | No other preparation is needed to run the notebook example. You can head to ``examples/SQLite.ipynb`` and run the code. 19 | 20 | More information about SQLite can be found in the SOCI documentation_. 21 | 22 | .. _documentation: http://soci.sourceforge.net/doc/release/4.0/backends/sqlite3/ 23 | -------------------------------------------------------------------------------- /test/main.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2020, QuantStack and Xeus-SQLite contributors * 3 | * * 4 | * * 5 | * Distributed under the terms of the BSD 3-Clause License. * 6 | * * 7 | * The full license is in the file LICENSE, distributed with this software. * 8 | ****************************************************************************/ 9 | #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN 10 | #include "doctest/doctest.h" 11 | 12 | -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import os 5 | import subprocess 6 | 7 | on_rtd = os.environ.get('READTHEDOCS', None) == 'True' 8 | 9 | if on_rtd: 10 | subprocess.call('cd ..; doxygen', shell=True) 11 | 12 | import sphinx_rtd_theme 13 | 14 | html_theme = "sphinx_rtd_theme" 15 | html_theme_options = { 16 | "navigation_depth": 4, 17 | "collapse_navigation": False, 18 | } 19 | 20 | html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] 21 | 22 | def setup(app): 23 | app.add_css_file("main_stylesheet.css") 24 | 25 | extensions = ['breathe', 'sphinx_rtd_theme', 'sphinx_tabs.tabs'] 26 | breathe_projects = { 'xeus-sql': '../xml' } 27 | templates_path = ['_templates'] 28 | source_suffix = '.rst' 29 | master_doc = 'index' 30 | project = 'xeus-sql' 31 | copyright = '2020, Mariana Meireles' 32 | author = 'Mariana Meireles' 33 | 34 | html_logo = 'quantstack-white.svg' 35 | 36 | exclude_patterns = [] 37 | pygments_style = 'sphinx' 38 | todo_include_todos = False 39 | htmlhelp_basename = 'xeus-sqldoc' 40 | -------------------------------------------------------------------------------- /examples/PostgreSQL.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "%LOAD postgresql dbname=newdvdrental" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": null, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "SELECT * FROM category LIMIT 5" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": null, 24 | "metadata": {}, 25 | "outputs": [], 26 | "source": [ 27 | "%XVEGA_PLOT X_FIELD rental_id Y_FIELD amount MARK line COLOR purple WIDTH 400 HEIGHT 200 <> SELECT * FROM payment LIMIT 5" 28 | ] 29 | } 30 | ], 31 | "metadata": { 32 | "kernelspec": { 33 | "display_name": "xsql", 34 | "language": "sqlite", 35 | "name": "xsql" 36 | }, 37 | "language_info": { 38 | "codemirror_mode": "sql", 39 | "file_extension": "", 40 | "mimetype": "", 41 | "name": "mysql", 42 | "version": "0.0.4" 43 | } 44 | }, 45 | "nbformat": 4, 46 | "nbformat_minor": 4 47 | } 48 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | .. Copyright (c) 2020, Mariana Meireles 2 | 3 | Distributed under the terms of the BSD 3-Clause License. 4 | 5 | The full license is in the file LICENSE, distributed with this software. 6 | 7 | Introduction 8 | ============ 9 | 10 | ``xeus-sql`` is a Jupyter kernel for general SQL implementations based on the native implementation of the Jupyter protocol xeus_ and SOCI_, a database access library for C++. 11 | 12 | Licensing 13 | ========= 14 | 15 | We use a shared copyright model that enables all contributors to maintain the 16 | copyright on their contributions. 17 | 18 | This software is licensed under the BSD-3-Clause license. See the LICENSE file for details. 19 | 20 | 21 | .. toctree:: 22 | :caption: Getting started 23 | :maxdepth: 1 24 | 25 | installation 26 | 27 | .. toctree:: 28 | :caption: Connecting to databases 29 | :maxdepth: 1 30 | 31 | DB2 32 | Firebird 33 | MySQL 34 | ODBC 35 | Oracle 36 | PostgreSQL 37 | SQLite3 38 | 39 | .. toctree:: 40 | :caption: API 41 | :maxdepth: 1 42 | 43 | api 44 | sql_magic 45 | xvega_magic 46 | 47 | .. _xeus: https://github.com/jupyter-xeus/xeus 48 | .. _SOCI: https://github.com/SOCI/soci 49 | -------------------------------------------------------------------------------- /test/test_db.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2020, QuantStack and xeus-sql contributors * 3 | * * 4 | * * 5 | * Distributed under the terms of the BSD 3-Clause License. * 6 | * * 7 | * The full license is in the file LICENSE, distributed with this software. * 8 | ****************************************************************************/ 9 | 10 | #ifndef TEST_DB_HPP 11 | #define TEST_DB_HPP 12 | 13 | #include "doctest/doctest.h" 14 | 15 | #include "xeus-sql/xeus_sql_interpreter.hpp" 16 | #include "xvega-bindings/utils.hpp" 17 | 18 | namespace xeus_sql 19 | { 20 | 21 | TEST_SUITE("xeus_sql_interpreter") 22 | { 23 | TEST_CASE("tokenizer") 24 | { 25 | std::string code = "\%LOAD database.db"; 26 | std::vector tokenized_code; 27 | tokenized_code = xv_bindings::tokenizer(code); 28 | REQUIRE_EQ(tokenized_code[1], "database.db"); 29 | } 30 | } 31 | } 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /docs/source/PostgreSQL.rst: -------------------------------------------------------------------------------- 1 | .. Copyright (c) 2020, Mariana Meireles 2 | 3 | Distributed under the terms of the BSD 3-Clause License. 4 | 5 | The full license is in the file LICENSE, distributed with this software. 6 | 7 | PostgreSQL 8 | ========== 9 | 10 | **Requirements:** ``soci-postgresql`` 11 | 12 | .. code:: 13 | 14 | conda install soci-postgresql -c conda-forge 15 | 16 | 17 | Linux 18 | ----- 19 | 20 | If you're running ``xeus-sql`` with a conda-forge PostgreSQL build, you will have to create a symbolic link to ``/tmp/``: 21 | 22 | .. code:: 23 | 24 | sudo ln -s /var/run/postgresql/.s.PGSQL.5432 /tmp/.s.PGSQL.5432 25 | 26 | Create a user: 27 | 28 | .. code:: 29 | 30 | sudo -u postgres createuser --superuser $USER_NAME 31 | 32 | Start the service: 33 | 34 | .. code:: 35 | 36 | sudo service postgresql start sudo -u $USER_NAME psql 37 | 38 | Create a new database: 39 | 40 | .. code:: 41 | 42 | createdb newdvdrental 43 | 44 | 45 | Use the example available on this repository: 46 | 47 | .. code:: 48 | 49 | pg_restore --dbname=newdvdrental -U $USER_NAME path/to/xeus-sql/examples/dvdrental.tar 50 | 51 | You can now run the example contained in ``examples/PostgreSQL.ipynb``. 52 | 53 | More information about PostgreSQL can be found in the SOCI documentation_. 54 | 55 | .. _documentation: http://soci.sourceforge.net/doc/release/4.0/backends/postgresql/ 56 | -------------------------------------------------------------------------------- /cmake/Findmysql.cmake: -------------------------------------------------------------------------------- 1 | # - Find mysqlclient 2 | # Find the native MySQL includes and library 3 | # 4 | # MYSQL_INCLUDE_DIR - where to find mysql.h, etc. 5 | # MYSQL_LIBRARIES - List of libraries when using MySQL. 6 | # MYSQL_FOUND - True if MySQL found. 7 | 8 | IF (MYSQL_INCLUDE_DIR) 9 | # Already in cache, be silent 10 | SET(MYSQL_FIND_QUIETLY TRUE) 11 | ENDIF (MYSQL_INCLUDE_DIR) 12 | 13 | FIND_PATH(MYSQL_INCLUDE_DIR mysql.h 14 | /usr/local/include/mysql 15 | /usr/include/mysql 16 | ) 17 | 18 | SET(MYSQL_NAMES mysqlclient mysqlclient_r) 19 | FIND_LIBRARY(MYSQL_LIBRARY 20 | NAMES ${MYSQL_NAMES} 21 | PATHS /usr/lib /usr/local/lib 22 | PATH_SUFFIXES mysql 23 | ) 24 | 25 | IF (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY) 26 | SET(MYSQL_FOUND TRUE) 27 | SET( MYSQL_LIBRARIES ${MYSQL_LIBRARY} ) 28 | ELSE (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY) 29 | SET(MYSQL_FOUND FALSE) 30 | SET( MYSQL_LIBRARIES ) 31 | ENDIF (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY) 32 | 33 | IF (MYSQL_FOUND) 34 | IF (NOT MYSQL_FIND_QUIETLY) 35 | MESSAGE(STATUS "Found MySQL: ${MYSQL_LIBRARY}") 36 | ENDIF (NOT MYSQL_FIND_QUIETLY) 37 | ELSE (MYSQL_FOUND) 38 | IF (MYSQL_FIND_REQUIRED) 39 | MESSAGE(STATUS "Looked for MySQL libraries named ${MYSQL_NAMES}.") 40 | MESSAGE(FATAL_ERROR "Could NOT find MySQL library") 41 | ENDIF (MYSQL_FIND_REQUIRED) 42 | ENDIF (MYSQL_FOUND) 43 | 44 | MARK_AS_ADVANCED( 45 | MYSQL_LIBRARY 46 | MYSQL_INCLUDE_DIR 47 | ) -------------------------------------------------------------------------------- /examples/Firebird.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "%LOAD firebird service=firebird.fdb user=SYSDBA" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": null, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "INSERT INTO STUDENT VALUES (1, 'Angelo')" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": null, 24 | "metadata": {}, 25 | "outputs": [], 26 | "source": [ 27 | "INSERT INTO STUDENT VALUES (2, 'Barbara')" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": null, 33 | "metadata": {}, 34 | "outputs": [], 35 | "source": [ 36 | "INSERT INTO STUDENT VALUES (3, 'Dandelion')" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": null, 42 | "metadata": {}, 43 | "outputs": [], 44 | "source": [ 45 | "SELECT * FROM STUDENT" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": null, 51 | "metadata": {}, 52 | "outputs": [], 53 | "source": [] 54 | } 55 | ], 56 | "metadata": { 57 | "kernelspec": { 58 | "display_name": "xsql", 59 | "language": "sqlite", 60 | "name": "xsql" 61 | }, 62 | "language_info": { 63 | "codemirror_mode": "sql", 64 | "file_extension": "", 65 | "mimetype": "", 66 | "name": "mysql", 67 | "version": "0.0.3" 68 | } 69 | }, 70 | "nbformat": 4, 71 | "nbformat_minor": 4 72 | } 73 | -------------------------------------------------------------------------------- /examples/MySQL.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "%LOAD mysql db=dbname user=user1 password='Password123#@!'" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": null, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "show databases;" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": null, 24 | "metadata": {}, 25 | "outputs": [], 26 | "source": [ 27 | "SELECT * FROM tidb" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": null, 33 | "metadata": {}, 34 | "outputs": [], 35 | "source": [ 36 | "INSERT INTO example VALUES (2, 'Core')" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": null, 42 | "metadata": {}, 43 | "outputs": [], 44 | "source": [ 45 | "SELECT * FROM example" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": null, 51 | "metadata": {}, 52 | "outputs": [], 53 | "source": [ 54 | "INSERT INTO example VALUES (3, 'Table')" 55 | ] 56 | } 57 | ], 58 | "metadata": { 59 | "kernelspec": { 60 | "display_name": "xsql", 61 | "language": "sqlite", 62 | "name": "xsql" 63 | }, 64 | "language_info": { 65 | "codemirror_mode": "sql", 66 | "file_extension": "", 67 | "mimetype": "", 68 | "name": "mysql", 69 | "version": "0.0.5" 70 | } 71 | }, 72 | "nbformat": 4, 73 | "nbformat_minor": 4 74 | } 75 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, QuantStack 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /include/xeus-sql/xeus_sql_config.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2020, QuantStack and xeus-SQLite contributors * 3 | * * 4 | * * 5 | * Distributed under the terms of the BSD 3-Clause License. * 6 | * * 7 | * The full license is in the file LICENSE, distributed with this software. * 8 | ****************************************************************************/ 9 | 10 | #ifndef XEUS_SQL_CONFIG_HPP 11 | #define XEUS_SQL_CONFIG_HPP 12 | 13 | // Project version 14 | #define XSQL_VERSION_MAJOR 0 15 | #define XSQL_VERSION_MINOR 3 16 | #define XSQL_VERSION_PATCH 1 17 | 18 | // Composing the version string from major, minor and patch 19 | #define XSQL_CONCATENATE(A, B) XSQL_CONCATENATE_IMPL(A, B) 20 | #define XSQL_CONCATENATE_IMPL(A, B) A##B 21 | #define XSQL_STRINGIFY(a) XSQL_STRINGIFY_IMPL(a) 22 | #define XSQL_STRINGIFY_IMPL(a) #a 23 | 24 | #define XSQL_VERSION XSQL_STRINGIFY(XSQL_CONCATENATE(XSQL_VERSION_MAJOR, \ 25 | XSQL_CONCATENATE(.,XSQL_CONCATENATE(XSQL_VERSION_MINOR, \ 26 | XSQL_CONCATENATE(.,XSQL_VERSION_PATCH))))) 27 | 28 | #ifdef _WIN32 29 | #ifdef XEUS_SQL_EXPORTS 30 | #define XEUS_SQL_API __declspec(dllexport) 31 | #else 32 | #define XEUS_SQL_API __declspec(dllimport) 33 | #endif 34 | #else 35 | #define XEUS_SQL_API 36 | #endif 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to xeus-sql 2 | 3 | xeus and xeus-sql are subprojects of Project Jupyter and subject to the [Jupyter governance](https://github.com/jupyter/governance) and [Code of conduct](https://github.com/jupyter/governance/blob/master/conduct/code_of_conduct.md). 4 | 5 | ## General Guidelines 6 | 7 | For general documentation about contributing to Jupyter projects, see the [Project Jupyter Contributor Documentation](https://jupyter.readthedocs.io/en/latest/contributor/content-contributor.html). 8 | 9 | ## Community 10 | 11 | The xeus team organizes public video meetings. The schedule for future meetings and minutes of past meetings can be found on our [team compass](https://jupyter-xeus.github.io/). 12 | 13 | ## Setting up a development environment 14 | 15 | ### Installing from source 16 | 17 | To install the xeus-sql dependencies: 18 | 19 | ```bash 20 | mamba install nlohmann_json xtl cppzmq xeus xeus-zmq cpp-tabulate>=1.5 xvega xvega-bindings xproperty jupyterlab soci-core compilers cmake -c conda-forge 21 | ``` 22 | 23 | #### Known issues 24 | 25 | If you're facing issues with your `cmake` installation, installing it again with `mamba install cmake -c conda-forge` works for me. 26 | 27 | Then you can compile the sources 28 | 29 | ```bash 30 | mkdir build 31 | cd build 32 | cmake -D CMAKE_INSTALL_PREFIX=$CONDA_PREFIX .. 33 | # You can add options like -DXSQL_WITH_SQLITE3 to make the db type as required 34 | # and we will handle the runtime error for that db 35 | # cmake -D CMAKE_INSTALL_PREFIX=$CONDA_PREFIX -DXSQL_WITH_SQLITE3 .. 36 | make 37 | make install 38 | ``` 39 | 40 | ### Build docs 41 | 42 | ``` 43 | mamba install sphinx breathe doxygen sphinx_rtd_theme 44 | ``` 45 | -------------------------------------------------------------------------------- /docs/source/MySQL.rst: -------------------------------------------------------------------------------- 1 | .. Copyright (c) 2020, Mariana Meireles 2 | 3 | Distributed under the terms of the BSD 3-Clause License. 4 | 5 | The full license is in the file LICENSE, distributed with this software. 6 | 7 | MySQL 8 | ===== 9 | 10 | Linux 11 | ----- 12 | 13 | Installation 14 | ************ 15 | 16 | You can get MySQL from ``conda-forge`` 17 | 18 | .. code:: 19 | 20 | conda install xeus-sql soci-mysql jupyterlab -c conda-forge 21 | 22 | Usage 23 | ***** 24 | 25 | To use MySQL from inside a notebook you need to first edit your MySQL configuration file that can usually be found at ``/etc/mysql/my.cnf``: 26 | 27 | .. code:: 28 | 29 | [server] 30 | socket=/tmp/mysql.sock 31 | 32 | [client] 33 | socket=/tmp/mysql.sock 34 | 35 | 36 | To run the example notebook you'll need to load the ``dbname`` database or create one for yourself: 37 | 38 | .. code:: 39 | 40 | CREATE DATABASE dbname; 41 | CREATE TABLE example ( id smallint unsigned not null auto_increment, name varchar(20) not null, constraint pk_example primary key (id) ); 42 | 43 | You will also need to create a new user and grant access to it to the newly create database. You can achieve this with the following lines in your MySQL console: 44 | 45 | .. code:: 46 | 47 | CREATE USER 'user1'@'localhost' IDENTIFIED BY 'Password123#@!'; 48 | GRANT ALL PRIVILEGES ON dbname.* TO ‘user1’@’localhost’; 49 | 50 | Note that it might be necessary to install MySQL from different sources other than conda if you intend to manipulate users and creation of databases. 51 | 52 | More information about MySQL can be found in the SOCI documentation_. 53 | 54 | .. _documentation: http://soci.sourceforge.net/doc/release/4.0/backends/mysql/ 55 | -------------------------------------------------------------------------------- /docs/source/Firebird.rst: -------------------------------------------------------------------------------- 1 | .. Copyright (c) 2020, Mariana Meireles 2 | 3 | Distributed under the terms of the BSD 3-Clause License. 4 | 5 | The full license is in the file LICENSE, distributed with this software. 6 | 7 | Firebird 8 | ======== 9 | 10 | Linux 11 | ----- 12 | 13 | Installation 14 | ************ 15 | 16 | Install Firebird using your preferred method. You will likely need the developer's version of Firebird for it to be picked up by SOCI. 17 | 18 | If you're using a system's package manager, your Firebird installation won't be picked up by the SOCI package available on ``conda-forge``, meaning that you will either have to install SOCI from source or download it from SOCI `downloads page `_. 19 | 20 | Make sure you're installing SOCI after you have Firebird in your system. 21 | 22 | You can still get ``xeus-sql`` from conda with: 23 | 24 | .. code:: 25 | 26 | conda install xeus-sql jupyterlab -c conda-forge 27 | 28 | From source 29 | +++++++++++ 30 | 31 | To install SOCI from source use the following flags when building: 32 | 33 | .. code:: 34 | 35 | cmake -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX -G "Unix Makefiles" -DWITH_BOOST=OFF -DSOCI_CXX11=ON -DCMAKE_BUILD_TYPE=Release -DSOCI_LIBDIR=lib .. 36 | 37 | make install 38 | 39 | Just make sure to do that in the same environment as the rest of your installation. 40 | 41 | Usage 42 | ***** 43 | 44 | Either way you decide to conduct your installation process you have to make sure that the directory where your database is is accessible by JupyterLab. To do that, you can add the user of the machine to the ``firebird`` group: 45 | 46 | .. code:: 47 | 48 | sudo chown firebird:firebird $DATABASE_NAME 49 | sudo usermod -a -G firebird $USER_NAME 50 | 51 | That's all there's to it. You can now run the example contained in ``examples/Firebird.ipynb``. 52 | 53 | More information about Firebird can be found in the SOCI documentation_. 54 | 55 | .. _documentation: http://soci.sourceforge.net/doc/release/4.0/backends/firebird/ 56 | -------------------------------------------------------------------------------- /xeus-sqlConfig.cmake.in: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | # Copyright (c) 2018, Martin Renou, Johan Mabille, Sylvain Corlay and # 3 | # Wolf Vollprecht, Mariana Meireles # 4 | # # 5 | # Distributed under the terms of the BSD 3-Clause License. # 6 | # # 7 | # The full license is in the file LICENSE, distributed with this software. # 8 | ############################################################################ 9 | 10 | # xeus-sql cmake module 11 | # This module sets the following variables in your project:: 12 | # 13 | # xeus-sql_FOUND - true if xeus-sql found on the system 14 | # xeus-sql_INCLUDE_DIRS - the directory containing xeus-sql headers 15 | # xeus-sql_LIBRARY - the library for dynamic linking 16 | # xeus-sql_STATIC_LIBRARY - the library for static linking 17 | 18 | @PACKAGE_INIT@ 19 | 20 | set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR};${CMAKE_MODULE_PATH}") 21 | 22 | @XEUS_SQL_CONFIG_CODE@ 23 | 24 | include(CMakeFindDependencyMacro) 25 | find_dependency(xeus @xeus_REQUIRED_VERSION@) 26 | find_dependency(xvega @xvega_REQUIRED_VERSION@) 27 | find_dependency(xvega-bindings @xvega-bindings_REQUIRED_VERSION@) 28 | 29 | find_dependency(Soci @Soci_REQUIRED_VERSION@) 30 | find_dependency(SQLite3) 31 | find_dependency(mysql) 32 | find_dependency(PostgreSQL) 33 | 34 | find_dependency(Threads @Threads_REQUIRED_VERSION@) 35 | #find_dependency(tabulate @tabulate_REQUIRED_VERSION@) 36 | 37 | if (NOT TARGET xeus-sql) 38 | include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") 39 | 40 | get_target_property(@PROJECT_NAME@_INCLUDE_DIR xeus-sql INTERFACE_INCLUDE_DIRECTORIES) 41 | get_target_property(@PROJECT_NAME@_LIBRARY xeus-sql LOCATION) 42 | 43 | if (TARGET xeus-sql-static) 44 | get_target_property(@PROJECT_NAME@_STATIC_LIBRARY xeus-sql-static LOCATION) 45 | endif () 46 | endif () 47 | -------------------------------------------------------------------------------- /docs/source/ODBC.rst: -------------------------------------------------------------------------------- 1 | .. Copyright (c) 2020, Mariana Meireles 2 | 2025, Chiara Marmo 3 | 4 | Distributed under the terms of the BSD 3-Clause License. 5 | 6 | The full license is in the file LICENSE, distributed with this software. 7 | 8 | ODBC 9 | ==== 10 | 11 | Linux 12 | ----- 13 | 14 | Installation 15 | ************ 16 | 17 | For now `soci-odbc` is not available from ``conda-forge``. 18 | The package is available under different names depending on your Linux distribution. 19 | 20 | For example: 21 | 22 | .. tabs:: 23 | 24 | .. group-tab:: Fedora 64bit 25 | 26 | .. code-block:: bash 27 | 28 | sudo dnf install libaio.x86_64 soci.x86_64 soci-odbc.x86_64 29 | 30 | .. group-tab:: Ubuntu 64bit 31 | 32 | .. code-block:: bash 33 | 34 | sudo apt-get install libaio-dev libsoci-core4.0 libsoci-odbc4.0 35 | 36 | Then from conda 37 | 38 | .. code:: 39 | 40 | conda install xeus-sql jupyterlab -c conda-forge 41 | 42 | Usage 43 | ***** 44 | 45 | To use the ODBC driver from inside a notebook you need to connect to the compatible database with the 46 | ```LOAD``` magic and the related driver. 47 | 48 | For example: 49 | 50 | .. tabs:: 51 | 52 | .. group-tab:: PostGreSQL (to be tested) 53 | 54 | Once the `PostGreSQL driver `_ installed 55 | 56 | .. code-block:: bash 57 | 58 | %LOAD odbc DRIVER=;DBQ=:/;UID=;PWD= 59 | 60 | .. group-tab:: Oracle 61 | 62 | Once the `Oracle driver `_ installed 63 | 64 | .. code-block:: bash 65 | 66 | %LOAD odbc DRIVER=;DBQ=:/;UID=;PWD= 67 | 68 | Oracle does not distribute debian based packages but the driver can be installed on any Linux distribution via the 69 | `available zip archives `_. 70 | 71 | .. _documentation: http://soci.sourceforge.net/doc/release/4.0/backends/odbc/ 72 | -------------------------------------------------------------------------------- /include/xeus-sql/xeus_sql_interpreter.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2020, QuantStack and xeus-sql contributors * 3 | * * 4 | * * 5 | * Distributed under the terms of the BSD 3-Clause License. * 6 | * * 7 | * The full license is in the file LICENSE, distributed with this software. * 8 | ****************************************************************************/ 9 | 10 | #ifndef XEUS_SQL_INTERPRETER_HPP 11 | #define XEUS_SQL_INTERPRETER_HPP 12 | 13 | #include "nlohmann/json.hpp" 14 | #include "xeus/xinterpreter.hpp" 15 | #include "soci/soci.h" 16 | #include "xvega-bindings/xvega_bindings.hpp" 17 | 18 | #include "xeus_sql_interpreter.hpp" 19 | #include "xeus_sql_config.hpp" 20 | 21 | 22 | namespace nl = nlohmann; 23 | 24 | namespace xeus_sql 25 | { 26 | class XEUS_SQL_API interpreter : public xeus::xinterpreter 27 | { 28 | public: 29 | interpreter() = default; 30 | virtual ~interpreter() = default; 31 | 32 | private: 33 | void configure_impl() override; 34 | void execute_request_impl(send_reply_callback cb, 35 | int /*execution_counter*/, 36 | const std::string& /*code*/, 37 | xeus::execute_request_config /*config*/, 38 | nl::json /*user_expressions*/) override; 39 | nl::json complete_request_impl(const std::string& code, 40 | int cursor_pos) override; 41 | nl::json inspect_request_impl(const std::string& code, 42 | int cursor_pos, 43 | int detail_level) override; 44 | nl::json is_complete_request_impl(const std::string& code) override; 45 | nl::json kernel_info_request_impl() override; 46 | void shutdown_request_impl() override; 47 | 48 | nl::json process_SQL_input(const std::string& code, 49 | xv::df_type& xv_sqlite_df); 50 | 51 | std::unique_ptr sql; 52 | std::map specs; 53 | }; 54 | } 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.20) 2 | 3 | if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) 4 | project(xeus_sql-test) 5 | 6 | find_package(xeus REQUIRED CONFIG) 7 | set(XEUS_SQL_INCLUDE_DIR ${XEUS_SQL_INCLUDE_DIRS}) 8 | endif () 9 | 10 | if(NOT CMAKE_BUILD_TYPE) 11 | message(STATUS "Setting tests build type to Release") 12 | set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE) 13 | else() 14 | message(STATUS "Tests build type is ${CMAKE_BUILD_TYPE}") 15 | endif() 16 | 17 | 18 | include(CheckCXXCompilerFlag) 19 | 20 | string(TOUPPER "${CMAKE_BUILD_TYPE}" U_CMAKE_BUILD_TYPE) 21 | 22 | if(CMAKE_CXX_COMPILER_ID MATCHES Clang OR CMAKE_CXX_COMPILER_ID MATCHES GNU OR CMAKE_CXX_COMPILER_ID MATCHES Intel) 23 | add_compile_options(-Wunused-parameter -Wextra -Wreorder -Wconversion -Wsign-conversion) 24 | 25 | CHECK_CXX_COMPILER_FLAG(-march=native HAS_MARCH_NATIVE) 26 | if (HAS_MARCH_NATIVE) 27 | add_compile_options(-march=native) 28 | endif() 29 | endif() 30 | 31 | 32 | if(CMAKE_CXX_COMPILER_ID MATCHES MSVC) 33 | add_compile_options(/EHsc /MP /bigobj) 34 | set(CMAKE_EXE_LINKER_FLAGS /MANIFEST:NO) 35 | endif() 36 | 37 | find_package(doctest REQUIRED) 38 | find_package(Threads) 39 | 40 | set(XEUS_SQL_TESTS 41 | main.cpp 42 | test_db.cpp 43 | ) 44 | 45 | add_executable(test_xeus_sql ${XEUS_SQL_TESTS}) 46 | 47 | if (APPLE) 48 | set_target_properties(test_xeus_sql PROPERTIES 49 | MACOSX_RPATH ON 50 | ) 51 | else() 52 | set_target_properties(test_xeus_sql PROPERTIES 53 | BUILD_WITH_INSTALL_RPATH 1 54 | SKIP_BUILD_RPATH FALSE 55 | ) 56 | endif() 57 | 58 | set_target_properties(test_xeus_sql PROPERTIES 59 | INSTALL_RPATH_USE_LINK_PATH TRUE 60 | ) 61 | 62 | target_compile_features(test_xeus_sql PRIVATE cxx_std_17) 63 | 64 | if (XSQL_BUILD_SHARED) 65 | set(XSQL_TEST_LINK_TARGET xeus-sql) 66 | else() 67 | set(XSQL_TEST_LINK_TARGET xeus-sql-static) 68 | endif() 69 | include_directories(${XSQL_INCLUDE_DIRS}) 70 | target_link_libraries(test_xeus_sql PRIVATE ${XSQL_TEST_LINK_TARGET} xeus doctest::doctest ${CMAKE_THREAD_LIBS_INIT}) 71 | target_compile_definitions(test_xeus_sql PRIVATE XEUS_SQL_HOME="${XSQL_PREFIX}") 72 | target_include_directories(test_xeus_sql PRIVATE ${XEUS_SQL_INCLUDE_DIR}) 73 | 74 | add_custom_target( 75 | xtest 76 | COMMAND test_xeus_sql 77 | DEPENDS test_xeus_sql) 78 | -------------------------------------------------------------------------------- /include/xeus-sql/soci_handler.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2020, QuantStack and xeus-sql contributors * 3 | * * 4 | * * 5 | * Distributed under the terms of the BSD 3-Clause License. * 6 | * * 7 | * The full license is in the file LICENSE, distributed with this software. * 8 | ****************************************************************************/ 9 | 10 | #ifndef XEUS_SQL_HANDLER_HPP 11 | #define XEUS_SQL_HANDLER_HPP 12 | 13 | #include 14 | #include 15 | 16 | #include "nlohmann/json.hpp" 17 | #include "soci/soci.h" 18 | #include "xeus/xinterpreter.hpp" 19 | #include "xvega-bindings/xvega_bindings.hpp" 20 | 21 | #include "xeus_sql_interpreter.hpp" 22 | 23 | namespace nl = nlohmann; 24 | 25 | namespace xeus_sql 26 | { 27 | static std::unique_ptr load_db( 28 | const std::vector tokenized_input) 29 | { 30 | std::string aux; 31 | for (std::size_t i = 2; i < tokenized_input.size(); i++) 32 | { 33 | aux += tokenized_input[i] + ' '; 34 | } 35 | return std::make_unique( 36 | xv_bindings::to_lower(tokenized_input[1]), aux); 37 | } 38 | 39 | static std::unique_ptr parse_SQL_magic( 40 | const std::vector& tokenized_input) 41 | { 42 | if (xv_bindings::case_insentive_equals(tokenized_input[0], "LOAD")) 43 | { 44 | return load_db(tokenized_input); 45 | } 46 | throw std::runtime_error("Command is not valid."); 47 | } 48 | 49 | static std::pair, std::vector> 50 | split_xv_sql_input(std::vector complete_input) 51 | { 52 | //TODO: test edge cases 53 | auto found = std::find(complete_input.begin(), 54 | complete_input.end(), 55 | "<>"); 56 | 57 | std::vector xvega_input(complete_input.begin(), found); 58 | std::vector sql_input(found + 1, complete_input.end()); 59 | 60 | return std::make_pair(xvega_input, sql_input); 61 | } 62 | } 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /docs/source/installation.rst: -------------------------------------------------------------------------------- 1 | .. Copyright (c) 2020, Mariana Meireles 2 | 3 | Distributed under the terms of the BSD 3-Clause License. 4 | 5 | The full license is in the file LICENSE, distributed with this software. 6 | 7 | Installation 8 | ============ 9 | 10 | With Conda or Mamba 11 | ------------------- 12 | 13 | ``xeus-sql`` has been packaged for the conda package manager. 14 | 15 | To ensure that the installation works, it is preferable to install ``xeus-sql`` in a fresh conda/mamba environment. 16 | It is also needed to use a miniconda_ installation because with the full anaconda_ you may have a conflict with 17 | the ``zeromq`` library which is already installed in the anaconda distribution. 18 | 19 | 20 | The safest usage is to create an environment named ``xeus-sql`` with your miniconda installation 21 | 22 | .. code:: 23 | 24 | conda create -n xeus-sql 25 | conda activate xeus-sql # Or `source activate xeus-sql` for conda < 4.6 26 | 27 | .. code:: 28 | 29 | mamba create -n xeus-sql 30 | mamba activate xeus-sql 31 | 32 | Then you can install in this freshly created environment ``xeus-sql`` and its dependencies 33 | 34 | .. code:: 35 | 36 | conda install xeus-sql notebook -c conda-forge 37 | 38 | .. code:: 39 | 40 | mamba install xeus-sql notebook -c conda-forge 41 | 42 | or, if you prefer to use JupyterLab_ 43 | 44 | .. code:: 45 | 46 | conda install xeus-sql jupyterlab -c conda-forge 47 | 48 | .. code:: 49 | 50 | mamba install xeus-sql jupyterlab -c conda-forge 51 | 52 | Conda forge offers packaged versions for MySQL, PostgreSQL and SQLite and you can download them with: `soci-mysql`, `soci-postresql` or `soci-sqlite`. 53 | 54 | ``xeus-sql`` includes ``soci-core`` only. Which consists on the SOCI package with no DB extension attached. 55 | 56 | From Source 57 | ----------- 58 | 59 | You can install ``xeus-sql`` from source with ``cmake``. This requires that you have all the dependencies installed in the same prefix. 60 | 61 | 62 | .. code:: 63 | 64 | conda install cmake nlohmann_json xtl cppzmq xeus mysql sqlite postgresql cpp-tabulate>=1.5 xvega xvega-bindings xproperty jupyterlab compilers -c conda-forge 65 | 66 | .. code:: 67 | 68 | mamba install cmake nlohmann_json xtl cppzmq xeus mysql sqlite postgresql cpp-tabulate>=1.5 xvega xvega-bindings xproperty jupyterlab compilers -c conda-forge 69 | 70 | .. code:: 71 | 72 | mkdir build 73 | cd build 74 | cmake -DCMAKE_INSTALL_PREFIX=/path/to/prefix .. 75 | make install 76 | 77 | On Windows platforms, from the source directory: 78 | 79 | .. code:: 80 | 81 | mkdir build 82 | cd build 83 | cmake -G "NMake Makefiles" -DCMAKE_INSTALL_PREFIX=/path/to/prefix .. 84 | nmake 85 | nmake install 86 | 87 | .. _miniconda: https://conda.io/miniconda.html 88 | .. _anaconda: https://www.anaconda.com 89 | .. _JupyterLab: https://jupyterlab.readthedocs.io 90 | -------------------------------------------------------------------------------- /cmake/FindSoci.cmake: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # CMake module to search for SOCI library 3 | # 4 | # WARNING: This module is experimental work in progress. 5 | # 6 | # This module defines: 7 | # SOCI_INCLUDE_DIRS = include dirs to be used when using the soci library 8 | # SOCI_LIBRARY = full path to the soci library 9 | # SOCI_VERSION = the soci version found (not yet. soci does not provide that info.) 10 | # SOCI_FOUND = true if soci was found 11 | # 12 | # This module respects: 13 | # LIB_SUFFIX = (64|32|"") Specifies the suffix for the lib directory 14 | # 15 | # For each component you specify in find_package(), the following variables are set. 16 | # 17 | # SOCI_${COMPONENT}_PLUGIN = full path to the soci plugin 18 | # SOCI_${COMPONENT}_FOUND 19 | # 20 | # Copyright (c) 2011 Michael Jansen 21 | # 22 | # Redistribution and use is allowed according to the terms of the BSD license. 23 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file. 24 | # 25 | ############################################################################### 26 | # 27 | ### Global Configuration Section 28 | # 29 | SET(_SOCI_ALL_PLUGINS mysql odbc postgresql sqlite3) 30 | SET(_SOCI_REQUIRED_VARS SOCI_INCLUDE_DIR SOCI_LIBRARY) 31 | 32 | # 33 | ### FIRST STEP: Find the soci headers. 34 | # 35 | FIND_PATH( 36 | SOCI_INCLUDE_DIR soci.h 37 | PATH "/usr/local" 38 | PATH_SUFFIXES "" "soci" 39 | DOC "Soci (http://soci.sourceforge.net) include directory") 40 | MARK_AS_ADVANCED(SOCI_INCLUDE_DIR) 41 | 42 | SET(SOCI_INCLUDE_DIRS ${SOCI_INCLUDE_DIR}) 43 | 44 | # 45 | ### SECOND STEP: Find the soci core library. Respect LIB_SUFFIX 46 | # 47 | FIND_LIBRARY( 48 | SOCI_LIBRARY 49 | NAMES soci_core soci_core_4_0 50 | HINTS ${SOCI_INCLUDE_DIR}/../../lib 51 | PATH_SUFFIXES lib${LIB_SUFFIX}) 52 | MARK_AS_ADVANCED(SOCI_LIBRARY) 53 | 54 | GET_FILENAME_COMPONENT(SOCI_LIBRARY_DIR ${SOCI_LIBRARY} PATH) 55 | MARK_AS_ADVANCED(SOCI_LIBRARY_DIR) 56 | 57 | # 58 | ### THIRD STEP: Find all installed plugins if the library was found 59 | # 60 | IF(SOCI_INCLUDE_DIR AND SOCI_LIBRARY) 61 | 62 | MESSAGE(STATUS "Soci found: Looking for plugins") 63 | FOREACH(plugin IN LISTS _SOCI_ALL_PLUGINS) 64 | 65 | FIND_LIBRARY( 66 | SOCI_${plugin}_PLUGIN 67 | NAMES soci_${plugin} 68 | HINTS ${SOCI_INCLUDE_DIR}/.. 69 | PATH_SUFFIXES lib${LIB_SUFFIX}) 70 | MARK_AS_ADVANCED(SOCI_${plugin}_PLUGIN) 71 | 72 | IF(SOCI_${plugin}_PLUGIN) 73 | MESSAGE(STATUS " * Plugin ${plugin} found ${SOCI_${plugin}_PLUGIN}.") 74 | SET(SOCI_${plugin}_FOUND True) 75 | ELSE() 76 | MESSAGE(STATUS " * Plugin ${plugin} not found.") 77 | SET(SOCI_${plugin}_FOUND False) 78 | ENDIF() 79 | 80 | ENDFOREACH() 81 | 82 | # 83 | ### FOURTH CHECK: Check if the required components were all found 84 | # 85 | FOREACH(component ${Soci_FIND_COMPONENTS}) 86 | IF(NOT SOCI_${component}_FOUND) 87 | MESSAGE(SEND_ERROR "Required component ${component} not found.") 88 | ENDIF() 89 | ENDFOREACH() 90 | 91 | ENDIF() 92 | 93 | # 94 | ### ADHERE TO STANDARDS 95 | # 96 | include(FindPackageHandleStandardArgs) 97 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(Soci DEFAULT_MSG ${_SOCI_REQUIRED_VARS}) 98 | 99 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - main 8 | pull_request: 9 | branches: 10 | - main 11 | 12 | defaults: 13 | run: 14 | shell: bash -l {0} 15 | 16 | 17 | jobs: 18 | test-unix: 19 | 20 | runs-on: ${{ matrix.os }} 21 | 22 | strategy: 23 | fail-fast: false 24 | matrix: 25 | os: [ubuntu-24.04, macos-14] 26 | build_type: [static_build, shared_build] 27 | 28 | steps: 29 | - uses: actions/checkout@v4 30 | 31 | - name: Get number of CPU cores 32 | uses: SimenB/github-actions-cpu-cores@v2 33 | 34 | - name: Install micromamba 35 | uses: mamba-org/setup-micromamba@v2 36 | with: 37 | environment-file: environment-dev.yml 38 | 39 | - name: Make build directory 40 | run: mkdir build 41 | 42 | - name: Static build option 43 | if: matrix.build_type == 'static_build' 44 | run: | 45 | CMAKE_EXTRA_ARGS="$CMAKE_EXTRA_ARGS -DXSQL_BUILD_SHARED=OFF -DXSQL_USE_SHARED_XEUS_SQL=OFF" 46 | echo "CMAKE_EXTRA_ARGS=$CMAKE_EXTRA_ARGS" >> $GITHUB_ENV 47 | 48 | - name: Shared build option 49 | if: matrix.build_type == 'shared_build' 50 | run: | 51 | CMAKE_EXTRA_ARGS="$CMAKE_EXTRA_ARGS -DXSQL_BUILD_STATIC=OFF" 52 | echo "CMAKE_EXTRA_ARGS=$CMAKE_EXTRA_ARGS" >> $GITHUB_ENV 53 | 54 | - name: Configure cmake 55 | run: | 56 | cmake .. \ 57 | -D CMAKE_PREFIX_PATH=$CONDA_PREFIX \ 58 | -D CMAKE_INSTALL_PREFIX=$CONDA_PREFIX \ 59 | -D CMAKE_INSTALL_LIBDIR=lib \ 60 | -D XSQL_BUILD_TESTS=ON \ 61 | -D CMAKE_C_COMPILER=$CC \ 62 | -D CMAKE_CXX_COMPILER=$CXX \ 63 | ${{ env.CMAKE_EXTRA_ARGS }} 64 | working-directory: build 65 | 66 | - name: Install 67 | run: make -j ${{ steps.cpu-cores.outputs.count }} install 68 | working-directory: build 69 | 70 | - name: Test xeus-sql C++ 71 | run: ./test_xeus_sql 72 | timeout-minutes: 4 73 | working-directory: build/test 74 | 75 | test-win: 76 | 77 | runs-on: ${{ matrix.os }} 78 | 79 | strategy: 80 | fail-fast: false 81 | matrix: 82 | os: [windows-2022] 83 | build_type: [static_build, shared_build] 84 | 85 | steps: 86 | - uses: actions/checkout@v4 87 | 88 | - name: Install micromamba 89 | uses: mamba-org/setup-micromamba@v2 90 | with: 91 | init-shell: >- 92 | powershell 93 | cmd.exe 94 | environment-file: environment-dev.yml 95 | 96 | - name: Make build directory 97 | run: mkdir build 98 | 99 | - name: Static build option 100 | if: matrix.build_type == 'static_build' 101 | run: | 102 | CMAKE_EXTRA_ARGS="$CMAKE_EXTRA_ARGS -DXSQL_BUILD_SHARED=OFF -DXSQL_USE_SHARED_XEUS_SQL=OFF" 103 | echo "CMAKE_EXTRA_ARGS=$CMAKE_EXTRA_ARGS" >> $GITHUB_ENV 104 | 105 | - name: Shared build option 106 | if: matrix.build_type == 'shared_build' 107 | run: | 108 | CMAKE_EXTRA_ARGS="$CMAKE_EXTRA_ARGS -DXSQL_BUILD_STATIC=OFF" 109 | echo "CMAKE_EXTRA_ARGS=$CMAKE_EXTRA_ARGS" >> $GITHUB_ENV 110 | 111 | - name: Configure cmake 112 | shell: cmd /C call {0} 113 | run: | 114 | cmake .. ^ 115 | -GNinja ^ 116 | -DCMAKE_BUILD_TYPE=Release ^ 117 | -DCMAKE_INSTALL_PREFIX="%CONDA_PREFIX%\Library" ^ 118 | -DXEXTRA_JUPYTER_DATA_DIR=%CONDA_PREFIX%\share\jupyter ^ 119 | -D CMAKE_CXX_FLAGS=" /D_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR" ^ 120 | -D XSQL_BUILD_TESTS=ON ^ 121 | ${{ env.CMAKE_EXTRA_ARGS }} 122 | working-directory: build 123 | 124 | - name: Build 125 | shell: cmd /C call {0} 126 | run: | 127 | set CL=/MP 128 | ninja install 129 | working-directory: build 130 | 131 | - name: Test xeus-sql C++ 132 | shell: cmd /C call {0} 133 | run: test_xeus_sql 134 | timeout-minutes: 4 135 | working-directory: build\test 136 | -------------------------------------------------------------------------------- /examples/XVega operations.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "%LOAD sqlite3 db=chinook.db timeout=2 shared_cache=true" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": null, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "%XVEGA_PLOT X_FIELD EmployeeId Y_FIELD ReportsTo BIN TRUE MARK square WIDTH 100 HEIGHT 200 <> SELECT EmployeeId, ReportsTo FROM employees" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": null, 24 | "metadata": {}, 25 | "outputs": [], 26 | "source": [ 27 | "%XVEGA_PLOT X_FIELD EmployeeId Y_FIELD ReportsTo BIN MAXBINS 3 MARK bar COLOR red WIDTH 200 HEIGHT 200 <> SELECT EmployeeId, ReportsTo FROM employees" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": null, 33 | "metadata": {}, 34 | "outputs": [], 35 | "source": [ 36 | "%XVEGA_PLOT X_FIELD EmployeeId Y_FIELD ReportsTo TYPE ordinal MARK bar COLOR green WIDTH 200 HEIGHT 200 <> SELECT EmployeeId, ReportsTo FROM employees" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": null, 42 | "metadata": {}, 43 | "outputs": [], 44 | "source": [ 45 | "%XVEGA_PLOT X_FIELD Name TYPE nominal Y_FIELD ArtistId BIN MAXBINS 1 MARK line COLOR purple WIDTH 200 HEIGHT 200 <> SELECT Name, ArtistId FROM artists LIMIT 10" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": null, 51 | "metadata": {}, 52 | "outputs": [], 53 | "source": [ 54 | "%XVEGA_PLOT X_FIELD EmployeeId GRID false Y_FIELD ReportsTo MARK area COLOR pink WIDTH 200 HEIGHT 200 <> SELECT EmployeeId, ReportsTo FROM employees" 55 | ] 56 | }, 57 | { 58 | "cell_type": "markdown", 59 | "metadata": {}, 60 | "source": [ 61 | "`%VEGA_LITE` follow by a json specs, with a new line followed by a SQL commands" 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": null, 67 | "metadata": {}, 68 | "outputs": [], 69 | "source": [ 70 | "%VEGA_LITE rect_category_heatmap.vl.json\n", 71 | "select i.BillingCountry as Country, g.name as Genre, count(1) as c\n", 72 | "from invoices i \n", 73 | " inner join invoice_items il on i.InvoiceId=il.InvoiceId \n", 74 | " inner join tracks t on t.TrackId=il.TrackId \n", 75 | " inner join genres g on g.GenreId=t.GenreId\n", 76 | "group by 1,2" 77 | ] 78 | }, 79 | { 80 | "cell_type": "markdown", 81 | "metadata": {}, 82 | "source": [ 83 | "Create a new spec on the fly by `VEGA_LITE SET spec_name` then followed by the json spec" 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "execution_count": null, 89 | "metadata": {}, 90 | "outputs": [], 91 | "source": [ 92 | "%VEGA_LITE SET colored_scatterplot.vl.json\n", 93 | "{\n", 94 | " \"$schema\": \"https://vega.github.io/schema/vega-lite/v4.json\",\n", 95 | " \"data\": {\"url\": \"data/movies.json\"},\n", 96 | " \"mark\": \"circle\",\n", 97 | " \"width\": 400,\n", 98 | " \"height\": 300,\n", 99 | " \"encoding\": {\n", 100 | " \"x\": {\n", 101 | " \"field\": \"trackNo\", \"sort\": \"ascending\", \"type\": \"quantitative\"\n", 102 | " },\n", 103 | " \"y\": {\n", 104 | " \"field\": \"sales\", \"type\": \"quantitative\"\n", 105 | " },\n", 106 | " \"color\": {\"field\": \"name\", \"type\": \"nominal\", \"sort\": {\"field\": \"-x\", \"order\": \"descending\"}},\n", 107 | " \"size\": {\"field\": \"sales\", \"type\": \"quantitative\"}\n", 108 | " }\n", 109 | "}" 110 | ] 111 | }, 112 | { 113 | "cell_type": "markdown", 114 | "metadata": {}, 115 | "source": [ 116 | "When plot we will first try if the spec is defined before, then check the file" 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": null, 122 | "metadata": {}, 123 | "outputs": [], 124 | "source": [ 125 | "%VEGA_LITE colored_scatterplot.vl.json\n", 126 | "select g.name name, sum(i.total) sales, count(distinct t.trackId) trackNo \n", 127 | "from tracks t \n", 128 | " inner join genres g on g.genreId=t.genreId \n", 129 | " inner join invoice_items il on il.trackId=t.trackId\n", 130 | " inner join invoices i on i.invoiceId=il.invoiceLineId\n", 131 | "group by g.name\n", 132 | "order by sales desc limit 10;" 133 | ] 134 | } 135 | ], 136 | "metadata": { 137 | "kernelspec": { 138 | "display_name": "xsql", 139 | "language": "sqlite", 140 | "name": "xsql" 141 | }, 142 | "language_info": { 143 | "codemirror_mode": "sql", 144 | "file_extension": "", 145 | "mimetype": "", 146 | "name": "mysql", 147 | "version": "0.0.6" 148 | } 149 | }, 150 | "nbformat": 4, 151 | "nbformat_minor": 4 152 | } 153 | -------------------------------------------------------------------------------- /docs/source/quantstack-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | image/svg+xml -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # xeus-sql 2 | [![GithubActions](https://github.com/jupyter-xeus/xeus-sql/actions/workflows/main.yml/badge.svg)](https://github.com/jupyter-xeus/xeus-sql/actions/workflows/main.yml) 3 | [![Documentation Status](https://readthedocs.org/projects/xeus-sql/badge/?version=latest)](https://xeus-sql.readthedocs.io/en/latest/?badge=latest) 4 | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/jupyter-xeus/xeus-sql/stable?urlpath=lab/tree/examples/SQLite.ipynb) 5 | [![Zulip](https://img.shields.io/badge/social_chat-zulip-blue.svg)](https://jupyter.zulipchat.com/#narrow/channel/539737-Jupyter-Kernels) 6 | 7 | `xeus-sql` is a Jupyter kernel for general SQL implementations based on the native implementation of the Jupyter protocol [xeus](https://github.com/jupyter-xeus/xeus) and [SOCI](https://github.com/SOCI/soci), a database access library for C++. 8 | 9 | ![xeus-sql screencast](xeus-sql-screencast.gif) 10 | 11 | ## Usage 12 | 13 | Launch the Jupyter notebook with `jupyter notebook` or Jupyter lab with `jupyter lab` and launch a new SQL notebook by selecting the **xsql** kernel. 14 | 15 | Note that `xeus-sql` support the following SQL implementations: 16 | 17 | * DB2 18 | * Firebird 19 | * MySQL 20 | * ODBC (generic backend) 21 | * Oracle 22 | * PostgreSQL 23 | * SQLite3 24 | 25 | ## Installation 26 | 27 | `xeus-sql` has been packaged for the mamba (or conda) package manager. 28 | 29 | To ensure that the installation works, it is preferable to install `xeus-sql` in a fresh environment. 30 | 31 | To ensure that the installation works, it is preferable to install `xeus` in a fresh environment. It is also needed to use 32 | a [miniforge](https://github.com/conda-forge/miniforge#mambaforge) or [miniconda](https://conda.io/miniconda.html) installation because with the full [anaconda](https://www.anaconda.com/) 33 | you may have a conflict. 34 | 35 | The safest usage is to create an environment named `xeus-sql` 36 | 37 | ``` 38 | mamba create -n xeus-sql 39 | source activate xeus-sql 40 | ``` 41 | 42 | ### Installing from conda-forge 43 | 44 | To install xeus-sql with the mamba (or conda) package manager: 45 | 46 | ``` 47 | mamba install xeus-sql jupyterlab -c conda-forge 48 | ``` 49 | 50 | With mamba: 51 | 52 | ``` 53 | mamba install xeus-sql jupyterlab -c conda-forge 54 | ``` 55 | 56 | Conda forge offers packaged versions for MySQL, PostgreSQL and SQLite and you can download them with: `soci-mysql`, `soci-postgresql` or `soci-sqlite`. 57 | 58 | `xeus-sql` includes `soci-core` only. Which consists on the SOCI package with no DB extension attached. 59 | 60 | ## Documentation 61 | 62 | https://xeus-sql.readthedocs.io/en/latest/ 63 | 64 | ## Dependencies 65 | 66 | ``xeus-sql`` depends on 67 | 68 | - [xeus](https://github.com/jupyter-xeus/xeus) 69 | - [Tabulate](https://github.com/p-ranav/tabulate) 70 | - [xvega](https://github.com/Quantstack/xvega) 71 | - [SQLite\*](https://github.com/sqlite/sqlite) 72 | - [PostgreSQL\*](https://github.com/postgres) 73 | - [MySQL\*](https://github.com/mysql/mysql-server) 74 | 75 | ##### xeus dependencies 76 | 77 | | `xeus-sql` | `xeus-zmq` | `tabulate` | `nlohmann_json` | `xproperty` | `xvega-bindings` | `soci-core` | 78 | |------------|-----------------|----------------|--------------------|-------------|------------------|-------------| 79 | | main | >=3.1.1, <4.0 | >=1.4\|>=3.0.0 | 3.12.0 | >=0.12.1 | >=0.1.1 | >=4.0.1 | 80 | | 0.3.1 | >=3.1.1, <4.0 | >=1.4\|>=3.0.0 | 3.12.0 | >=0.12.1 | >=0.1.1 | >=4.0.1 | 81 | | 0.3.0 | >=3.1.0, <4.0 | >=1.4\|>=3.0.0 | >= 0.0.10, <3.10.0 | >=0.11.0 | >=0.0.10 | >=4.0.1 | 82 | | 0.2.1 | >=1.0.1, <2.0 | >=1.4\|>=3.0.0 | >= 0.0.10, <3.10.0 | >=0.11.0 | >=0.0.10 | >=4.0.1 | 83 | | 0.2.0 | >=1.0.1, <2.0 | >=1.4\|>=3.0.0 | >= 0.0.10, <3.10.0 | >=0.11.0 | >=0.0.10 | >=4.0.1 | 84 | 85 | Prior to version 0.2, xeus-sql was depending on 86 | 87 | | `xeus-sql` | `xeus` | `tabulate` | `nlohmann_json` | `xproperty` | `xvega-bindings` | `soci-core` | 88 | |------------|-----------------|----------------|--------------------|-------------|------------------|-------------| 89 | | <=0.1.5 | >=2.0.0, <3.0 | >=1.4\|>=3.0.0 | >= 0.0.10, <3.10.0 | >=0.10.4 | >=0.0.10 | >=4.0.1 | 90 | | <=0.1.2 | >=1.0.0, <2.0 | >=1.4\|>=3.0.0 | >= 0.0.10 \| 4.0.1 | >=0.10.4 | >=0.0.10 | >=4.0.1 | 91 | | <=0.0.6 | >=0.24.0, <0.25 | >=1.4\|>=3.0.0 | >= 0.0.5 \| 4.0.1 | >=0.10.4 | >=0.0.3 | >=4.0.1 | 92 | 93 | ##### SQL dependencies 94 | 95 | These are optional dependencies that come by default with `xeus-sql` but may or may not be added to your project in case you're building manually. For more information check the CONTRIBUTING file. 96 | 97 | | `xeus-sql` | `PostgreSQL` | `SQLite` | `MySQL` | `soci-sqlite`, `soci-postgres`, `soci-mysql` | 98 | |------------|--------------|-------------|--------------|----------------------------------------------| 99 | | main | >=3.30.1, <4 | >=3.0.0, <4 | >=1.3.0,<2.0 | >=4.0.1 | 100 | | <=0.1.5 | >=3.30.1, <4 | >=3.0.0, <4 | >=1.3.0,<2.0 | >=4.0.1 | 101 | 102 | ## Contributing 103 | 104 | See [CONTRIBUTING.md](./CONTRIBUTING.md) to know how to contribute and set up a development environment. 105 | 106 | ## License 107 | 108 | We use a shared copyright model that enables all contributors to maintain the 109 | copyright on their contributions. 110 | 111 | This software is licensed under the BSD-3-Clause license. See the [LICENSE](LICENSE) file for details. 112 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2020, QuantStack and xeus-SQLite contributors * 3 | * * 4 | * * 5 | * Distributed under the terms of the BSD 3-Clause License. * 6 | * * 7 | * The full license is in the file LICENSE, distributed with this software. * 8 | ****************************************************************************/ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #ifdef __GNUC__ 15 | #include 16 | #include 17 | #include 18 | #include 19 | #endif 20 | 21 | #include "xeus/xkernel.hpp" 22 | #include "xeus/xkernel_configuration.hpp" 23 | 24 | #include "xeus-zmq/xserver_zmq_split.hpp" 25 | #include "xeus-zmq/xzmq_context.hpp" 26 | 27 | #include "xeus-sql/xeus_sql_interpreter.hpp" 28 | 29 | #ifdef __GNUC__ 30 | void handler(int sig) 31 | { 32 | void* array[10]; 33 | 34 | // get void*'s for all entries on the stack 35 | size_t size = backtrace(array, 10); 36 | 37 | // print out all the frames to stderr 38 | fprintf(stderr, "Error: signal %d:\n", sig); 39 | backtrace_symbols_fd(array, size, STDERR_FILENO); 40 | exit(1); 41 | } 42 | #endif 43 | 44 | void stop_handler(int /*sig*/) 45 | { 46 | exit(0); 47 | } 48 | 49 | std::string extract_filename(int& argc, char* argv[]) 50 | { 51 | std::string res = ""; 52 | for (int i = 0; i < argc; ++i) 53 | { 54 | if ((std::string(argv[i]) == "-f") && (i + 1 < argc)) 55 | { 56 | res = argv[i + 1]; 57 | for (int j = i; j < argc - 2; ++j) 58 | { 59 | argv[j] = argv[j + 2]; 60 | } 61 | argc -= 2; 62 | break; 63 | } 64 | } 65 | return res; 66 | } 67 | 68 | int main(int argc, char* argv[]) 69 | { 70 | // Registering SIGSEGV handler 71 | #ifdef __GNUC__ 72 | std::clog << "registering handler for SIGSEGV" << std::endl; 73 | signal(SIGSEGV, handler); 74 | 75 | // Registering SIGINT and SIGKILL handlers 76 | signal(SIGKILL, stop_handler); 77 | #endif 78 | signal(SIGINT, stop_handler); 79 | 80 | // Load configuration file 81 | std::string file_name = extract_filename(argc, argv); 82 | 83 | std::unique_ptr context = xeus::make_zmq_context(); 84 | 85 | // Create interpreter instance 86 | using interpreter_ptr = std::unique_ptr; 87 | interpreter_ptr interpreter = std::make_unique(); 88 | 89 | // Create kernel instance and start it 90 | // xeus::xkernel kernel(config, xeus::get_user_name(), std::move(interpreter)); 91 | // kernel.start(); 92 | using history_manager_ptr = std::unique_ptr; 93 | history_manager_ptr hist = xeus::make_in_memory_history_manager(); 94 | 95 | try 96 | { 97 | if (!file_name.empty()) 98 | { 99 | xeus::xconfiguration config = xeus::load_configuration(file_name); 100 | 101 | xeus::xkernel kernel(config, 102 | xeus::get_user_name(), 103 | std::move(context), 104 | std::move(interpreter), 105 | xeus::make_xserver_shell_main, 106 | std::move(hist), 107 | xeus::make_console_logger(xeus::xlogger::msg_type, 108 | xeus::make_file_logger(xeus::xlogger::content, "xeus.log"))); 109 | 110 | std::clog << 111 | "Starting xeus-sql kernel...\n\n" 112 | "If you want to connect to this kernel from an other client, you can use" 113 | " the " + file_name + " file." 114 | << std::endl; 115 | 116 | kernel.start(); 117 | } 118 | else 119 | { 120 | xeus::xkernel kernel(xeus::get_user_name(), 121 | std::move(context), 122 | std::move(interpreter), 123 | xeus::make_xserver_shell_main, 124 | std::move(hist), 125 | nullptr); 126 | 127 | const auto& config = kernel.get_config(); 128 | std::clog << 129 | "Starting xeus-sql kernel...\n\n" 130 | "If you want to connect to this kernel from an other client, just copy" 131 | " and paste the following content inside of a `kernel.json` file. And then run for example:\n\n" 132 | "# jupyter console --existing kernel.json\n\n" 133 | "kernel.json\n```\n{\n" 134 | " \"transport\": \"" + config.m_transport + "\",\n" 135 | " \"ip\": \"" + config.m_ip + "\",\n" 136 | " \"control_port\": " + config.m_control_port + ",\n" 137 | " \"shell_port\": " + config.m_shell_port + ",\n" 138 | " \"stdin_port\": " + config.m_stdin_port + ",\n" 139 | " \"iopub_port\": " + config.m_iopub_port + ",\n" 140 | " \"hb_port\": " + config.m_hb_port + ",\n" 141 | " \"signature_scheme\": \"" + config.m_signature_scheme + "\",\n" 142 | " \"key\": \"" + config.m_key + "\"\n" 143 | "}\n```\n"; 144 | 145 | kernel.start(); 146 | } 147 | } 148 | catch(std::exception& e) 149 | { 150 | std::clog << e.what() << std::endl; 151 | // This is not clean, but we need an additional API in xeus to 152 | // stop the kernel in a clean way 153 | throw e; 154 | } 155 | catch(const char* p) 156 | { 157 | std::clog << p << std::endl; 158 | // This is not clean, but we need an additional API in xeus to 159 | // stop the kernel in a clean way 160 | throw p; 161 | } 162 | 163 | return 0; 164 | } 165 | 166 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # You can set these variables from the command line. 2 | SPHINXOPTS = 3 | SPHINXBUILD = sphinx-build 4 | PAPER = 5 | BUILDDIR = build 6 | 7 | # User-friendly check for sphinx-build 8 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 9 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) 10 | endif 11 | 12 | # Internal variables. 13 | PAPEROPT_a4 = -D latex_paper_size=a4 14 | PAPEROPT_letter = -D latex_paper_size=letter 15 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source 16 | # the i18n builder cannot share the environment and doctrees with the others 17 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source 18 | 19 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext api 20 | 21 | default: html 22 | 23 | help: 24 | @echo "Please use \`make ' where is one of" 25 | @echo " html to make standalone HTML files" 26 | @echo " dirhtml to make HTML files named index.html in directories" 27 | @echo " singlehtml to make a single large HTML file" 28 | @echo " pickle to make pickle files" 29 | @echo " json to make JSON files" 30 | @echo " htmlhelp to make HTML files and a HTML help project" 31 | @echo " qthelp to make HTML files and a qthelp project" 32 | @echo " applehelp to make an Apple Help Book" 33 | @echo " devhelp to make HTML files and a Devhelp project" 34 | @echo " epub to make an epub" 35 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 36 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 37 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 38 | @echo " text to make text files" 39 | @echo " man to make manual pages" 40 | @echo " texinfo to make Texinfo files" 41 | @echo " info to make Texinfo files and run them through makeinfo" 42 | @echo " gettext to make PO message catalogs" 43 | @echo " changes to make an overview of all changed/added/deprecated items" 44 | @echo " xml to make Docutils-native XML files" 45 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 46 | @echo " linkcheck to check all external links for integrity" 47 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 48 | @echo " coverage to run coverage check of the documentation (if enabled)" 49 | 50 | clean: 51 | rm -rf $(BUILDDIR)/* 52 | 53 | html: 54 | doxygen 55 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 56 | @echo 57 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 58 | 59 | dirhtml: 60 | doxygen 61 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 62 | @echo 63 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 64 | 65 | singlehtml: 66 | doxygen 67 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 68 | @echo 69 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 70 | 71 | pickle: 72 | doxygen 73 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 74 | @echo 75 | @echo "Build finished; now you can process the pickle files." 76 | 77 | json: 78 | doxygen 79 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 80 | @echo 81 | @echo "Build finished; now you can process the JSON files." 82 | 83 | htmlhelp: 84 | doxygen 85 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 86 | @echo 87 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 88 | ".hhp project file in $(BUILDDIR)/htmlhelp." 89 | 90 | epub: 91 | doxygen 92 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 93 | @echo 94 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 95 | 96 | latex: 97 | doxygen 98 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 99 | @echo 100 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 101 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 102 | "(use \`make latexpdf' here to do that automatically)." 103 | 104 | latexpdf: 105 | doxygen 106 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 107 | @echo "Running LaTeX files through pdflatex..." 108 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 109 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 110 | 111 | latexpdfja: 112 | doxygen 113 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 114 | @echo "Running LaTeX files through platex and dvipdfmx..." 115 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 116 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 117 | 118 | text: 119 | doxygen 120 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 121 | @echo 122 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 123 | 124 | man: 125 | doxygen 126 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 127 | @echo 128 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 129 | 130 | texinfo: 131 | doxygen 132 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 133 | @echo 134 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 135 | @echo "Run \`make' in that directory to run these through makeinfo" \ 136 | "(use \`make info' here to do that automatically)." 137 | 138 | info: 139 | doxygen 140 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 141 | @echo "Running Texinfo files through makeinfo..." 142 | make -C $(BUILDDIR)/texinfo info 143 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 144 | 145 | gettext: 146 | doxygen 147 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 148 | @echo 149 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 150 | 151 | changes: 152 | doxygen 153 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 154 | @echo 155 | @echo "The overview file is in $(BUILDDIR)/changes." 156 | 157 | linkcheck: 158 | doxygen 159 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 160 | @echo 161 | @echo "Link check complete; look for any errors in the above output " \ 162 | "or in $(BUILDDIR)/linkcheck/output.txt." 163 | 164 | doctest: 165 | doxygen 166 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 167 | @echo "Testing of doctests in the sources finished, look at the " \ 168 | "results in $(BUILDDIR)/doctest/output.txt." 169 | 170 | coverage: 171 | doxygen 172 | $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage 173 | @echo "Testing of coverage in the sources finished, look at the " \ 174 | "results in $(BUILDDIR)/coverage/python.txt." 175 | 176 | xml: 177 | doxygen 178 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 179 | @echo 180 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 181 | 182 | pseudoxml: 183 | doxygen 184 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 185 | @echo 186 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 187 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Command file for Sphinx documentation 4 | 5 | if "%SPHINXBUILD%" == "" ( 6 | set SPHINXBUILD=sphinx-build 7 | ) 8 | set BUILDDIR=build 9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source 10 | set I18NSPHINXOPTS=%SPHINXOPTS% source 11 | if NOT "%PAPER%" == "" ( 12 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% 13 | set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% 14 | ) 15 | 16 | if "%1" == "" goto help 17 | 18 | if "%1" == "help" ( 19 | :help 20 | echo.Please use `make ^` where ^ is one of 21 | echo. html to make standalone HTML files 22 | echo. dirhtml to make HTML files named index.html in directories 23 | echo. singlehtml to make a single large HTML file 24 | echo. pickle to make pickle files 25 | echo. json to make JSON files 26 | echo. htmlhelp to make HTML files and a HTML help project 27 | echo. qthelp to make HTML files and a qthelp project 28 | echo. devhelp to make HTML files and a Devhelp project 29 | echo. epub to make an epub 30 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter 31 | echo. text to make text files 32 | echo. man to make manual pages 33 | echo. texinfo to make Texinfo files 34 | echo. gettext to make PO message catalogs 35 | echo. changes to make an overview over all changed/added/deprecated items 36 | echo. xml to make Docutils-native XML files 37 | echo. pseudoxml to make pseudoxml-XML files for display purposes 38 | echo. linkcheck to check all external links for integrity 39 | echo. doctest to run all doctests embedded in the documentation if enabled 40 | echo. coverage to run coverage check of the documentation if enabled 41 | goto end 42 | ) 43 | 44 | if "%1" == "clean" ( 45 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i 46 | del /q /s %BUILDDIR%\* 47 | goto end 48 | ) 49 | 50 | 51 | REM Check if sphinx-build is available and fallback to Python version if any 52 | %SPHINXBUILD% 1>NUL 2>NUL 53 | if errorlevel 9009 goto sphinx_python 54 | goto sphinx_ok 55 | 56 | :sphinx_python 57 | 58 | set SPHINXBUILD=python -m sphinx.__init__ 59 | %SPHINXBUILD% 2> nul 60 | if errorlevel 9009 ( 61 | echo. 62 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 63 | echo.installed, then set the SPHINXBUILD environment variable to point 64 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 65 | echo.may add the Sphinx directory to PATH. 66 | echo. 67 | echo.If you don't have Sphinx installed, grab it from 68 | echo.http://sphinx-doc.org/ 69 | exit /b 1 70 | ) 71 | 72 | :sphinx_ok 73 | 74 | 75 | if "%1" == "html" ( 76 | doxygen 77 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html 78 | if errorlevel 1 exit /b 1 79 | echo. 80 | echo.Build finished. The HTML pages are in %BUILDDIR%/html. 81 | goto end 82 | ) 83 | 84 | if "%1" == "dirhtml" ( 85 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml 86 | if errorlevel 1 exit /b 1 87 | echo. 88 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. 89 | goto end 90 | ) 91 | 92 | if "%1" == "singlehtml" ( 93 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml 94 | if errorlevel 1 exit /b 1 95 | echo. 96 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. 97 | goto end 98 | ) 99 | 100 | if "%1" == "pickle" ( 101 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle 102 | if errorlevel 1 exit /b 1 103 | echo. 104 | echo.Build finished; now you can process the pickle files. 105 | goto end 106 | ) 107 | 108 | if "%1" == "json" ( 109 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json 110 | if errorlevel 1 exit /b 1 111 | echo. 112 | echo.Build finished; now you can process the JSON files. 113 | goto end 114 | ) 115 | 116 | if "%1" == "htmlhelp" ( 117 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp 118 | if errorlevel 1 exit /b 1 119 | echo. 120 | echo.Build finished; now you can run HTML Help Workshop with the ^ 121 | .hhp project file in %BUILDDIR%/htmlhelp. 122 | goto end 123 | ) 124 | 125 | if "%1" == "qthelp" ( 126 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp 127 | if errorlevel 1 exit /b 1 128 | echo. 129 | echo.Build finished; now you can run "qcollectiongenerator" with the ^ 130 | .qhcp project file in %BUILDDIR%/qthelp, like this: 131 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\packagename.qhcp 132 | echo.To view the help file: 133 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\packagename.ghc 134 | goto end 135 | ) 136 | 137 | if "%1" == "devhelp" ( 138 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp 139 | if errorlevel 1 exit /b 1 140 | echo. 141 | echo.Build finished. 142 | goto end 143 | ) 144 | 145 | if "%1" == "epub" ( 146 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub 147 | if errorlevel 1 exit /b 1 148 | echo. 149 | echo.Build finished. The epub file is in %BUILDDIR%/epub. 150 | goto end 151 | ) 152 | 153 | if "%1" == "latex" ( 154 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 155 | if errorlevel 1 exit /b 1 156 | echo. 157 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. 158 | goto end 159 | ) 160 | 161 | if "%1" == "latexpdf" ( 162 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 163 | cd %BUILDDIR%/latex 164 | make all-pdf 165 | cd %~dp0 166 | echo. 167 | echo.Build finished; the PDF files are in %BUILDDIR%/latex. 168 | goto end 169 | ) 170 | 171 | if "%1" == "latexpdfja" ( 172 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 173 | cd %BUILDDIR%/latex 174 | make all-pdf-ja 175 | cd %~dp0 176 | echo. 177 | echo.Build finished; the PDF files are in %BUILDDIR%/latex. 178 | goto end 179 | ) 180 | 181 | if "%1" == "text" ( 182 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text 183 | if errorlevel 1 exit /b 1 184 | echo. 185 | echo.Build finished. The text files are in %BUILDDIR%/text. 186 | goto end 187 | ) 188 | 189 | if "%1" == "man" ( 190 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man 191 | if errorlevel 1 exit /b 1 192 | echo. 193 | echo.Build finished. The manual pages are in %BUILDDIR%/man. 194 | goto end 195 | ) 196 | 197 | if "%1" == "texinfo" ( 198 | %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo 199 | if errorlevel 1 exit /b 1 200 | echo. 201 | echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. 202 | goto end 203 | ) 204 | 205 | if "%1" == "gettext" ( 206 | %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale 207 | if errorlevel 1 exit /b 1 208 | echo. 209 | echo.Build finished. The message catalogs are in %BUILDDIR%/locale. 210 | goto end 211 | ) 212 | 213 | if "%1" == "changes" ( 214 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes 215 | if errorlevel 1 exit /b 1 216 | echo. 217 | echo.The overview file is in %BUILDDIR%/changes. 218 | goto end 219 | ) 220 | 221 | if "%1" == "linkcheck" ( 222 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck 223 | if errorlevel 1 exit /b 1 224 | echo. 225 | echo.Link check complete; look for any errors in the above output ^ 226 | or in %BUILDDIR%/linkcheck/output.txt. 227 | goto end 228 | ) 229 | 230 | if "%1" == "doctest" ( 231 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest 232 | if errorlevel 1 exit /b 1 233 | echo. 234 | echo.Testing of doctests in the sources finished, look at the ^ 235 | results in %BUILDDIR%/doctest/output.txt. 236 | goto end 237 | ) 238 | 239 | if "%1" == "coverage" ( 240 | %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage 241 | if errorlevel 1 exit /b 1 242 | echo. 243 | echo.Testing of coverage in the sources finished, look at the ^ 244 | results in %BUILDDIR%/coverage/python.txt. 245 | goto end 246 | ) 247 | 248 | if "%1" == "xml" ( 249 | %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml 250 | if errorlevel 1 exit /b 1 251 | echo. 252 | echo.Build finished. The XML files are in %BUILDDIR%/xml. 253 | goto end 254 | ) 255 | 256 | if "%1" == "pseudoxml" ( 257 | %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml 258 | if errorlevel 1 exit /b 1 259 | echo. 260 | echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. 261 | goto end 262 | ) 263 | 264 | :end 265 | -------------------------------------------------------------------------------- /docs/source/xvega_magic.rst: -------------------------------------------------------------------------------- 1 | XVega magics 2 | ============ 3 | 4 | Magics that allow you to create graph visualizations using `XVega`_ an implementation of vega-light to C++. 5 | 6 | X_FIELD 7 | ~~~~~~~ 8 | 9 | .. object:: %X_FIELD name_of_column 10 | 11 | Represents the X axis of the graph. The name of the axis should be the same as the name of the SQLite column (or result of SQLite query). 12 | 13 | TYPE 14 | **** 15 | 16 | .. object:: %TYPE type_of_field 17 | 18 | Sub-attribute of **X_FIELD**. 19 | 20 | Bellow there's list of the types supported by `xeus-sqlite`. If you want to learn more about types please refer to `vega lite type official documentation`_. 21 | 22 | * QUANTITATIVE 23 | * NOMINAL 24 | * ORDINAL 25 | * TEMPORAL 26 | 27 | BIN 28 | *** 29 | 30 | .. object:: %BIN type_of_field 31 | 32 | Sub-attribute of **X_FIELD**. 33 | 34 | Binning discretizes numeric values into a set of bins. If bin is true, default binning parameters are used. 35 | 36 | To customize binning parameters, you can set bin to a bin definition object, which can have the following properties: 37 | 38 | If you want to learn more about bin please refer to `vega lite bin official documentation`_. 39 | 40 | ANCHOR 41 | ++++++ 42 | 43 | .. object:: %ANCHOR bin_position 44 | 45 | Sub-attribute of **BIN**. 46 | 47 | A value in the binned domain at which to anchor the bins, shifting the bin boundaries if necessary to ensure that a boundary aligns with the anchor value. 48 | 49 | BASE 50 | ++++ 51 | 52 | .. object:: %BASE number 53 | 54 | Sub-attribute of **BIN**. 55 | 56 | The number base to use for automatic bin determination (default is base 10). 57 | 58 | BINNED 59 | ++++++ 60 | 61 | .. object:: %BASE boolean 62 | 63 | Sub-attribute of **BIN**. 64 | 65 | MAXBINS 66 | +++++++ 67 | 68 | .. object:: %MAXBINS number 69 | 70 | Sub-attribute of **BIN**. 71 | 72 | Maximum number of bins. 73 | 74 | MINSTEP 75 | +++++++ 76 | 77 | .. object:: %MINSTEP number 78 | 79 | Sub-attribute of **BIN**. 80 | 81 | A minimum allowable step size (particularly useful for integer values). 82 | 83 | NICE 84 | ++++ 85 | 86 | .. object:: %NICE bool 87 | 88 | Sub-attribute of **BIN**. 89 | 90 | If true, attempts to make the bin boundaries use human-friendly boundaries, such as multiples of ten. 91 | 92 | STEP 93 | ++++ 94 | 95 | .. object:: %STEP number 96 | 97 | Sub-attribute of **BIN**. 98 | 99 | An exact step size to use between bins. 100 | 101 | AGGREGATE 102 | ********* 103 | 104 | .. object:: %AGGREGATE type_of_aggregation 105 | 106 | Sub-attribute of **X_FIELD**. 107 | 108 | The aggregate property of a field definition can be used to compute aggregate summary statistics (e.g., median, min, max) over groups of data. 109 | 110 | Bellow there's list of the aggregations supported by `xeus-sqlite`. If you want to learn more about aggregations please refer to `vega lite aggregate official documentation`_. 111 | 112 | * COUNT 113 | * VALID 114 | * MISSING 115 | * DISTINCT 116 | * SUM 117 | * PRODUCT 118 | * MEAN 119 | * AVERAGE 120 | * VARIANCE 121 | * VARIANCEP 122 | * STDEV 123 | * STEDEVP 124 | * STEDERR 125 | * MEDIAN 126 | * Q1 127 | * Q3 128 | * CI0 129 | * CI1 130 | * MIN 131 | * MAX 132 | * ARGMIN 133 | * ARGMAX 134 | 135 | TIME_UNIT 136 | ********* 137 | 138 | .. object:: %TIME_UNIT time 139 | 140 | Sub-attribute of **X_FIELD**. 141 | 142 | Time unit is used to discretize time. 143 | 144 | Bellow there's list of the time units supported by `xeus-sqlite`. If you want to learn more about time units please refer to `vega lite time unit official documentation`_. 145 | 146 | * YEAR 147 | * QUARTER 148 | * MONTH 149 | * DAY 150 | * DATE 151 | * HOURS 152 | * MINUTES 153 | * SECONDS 154 | * MILISECONDS 155 | 156 | Y_FIELD 157 | ~~~~~~~ 158 | 159 | .. object:: %Y_FIELD name_of_column 160 | 161 | Represents the Y axis of the graph. The name of the axis should be the same as the name of the SQLite column (or result of SQLite query). 162 | 163 | TYPE 164 | **** 165 | 166 | .. object:: %TYPE type_of_field 167 | 168 | Sub-attribute of **Y_FIELD**. 169 | 170 | Bellow there's list of the types supported by `xeus-sqlite`. If you want to learn more about types please refer to `vega lite type official documentation`_. 171 | 172 | * QUANTITATIVE 173 | * NOMINAL 174 | * ORDINAL 175 | * TEMPORAL 176 | 177 | BIN 178 | *** 179 | 180 | .. object:: %BIN type_of_field 181 | 182 | Sub-attribute of **Y_FIELD**. 183 | 184 | Binning discretizes numeric values into a set of bins. If bin is true, default binning parameters are used. 185 | 186 | To customize binning parameters, you can set bin to a bin definition object, which can have the following properties: 187 | 188 | If you want to learn more about bin please refer to `vega lite bin official documentation`_. 189 | 190 | ANCHOR 191 | ++++++ 192 | 193 | .. object:: %ANCHOR bin_position 194 | 195 | Sub-attribute of **BIN**. 196 | 197 | A value in the binned domain at which to anchor the bins, shifting the bin boundaries if necessary to ensure that a boundary aligns with the anchor value. 198 | 199 | BASE 200 | +++++ 201 | 202 | .. object:: %BASE number 203 | 204 | Sub-attribute of **BIN**. 205 | 206 | The number base to use for automatic bin determination (default is base 10). 207 | 208 | BINNED 209 | ++++++ 210 | 211 | .. object:: %BASE boolean 212 | 213 | Sub-attribute of **BIN**. 214 | 215 | MAXBINS 216 | +++++++ 217 | 218 | .. object:: %MAXBINS number 219 | 220 | Sub-attribute of **BIN**. 221 | 222 | Maximum number of bins. 223 | 224 | MINSTEP 225 | +++++++ 226 | 227 | .. object:: %MINSTEP number 228 | 229 | Sub-attribute of **BIN**. 230 | 231 | A minimum allowable step size (particularly useful for integer values). 232 | 233 | NICE 234 | ++++ 235 | 236 | .. object:: %NICE bool 237 | 238 | Sub-attribute of **BIN**. 239 | 240 | If true, attempts to make the bin boundaries use human-friendly boundaries, such as multiples of ten. 241 | 242 | STEP 243 | ++++ 244 | 245 | .. object:: %STEP number 246 | 247 | Sub-attribute of **BIN**. 248 | 249 | An exact step size to use between bins. 250 | 251 | AGGREGATE 252 | ********* 253 | 254 | .. object:: %AGGREGATE type_of_aggregation 255 | 256 | Sub-attribute of **Y_FIELD**. 257 | 258 | The aggregate property of a field definition can be used to compute aggregate summary statistics (e.g., median, min, max) over groups of data. 259 | 260 | Bellow there's list of the aggregations supported by `xeus-sqlite`. If you want to learn more about aggregations please refer to `vega lite aggregate official documentation`_. 261 | 262 | * COUNT 263 | * VALID 264 | * MISSING 265 | * DISTINCT 266 | * SUM 267 | * PRODUCT 268 | * MEAN 269 | * AVERAGE 270 | * VARIANCE 271 | * VARIANCEP 272 | * STDEV 273 | * STEDEVP 274 | * STEDERR 275 | * MEDIAN 276 | * Q1 277 | * Q3 278 | * CI0 279 | * CI1 280 | * MIN 281 | * MAX 282 | * ARGMIN 283 | * ARGMAX 284 | 285 | TIME_UNIT 286 | ********* 287 | 288 | .. object:: %TIME_UNIT time 289 | 290 | Sub-attribute of **Y_FIELD**. 291 | 292 | Time unit is used to discretize time. 293 | 294 | Bellow there's list of the time units supported by `xeus-sqlite`. If you want to learn more about time units please refer to `vega lite time unit official documentation`_. 295 | 296 | * YEAR 297 | * QUARTER 298 | * MONTH 299 | * DAY 300 | * DATE 301 | * HOURS 302 | * MINUTES 303 | * SECONDS 304 | * MILISECONDS 305 | 306 | WIDTH 307 | ~~~~~ 308 | 309 | .. object:: %WIDTH number 310 | 311 | Width of the graph in pixels. 312 | 313 | HEIGHT 314 | ~~~~~~ 315 | 316 | .. object:: %HEIGHT number 317 | 318 | Height of the graph in pixels. 319 | 320 | MARK 321 | ~~~~ 322 | 323 | .. object:: %MARK mark 324 | 325 | Marcs can be one of the following: 326 | 327 | * ARC 328 | * AREA 329 | * BAR 330 | * CIRCLE 331 | * LINE 332 | * POINT 333 | * RECT 334 | * RULE 335 | * SQUARE 336 | * TICK 337 | * TRAIL 338 | 339 | COLOR 340 | ***** 341 | 342 | .. object:: %COLOR color 343 | 344 | Sub-attribute of **MARK**. 345 | 346 | Sets the color of a mark. The color can be one of the `valid CSS color string`_. 347 | 348 | GRID 349 | ~~~~ 350 | 351 | .. object:: %HEIGHT boolean 352 | 353 | Enable or disable grid view on graph. 354 | 355 | 356 | .. _XVega: https://github.com/Quantstack/xvega 357 | .. _valid CSS color string: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value 358 | .. _vega lite aggregate official documentation: https://vega.github.io/vega-lite/docs/aggregate.html#ops 359 | .. _vega lite type official documentation: https://vega.github.io/vega-lite/docs/type.html 360 | .. _vega lite bin official documentation: https://vega.github.io/vega-lite/docs/bin.html#bin-parameters 361 | .. _vega lite time unit official documentation: https://vega.github.io/vega-lite/docs/timeunit.html 362 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | # Copyright (c) 2020, QuantStack and xeus-sql contributors # 3 | # # 4 | # # 5 | # Distributed under the terms of the BSD 3-Clause License. # 6 | # # 7 | # The full license is in the file LICENSE, distributed with this software. # 8 | ############################################################################ 9 | 10 | cmake_minimum_required(VERSION 3.20) 11 | project(xeus-sql) 12 | 13 | set(XEUS_SQL_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include) 14 | set(XEUS_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/test) 15 | 16 | set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") 17 | 18 | # Versioning 19 | # ========== 20 | 21 | file(STRINGS "${XEUS_SQL_INCLUDE_DIR}/xeus-sql/xeus_sql_config.hpp" xsql_version_defines 22 | REGEX "#define XSQL_VERSION_(MAJOR|MINOR|PATCH)") 23 | foreach(ver ${xsql_version_defines}) 24 | if(ver MATCHES "#define XSQL_VERSION_(MAJOR|MINOR|PATCH) +([^ ]+) *$") 25 | set(XSQL_VERSION_${CMAKE_MATCH_1} "${CMAKE_MATCH_2}" CACHE INTERNAL "") 26 | endif() 27 | endforeach() 28 | set(${PROJECT_NAME}_VERSION 29 | ${XSQL_VERSION_MAJOR}.${XSQL_VERSION_MINOR}.${XSQL_VERSION_PATCH}) 30 | message(STATUS "Building xeus-sql v${${PROJECT_NAME}_VERSION}") 31 | 32 | # Configuration 33 | # ============= 34 | 35 | include(GNUInstallDirs) 36 | 37 | # We generate the kernel.json file, given the installation prefix and the executable name 38 | configure_file ( 39 | "${CMAKE_CURRENT_SOURCE_DIR}/share/jupyter/kernels/xsql/kernel.json.in" 40 | "${CMAKE_CURRENT_SOURCE_DIR}/share/jupyter/kernels/xsql/kernel.json" 41 | ) 42 | 43 | # Build options 44 | # ============= 45 | 46 | OPTION(XSQL_BUILD_STATIC "Build xeus-sql static library" ON) 47 | OPTION(XSQL_BUILD_SHARED "Split xsql build into executable and library" ON) 48 | OPTION(XSQL_BUILD_XSQL_EXECUTABLE "Build the xsql executable" ON) 49 | 50 | OPTION(XSQL_USE_SHARED_XEUS "Link xsql with the xeus shared library (instead of the static library)" ON) 51 | OPTION(XSQL_USE_SHARED_XEUS_SQL "Link xsql with the xeus-sql shared library (instead of the static library)" ON) 52 | 53 | OPTION(XSQL_BUILD_TESTS "xeus-sql test suite" OFF) 54 | 55 | OPTION(CMAKE_USE_WIN32_THREADS_INIT "using WIN32 threads" ON) 56 | 57 | # Dependencies 58 | # ============ 59 | 60 | # Be sure to use recent versions 61 | set(xeus-zmq_REQUIRED_VERSION 1.1.1) 62 | 63 | find_package(xeus-zmq ${xeus-zmq_REQUIRED_VERSION} REQUIRED) 64 | find_package(xvega) 65 | 66 | #find_package(tabulate REQUIRED) 67 | find_package(Threads REQUIRED) 68 | 69 | find_package(Soci REQUIRED MODULE) 70 | 71 | # https://stackoverflow.com/a/15212881/1203241 72 | OPTION(XSQL_WITH_POSTGRE_SQL "Option to require PostgreSQL" OFF) 73 | OPTION(XSQL_WITH_MYSQL "Option to require MySQL" OFF) 74 | OPTION(XSQL_WITH_SQLITE3 "Option to require SQLite3" OFF) 75 | 76 | if(XSQL_WITH_POSTGRE_SQL) 77 | find_package(PostgreSQL REQUIRED) 78 | add_definitions(-DUSE_POSTGRE_SQL=1) 79 | else() 80 | find_package(PostgreSQL) 81 | endif() 82 | 83 | if(XSQL_WITH_MYSQL) 84 | find_package(mysql REQUIRED) 85 | add_definitions(-DUSE_MYSQL=1) 86 | else() 87 | find_package(mysql) 88 | endif() 89 | 90 | if(XSQL_WITH_SQLITE3) 91 | find_package(SQLite3 REQUIRED) 92 | add_definitions(-DUSE_SQLITE3=1) 93 | else() 94 | find_package(SQLite3) 95 | endif() 96 | 97 | 98 | # Target and link 99 | # =============== 100 | 101 | string(TOUPPER "${CMAKE_BUILD_TYPE}" U_CMAKE_BUILD_TYPE) 102 | 103 | # xeus-sql source directory 104 | set(XEUS_SQL_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src) 105 | 106 | # xeus-sql source files 107 | set(XEUS_SQL_SRC 108 | ${XEUS_SQL_SRC_DIR}/xeus_sql_interpreter.cpp 109 | ) 110 | 111 | set(XEUS_SQL_HEADERS 112 | include/xeus-sql/soci_handler.hpp 113 | include/xeus-sql/xeus_sql_config.hpp 114 | include/xeus-sql/xeus_sql_interpreter.hpp 115 | ) 116 | 117 | set(XSQL_SRC ${XEUS_SQL_SRC_DIR}/main.cpp) 118 | 119 | # Targets and link - Macros 120 | # ========================= 121 | 122 | include(CheckCXXCompilerFlag) 123 | 124 | set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE) 125 | string(TOUPPER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE) 126 | 127 | set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib:${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") 128 | 129 | macro(xsql_set_common_options target_name) 130 | if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR 131 | CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR 132 | CMAKE_CXX_COMPILER_ID MATCHES "Intel") 133 | target_compile_options(${target_name} PUBLIC -Wunused-parameter -Wextra -Wreorder) 134 | endif () 135 | 136 | target_compile_features(${target_name} PRIVATE cxx_std_17) 137 | 138 | if (APPLE) 139 | set_target_properties(${target_name} PROPERTIES 140 | MACOSX_RPATH ON 141 | ) 142 | else () 143 | set_target_properties(${target_name} PROPERTIES 144 | BUILD_WITH_INSTALL_RPATH 1 145 | SKIP_BUILD_RPATH FALSE 146 | ) 147 | endif () 148 | 149 | set_target_properties(${target_name} PROPERTIES 150 | INSTALL_RPATH_USE_LINK_PATH TRUE 151 | ) 152 | endmacro() 153 | 154 | 155 | # Common macro for shared and static library xeus-sql 156 | macro(xsql_create_target target_name linkage output_name) 157 | string(TOUPPER "${linkage}" linkage_upper) 158 | 159 | if (NOT ${linkage_upper} MATCHES "^(SHARED|STATIC)$") 160 | message(FATAL_ERROR "Invalid library linkage: ${linkage}") 161 | endif () 162 | 163 | add_library(${target_name} ${linkage_upper} ${XEUS_SQL_SRC} ${XEUS_SQL_HEADERS}) 164 | xsql_set_common_options(${target_name}) 165 | 166 | set_target_properties(${target_name} PROPERTIES 167 | PUBLIC_HEADER "${XEUS_SQL_HEADERS}" 168 | # COMPILE_DEFINITIONS "XEUS_SQL_EXPORTS" 169 | PREFIX "" 170 | VERSION ${${PROJECT_NAME}_VERSION} 171 | SOVERSION ${XSQL_VERSION_MAJOR} 172 | OUTPUT_NAME "lib${output_name}") 173 | 174 | target_compile_definitions(${target_name} PUBLIC "XEUS_SQL_EXPORTS") 175 | 176 | target_include_directories(${target_name} 177 | PUBLIC 178 | $ 179 | $) 180 | 181 | if (XSQL_USE_SHARED_XEUS) 182 | set(XSQL_XEUS_TARGET xeus-zmq) 183 | else () 184 | set(XSQL_XEUS_TARGET xeus-zmq-static) 185 | endif () 186 | 187 | target_link_libraries(${target_name} PUBLIC 188 | ${XSQL_XEUS_TARGET} 189 | xvega 190 | ${SOCI_LIBRARY} 191 | ) 192 | 193 | # find_package(Threads) # TODO: add Threads as a dependence of xeus-static? 194 | target_link_libraries(${target_name} PRIVATE ${CMAKE_THREAD_LIBS_INIT}) 195 | endmacro() 196 | 197 | # xeus-sql 198 | # =========== 199 | 200 | set(XEUS_SQL_TARGETS "") 201 | 202 | if (XSQL_BUILD_SHARED) 203 | # Build libraries 204 | xsql_create_target(xeus-sql SHARED xeus-sql) 205 | list(APPEND XEUS_SQL_TARGETS xeus-sql) 206 | endif () 207 | 208 | if (XSQL_BUILD_STATIC) 209 | # On Windows, a static library should use a different output name 210 | # to avoid the conflict with the import library of a shared one. 211 | if (CMAKE_HOST_WIN32) 212 | xsql_create_target(xeus-sql-static STATIC xeus-sql-static) 213 | else () 214 | xsql_create_target(xeus-sql-static STATIC xeus-sql) 215 | endif () 216 | list(APPEND XEUS_SQL_TARGETS xeus-sql-static) 217 | endif () 218 | 219 | # xsql 220 | # ======= 221 | 222 | if (XSQL_BUILD_XSQL_EXECUTABLE) 223 | add_executable(xsql ${XSQL_SRC}) 224 | set_target_properties(xsql PROPERTIES ENABLE_EXPORTS 1) 225 | 226 | xsql_set_common_options(xsql) 227 | 228 | if (XSQL_USE_SHARED_XEUS_SQL) 229 | target_link_libraries(xsql PRIVATE xeus-sql) 230 | 231 | if(CMAKE_DL_LIBS) 232 | target_link_libraries(xsql PRIVATE ${CMAKE_DL_LIBS} util) 233 | endif() 234 | else () 235 | target_link_libraries(xsql PRIVATE xeus-sql-static) 236 | endif() 237 | endif() 238 | 239 | 240 | # Tests 241 | # ===== 242 | 243 | if(XSQL_BUILD_TESTS) 244 | add_subdirectory(test) 245 | endif() 246 | 247 | # Installation 248 | # ============ 249 | 250 | include(CMakePackageConfigHelpers) 251 | 252 | set(XEUS_SQL_CMAKECONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" CACHE STRING "install path for xeus-sqlConfig.cmake") 253 | 254 | # Install xeus-sql and xsql 255 | if (XSQL_BUILD_SHARED OR XSQL_BUILD_STATIC) 256 | install(TARGETS ${XEUS_SQL_TARGETS} 257 | EXPORT ${PROJECT_NAME}-targets 258 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 259 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 260 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} 261 | PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/xeus-sql) 262 | 263 | # Makes the project importable from the build directory 264 | export(EXPORT ${PROJECT_NAME}-targets 265 | FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake") 266 | endif () 267 | 268 | # Install xsql 269 | if (XSQL_BUILD_XSQL_EXECUTABLE) 270 | install(TARGETS xsql 271 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 272 | 273 | # Configuration and data directories for jupyter and xeus_sql 274 | set(XJUPYTER_DATA_DIR "share/jupyter" CACHE STRING "Jupyter data directory") 275 | 276 | # Install xsql Jupyter kernelspecs 277 | set(XSQL_KERNELSPEC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/share/jupyter/kernels) 278 | install(DIRECTORY ${XSQL_KERNELSPEC_DIR} 279 | DESTINATION ${XJUPYTER_DATA_DIR} 280 | PATTERN "*.in" EXCLUDE) 281 | 282 | 283 | # Extra path for installing Jupyter kernelspec 284 | if (XEXTRA_JUPYTER_DATA_DIR) 285 | install(DIRECTORY ${XSQL_KERNELSPEC_DIR} 286 | DESTINATION ${XEXTRA_JUPYTER_DATA_DIR} 287 | PATTERN "*.in" EXCLUDE) 288 | endif(XEXTRA_JUPYTER_DATA_DIR) 289 | endif() 290 | 291 | # Configure 'xeus-sqlConfig.cmake' for a build tree 292 | set(XEUS_SQL_CONFIG_CODE "####### Expanded from \@XEUS_SQL_CONFIG_CODE\@ #######\n") 293 | set(XEUS_SQL_CONFIG_CODE "${XEUS_SQL_CONFIG_CODE}set(CMAKE_MODULE_PATH \"${CMAKE_CURRENT_SOURCE_DIR}/cmake;\${CMAKE_MODULE_PATH}\")\n") 294 | set(XEUS_SQL_CONFIG_CODE "${XEUS_SQL_CONFIG_CODE}##################################################") 295 | configure_package_config_file(${PROJECT_NAME}Config.cmake.in 296 | "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" 297 | INSTALL_DESTINATION ${PROJECT_BINARY_DIR}) 298 | 299 | # Configure 'xeus-sqlConfig.cmake' for an install tree 300 | set(XEUS_SQL_CONFIG_CODE "") 301 | configure_package_config_file(${PROJECT_NAME}Config.cmake.in 302 | "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${PROJECT_NAME}Config.cmake" 303 | INSTALL_DESTINATION ${XEUS_SQL_CMAKECONFIG_INSTALL_DIR}) 304 | 305 | write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake 306 | VERSION ${${PROJECT_NAME}_VERSION} 307 | COMPATIBILITY AnyNewerVersion) 308 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${PROJECT_NAME}Config.cmake 309 | ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake 310 | DESTINATION ${XEUS_SQL_CMAKECONFIG_INSTALL_DIR}) 311 | 312 | if (XSQL_BUILD_SHARED) 313 | install(EXPORT ${PROJECT_NAME}-targets 314 | FILE ${PROJECT_NAME}Targets.cmake 315 | DESTINATION ${XEUS_SQL_CMAKECONFIG_INSTALL_DIR}) 316 | endif () 317 | -------------------------------------------------------------------------------- /src/xeus_sql_interpreter.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2020, QuantStack and xeus-sql contributors * 3 | * * 4 | * * 5 | * Distributed under the terms of the BSD 3-Clause License. * 6 | * * 7 | * The full license is in the file LICENSE, distributed with this software. * 8 | ****************************************************************************/ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "tabulate/table.hpp" 24 | #include "xeus/xinterpreter.hpp" 25 | 26 | #include "xeus-sql/xeus_sql_interpreter.hpp" 27 | #include "xeus-sql/soci_handler.hpp" 28 | 29 | #ifdef USE_POSTGRE_SQL 30 | #include "soci/postgresql/soci-postgresql.h" 31 | #endif 32 | #ifdef USE_MYSQL 33 | #include "soci/mysql/soci-mysql.h" 34 | #endif 35 | #ifdef USE_SQLITE3 36 | #include "soci/sqlite3/soci-sqlite3.h" 37 | #endif 38 | 39 | namespace xeus_sql 40 | { 41 | // implemented at the end of the file 42 | // for better readability 43 | const std::array & get_keywords(); 44 | 45 | inline bool startswith(const std::string& str, const std::string& cmp) 46 | { 47 | return str.compare(0, cmp.length(), cmp) == 0; 48 | } 49 | inline static bool is_identifier(char c) 50 | { 51 | return std::isalpha(c) || std::isdigit(c) || c == '_'; 52 | } 53 | 54 | void interpreter::configure_impl() 55 | { 56 | } 57 | 58 | // trim string https://stackoverflow.com/a/217605/1203241 59 | 60 | // trim from start (in place) 61 | static inline void ltrim(std::string &s) { 62 | s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { 63 | return !std::isspace(ch); 64 | })); 65 | } 66 | 67 | // trim from end (in place) 68 | static inline void rtrim(std::string &s) { 69 | s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { 70 | return !std::isspace(ch); 71 | }).base(), s.end()); 72 | } 73 | 74 | // trim from both ends (in place) 75 | static inline void trim(std::string &s) { 76 | ltrim(s); 77 | rtrim(s); 78 | } 79 | 80 | using clock = std::chrono::system_clock; 81 | using sec = std::chrono::duration; 82 | nl::json interpreter::process_SQL_input(const std::string& code, 83 | xv::df_type& xv_sql_df) 84 | { 85 | const auto before = clock::now(); 86 | soci::rowset rows = ((*this->sql).prepare << code); 87 | 88 | nl::json pub_data; 89 | 90 | tabulate::Table plain_table; 91 | std::stringstream html_table(""); 92 | /* Builds table body */ 93 | int row_count = 0; 94 | for (const soci::row& r : rows) 95 | { 96 | if (row_count == 0) { 97 | tabulate::Table::Row_t col_names; 98 | html_table << "\n\n"; 99 | for (std::size_t i = 0; i != r.size(); ++i) { 100 | std::string name = r.get_properties(i).get_name(); 101 | html_table << "\n"; 102 | col_names.push_back(name); 103 | } 104 | html_table << "\n"; 105 | plain_table.add_row(col_names); 106 | } 107 | row_count++; 108 | /* Iterates through cols' rows and builds different kinds of 109 | outputs 110 | */ 111 | tabulate::Table::Row_t row; 112 | html_table << "\n"; 113 | for(std::size_t i = 0; i != r.size(); ++i) 114 | { 115 | std::string cell; 116 | 117 | soci::column_properties props = r.get_properties(i); 118 | try { 119 | switch(props.get_data_type()) 120 | { 121 | case soci::dt_string: 122 | cell = r.get(i, "NULL"); 123 | break; 124 | case soci::dt_double: 125 | cell = std::to_string(r.get(i)); 126 | cell.erase(cell.find_last_not_of('0') + 1, std::string::npos); 127 | if (cell.back() == '.') { 128 | cell.pop_back(); 129 | } 130 | break; 131 | case soci::dt_integer: 132 | cell = std::to_string(r.get(i)); 133 | break; 134 | case soci::dt_long_long: 135 | cell = std::to_string(r.get(i)); 136 | break; 137 | case soci::dt_unsigned_long_long: 138 | cell = std::to_string(r.get(i)); 139 | break; 140 | case soci::dt_xml: 141 | case soci::dt_blob: 142 | break; 143 | case soci::dt_date: 144 | std::tm when = r.get(i); 145 | char buffer [20]; 146 | std::strftime(buffer, 20, "%Y-%m-%d %H:%M:%S", &when); 147 | cell = buffer; 148 | break; 149 | } 150 | } catch (...) { 151 | cell = "NULL"; 152 | } 153 | html_table << "\n"; 154 | row.push_back(cell); 155 | xv_sql_df[r.get_properties(i).get_name()].push_back(cell); 156 | } 157 | plain_table.add_row(row); 158 | html_table << "\n"; 159 | } 160 | html_table << "
" << name << "
" << cell << "
"; 161 | const sec duration = clock::now() - before; 162 | std::stringstream rows_info; 163 | rows_info << "\n"; 164 | if (row_count == 0) { 165 | rows_info << std::fixed << std::setprecision(2) << "Empty set (" 166 | << duration.count() << " sec)"; 167 | } else if (row_count == 1) { 168 | rows_info << std::fixed << std::setprecision(2) << "1 row in set (" 169 | << duration.count() << " sec)"; 170 | } else { 171 | rows_info << std::fixed << std::setprecision(2) << row_count 172 | << " rows in set (" << duration.count() << " sec)"; 173 | } 174 | 175 | pub_data["text/plain"] = rows_info.str() + plain_table.str(); 176 | pub_data["text/html"] = rows_info.str() + html_table.str(); 177 | 178 | return pub_data; 179 | } 180 | 181 | void interpreter::execute_request_impl(send_reply_callback cb, 182 | int execution_counter, 183 | const std::string& code, 184 | xeus::execute_request_config /*config*/, 185 | nl::json user_expressions) 186 | { 187 | auto ok = [&]() { 188 | nl::json jresult; 189 | jresult["status"] = "ok"; 190 | jresult["payload"] = nl::json::array(); 191 | jresult["user_expressions"] = user_expressions; 192 | return jresult; 193 | }; 194 | 195 | std::vector traceback; 196 | auto handle_exception = [&](std::string what) { 197 | nl::json jresult; 198 | jresult["status"] = "error"; 199 | jresult["ename"] = "Error"; 200 | jresult["evalue"] = what; 201 | traceback.push_back((std::string)jresult["ename"] + ": " + what); 202 | publish_execution_error(jresult["ename"], jresult["evalue"], traceback); 203 | traceback.clear(); 204 | return jresult; 205 | }; 206 | 207 | // we only need to tokenize the first line 208 | std::istringstream iss(code); 209 | std::string first_line; 210 | while (std::getline(iss, first_line)) { 211 | trim(first_line); 212 | if (first_line.size() > 0) break; 213 | } 214 | std::vector tokenized_input = xv_bindings::tokenizer(first_line); 215 | xv::df_type xv_sql_df; 216 | try 217 | { 218 | /* Runs magic */ 219 | if(xv_bindings::is_magic(tokenized_input)) 220 | { 221 | /* Removes "%" symbol */ 222 | tokenized_input[0].erase(0, 1); 223 | 224 | /* Runs xvega magic and SQL code */ 225 | if(xv_bindings::is_xvega(tokenized_input)) 226 | { 227 | tokenized_input = xv_bindings::tokenizer(code); 228 | /* Removes XVEGA_PLOT command */ 229 | tokenized_input.erase(tokenized_input.begin()); 230 | 231 | nl::json chart; 232 | std::vector xvega_input, sql_input; 233 | 234 | std::tie(xvega_input, sql_input) = split_xv_sql_input(tokenized_input); 235 | std::stringstream stringfied_sql_input; 236 | for (size_t i = 0; i < sql_input.size(); i++) { 237 | stringfied_sql_input << " " << sql_input[i]; 238 | } 239 | 240 | process_SQL_input(stringfied_sql_input.str(), xv_sql_df); 241 | 242 | chart = xv_bindings::process_xvega_input(xvega_input, 243 | xv_sql_df); 244 | 245 | publish_execution_result(execution_counter, 246 | std::move(chart), 247 | nl::json::object()); 248 | 249 | cb(ok()); 250 | return; 251 | } else if (xv_bindings::case_insentive_equals("VEGA_LITE", tokenized_input[0])) { 252 | if (tokenized_input.size() < 2) { 253 | throw std::runtime_error("invalid input: " + code); 254 | } 255 | if (xv_bindings::case_insentive_equals("SET", tokenized_input[1])) { 256 | // define vega-lite specs 257 | if (tokenized_input.size() < 3) { 258 | throw std::runtime_error("invalid input: " + code); 259 | } 260 | std::string spec_name = tokenized_input[2]; 261 | std::string json_str = code; 262 | json_str.erase(0, code.find(first_line) + first_line.length()); 263 | trim(json_str); 264 | if (json_str.length() == 0) { 265 | throw std::runtime_error("spec is empty: " + code); 266 | } 267 | nl::json spec_value = nl::json::parse(json_str); 268 | specs[spec_name] = spec_value; 269 | auto bundle = nl::json::object(); 270 | bundle["text/plain"] = "SET " + spec_name + " success."; 271 | publish_execution_result(execution_counter, std::move(bundle), nl::json::object()); 272 | cb(ok()); 273 | return; 274 | } 275 | nl::json j; 276 | auto v = specs.find(tokenized_input[1]); 277 | if (v != specs.end()) { 278 | j = v->second; 279 | } else { 280 | std::ifstream i(tokenized_input[1]); 281 | if (!i.good()) { 282 | throw std::runtime_error("invalid file name: " + tokenized_input[1]); 283 | } 284 | i >> j; 285 | } 286 | std::string sql = code; 287 | sql.erase(0, code.find(first_line) + first_line.length()); 288 | trim(sql); 289 | if (sql.length() > 0) { 290 | process_SQL_input(sql, xv_sql_df); 291 | if (xv_sql_df.size() == 0) { 292 | throw std::runtime_error("Empty result from sql, can't render"); 293 | } 294 | xv::data_frame data_frame; 295 | data_frame.values = xv_sql_df; 296 | j["data"] = data_frame; 297 | } 298 | auto bundle = nl::json::object(); 299 | bundle["application/vnd.vegalite.v3+json"] = j; 300 | publish_execution_result(execution_counter, std::move(bundle), nl::json::object()); 301 | cb(ok()); 302 | return; 303 | } 304 | 305 | /* Parses LOAD magic */ 306 | this->sql = parse_SQL_magic(tokenized_input); 307 | } 308 | /* Runs SQL code */ 309 | else 310 | { 311 | if (this->sql) 312 | { 313 | /* Shows rich output for tables */ 314 | if (xv_bindings::case_insentive_equals("SELECT", tokenized_input[0]) || 315 | xv_bindings::case_insentive_equals("DESC", tokenized_input[0]) || 316 | xv_bindings::case_insentive_equals("DESCRIBE", tokenized_input[0]) || 317 | xv_bindings::case_insentive_equals("SHOW", tokenized_input[0]) || 318 | xv_bindings::case_insentive_equals("--", tokenized_input[0])) 319 | { 320 | nl::json data = process_SQL_input(code, xv_sql_df); 321 | 322 | publish_execution_result(execution_counter, 323 | std::move(data), 324 | nl::json::object()); 325 | 326 | } 327 | /* Execute all SQL commands that don't output tables */ 328 | else 329 | { 330 | *this->sql << code; 331 | } 332 | } 333 | else 334 | { 335 | throw std::runtime_error("Database was not loaded."); 336 | } 337 | } 338 | } catch (const std::runtime_error &err) { 339 | cb(handle_exception((std::string)err.what())); 340 | #ifdef USE_POSTGRE_SQL 341 | } catch (const soci::postgresql_soci_error &err) { 342 | cb(handle_exception((std::string)err.what())); 343 | #endif 344 | #ifdef USE_MYSQL 345 | } catch (const soci::mysql_soci_error &err) { 346 | cb(handle_exception((std::string)err.what())); 347 | #endif 348 | #ifdef USE_SQLITE3 349 | } catch (const soci::sqlite3_soci_error &err) { 350 | cb(handle_exception((std::string)err.what())); 351 | #endif 352 | } catch (...) { 353 | // https: // stackoverflow.com/a/54242936/1203241 354 | try { 355 | std::exception_ptr curr_excp; 356 | if ((curr_excp = std::current_exception())) { 357 | std::rethrow_exception(curr_excp); 358 | } 359 | } catch (const std::exception &err) { 360 | cb(handle_exception((std::string)err.what())); 361 | } 362 | } 363 | cb(ok()); 364 | return; 365 | } 366 | nl::json interpreter::complete_request_impl(const std::string& raw_code, 367 | int cursor_pos) 368 | { 369 | 370 | nl::json result; 371 | 372 | const auto & keywords = get_keywords(); 373 | 374 | nl::json matches = nl::json::array(); 375 | 376 | // first we get a substring from string[0:curser_pos+1]std 377 | // and discard the right side of the curser pos 378 | const auto code = raw_code.substr(0, cursor_pos); 379 | 380 | 381 | // keyword matches 382 | // ............................ 383 | { 384 | auto pos = -1; 385 | for(int i=code.size()-1; i>=0; --i) 386 | { 387 | if(!is_identifier(code[i])) 388 | { 389 | pos = i; 390 | break; 391 | } 392 | } 393 | result["cursor_start"] = pos == -1 ? 0 : pos +1; 394 | auto to_match = pos == -1 ? code : code.substr(pos+1, code.size() -(pos+1)); 395 | 396 | // check for kw matches 397 | for(auto kw : keywords) 398 | { 399 | if(startswith(kw, to_match)) 400 | { 401 | matches.push_back(kw); 402 | } 403 | } 404 | } 405 | 406 | result["status"] = "ok"; 407 | result["cursor_end"] = cursor_pos; 408 | result["matches"] =matches; 409 | 410 | return result; 411 | }; 412 | 413 | nl::json interpreter::inspect_request_impl(const std::string& /*code*/, 414 | int /*cursor_pos*/, 415 | int /*detail_level*/) 416 | { 417 | nl::json jresult; 418 | jresult["status"] = "ok"; 419 | return jresult; 420 | }; 421 | 422 | nl::json interpreter::is_complete_request_impl(const std::string& /*code*/) 423 | { 424 | nl::json jresult; 425 | jresult["status"] = "complete"; 426 | return jresult; 427 | }; 428 | 429 | nl::json interpreter::kernel_info_request_impl() 430 | { 431 | nl::json result; 432 | result["implementation"] = "xsql"; 433 | result["implementation_version"] = XSQL_VERSION; 434 | 435 | /* The jupyter-console banner for xeus-sql is the following: 436 | _ 437 | | | 438 | __ _____ _ _ ___ ___ __ _| | 439 | \ \/ / _ \ | | / __| / __|/ _` | | 440 | > < __/ |_| \__ \ \__ \ (_| | | 441 | /_/\_\___|\__,_|___/ |___/\__, |_| 442 | | | 443 | |_| 444 | xeus-sql: a Jupyter kernel for SOCI 445 | SOCI version: x.x.x 446 | */ 447 | 448 | std::string banner = R"V0G0N( 449 | " _ " 450 | " | | " 451 | "__ _____ _ _ ___ ___ __ _| | " 452 | "\ \/ / _ \ | | / __| / __|/ _` | | " 453 | " > < __/ |_| \__ \ \__ \ (_| | | " 454 | "/_/\_\___|\__,_|___/ |___/\__, |_| " 455 | " | | " 456 | " |_| " 457 | " xeus-sql: a Jupyter kernel for SOCI" 458 | " XSQL version: ")V0G0N"; 459 | banner.append(XSQL_VERSION); 460 | 461 | result["banner"] = banner; 462 | //TODO: This should change with the language 463 | result["language_info"]["name"] = "mysql"; 464 | result["language_info"]["codemirror_mode"] = "sql"; 465 | result["language_info"]["version"] = XSQL_VERSION; 466 | result["language_info"]["mimetype"] = ""; 467 | result["language_info"]["file_extension"] = ""; 468 | return result; 469 | } 470 | 471 | void interpreter::shutdown_request_impl() 472 | { 473 | } 474 | 475 | 476 | const std::array & get_keywords() 477 | { 478 | static const std::array keywords = 479 | { 480 | "A", 481 | "ABORT", 482 | "ABS", 483 | "ABSOLUTE", 484 | "ACCESS", 485 | "ACTION", 486 | "ADA", 487 | "ADD", 488 | "ADMIN", 489 | "AFTER", 490 | "AGGREGATE", 491 | "ALIAS", 492 | "ALL", 493 | "ALLOCATE", 494 | "ALSO", 495 | "ALTER", 496 | "ALWAYS", 497 | "ANALYSE", 498 | "ANALYZE", 499 | "AND", 500 | "ANY", 501 | "ARE", 502 | "ARRAY", 503 | "AS", 504 | "ASC", 505 | "ASENSITIVE", 506 | "ASSERTION", 507 | "ASSIGNMENT", 508 | "ASYMMETRIC", 509 | "AT", 510 | "ATOMIC", 511 | "ATTRIBUTE", 512 | "ATTRIBUTES", 513 | "AUDIT", 514 | "AUTHORIZATION", 515 | "AUTO_INCREMENT", 516 | "AVG", 517 | "AVG_ROW_LENGTH", 518 | "BACKUP", 519 | "BACKWARD", 520 | "BEFORE", 521 | "BEGIN", 522 | "BERNOULLI", 523 | "BETWEEN", 524 | "BIGINT", 525 | "BINARY", 526 | "BIT", 527 | "BIT_LENGTH", 528 | "BITVAR", 529 | "BLOB", 530 | "BOOL", 531 | "BOOLEAN", 532 | "BOTH", 533 | "BREADTH", 534 | "BREAK", 535 | "BROWSE", 536 | "BULK", 537 | "BY", 538 | "C", 539 | "CACHE", 540 | "CALL", 541 | "CALLED", 542 | "CARDINALITY", 543 | "CASCADE", 544 | "CASCADED", 545 | "CASE", 546 | "CAST", 547 | "CATALOG", 548 | "CATALOG_NAME", 549 | "CEIL", 550 | "CEILING", 551 | "CHAIN", 552 | "CHANGE", 553 | "CHAR", 554 | "CHAR_LENGTH", 555 | "CHARACTER", 556 | "CHARACTER_LENGTH", 557 | "CHARACTER_SET_CATALOG", 558 | "CHARACTER_SET_NAME", 559 | "CHARACTER_SET_SCHEMA", 560 | "CHARACTERISTICS", 561 | "CHARACTERS", 562 | "CHECK", 563 | "CHECKED", 564 | "CHECKPOINT", 565 | "CHECKSUM", 566 | "CLASS", 567 | "CLASS_ORIGIN", 568 | "CLOB", 569 | "CLOSE", 570 | "CLUSTER", 571 | "CLUSTERED", 572 | "COALESCE", 573 | "COBOL", 574 | "COLLATE", 575 | "COLLATION", 576 | "COLLATION_CATALOG", 577 | "COLLATION_NAME", 578 | "COLLATION_SCHEMA", 579 | "COLLECT", 580 | "COLUMN", 581 | "COLUMN_NAME", 582 | "COLUMNS", 583 | "COMMAND_FUNCTION", 584 | "COMMAND_FUNCTION_CODE", 585 | "COMMENT", 586 | "COMMIT", 587 | "COMMITTED", 588 | "COMPLETION", 589 | "COMPRESS", 590 | "COMPUTE", 591 | "CONDITION", 592 | "CONDITION_NUMBER", 593 | "CONNECT", 594 | "CONNECTION", 595 | "CONNECTION_NAME", 596 | "CONSTRAINT", 597 | "CONSTRAINT_CATALOG", 598 | "CONSTRAINT_NAME", 599 | "CONSTRAINT_SCHEMA", 600 | "CONSTRAINTS", 601 | "CONSTRUCTOR", 602 | "CONTAINS", 603 | "CONTAINSTABLE", 604 | "CONTINUE", 605 | "CONVERSION", 606 | "CONVERT", 607 | "COPY", 608 | "CORR", 609 | "CORRESPONDING", 610 | "COUNT", 611 | "COVAR_POP", 612 | "COVAR_SAMP", 613 | "CREATE", 614 | "CREATEDB", 615 | "CREATEROLE", 616 | "CREATEUSER", 617 | "CROSS", 618 | "CSV", 619 | "CUBE", 620 | "CUME_DIST", 621 | "CURRENT", 622 | "CURRENT_DATE", 623 | "CURRENT_DEFAULT_TRANSFORM_GROUP", 624 | "CURRENT_PATH", 625 | "CURRENT_ROLE", 626 | "CURRENT_TIME", 627 | "CURRENT_TIMESTAMP", 628 | "CURRENT_TRANSFORM_GROUP_FOR_TYPE", 629 | "CURRENT_USER", 630 | "CURSOR", 631 | "CURSOR_NAME", 632 | "CYCLE", 633 | "DATA", 634 | "DATABASE", 635 | "DATABASES", 636 | "DATE", 637 | "DATETIME", 638 | "DATETIME_INTERVAL_CODE", 639 | "DATETIME_INTERVAL_PRECISION", 640 | "DAY", 641 | "DAY_HOUR", 642 | "DAY_MICROSECOND", 643 | "DAY_MINUTE", 644 | "DAY_SECOND", 645 | "DAYOFMONTH", 646 | "DAYOFWEEK", 647 | "DAYOFYEAR", 648 | "DBCC", 649 | "DEALLOCATE", 650 | "DEC", 651 | "DECIMAL", 652 | "DECLARE", 653 | "DEFAULT", 654 | "DEFAULTS", 655 | "DEFERRABLE", 656 | "DEFERRED", 657 | "DEFINED", 658 | "DEFINER", 659 | "DEGREE", 660 | "DELAY_KEY_WRITE", 661 | "DELAYED", 662 | "DELETE", 663 | "DELIMITER", 664 | "DELIMITERS", 665 | "DENSE_RANK", 666 | "DENY", 667 | "DEPTH", 668 | "DEREF", 669 | "DERIVED", 670 | "DESC", 671 | "DESCRIBE", 672 | "DESCRIPTOR", 673 | "DESTROY", 674 | "DESTRUCTOR", 675 | "DETERMINISTIC", 676 | "DIAGNOSTICS", 677 | "DICTIONARY", 678 | "DISABLE", 679 | "DISCONNECT", 680 | "DISK", 681 | "DISPATCH", 682 | "DISTINCT", 683 | "DISTINCTROW", 684 | "DISTRIBUTED", 685 | "DIV", 686 | "DO", 687 | "DOMAIN", 688 | "DOUBLE", 689 | "DROP", 690 | "DUAL", 691 | "DUMMY", 692 | "DUMP", 693 | "DYNAMIC", 694 | "DYNAMIC_FUNCTION", 695 | "DYNAMIC_FUNCTION_CODE", 696 | "EACH", 697 | "ELEMENT", 698 | "ELSE", 699 | "ELSEIF", 700 | "ENABLE", 701 | "ENCLOSED", 702 | "ENCODING", 703 | "ENCRYPTED", 704 | "END", 705 | "END-EXEC", 706 | "ENUM", 707 | "EQUALS", 708 | "ERRLVL", 709 | "ESCAPE", 710 | "ESCAPED", 711 | "EVERY", 712 | "EXCEPT", 713 | "EXCEPTION", 714 | "EXCLUDE", 715 | "EXCLUDING", 716 | "EXCLUSIVE", 717 | "EXEC", 718 | "EXECUTE", 719 | "EXISTING", 720 | "EXISTS", 721 | "EXIT", 722 | "EXP", 723 | "EXPLAIN", 724 | "EXTERNAL", 725 | "EXTRACT", 726 | "FALSE", 727 | "FETCH", 728 | "FIELDS", 729 | "FILE", 730 | "FILLFACTOR", 731 | "FILTER", 732 | "FINAL", 733 | "FIRST", 734 | "FLOAT", 735 | "FLOAT4", 736 | "FLOAT8", 737 | "FLOOR", 738 | "FLUSH", 739 | "FOLLOWING", 740 | "FOR", 741 | "FORCE", 742 | "FOREIGN", 743 | "FORTRAN", 744 | "FORWARD", 745 | "FOUND", 746 | "FREE", 747 | "FREETEXT", 748 | "FREETEXTTABLE", 749 | "FREEZE", 750 | "FROM", 751 | "FULL", 752 | "FULLTEXT", 753 | "FUNCTION", 754 | "FUSION", 755 | "G", 756 | "GENERAL", 757 | "GENERATED", 758 | "GET", 759 | "GLOBAL", 760 | "GO", 761 | "GOTO", 762 | "GRANT", 763 | "GRANTED", 764 | "GRANTS", 765 | "GREATEST", 766 | "GROUP", 767 | "GROUPING", 768 | "HANDLER", 769 | "HAVING", 770 | "HEADER", 771 | "HEAP", 772 | "HIERARCHY", 773 | "HIGH_PRIORITY", 774 | "HOLD", 775 | "HOLDLOCK", 776 | "HOST", 777 | "HOSTS", 778 | "HOUR", 779 | "HOUR_MICROSECOND", 780 | "HOUR_MINUTE", 781 | "HOUR_SECOND", 782 | "IDENTIFIED", 783 | "IDENTITY", 784 | "IDENTITY_INSERT", 785 | "IDENTITYCOL", 786 | "IF", 787 | "IGNORE", 788 | "ILIKE", 789 | "IMMEDIATE", 790 | "IMMUTABLE", 791 | "IMPLEMENTATION", 792 | "IMPLICIT", 793 | "IN", 794 | "INCLUDE", 795 | "INCLUDING", 796 | "INCREMENT", 797 | "INDEX", 798 | "INDICATOR", 799 | "INFILE", 800 | "INFIX", 801 | "INHERIT", 802 | "INHERITS", 803 | "INITIAL", 804 | "INITIALIZE", 805 | "INITIALLY", 806 | "INNER", 807 | "INOUT", 808 | "INPUT", 809 | "INSENSITIVE", 810 | "INSERT", 811 | "INSERT_ID", 812 | "INSTANCE", 813 | "INSTANTIABLE", 814 | "INSTEAD", 815 | "INT", 816 | "INT1", 817 | "INT2", 818 | "INT3", 819 | "INT4", 820 | "INT8", 821 | "INTEGER", 822 | "INTERSECT", 823 | "INTERSECTION", 824 | "INTERVAL", 825 | "INTO", 826 | "INVOKER", 827 | "IS", 828 | "ISAM", 829 | "ISNULL", 830 | "ISOLATION", 831 | "ITERATE", 832 | "JOIN", 833 | "K", 834 | "KEY", 835 | "KEY_MEMBER", 836 | "KEY_TYPE", 837 | "KEYS", 838 | "KILL", 839 | "LANCOMPILER", 840 | "LANGUAGE", 841 | "LARGE", 842 | "LAST", 843 | "LAST_INSERT_ID", 844 | "LATERAL", 845 | "LEAD", 846 | "LEADING", 847 | "LEAST", 848 | "LEAVE", 849 | "LEFT", 850 | "LENGTH", 851 | "LESS", 852 | "LEVEL", 853 | "LIKE", 854 | "LIMIT", 855 | "LINENO", 856 | "LINES", 857 | "LISTEN", 858 | "LN", 859 | "LOAD", 860 | "LOCAL", 861 | "LOCALTIME", 862 | "LOCALTIMESTAMP", 863 | "LOCATION", 864 | "LOCATOR", 865 | "LOCK", 866 | "LOGIN", 867 | "LOGS", 868 | "LONG", 869 | "LONGBLOB", 870 | "LONGTEXT", 871 | "LOOP", 872 | "LOW_PRIORITY", 873 | "LOWER", 874 | "M", 875 | "MAP", 876 | "MATCH", 877 | "MATCHED", 878 | "MAX", 879 | "MAX_ROWS", 880 | "MAXEXTENTS", 881 | "MAXVALUE", 882 | "MEDIUMBLOB", 883 | "MEDIUMINT", 884 | "MEDIUMTEXT", 885 | "MEMBER", 886 | "MERGE", 887 | "MESSAGE_LENGTH", 888 | "MESSAGE_OCTET_LENGTH", 889 | "MESSAGE_TEXT", 890 | "METHOD", 891 | "MIDDLEINT", 892 | "MIN", 893 | "MIN_ROWS", 894 | "MINUS", 895 | "MINUTE", 896 | "MINUTE_MICROSECOND", 897 | "MINUTE_SECOND", 898 | "MINVALUE", 899 | "MLSLABEL", 900 | "MOD", 901 | "MODE", 902 | "MODIFIES", 903 | "MODIFY", 904 | "MODULE", 905 | "MONTH", 906 | "MONTHNAME", 907 | "MORE", 908 | "MOVE", 909 | "MULTISET", 910 | "MUMPS", 911 | "MYISAM", 912 | "NAME", 913 | "NAMES", 914 | "NATIONAL", 915 | "NATURAL", 916 | "NCHAR", 917 | "NCLOB", 918 | "NESTING", 919 | "NEW", 920 | "NEXT", 921 | "NO", 922 | "NO_WRITE_TO_BINLOG", 923 | "NOAUDIT", 924 | "NOCHECK", 925 | "NOCOMPRESS", 926 | "NOCREATEDB", 927 | "NOCREATEROLE", 928 | "NOCREATEUSER", 929 | "NOINHERIT", 930 | "NOLOGIN", 931 | "NONCLUSTERED", 932 | "NONE", 933 | "NORMALIZE", 934 | "NORMALIZED", 935 | "NOSUPERUSER", 936 | "NOT", 937 | "NOTHING", 938 | "NOTIFY", 939 | "NOTNULL", 940 | "NOWAIT", 941 | "NULL", 942 | "NULLABLE", 943 | "NULLIF", 944 | "NULLS", 945 | "NUMBER", 946 | "NUMERIC", 947 | "OBJECT", 948 | "OCTET_LENGTH", 949 | "OCTETS", 950 | "OF", 951 | "OFF", 952 | "OFFLINE", 953 | "OFFSET", 954 | "OFFSETS", 955 | "OIDS", 956 | "OLD", 957 | "ON", 958 | "ONLINE", 959 | "ONLY", 960 | "OPEN", 961 | "OPENDATASOURCE", 962 | "OPENQUERY", 963 | "OPENROWSET", 964 | "OPENXML", 965 | "OPERATION", 966 | "OPERATOR", 967 | "OPTIMIZE", 968 | "OPTION", 969 | "OPTIONALLY", 970 | "OPTIONS", 971 | "OR", 972 | "ORDER", 973 | "ORDERING", 974 | "ORDINALITY", 975 | "OTHERS", 976 | "OUT", 977 | "OUTER", 978 | "OUTFILE", 979 | "OUTPUT", 980 | "OVER", 981 | "OVERLAPS", 982 | "OVERLAY", 983 | "OVERRIDING", 984 | "OWNER", 985 | "PACK_KEYS", 986 | "PAD", 987 | "PARAMETER", 988 | "PARAMETER_MODE", 989 | "PARAMETER_NAME", 990 | "PARAMETER_ORDINAL_POSITION", 991 | "PARAMETER_SPECIFIC_CATALOG", 992 | "PARAMETER_SPECIFIC_NAME", 993 | "PARAMETER_SPECIFIC_SCHEMA", 994 | "PARAMETERS", 995 | "PARTIAL", 996 | "PARTITION", 997 | "PASCAL", 998 | "PASSWORD", 999 | "PATH", 1000 | "PCTFREE", 1001 | "PERCENT", 1002 | "PERCENT_RANK", 1003 | "PERCENTILE_CONT", 1004 | "PERCENTILE_DISC", 1005 | "PLACING", 1006 | "PLAN", 1007 | "PLI", 1008 | "POSITION", 1009 | "POSTFIX", 1010 | "POWER", 1011 | "PRECEDING", 1012 | "PRECISION", 1013 | "PREFIX", 1014 | "PREORDER", 1015 | "PREPARE", 1016 | "PREPARED", 1017 | "PRESERVE", 1018 | "PRIMARY", 1019 | "PRINT", 1020 | "PRIOR", 1021 | "PRIVILEGES", 1022 | "PROC", 1023 | "PROCEDURAL", 1024 | "PROCEDURE", 1025 | "PROCESS", 1026 | "PROCESSLIST", 1027 | "PUBLIC", 1028 | "PURGE", 1029 | "QUOTE", 1030 | "RAID0", 1031 | "RAISERROR", 1032 | "RANGE", 1033 | "RANK", 1034 | "RAW", 1035 | "READ", 1036 | "READS", 1037 | "READTEXT", 1038 | "REAL", 1039 | "RECHECK", 1040 | "RECONFIGURE", 1041 | "RECURSIVE", 1042 | "REF", 1043 | "REFERENCES", 1044 | "REFERENCING", 1045 | "REGEXP", 1046 | "REGR_AVGX", 1047 | "REGR_AVGY", 1048 | "REGR_COUNT", 1049 | "REGR_INTERCEPT", 1050 | "REGR_R2", 1051 | "REGR_SLOPE", 1052 | "REGR_SXX", 1053 | "REGR_SXY", 1054 | "REGR_SYY", 1055 | "REINDEX", 1056 | "RELATIVE", 1057 | "RELEASE", 1058 | "RELOAD", 1059 | "RENAME", 1060 | "REPEAT", 1061 | "REPEATABLE", 1062 | "REPLACE", 1063 | "REPLICATION", 1064 | "REQUIRE", 1065 | "RESET", 1066 | "RESIGNAL", 1067 | "RESOURCE", 1068 | "RESTART", 1069 | "RESTORE", 1070 | "RESTRICT", 1071 | "RESULT", 1072 | "RETURN", 1073 | "RETURNED_CARDINALITY", 1074 | "RETURNED_LENGTH", 1075 | "RETURNED_OCTET_LENGTH", 1076 | "RETURNED_SQLSTATE", 1077 | "RETURNS", 1078 | "REVOKE", 1079 | "RIGHT", 1080 | "RLIKE", 1081 | "ROLE", 1082 | "ROLLBACK", 1083 | "ROLLUP", 1084 | "ROUTINE", 1085 | "ROUTINE_CATALOG", 1086 | "ROUTINE_NAME", 1087 | "ROUTINE_SCHEMA", 1088 | "ROW", 1089 | "ROW_COUNT", 1090 | "ROW_NUMBER", 1091 | "ROWCOUNT", 1092 | "ROWGUIDCOL", 1093 | "ROWID", 1094 | "ROWNUM", 1095 | "ROWS", 1096 | "RULE", 1097 | "SAVE", 1098 | "SAVEPOINT", 1099 | "SCALE", 1100 | "SCHEMA", 1101 | "SCHEMA_NAME", 1102 | "SCHEMAS", 1103 | "SCOPE", 1104 | "SCOPE_CATALOG", 1105 | "SCOPE_NAME", 1106 | "SCOPE_SCHEMA", 1107 | "SCROLL", 1108 | "SEARCH", 1109 | "SECOND", 1110 | "SECOND_MICROSECOND", 1111 | "SECTION", 1112 | "SECURITY", 1113 | "SELECT", 1114 | "SELF", 1115 | "SENSITIVE", 1116 | "SEPARATOR", 1117 | "SEQUENCE", 1118 | "SERIALIZABLE", 1119 | "SERVER_NAME", 1120 | "SESSION", 1121 | "SESSION_USER", 1122 | "SET", 1123 | "SETOF", 1124 | "SETS", 1125 | "SETUSER", 1126 | "SHARE", 1127 | "SHOW", 1128 | "SHUTDOWN", 1129 | "SIGNAL", 1130 | "SIMILAR", 1131 | "SIMPLE", 1132 | "SIZE", 1133 | "SMALLINT", 1134 | "SOME", 1135 | "SONAME", 1136 | "SOURCE", 1137 | "SPACE", 1138 | "SPATIAL", 1139 | "SPECIFIC", 1140 | "SPECIFIC_NAME", 1141 | "SPECIFICTYPE", 1142 | "SQL", 1143 | "SQL_BIG_RESULT", 1144 | "SQL_BIG_SELECTS", 1145 | "SQL_BIG_TABLES", 1146 | "SQL_CALC_FOUND_ROWS", 1147 | "SQL_LOG_OFF", 1148 | "SQL_LOG_UPDATE", 1149 | "SQL_LOW_PRIORITY_UPDATES", 1150 | "SQL_SELECT_LIMIT", 1151 | "SQL_SMALL_RESULT", 1152 | "SQL_WARNINGS", 1153 | "SQLCA", 1154 | "SQLCODE", 1155 | "SQLERROR", 1156 | "SQLEXCEPTION", 1157 | "SQLSTATE", 1158 | "SQLWARNING", 1159 | "SQRT", 1160 | "SSL", 1161 | "STABLE", 1162 | "START", 1163 | "STARTING", 1164 | "STATE", 1165 | "STATEMENT", 1166 | "STATIC", 1167 | "STATISTICS", 1168 | "STATUS", 1169 | "STDDEV_POP", 1170 | "STDDEV_SAMP", 1171 | "STDIN", 1172 | "STDOUT", 1173 | "STORAGE", 1174 | "STRAIGHT_JOIN", 1175 | "STRICT", 1176 | "STRING", 1177 | "STRUCTURE", 1178 | "STYLE", 1179 | "SUBCLASS_ORIGIN", 1180 | "SUBLIST", 1181 | "SUBMULTISET", 1182 | "SUBSTRING", 1183 | "SUCCESSFUL", 1184 | "SUM", 1185 | "SUPERUSER", 1186 | "SYMMETRIC", 1187 | "SYNONYM", 1188 | "SYSDATE", 1189 | "SYSID", 1190 | "SYSTEM", 1191 | "SYSTEM_USER", 1192 | "TABLE", 1193 | "TABLE_NAME", 1194 | "TABLES", 1195 | "TABLESAMPLE", 1196 | "TABLESPACE", 1197 | "TEMP", 1198 | "TEMPLATE", 1199 | "TEMPORARY", 1200 | "TERMINATE", 1201 | "TERMINATED", 1202 | "TEXT", 1203 | "TEXTSIZE", 1204 | "THAN", 1205 | "THEN", 1206 | "TIES", 1207 | "TIME", 1208 | "TIMESTAMP", 1209 | "TIMEZONE_HOUR", 1210 | "TIMEZONE_MINUTE", 1211 | "TINYBLOB", 1212 | "TINYINT", 1213 | "TINYTEXT", 1214 | "TO", 1215 | "TOAST", 1216 | "TOP", 1217 | "TOP_LEVEL_COUNT", 1218 | "TRAILING", 1219 | "TRAN", 1220 | "TRANSACTION", 1221 | "TRANSACTION_ACTIVE", 1222 | "TRANSACTIONS_COMMITTED", 1223 | "TRANSACTIONS_ROLLED_BACK", 1224 | "TRANSFORM", 1225 | "TRANSFORMS", 1226 | "TRANSLATE", 1227 | "TRANSLATION", 1228 | "TREAT", 1229 | "TRIGGER", 1230 | "TRIGGER_CATALOG", 1231 | "TRIGGER_NAME", 1232 | "TRIGGER_SCHEMA", 1233 | "TRIM", 1234 | "TRUE", 1235 | "TRUNCATE", 1236 | "TRUSTED", 1237 | "TSEQUAL", 1238 | "TYPE", 1239 | "UESCAPE", 1240 | "UID", 1241 | "UNBOUNDED", 1242 | "UNCOMMITTED", 1243 | "UNDER", 1244 | "UNDO", 1245 | "UNENCRYPTED", 1246 | "UNION", 1247 | "UNIQUE", 1248 | "UNKNOWN", 1249 | "UNLISTEN", 1250 | "UNLOCK", 1251 | "UNNAMED", 1252 | "UNNEST", 1253 | "UNSIGNED", 1254 | "UNTIL", 1255 | "UPDATE", 1256 | "UPDATETEXT", 1257 | "UPPER", 1258 | "USAGE", 1259 | "USE", 1260 | "USER", 1261 | "USER_DEFINED_TYPE_CATALOG", 1262 | "USER_DEFINED_TYPE_CODE", 1263 | "USER_DEFINED_TYPE_NAME", 1264 | "USER_DEFINED_TYPE_SCHEMA", 1265 | "USING", 1266 | "UTC_DATE", 1267 | "UTC_TIME", 1268 | "UTC_TIMESTAMP", 1269 | "VACUUM", 1270 | "VALID", 1271 | "VALIDATE", 1272 | "VALIDATOR", 1273 | "VALUE", 1274 | "VALUES", 1275 | "VAR_POP", 1276 | "VAR_SAMP", 1277 | "VARBINARY", 1278 | "VARCHAR", 1279 | "VARCHAR2", 1280 | "VARCHARACTER", 1281 | "VARIABLE", 1282 | "VARIABLES", 1283 | "VARYING", 1284 | "VERBOSE", 1285 | "VIEW", 1286 | "VOLATILE", 1287 | "WAITFOR", 1288 | "WHEN", 1289 | "WHENEVER", 1290 | "WHERE", 1291 | "WHILE", 1292 | "WIDTH_BUCKET", 1293 | "WINDOW", 1294 | "WITH", 1295 | "WITHIN", 1296 | "WITHOUT", 1297 | "WORK", 1298 | "WRITE", 1299 | "WRITETEXT", 1300 | "X509", 1301 | "XOR", 1302 | "YEAR", 1303 | "YEAR_MONTH", 1304 | "ZEROFILL", 1305 | "ZONE" 1306 | }; 1307 | return keywords; 1308 | } 1309 | 1310 | 1311 | } 1312 | -------------------------------------------------------------------------------- /examples/SQLite.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "%LOAD sqlite3 db=chinook.db timeout=2 shared_cache=true" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 2, 15 | "metadata": {}, 16 | "outputs": [ 17 | { 18 | "data": { 19 | "text/html": [ 20 | "\n", 21 | "\n", 22 | "\n", 23 | "\n", 24 | "\n", 25 | "\n", 26 | "\n", 27 | "\n", 28 | "\n", 29 | "\n", 30 | "\n", 31 | "\n", 32 | "\n", 33 | "\n", 34 | "\n", 35 | "\n", 36 | "\n", 37 | "\n", 38 | "\n", 39 | "\n", 40 | "\n", 41 | "\n", 42 | "\n", 43 | "\n", 44 | "\n", 45 | "\n", 46 | "\n", 47 | "\n", 48 | "\n", 49 | "\n", 50 | "\n", 51 | "\n", 52 | "\n", 53 | "\n", 54 | "\n", 55 | "\n", 56 | "\n", 57 | "\n", 58 | "\n", 59 | "\n", 60 | "\n", 61 | "\n", 62 | "\n", 63 | "\n", 64 | "\n", 65 | "\n", 66 | "\n", 67 | "\n", 68 | "\n", 69 | "\n", 70 | "\n", 71 | "\n", 72 | "\n", 73 | "\n", 74 | "\n", 75 | "\n", 76 | "\n", 77 | "\n", 78 | "\n", 79 | "\n", 80 | "\n", 81 | "\n", 82 | "\n", 83 | "\n", 84 | "\n", 85 | "\n", 86 | "\n", 87 | "
GenreIdNameMediaTypeIdName
1Rock1MPEG audio file
2Jazz1MPEG audio file
3Metal1MPEG audio file
4Alternative & Punk1MPEG audio file
5Rock And Roll1MPEG audio file
6Blues1MPEG audio file
7Latin1MPEG audio file
8Reggae1MPEG audio file
9Pop1MPEG audio file
10Soundtrack1MPEG audio file
\n", 88 | "10 rows in set (0.00 sec)" 89 | ], 90 | "text/plain": [ 91 | "+---------+--------------------+-------------+-----------------+\n", 92 | "| GenreId | Name | MediaTypeId | Name |\n", 93 | "+---------+--------------------+-------------+-----------------+\n", 94 | "| 1 | Rock | 1 | MPEG audio file |\n", 95 | "+---------+--------------------+-------------+-----------------+\n", 96 | "| 2 | Jazz | 1 | MPEG audio file |\n", 97 | "+---------+--------------------+-------------+-----------------+\n", 98 | "| 3 | Metal | 1 | MPEG audio file |\n", 99 | "+---------+--------------------+-------------+-----------------+\n", 100 | "| 4 | Alternative & Punk | 1 | MPEG audio file |\n", 101 | "+---------+--------------------+-------------+-----------------+\n", 102 | "| 5 | Rock And Roll | 1 | MPEG audio file |\n", 103 | "+---------+--------------------+-------------+-----------------+\n", 104 | "| 6 | Blues | 1 | MPEG audio file |\n", 105 | "+---------+--------------------+-------------+-----------------+\n", 106 | "| 7 | Latin | 1 | MPEG audio file |\n", 107 | "+---------+--------------------+-------------+-----------------+\n", 108 | "| 8 | Reggae | 1 | MPEG audio file |\n", 109 | "+---------+--------------------+-------------+-----------------+\n", 110 | "| 9 | Pop | 1 | MPEG audio file |\n", 111 | "+---------+--------------------+-------------+-----------------+\n", 112 | "| 10 | Soundtrack | 1 | MPEG audio file |\n", 113 | "+---------+--------------------+-------------+-----------------+\n", 114 | "10 rows in set (0.00 sec)" 115 | ] 116 | }, 117 | "execution_count": 2, 118 | "metadata": {}, 119 | "output_type": "execute_result" 120 | } 121 | ], 122 | "source": [ 123 | "SELECT * FROM genres, media_types limit 10" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": 3, 129 | "metadata": {}, 130 | "outputs": [ 131 | { 132 | "data": { 133 | "application/vnd.vegalite.v3+json": { 134 | "$schema": "https://vega.github.io/schema/vega-lite/v4.json", 135 | "config": { 136 | "axis": { 137 | "grid": true 138 | } 139 | }, 140 | "data": { 141 | "values": [ 142 | { 143 | "GenreId": "1", 144 | "MediaTypeId": "1", 145 | "Name": "Rock" 146 | }, 147 | { 148 | "GenreId": "2", 149 | "MediaTypeId": "1", 150 | "Name": "MPEG audio file" 151 | }, 152 | { 153 | "GenreId": "3", 154 | "MediaTypeId": "1", 155 | "Name": "Jazz" 156 | }, 157 | { 158 | "GenreId": "4", 159 | "MediaTypeId": "1", 160 | "Name": "MPEG audio file" 161 | }, 162 | { 163 | "GenreId": "5", 164 | "MediaTypeId": "1", 165 | "Name": "Metal" 166 | }, 167 | { 168 | "GenreId": "6", 169 | "MediaTypeId": "1", 170 | "Name": "MPEG audio file" 171 | }, 172 | { 173 | "GenreId": "7", 174 | "MediaTypeId": "1", 175 | "Name": "Alternative & Punk" 176 | }, 177 | { 178 | "GenreId": "8", 179 | "MediaTypeId": "1", 180 | "Name": "MPEG audio file" 181 | }, 182 | { 183 | "GenreId": "9", 184 | "MediaTypeId": "1", 185 | "Name": "Rock And Roll" 186 | }, 187 | { 188 | "GenreId": "10", 189 | "MediaTypeId": "1", 190 | "Name": "MPEG audio file" 191 | }, 192 | { 193 | "GenreId": "11", 194 | "MediaTypeId": "1", 195 | "Name": "Blues" 196 | }, 197 | { 198 | "GenreId": "12", 199 | "MediaTypeId": "1", 200 | "Name": "MPEG audio file" 201 | }, 202 | { 203 | "GenreId": "13", 204 | "MediaTypeId": "1", 205 | "Name": "Latin" 206 | }, 207 | { 208 | "GenreId": "14", 209 | "MediaTypeId": "1", 210 | "Name": "MPEG audio file" 211 | }, 212 | { 213 | "GenreId": "15", 214 | "MediaTypeId": "1", 215 | "Name": "Reggae" 216 | }, 217 | { 218 | "GenreId": "16", 219 | "MediaTypeId": "1", 220 | "Name": "MPEG audio file" 221 | }, 222 | { 223 | "GenreId": "17", 224 | "MediaTypeId": "1", 225 | "Name": "Pop" 226 | }, 227 | { 228 | "GenreId": "18", 229 | "MediaTypeId": "1", 230 | "Name": "MPEG audio file" 231 | }, 232 | { 233 | "GenreId": "19", 234 | "MediaTypeId": "1", 235 | "Name": "Soundtrack" 236 | }, 237 | { 238 | "GenreId": "20", 239 | "MediaTypeId": "1", 240 | "Name": "MPEG audio file" 241 | }, 242 | { 243 | "GenreId": "21", 244 | "MediaTypeId": "1", 245 | "Name": "Bossa Nova" 246 | }, 247 | { 248 | "GenreId": "22", 249 | "MediaTypeId": "1", 250 | "Name": "MPEG audio file" 251 | }, 252 | { 253 | "GenreId": "23", 254 | "MediaTypeId": "1", 255 | "Name": "Easy Listening" 256 | }, 257 | { 258 | "GenreId": "24", 259 | "MediaTypeId": "1", 260 | "Name": "MPEG audio file" 261 | }, 262 | { 263 | "GenreId": "25", 264 | "MediaTypeId": "1", 265 | "Name": "Heavy Metal" 266 | }, 267 | { 268 | "GenreId": "1", 269 | "MediaTypeId": "2", 270 | "Name": "MPEG audio file" 271 | }, 272 | { 273 | "GenreId": "2", 274 | "MediaTypeId": "2", 275 | "Name": "R&B/Soul" 276 | }, 277 | { 278 | "GenreId": "3", 279 | "MediaTypeId": "2", 280 | "Name": "MPEG audio file" 281 | }, 282 | { 283 | "GenreId": "4", 284 | "MediaTypeId": "2", 285 | "Name": "Electronica/Dance" 286 | }, 287 | { 288 | "GenreId": "5", 289 | "MediaTypeId": "2", 290 | "Name": "MPEG audio file" 291 | }, 292 | { 293 | "GenreId": "6", 294 | "MediaTypeId": "2", 295 | "Name": "World" 296 | }, 297 | { 298 | "GenreId": "7", 299 | "MediaTypeId": "2", 300 | "Name": "MPEG audio file" 301 | }, 302 | { 303 | "GenreId": "8", 304 | "MediaTypeId": "2", 305 | "Name": "Hip Hop/Rap" 306 | }, 307 | { 308 | "GenreId": "9", 309 | "MediaTypeId": "2", 310 | "Name": "MPEG audio file" 311 | }, 312 | { 313 | "GenreId": "10", 314 | "MediaTypeId": "2", 315 | "Name": "Science Fiction" 316 | }, 317 | { 318 | "GenreId": "11", 319 | "MediaTypeId": "2", 320 | "Name": "MPEG audio file" 321 | }, 322 | { 323 | "GenreId": "12", 324 | "MediaTypeId": "2", 325 | "Name": "TV Shows" 326 | }, 327 | { 328 | "GenreId": "13", 329 | "MediaTypeId": "2", 330 | "Name": "MPEG audio file" 331 | }, 332 | { 333 | "GenreId": "14", 334 | "MediaTypeId": "2", 335 | "Name": "Sci Fi & Fantasy" 336 | }, 337 | { 338 | "GenreId": "15", 339 | "MediaTypeId": "2", 340 | "Name": "MPEG audio file" 341 | }, 342 | { 343 | "GenreId": "16", 344 | "MediaTypeId": "2", 345 | "Name": "Drama" 346 | }, 347 | { 348 | "GenreId": "17", 349 | "MediaTypeId": "2", 350 | "Name": "MPEG audio file" 351 | }, 352 | { 353 | "GenreId": "18", 354 | "MediaTypeId": "2", 355 | "Name": "Comedy" 356 | }, 357 | { 358 | "GenreId": "19", 359 | "MediaTypeId": "2", 360 | "Name": "MPEG audio file" 361 | }, 362 | { 363 | "GenreId": "20", 364 | "MediaTypeId": "2", 365 | "Name": "Alternative" 366 | }, 367 | { 368 | "GenreId": "21", 369 | "MediaTypeId": "2", 370 | "Name": "MPEG audio file" 371 | }, 372 | { 373 | "GenreId": "22", 374 | "MediaTypeId": "2", 375 | "Name": "Classical" 376 | }, 377 | { 378 | "GenreId": "23", 379 | "MediaTypeId": "2", 380 | "Name": "MPEG audio file" 381 | }, 382 | { 383 | "GenreId": "24", 384 | "MediaTypeId": "2", 385 | "Name": "Opera" 386 | }, 387 | { 388 | "GenreId": "25", 389 | "MediaTypeId": "2", 390 | "Name": "MPEG audio file" 391 | }, 392 | { 393 | "GenreId": "1", 394 | "MediaTypeId": "3", 395 | "Name": "Rock" 396 | }, 397 | { 398 | "GenreId": "2", 399 | "MediaTypeId": "3", 400 | "Name": "Protected AAC audio file" 401 | }, 402 | { 403 | "GenreId": "3", 404 | "MediaTypeId": "3", 405 | "Name": "Jazz" 406 | }, 407 | { 408 | "GenreId": "4", 409 | "MediaTypeId": "3", 410 | "Name": "Protected AAC audio file" 411 | }, 412 | { 413 | "GenreId": "5", 414 | "MediaTypeId": "3", 415 | "Name": "Metal" 416 | }, 417 | { 418 | "GenreId": "6", 419 | "MediaTypeId": "3", 420 | "Name": "Protected AAC audio file" 421 | }, 422 | { 423 | "GenreId": "7", 424 | "MediaTypeId": "3", 425 | "Name": "Alternative & Punk" 426 | }, 427 | { 428 | "GenreId": "8", 429 | "MediaTypeId": "3", 430 | "Name": "Protected AAC audio file" 431 | }, 432 | { 433 | "GenreId": "9", 434 | "MediaTypeId": "3", 435 | "Name": "Rock And Roll" 436 | }, 437 | { 438 | "GenreId": "10", 439 | "MediaTypeId": "3", 440 | "Name": "Protected AAC audio file" 441 | }, 442 | { 443 | "GenreId": "11", 444 | "MediaTypeId": "3", 445 | "Name": "Blues" 446 | }, 447 | { 448 | "GenreId": "12", 449 | "MediaTypeId": "3", 450 | "Name": "Protected AAC audio file" 451 | }, 452 | { 453 | "GenreId": "13", 454 | "MediaTypeId": "3", 455 | "Name": "Latin" 456 | }, 457 | { 458 | "GenreId": "14", 459 | "MediaTypeId": "3", 460 | "Name": "Protected AAC audio file" 461 | }, 462 | { 463 | "GenreId": "15", 464 | "MediaTypeId": "3", 465 | "Name": "Reggae" 466 | }, 467 | { 468 | "GenreId": "16", 469 | "MediaTypeId": "3", 470 | "Name": "Protected AAC audio file" 471 | }, 472 | { 473 | "GenreId": "17", 474 | "MediaTypeId": "3", 475 | "Name": "Pop" 476 | }, 477 | { 478 | "GenreId": "18", 479 | "MediaTypeId": "3", 480 | "Name": "Protected AAC audio file" 481 | }, 482 | { 483 | "GenreId": "19", 484 | "MediaTypeId": "3", 485 | "Name": "Soundtrack" 486 | }, 487 | { 488 | "GenreId": "20", 489 | "MediaTypeId": "3", 490 | "Name": "Protected AAC audio file" 491 | }, 492 | { 493 | "GenreId": "21", 494 | "MediaTypeId": "3", 495 | "Name": "Bossa Nova" 496 | }, 497 | { 498 | "GenreId": "22", 499 | "MediaTypeId": "3", 500 | "Name": "Protected AAC audio file" 501 | }, 502 | { 503 | "GenreId": "23", 504 | "MediaTypeId": "3", 505 | "Name": "Easy Listening" 506 | }, 507 | { 508 | "GenreId": "24", 509 | "MediaTypeId": "3", 510 | "Name": "Protected AAC audio file" 511 | }, 512 | { 513 | "GenreId": "25", 514 | "MediaTypeId": "3", 515 | "Name": "Heavy Metal" 516 | }, 517 | { 518 | "GenreId": "1", 519 | "MediaTypeId": "4", 520 | "Name": "Protected AAC audio file" 521 | }, 522 | { 523 | "GenreId": "2", 524 | "MediaTypeId": "4", 525 | "Name": "R&B/Soul" 526 | }, 527 | { 528 | "GenreId": "3", 529 | "MediaTypeId": "4", 530 | "Name": "Protected AAC audio file" 531 | }, 532 | { 533 | "GenreId": "4", 534 | "MediaTypeId": "4", 535 | "Name": "Electronica/Dance" 536 | }, 537 | { 538 | "GenreId": "5", 539 | "MediaTypeId": "4", 540 | "Name": "Protected AAC audio file" 541 | }, 542 | { 543 | "GenreId": "6", 544 | "MediaTypeId": "4", 545 | "Name": "World" 546 | }, 547 | { 548 | "GenreId": "7", 549 | "MediaTypeId": "4", 550 | "Name": "Protected AAC audio file" 551 | }, 552 | { 553 | "GenreId": "8", 554 | "MediaTypeId": "4", 555 | "Name": "Hip Hop/Rap" 556 | }, 557 | { 558 | "GenreId": "9", 559 | "MediaTypeId": "4", 560 | "Name": "Protected AAC audio file" 561 | }, 562 | { 563 | "GenreId": "10", 564 | "MediaTypeId": "4", 565 | "Name": "Science Fiction" 566 | }, 567 | { 568 | "GenreId": "11", 569 | "MediaTypeId": "4", 570 | "Name": "Protected AAC audio file" 571 | }, 572 | { 573 | "GenreId": "12", 574 | "MediaTypeId": "4", 575 | "Name": "TV Shows" 576 | }, 577 | { 578 | "GenreId": "13", 579 | "MediaTypeId": "4", 580 | "Name": "Protected AAC audio file" 581 | }, 582 | { 583 | "GenreId": "14", 584 | "MediaTypeId": "4", 585 | "Name": "Sci Fi & Fantasy" 586 | }, 587 | { 588 | "GenreId": "15", 589 | "MediaTypeId": "4", 590 | "Name": "Protected AAC audio file" 591 | }, 592 | { 593 | "GenreId": "16", 594 | "MediaTypeId": "4", 595 | "Name": "Drama" 596 | }, 597 | { 598 | "GenreId": "17", 599 | "MediaTypeId": "4", 600 | "Name": "Protected AAC audio file" 601 | }, 602 | { 603 | "GenreId": "18", 604 | "MediaTypeId": "4", 605 | "Name": "Comedy" 606 | }, 607 | { 608 | "GenreId": "19", 609 | "MediaTypeId": "4", 610 | "Name": "Protected AAC audio file" 611 | }, 612 | { 613 | "GenreId": "20", 614 | "MediaTypeId": "4", 615 | "Name": "Alternative" 616 | }, 617 | { 618 | "GenreId": "21", 619 | "MediaTypeId": "4", 620 | "Name": "Protected AAC audio file" 621 | }, 622 | { 623 | "GenreId": "22", 624 | "MediaTypeId": "4", 625 | "Name": "Classical" 626 | }, 627 | { 628 | "GenreId": "23", 629 | "MediaTypeId": "4", 630 | "Name": "Protected AAC audio file" 631 | }, 632 | { 633 | "GenreId": "24", 634 | "MediaTypeId": "4", 635 | "Name": "Opera" 636 | }, 637 | { 638 | "GenreId": "25", 639 | "MediaTypeId": "4", 640 | "Name": "Protected AAC audio file" 641 | }, 642 | { 643 | "GenreId": "1", 644 | "MediaTypeId": "5", 645 | "Name": "Rock" 646 | }, 647 | { 648 | "GenreId": "2", 649 | "MediaTypeId": "5", 650 | "Name": "Protected MPEG-4 video file" 651 | }, 652 | { 653 | "GenreId": "3", 654 | "MediaTypeId": "5", 655 | "Name": "Jazz" 656 | }, 657 | { 658 | "GenreId": "4", 659 | "MediaTypeId": "5", 660 | "Name": "Protected MPEG-4 video file" 661 | }, 662 | { 663 | "GenreId": "5", 664 | "MediaTypeId": "5", 665 | "Name": "Metal" 666 | }, 667 | { 668 | "GenreId": "6", 669 | "MediaTypeId": "5", 670 | "Name": "Protected MPEG-4 video file" 671 | }, 672 | { 673 | "GenreId": "7", 674 | "MediaTypeId": "5", 675 | "Name": "Alternative & Punk" 676 | }, 677 | { 678 | "GenreId": "8", 679 | "MediaTypeId": "5", 680 | "Name": "Protected MPEG-4 video file" 681 | }, 682 | { 683 | "GenreId": "9", 684 | "MediaTypeId": "5", 685 | "Name": "Rock And Roll" 686 | }, 687 | { 688 | "GenreId": "10", 689 | "MediaTypeId": "5", 690 | "Name": "Protected MPEG-4 video file" 691 | }, 692 | { 693 | "GenreId": "11", 694 | "MediaTypeId": "5", 695 | "Name": "Blues" 696 | }, 697 | { 698 | "GenreId": "12", 699 | "MediaTypeId": "5", 700 | "Name": "Protected MPEG-4 video file" 701 | }, 702 | { 703 | "GenreId": "13", 704 | "MediaTypeId": "5", 705 | "Name": "Latin" 706 | }, 707 | { 708 | "GenreId": "14", 709 | "MediaTypeId": "5", 710 | "Name": "Protected MPEG-4 video file" 711 | }, 712 | { 713 | "GenreId": "15", 714 | "MediaTypeId": "5", 715 | "Name": "Reggae" 716 | }, 717 | { 718 | "GenreId": "16", 719 | "MediaTypeId": "5", 720 | "Name": "Protected MPEG-4 video file" 721 | }, 722 | { 723 | "GenreId": "17", 724 | "MediaTypeId": "5", 725 | "Name": "Pop" 726 | }, 727 | { 728 | "GenreId": "18", 729 | "MediaTypeId": "5", 730 | "Name": "Protected MPEG-4 video file" 731 | }, 732 | { 733 | "GenreId": "19", 734 | "MediaTypeId": "5", 735 | "Name": "Soundtrack" 736 | }, 737 | { 738 | "GenreId": "20", 739 | "MediaTypeId": "5", 740 | "Name": "Protected MPEG-4 video file" 741 | }, 742 | { 743 | "GenreId": "21", 744 | "MediaTypeId": "5", 745 | "Name": "Bossa Nova" 746 | }, 747 | { 748 | "GenreId": "22", 749 | "MediaTypeId": "5", 750 | "Name": "Protected MPEG-4 video file" 751 | }, 752 | { 753 | "GenreId": "23", 754 | "MediaTypeId": "5", 755 | "Name": "Easy Listening" 756 | }, 757 | { 758 | "GenreId": "24", 759 | "MediaTypeId": "5", 760 | "Name": "Protected MPEG-4 video file" 761 | }, 762 | { 763 | "GenreId": "25", 764 | "MediaTypeId": "5", 765 | "Name": "Heavy Metal" 766 | }, 767 | { 768 | "Name": "Protected MPEG-4 video file" 769 | }, 770 | { 771 | "Name": "R&B/Soul" 772 | }, 773 | { 774 | "Name": "Protected MPEG-4 video file" 775 | }, 776 | { 777 | "Name": "Electronica/Dance" 778 | }, 779 | { 780 | "Name": "Protected MPEG-4 video file" 781 | }, 782 | { 783 | "Name": "World" 784 | }, 785 | { 786 | "Name": "Protected MPEG-4 video file" 787 | }, 788 | { 789 | "Name": "Hip Hop/Rap" 790 | }, 791 | { 792 | "Name": "Protected MPEG-4 video file" 793 | }, 794 | { 795 | "Name": "Science Fiction" 796 | }, 797 | { 798 | "Name": "Protected MPEG-4 video file" 799 | }, 800 | { 801 | "Name": "TV Shows" 802 | }, 803 | { 804 | "Name": "Protected MPEG-4 video file" 805 | }, 806 | { 807 | "Name": "Sci Fi & Fantasy" 808 | }, 809 | { 810 | "Name": "Protected MPEG-4 video file" 811 | }, 812 | { 813 | "Name": "Drama" 814 | }, 815 | { 816 | "Name": "Protected MPEG-4 video file" 817 | }, 818 | { 819 | "Name": "Comedy" 820 | }, 821 | { 822 | "Name": "Protected MPEG-4 video file" 823 | }, 824 | { 825 | "Name": "Alternative" 826 | }, 827 | { 828 | "Name": "Protected MPEG-4 video file" 829 | }, 830 | { 831 | "Name": "Classical" 832 | }, 833 | { 834 | "Name": "Protected MPEG-4 video file" 835 | }, 836 | { 837 | "Name": "Opera" 838 | }, 839 | { 840 | "Name": "Protected MPEG-4 video file" 841 | }, 842 | { 843 | "Name": "Rock" 844 | }, 845 | { 846 | "Name": "Purchased AAC audio file" 847 | }, 848 | { 849 | "Name": "Jazz" 850 | }, 851 | { 852 | "Name": "Purchased AAC audio file" 853 | }, 854 | { 855 | "Name": "Metal" 856 | }, 857 | { 858 | "Name": "Purchased AAC audio file" 859 | }, 860 | { 861 | "Name": "Alternative & Punk" 862 | }, 863 | { 864 | "Name": "Purchased AAC audio file" 865 | }, 866 | { 867 | "Name": "Rock And Roll" 868 | }, 869 | { 870 | "Name": "Purchased AAC audio file" 871 | }, 872 | { 873 | "Name": "Blues" 874 | }, 875 | { 876 | "Name": "Purchased AAC audio file" 877 | }, 878 | { 879 | "Name": "Latin" 880 | }, 881 | { 882 | "Name": "Purchased AAC audio file" 883 | }, 884 | { 885 | "Name": "Reggae" 886 | }, 887 | { 888 | "Name": "Purchased AAC audio file" 889 | }, 890 | { 891 | "Name": "Pop" 892 | }, 893 | { 894 | "Name": "Purchased AAC audio file" 895 | }, 896 | { 897 | "Name": "Soundtrack" 898 | }, 899 | { 900 | "Name": "Purchased AAC audio file" 901 | }, 902 | { 903 | "Name": "Bossa Nova" 904 | }, 905 | { 906 | "Name": "Purchased AAC audio file" 907 | }, 908 | { 909 | "Name": "Easy Listening" 910 | }, 911 | { 912 | "Name": "Purchased AAC audio file" 913 | }, 914 | { 915 | "Name": "Heavy Metal" 916 | }, 917 | { 918 | "Name": "Purchased AAC audio file" 919 | }, 920 | { 921 | "Name": "R&B/Soul" 922 | }, 923 | { 924 | "Name": "Purchased AAC audio file" 925 | }, 926 | { 927 | "Name": "Electronica/Dance" 928 | }, 929 | { 930 | "Name": "Purchased AAC audio file" 931 | }, 932 | { 933 | "Name": "World" 934 | }, 935 | { 936 | "Name": "Purchased AAC audio file" 937 | }, 938 | { 939 | "Name": "Hip Hop/Rap" 940 | }, 941 | { 942 | "Name": "Purchased AAC audio file" 943 | }, 944 | { 945 | "Name": "Science Fiction" 946 | }, 947 | { 948 | "Name": "Purchased AAC audio file" 949 | }, 950 | { 951 | "Name": "TV Shows" 952 | }, 953 | { 954 | "Name": "Purchased AAC audio file" 955 | }, 956 | { 957 | "Name": "Sci Fi & Fantasy" 958 | }, 959 | { 960 | "Name": "Purchased AAC audio file" 961 | }, 962 | { 963 | "Name": "Drama" 964 | }, 965 | { 966 | "Name": "Purchased AAC audio file" 967 | }, 968 | { 969 | "Name": "Comedy" 970 | }, 971 | { 972 | "Name": "Purchased AAC audio file" 973 | }, 974 | { 975 | "Name": "Alternative" 976 | }, 977 | { 978 | "Name": "Purchased AAC audio file" 979 | }, 980 | { 981 | "Name": "Classical" 982 | }, 983 | { 984 | "Name": "Purchased AAC audio file" 985 | }, 986 | { 987 | "Name": "Opera" 988 | }, 989 | { 990 | "Name": "Purchased AAC audio file" 991 | }, 992 | { 993 | "Name": "Rock" 994 | }, 995 | { 996 | "Name": "AAC audio file" 997 | }, 998 | { 999 | "Name": "Jazz" 1000 | }, 1001 | { 1002 | "Name": "AAC audio file" 1003 | }, 1004 | { 1005 | "Name": "Metal" 1006 | }, 1007 | { 1008 | "Name": "AAC audio file" 1009 | }, 1010 | { 1011 | "Name": "Alternative & Punk" 1012 | }, 1013 | { 1014 | "Name": "AAC audio file" 1015 | }, 1016 | { 1017 | "Name": "Rock And Roll" 1018 | }, 1019 | { 1020 | "Name": "AAC audio file" 1021 | }, 1022 | { 1023 | "Name": "Blues" 1024 | }, 1025 | { 1026 | "Name": "AAC audio file" 1027 | }, 1028 | { 1029 | "Name": "Latin" 1030 | }, 1031 | { 1032 | "Name": "AAC audio file" 1033 | }, 1034 | { 1035 | "Name": "Reggae" 1036 | }, 1037 | { 1038 | "Name": "AAC audio file" 1039 | }, 1040 | { 1041 | "Name": "Pop" 1042 | }, 1043 | { 1044 | "Name": "AAC audio file" 1045 | }, 1046 | { 1047 | "Name": "Soundtrack" 1048 | }, 1049 | { 1050 | "Name": "AAC audio file" 1051 | }, 1052 | { 1053 | "Name": "Bossa Nova" 1054 | }, 1055 | { 1056 | "Name": "AAC audio file" 1057 | }, 1058 | { 1059 | "Name": "Easy Listening" 1060 | }, 1061 | { 1062 | "Name": "AAC audio file" 1063 | }, 1064 | { 1065 | "Name": "Heavy Metal" 1066 | }, 1067 | { 1068 | "Name": "AAC audio file" 1069 | }, 1070 | { 1071 | "Name": "R&B/Soul" 1072 | }, 1073 | { 1074 | "Name": "AAC audio file" 1075 | }, 1076 | { 1077 | "Name": "Electronica/Dance" 1078 | }, 1079 | { 1080 | "Name": "AAC audio file" 1081 | }, 1082 | { 1083 | "Name": "World" 1084 | }, 1085 | { 1086 | "Name": "AAC audio file" 1087 | }, 1088 | { 1089 | "Name": "Hip Hop/Rap" 1090 | }, 1091 | { 1092 | "Name": "AAC audio file" 1093 | }, 1094 | { 1095 | "Name": "Science Fiction" 1096 | }, 1097 | { 1098 | "Name": "AAC audio file" 1099 | }, 1100 | { 1101 | "Name": "TV Shows" 1102 | }, 1103 | { 1104 | "Name": "AAC audio file" 1105 | }, 1106 | { 1107 | "Name": "Sci Fi & Fantasy" 1108 | }, 1109 | { 1110 | "Name": "AAC audio file" 1111 | }, 1112 | { 1113 | "Name": "Drama" 1114 | }, 1115 | { 1116 | "Name": "AAC audio file" 1117 | }, 1118 | { 1119 | "Name": "Comedy" 1120 | }, 1121 | { 1122 | "Name": "AAC audio file" 1123 | }, 1124 | { 1125 | "Name": "Alternative" 1126 | }, 1127 | { 1128 | "Name": "AAC audio file" 1129 | }, 1130 | { 1131 | "Name": "Classical" 1132 | }, 1133 | { 1134 | "Name": "AAC audio file" 1135 | }, 1136 | { 1137 | "Name": "Opera" 1138 | }, 1139 | { 1140 | "Name": "AAC audio file" 1141 | } 1142 | ] 1143 | }, 1144 | "encoding": { 1145 | "x": { 1146 | "field": "GenreId", 1147 | "type": "quantitative" 1148 | }, 1149 | "y": { 1150 | "field": "MediaTypeId", 1151 | "type": "quantitative" 1152 | } 1153 | }, 1154 | "height": 300, 1155 | "mark": { 1156 | "color": "red", 1157 | "type": "area" 1158 | }, 1159 | "width": 300 1160 | }, 1161 | "image/png": "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" 1162 | }, 1163 | "execution_count": 3, 1164 | "metadata": {}, 1165 | "output_type": "execute_result" 1166 | } 1167 | ], 1168 | "source": [ 1169 | "%XVEGA_PLOT X_FIELD GenreId Y_FIELD MediaTypeId MARK area COLOR red WIDTH 300 HEIGHT 300 <> SELECT * FROM genres, media_types" 1170 | ] 1171 | }, 1172 | { 1173 | "cell_type": "code", 1174 | "execution_count": 4, 1175 | "metadata": {}, 1176 | "outputs": [ 1177 | { 1178 | "data": { 1179 | "text/html": [ 1180 | "\n", 1181 | "\n", 1182 | "\n", 1183 | "\n", 1184 | "\n", 1185 | "\n", 1186 | "\n", 1187 | "
count(*)
25
\n", 1188 | "1 row in set (0,00 sec)" 1189 | ], 1190 | "text/plain": [ 1191 | "+----------+\n", 1192 | "| count(*) |\n", 1193 | "+----------+\n", 1194 | "| 25 |\n", 1195 | "+----------+\n", 1196 | "1 row in set (0,00 sec)" 1197 | ] 1198 | }, 1199 | "execution_count": 4, 1200 | "metadata": {}, 1201 | "output_type": "execute_result" 1202 | } 1203 | ], 1204 | "source": [ 1205 | "select count(*) from genres;" 1206 | ] 1207 | }, 1208 | { 1209 | "cell_type": "code", 1210 | "execution_count": 5, 1211 | "metadata": {}, 1212 | "outputs": [ 1213 | { 1214 | "data": { 1215 | "text/html": [ 1216 | "\n", 1217 | "\n", 1218 | "\n", 1219 | "\n", 1220 | "\n", 1221 | "\n", 1222 | "\n", 1223 | "\n", 1224 | "\n", 1225 | "\n", 1226 | "\n", 1227 | "\n", 1228 | "\n", 1229 | "\n", 1230 | "\n", 1231 | "\n", 1232 | "\n", 1233 | "\n", 1234 | "\n", 1235 | "\n", 1236 | "\n", 1237 | "\n", 1238 | "\n", 1239 | "\n", 1240 | "\n", 1241 | "\n", 1242 | "\n", 1243 | "\n", 1244 | "\n", 1245 | "\n", 1246 | "\n", 1247 | "\n", 1248 | "\n", 1249 | "\n", 1250 | "\n", 1251 | "\n", 1252 | "\n", 1253 | "\n", 1254 | "\n", 1255 | "\n", 1256 | "\n", 1257 | "\n", 1258 | "\n", 1259 | "\n", 1260 | "\n", 1261 | "\n", 1262 | "\n", 1263 | "\n", 1264 | "\n", 1265 | "\n", 1266 | "\n", 1267 | "\n", 1268 | "\n", 1269 | "\n", 1270 | "\n", 1271 | "\n", 1272 | "\n", 1273 | "\n", 1274 | "\n", 1275 | "\n", 1276 | "\n", 1277 | "\n", 1278 | "\n", 1279 | "\n", 1280 | "\n", 1281 | "\n", 1282 | "\n", 1283 | "\n", 1284 | "\n", 1285 | "\n", 1286 | "\n", 1287 | "\n", 1288 | "\n", 1289 | "\n", 1290 | "\n", 1291 | "\n", 1292 | "\n", 1293 | "\n", 1294 | "\n", 1295 | "\n", 1296 | "\n", 1297 | "\n", 1298 | "\n", 1299 | "\n", 1300 | "\n", 1301 | "\n", 1302 | "\n", 1303 | "\n", 1304 | "\n", 1305 | "\n", 1306 | "\n", 1307 | "\n", 1308 | "\n", 1309 | "\n", 1310 | "\n", 1311 | "\n", 1312 | "\n", 1313 | "\n", 1314 | "\n", 1315 | "\n", 1316 | "\n", 1317 | "\n", 1318 | "\n", 1319 | "
EmployeeIdLastNameFirstNameTitleReportsToBirthDateHireDateAddressCityStateCountryPostalCodePhoneFaxEmail
1AdamsAndrewGeneral ManagerNULL1962-02-18 00:00:002002-08-14 00:00:0011120 Jasper Ave NWEdmontonABCanadaT5K 2N1+1 (780) 428-9482+1 (780) 428-3457andrew@chinookcorp.com
2EdwardsNancySales Manager11958-12-08 00:00:002002-05-01 00:00:00825 8 Ave SWCalgaryABCanadaT2P 2T3+1 (403) 262-3443+1 (403) 262-3322nancy@chinookcorp.com
3PeacockJaneSales Support Agent21973-08-29 00:00:002002-04-01 00:00:001111 6 Ave SWCalgaryABCanadaT2P 5M5+1 (403) 262-3443+1 (403) 262-6712jane@chinookcorp.com
4ParkMargaretSales Support Agent21947-09-19 00:00:002003-05-03 00:00:00683 10 Street SWCalgaryABCanadaT2P 5G3+1 (403) 263-4423+1 (403) 263-4289margaret@chinookcorp.com
5JohnsonSteveSales Support Agent21965-03-03 00:00:002003-10-17 00:00:007727B 41 AveCalgaryABCanadaT3B 1Y71 (780) 836-99871 (780) 836-9543steve@chinookcorp.com
\n", 1320 | "5 rows in set (0,00 sec)" 1321 | ], 1322 | "text/plain": [ 1323 | "+------------+----------+-----------+---------------------+-----------+---------------------+---------------------+---------------------+----------+-------+---------+------------+-------------------+-------------------+--------------------------+\n", 1324 | "| EmployeeId | LastName | FirstName | Title | ReportsTo | BirthDate | HireDate | Address | City | State | Country | PostalCode | Phone | Fax | Email |\n", 1325 | "+------------+----------+-----------+---------------------+-----------+---------------------+---------------------+---------------------+----------+-------+---------+------------+-------------------+-------------------+--------------------------+\n", 1326 | "| 1 | Adams | Andrew | General Manager | NULL | 1962-02-18 00:00:00 | 2002-08-14 00:00:00 | 11120 Jasper Ave NW | Edmonton | AB | Canada | T5K 2N1 | +1 (780) 428-9482 | +1 (780) 428-3457 | andrew@chinookcorp.com |\n", 1327 | "+------------+----------+-----------+---------------------+-----------+---------------------+---------------------+---------------------+----------+-------+---------+------------+-------------------+-------------------+--------------------------+\n", 1328 | "| 2 | Edwards | Nancy | Sales Manager | 1 | 1958-12-08 00:00:00 | 2002-05-01 00:00:00 | 825 8 Ave SW | Calgary | AB | Canada | T2P 2T3 | +1 (403) 262-3443 | +1 (403) 262-3322 | nancy@chinookcorp.com |\n", 1329 | "+------------+----------+-----------+---------------------+-----------+---------------------+---------------------+---------------------+----------+-------+---------+------------+-------------------+-------------------+--------------------------+\n", 1330 | "| 3 | Peacock | Jane | Sales Support Agent | 2 | 1973-08-29 00:00:00 | 2002-04-01 00:00:00 | 1111 6 Ave SW | Calgary | AB | Canada | T2P 5M5 | +1 (403) 262-3443 | +1 (403) 262-6712 | jane@chinookcorp.com |\n", 1331 | "+------------+----------+-----------+---------------------+-----------+---------------------+---------------------+---------------------+----------+-------+---------+------------+-------------------+-------------------+--------------------------+\n", 1332 | "| 4 | Park | Margaret | Sales Support Agent | 2 | 1947-09-19 00:00:00 | 2003-05-03 00:00:00 | 683 10 Street SW | Calgary | AB | Canada | T2P 5G3 | +1 (403) 263-4423 | +1 (403) 263-4289 | margaret@chinookcorp.com |\n", 1333 | "+------------+----------+-----------+---------------------+-----------+---------------------+---------------------+---------------------+----------+-------+---------+------------+-------------------+-------------------+--------------------------+\n", 1334 | "| 5 | Johnson | Steve | Sales Support Agent | 2 | 1965-03-03 00:00:00 | 2003-10-17 00:00:00 | 7727B 41 Ave | Calgary | AB | Canada | T3B 1Y7 | 1 (780) 836-9987 | 1 (780) 836-9543 | steve@chinookcorp.com |\n", 1335 | "+------------+----------+-----------+---------------------+-----------+---------------------+---------------------+---------------------+----------+-------+---------+------------+-------------------+-------------------+--------------------------+\n", 1336 | "5 rows in set (0,00 sec)" 1337 | ] 1338 | }, 1339 | "execution_count": 5, 1340 | "metadata": {}, 1341 | "output_type": "execute_result" 1342 | } 1343 | ], 1344 | "source": [ 1345 | "select * from employees LIMIT 5;" 1346 | ] 1347 | } 1348 | ], 1349 | "metadata": { 1350 | "kernelspec": { 1351 | "display_name": "xsql", 1352 | "language": "sqlite", 1353 | "name": "xsql" 1354 | }, 1355 | "language_info": { 1356 | "codemirror_mode": "sql", 1357 | "file_extension": "", 1358 | "mimetype": "", 1359 | "name": "mysql", 1360 | "version": "0.1.2" 1361 | } 1362 | }, 1363 | "nbformat": 4, 1364 | "nbformat_minor": 4 1365 | } 1366 | --------------------------------------------------------------------------------