Skip to content

Instantly share code, notes, and snippets.

@gaperton
Last active May 31, 2019 05:43
Show Gist options
  • Save gaperton/3944b8bd8e6e2cdb42f397b012dd8308 to your computer and use it in GitHub Desktop.
Save gaperton/3944b8bd8e6e2cdb42f397b012dd8308 to your computer and use it in GitHub Desktop.
class Statement {
constructor( state ){
this.state = state || [];
}
toString(){
return this.state
.map( part => part.toString() )
.join( '\n' );
}
}
function statement( parts ){
const partNames = Object.keys( parts ),
constructors = Object.values( parts );
class TheStatement extends Statement {}
partNames.forEach( ( name, i ) => {
TheStatement.prototype[ name ] = function( ...args ){
const state = this.state.slice(),
part = state[ i ] || ( state[ i ] = new constructors[ i ]() );
state[ i ] = part.append( args );
return new TheStatement( state );
}
});
return ( ...args ) => {
const statement = new TheStatement();
return statement[ partNames[ 0 ]]( args );
};
}
class Concatenator {
constructor( state ){
this.state = state || [];
}
append( args ){
return new this.constructor( [ ...this.state, ...args ] );
}
}
function all( prefix, separator, map = x => String( x ) ){
return class extends Concatenator {
toString(){
return `${prefix} ${this.state.map( map ).join( ' ' + separator + ' ')}`
}
}
}
function last( name ){
return class extends Concatenator {
toString(){
return name + ' ' + this.state[ this.state.length - 1 ];
}
}
}
/* This code above doesn't make any sense, isn't it?
Now, watch: */
const select = statement({
select : all( 'SELECT', ',' ),
from : all( 'FROM', ',', x => (
typeof x === 'string' ? x :
'(\n' + x.toString( ) + '\n)'
)),
where : all( 'WHERE', 'AND', x => `(${x})` ),
groupBy : all( 'GROUP BY', ',' ),
orderBy : all( 'ORDER BY', ',' ),
limit : last( 'LIMIT' ),
offset : last( 'OFFSET' )
})
const a = select( 'name', 'address' )
.from( 'users', 'addresses' )
.where( 'users.id = addresses.user_id');
const b = a.from( select( 'name as country').from( 'countries') )
.where( 'users.active = TRUE' );
console.log(
a.toString()
);
console.log(
b.toString()
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment