import * as moment from 'moment-timezone' ; import { Timezone } from 'chronoshift' ; import { Dataset , PlyType } from "plywood" ; import * as mysql from 'vogievetsky-mysql2' ; const TYPES = require ( 'vogievetsky-mysql2/lib/constants/types' ) ; const CHARSETS = require ( 'vogievetsky-mysql2/lib/constants/charsets' ) ; const CLIENT = require ( 'vogievetsky-mysql2/lib/constants/client' ) ; const capabilityFlags = 0 | CLIENT [ 'LONG_PASSWORD' ] | CLIENT [ 'FOUND_ROWS' ] | CLIENT [ 'LONG_FLAG' ] | CLIENT [ 'CONNECT_WITH_DB' ] | CLIENT [ 'NO_SCHEMA' ] | CLIENT [ 'ODBC' ] | CLIENT [ 'LOCAL_FILES' ] | CLIENT [ 'IGNORE_SPACE' ] | CLIENT [ 'PROTOCOL_41' ] | CLIENT [ 'INTERACTIVE' ] | CLIENT [ 'IGNORE_SIGPIPE' ] | CLIENT [ 'TRANSACTIONS' ] | CLIENT [ 'RESERVED' ] | CLIENT [ 'SECURE_CONNECTION' ] | CLIENT [ 'PLUGIN_AUTH' ] | CLIENT [ 'SSL_VERIFY_SERVER_CERT' ] ; export function dateToSQL ( d , timezone ) { return moment . tz ( d , timezone . toString ( ) ) . format ( 'YYYY-MM-DD HH:mm:ss' ) ; } export function plywoodTypeToMySQL ( type ) { switch ( type ) { case 'NULL' : return TYPES [ 'VAR_STRING' ] ; case 'BOOLEAN' : return TYPES [ 'TINY' ] ; case 'STRING' : case 'SET/STRING' : return TYPES [ 'VAR_STRING' ] ; case 'NUMBER' : return TYPES [ 'DOUBLE' ] ; case 'NUMBER_RANGE' : return TYPES [ 'DOUBLE' ] ; case 'TIME' : return TYPES [ 'TIMESTAMP' ] ; case 'TIME_RANGE' : return TYPES [ 'TIMESTAMP' ] ; default : throw new Error ( `unsupported type ${ type }` ) ; } } export function columnToMySQL ( column , table ) { table = table || '' ; return { catalog : 'def' , schema : '' , name : column . name , orgName : column . name , table : table , orgTable : table , characterSet : CHARSETS [ 'UTF8MB4_UNICODE_CI' ] , columnLength : 500 , columnType : plywoodTypeToMySQL ( column . type ) , flags : 32896 , decimals : 0 } ; } export interface MySQLParameters { sql : string ; connectionId : number ; } export interface MySQLQueryProcessor { ( parameters , conn ) : void ; } export function createMySQLGateway ( port , queryProcessor ) { let server = mysql . createServer ( ) ; server . listen ( port ) ; console . log ( `MySQL Gateway listening on port: ${ port }` ) ; console . log ( `you can connect to it using \`mysql --host=127.0.0.1 --port=${ port }\`` ) ; let connectionId = 0 ; server . on ( 'connection' , function ( conn ) { connectionId ++ ; console . log ( `New connection ${ connectionId }` ) ; conn . serverHandshake ( { protocolVersion : 10 , serverVersion : '5.7.11' , connectionId , statusFlags : 2 , characterSet : CHARSETS [ 'UTF8MB4_UNICODE_CI' ] , capabilityFlags } ) ; conn . on ( 'query' , ( sql ) => { console . log ( `[${ connectionId }] Got SQL: ${ sql }` ) ; queryProcessor ( { sql , connectionId } , conn ) ; } ) ; conn . on ( 'error' , ( err ) => { console . log ( `[${ connectionId }] Error: ${ err . message }` ) ; } ) ; } ) ; } export function fallbackMySQLFactory ( connectionUri ) { let remote = mysql . createConnection ( connectionUri ) ; remote . query ( 'select 1 as one' , ( err , res ) => { if ( err ) { console . log ( 'Connection to real MySQL fail' ) ; process . exit ( 1 ) ; } else { console . log ( 'Connection to real MySQL success' ) ; } } ) ; return function ( sql , conn ) { remote . query ( sql , function ( err , rows , columns ) { if ( err ) { console . log ( 'GOT ERROR' , ( err as any ) . code , err . message ) ; conn . writeError ( { code : 1149 , message : 'Bad query' } ) ; return ; } if ( ! Array . isArray ( rows ) ) { console . log ( 'other result' , rows ) ; conn . writeOk ( rows ) ; return ; } console . log ( 'columns' , columns . map ( ( d ) => `${ d . name }(${ d . columnType })` ) ) ; console . log ( 'columns' , columns ) ; let n = Math . min ( 5 , rows . length ) ; for ( let i = 0 ; i < n ; i ++ ) { console . log ( rows [ i ] ) ; } if ( n < rows . length ) { console . log ( '... ' + String ( rows . length - n ) ) ; } conn . writeTextResult ( rows , columns ) ; } ) ; } ; }