Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Postgres - Interface #421

Open
wants to merge 57 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
b663b42
initial changes that allow the creation of a new interface (psql)
flurfis Aug 9, 2022
a9d6f41
1.)deletes a HttpRestServer interface correctly -- 2.) It is now poss…
flurfis Aug 16, 2022
e258b1d
working version for a simple connection (using assumeMinServerVersion…
flurfis Aug 25, 2022
18075ca
not yet able to handle queries, but set up to start doing so, expande…
flurfis Sep 14, 2022
5485082
(forgot to add) not working vs of psql interface, pushing because of …
flurfis Sep 22, 2022
3b16782
now it works again as far as implemented should (still not works as a…
flurfis Sep 22, 2022
345004f
data from Polypheny is handled, and ready to be sent to the client, b…
flurfis Sep 28, 2022
4f42c13
answer should now be sent correctly (it is not, but want to commit be…
flurfis Sep 29, 2022
bfe7565
it now sends the message correctly(?), but doesnt close the connectio…
flurfis Sep 29, 2022
ce9c4c8
some code cleanup and fixes, but the client still doesn't accept the …
flurfis Oct 5, 2022
975fef0
forgot to add in the commit before (missed the deleted files)
flurfis Oct 5, 2022
0171b9b
rowDescription is now sent correctly... although I don't know why... …
flurfis Oct 5, 2022
9cabb44
client doesn't respond
flurfis Oct 7, 2022
bf22259
hardcoded, client doesn't respond for real
flurfis Oct 7, 2022
2bdcd90
new hardcoded things
flurfis Oct 7, 2022
57015af
not implemented yet, but byte analysis from wireshark
flurfis Oct 7, 2022
11683d5
crude hardcoded version of response to query. Doesn't work yet, far t…
flurfis Oct 8, 2022
47d927e
now hardcoded is exactly the same as the original in wireshark, and i…
flurfis Oct 10, 2022
040e304
initial changes that allow the creation of a new interface (psql)
flurfis Aug 9, 2022
ddcb485
1.)deletes a HttpRestServer interface correctly -- 2.) It is now poss…
flurfis Aug 16, 2022
4941f5f
working version for a simple connection (using assumeMinServerVersion…
flurfis Aug 25, 2022
aba50d0
not yet able to handle queries, but set up to start doing so, expande…
flurfis Sep 14, 2022
5f332ce
(forgot to add) not working vs of psql interface, pushing because of …
flurfis Sep 22, 2022
55d1fb1
now it works again as far as implemented should (still not works as a…
flurfis Sep 22, 2022
8a1127f
data from Polypheny is handled, and ready to be sent to the client, b…
flurfis Sep 28, 2022
a6f60b8
answer should now be sent correctly (it is not, but want to commit be…
flurfis Sep 29, 2022
8fef091
it now sends the message correctly(?), but doesnt close the connectio…
flurfis Sep 29, 2022
0d195aa
some code cleanup and fixes, but the client still doesn't accept the …
flurfis Oct 5, 2022
b67f016
forgot to add in the commit before (missed the deleted files)
flurfis Oct 5, 2022
d1f5310
rowDescription is now sent correctly... although I don't know why... …
flurfis Oct 5, 2022
1ddc632
client doesn't respond
flurfis Oct 7, 2022
505e72f
hardcoded, client doesn't respond for real
flurfis Oct 7, 2022
84fe9bf
new hardcoded things
flurfis Oct 7, 2022
a46d56c
not implemented yet, but byte analysis from wireshark
flurfis Oct 7, 2022
3000e93
crude hardcoded version of response to query. Doesn't work yet, far t…
flurfis Oct 8, 2022
96de7bc
fixed merge conflict
datomo Oct 10, 2022
c0dc2ae
seems I didn't push before and only commited (?)... working select-re…
flurfis Oct 10, 2022
09c7ff0
a byte version that works and makes somehow a bit sense (analysis in …
flurfis Oct 10, 2022
93848f1
One value single value is sent correctly!!! With no hardcodiing!! Yay!!
flurfis Oct 12, 2022
1db8cd1
select * woooorks!!!!
flurfis Oct 12, 2022
8beef66
Some code cleanup and documentation
flurfis Oct 12, 2022
c975cc3
Select, create table and insert work now. Although I am not too sure …
flurfis Oct 17, 2022
77f5b05
barebones of prepared Statements
flurfis Oct 19, 2022
028a80e
prepared message is correctly prepared to be processed by polypheny
flurfis Oct 21, 2022
03368c6
except for adding the necessary values and types to the prepared stat…
flurfis Oct 21, 2022
6d9a93d
error message arrives on client side (not perfect, but it works...)
flurfis Oct 21, 2022
0ab1692
rudimentary postgres errorHandler implemented. (sends one type of err…
flurfis Oct 21, 2022
8ccaa99
added infrastructure for tests, fixed bug, if two clients execute at …
flurfis Oct 26, 2022
b5b0450
prepared statements seem to work now... yaay
flurfis Oct 26, 2022
c62ec9a
more errorhandling and new answers to client for DROP_TABLE, TRUNCATE…
flurfis Oct 26, 2022
789e07e
implemented tests, but no connection can be established as of yet...
flurfis Oct 26, 2022
e99981a
test works now, decide cycle is now handled slightly differently, fou…
flurfis Oct 27, 2022
4e17080
improved tests
flurfis Oct 31, 2022
126fbdc
updated tests for prepare statements, and prepare statements now hand…
flurfis Nov 1, 2022
fdba699
updated and added javadoc
flurfis Nov 1, 2022
ad1eb1f
updated codestyle
flurfis Nov 2, 2022
d14f78e
updated to plugin architecture, minor reformatting and adjustment of …
datomo Feb 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
/*
* Copyright 2019-2023 The Polypheny Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.polypheny.db.postgres;

import static org.junit.Assert.assertEquals;

import com.google.common.collect.ImmutableList;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import lombok.extern.slf4j.Slf4j;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.polypheny.db.TestHelper;
import org.polypheny.db.catalog.Catalog;
import org.polypheny.db.catalog.entity.CatalogTable;
import org.polypheny.db.catalog.exceptions.UnknownSchemaException;
import org.polypheny.db.catalog.exceptions.UnknownTableException;

//import static org.polypheny.db.postgresql.PGInterfaceInboundCommunicationHandler.ctx;


/**
* Tests the implementation of the PGInterface --> simulates a client that connects via JDBC
*/
@Slf4j
public class PGInterfaceIntegrationTests {

//select: SELECT * FROM public.PGInterfaceTestTable

//insert: INSERT INTO public.PGInterfaceTestTable(PkIdTest, VarcharTest, IntTest) VALUES (1, 'Franz', 1), (2, 'Hello', 2), (3, 'By', 3);
//create table: CREATE TABLE public.PGInterfaceTestTable(PkIdTest INTEGER NOT NULL, VarcharTest VARCHAR(255), IntTest INTEGER,PRIMARY KEY (PkIdTest))


/**
* starts an instance of Polypheny and creates a PGInterface, as it does not exist per default
*
* @throws SQLException
*/
@BeforeClass
public static void start() throws SQLException {
// Ensures that Polypheny-DB is running
//noinspection ResultOfMethodCallIgnored

TestHelper.getInstance();

try ( TestHelper.JdbcConnection polyphenyDbConnection = new TestHelper.JdbcConnection( false ) ) {
Connection connection = polyphenyDbConnection.getConnection();
try ( Statement statement = connection.createStatement() ) {
statement.executeUpdate( "ALTER INTERFACES ADD \"pgtestinterface\" USING 'org.polypheny.db.postgresql.PGInterface' WITH '{\"port\":\"5433\"}'" );
}
}

}


/**
* Cleans up after the tests
*
* @throws SQLException
*/
@AfterClass
public static void stop() throws SQLException {

try ( PsqlJdbcConnection psqlJdbcConnection = new PsqlJdbcConnection( false ) ) {
Connection connection = psqlJdbcConnection.getConnection();
try ( Statement statement = connection.createStatement() ) {
statement.executeUpdate( "DROP TABLE IF EXISTS public.pginterfacetesttable" );
//statement.executeUpdate( "ALTER INTERFACES DROP pgtestinerface" );
}
}
}


/**
* Test that executes the ddl command CREATE and checks within the database if a table was created
*
* @throws SQLException
*/
@Test
public void testIfDDLIsExecuted() throws SQLException {

try ( PsqlJdbcConnection psqlJdbcConnection = new PsqlJdbcConnection( false ) ) {
Connection connection = psqlJdbcConnection.getConnection();
try ( Statement statement = connection.createStatement() ) {
statement.executeUpdate( "DROP TABLE IF EXISTS public.pginterfacetesttable" );
statement.executeUpdate( "CREATE TABLE pginterfacetesttable(PkIdTest INTEGER NOT NULL, VarcharTest VARCHAR(255), IntTest INTEGER,PRIMARY KEY (PkIdTest))" );
CatalogTable catalogTable = Catalog.getInstance().getTable( Catalog.getInstance().getSchema( Catalog.defaultDatabaseId, "public" ).id, "PGInterfaceTestTable" );
assertEquals( catalogTable.name, "pginterfacetesttable" );
statement.executeUpdate( "DROP TABLE IF EXISTS public.pginterfacetesttable" );
} catch ( UnknownTableException e ) {
e.printStackTrace();
} catch ( UnknownSchemaException e ) {
e.printStackTrace();
}
}
}


/**
* This test executes several SQL-commands via the client, it creates a table, inserts and selects from it. The returned values from the select are tested
*
* @throws SQLException
*/
@Test
public void testIfDMLandDDLandDQLIsExecuted() throws SQLException {

try ( PsqlJdbcConnection psqlJdbcConnection = new PsqlJdbcConnection( false ) ) {
Connection connection = psqlJdbcConnection.getConnection();
try ( Statement statement = connection.createStatement() ) {
statement.executeUpdate( "DROP TABLE IF EXISTS public.pginterfacetesttable" );
statement.executeUpdate( "CREATE TABLE pginterfacetesttable(PkIdTest INTEGER NOT NULL, VarcharTest VARCHAR(255), IntTest INTEGER,PRIMARY KEY (PkIdTest))" );
statement.executeUpdate( "INSERT INTO pginterfacetesttable(PkIdTest, VarcharTest, IntTest) VALUES (1, 'Franz', 1), (2, 'Hello', 2), (3, 'By', 3);" );
ResultSet rs = statement.executeQuery( "SELECT * FROM pginterfacetesttable;" );

TestHelper.checkResultSet( rs, ImmutableList.of( new Object[]{ 1, "Franz", 1 }, new Object[]{ 2, "Hello", 2 }, new Object[]{ 3, "By", 3 } ) );

statement.executeUpdate( "DROP TABLE IF EXISTS public.pginterfacetesttable" );
}
}
}


/**
* Tests if a prepared statement is correctly executed if the PREPARE and EXECUTE statement are sent seperately
*
* @throws SQLException
*/
@Test
public void testPreparedAndExecuteInTwoParts() throws SQLException {

try ( PsqlJdbcConnection psqlJdbcConnection = new PsqlJdbcConnection( false ) ) {
Connection connection = psqlJdbcConnection.getConnection();
try ( Statement statement = connection.createStatement() ) {
statement.executeUpdate( "DROP TABLE IF EXISTS public.pginterfacetesttable" );
statement.executeUpdate( "CREATE TABLE pginterfacetesttable(PkIdTest INTEGER NOT NULL, VarcharTest VARCHAR(255), IntTest INTEGER,PRIMARY KEY (PkIdTest))" );

//ResultSet rss = statement.executeQuery("PREPARE lol (int) AS SELECT empid FROM public.emps WHERE empid = $1; EXECUTE lol (100);");
statement.executeUpdate( "PREPARE testPrepare (int, text, int) AS INSERT INTO pginterfacetesttable(PkIdTest, VarcharTest, IntTest) VALUES ($1, $2, $3);" );
statement.executeUpdate( "EXECUTE testPrepare (1, 'Franz', 1);" );
ResultSet rs = statement.executeQuery( "SELECT * FROM pginterfacetesttable;" );

TestHelper.checkResultSet( rs, ImmutableList.of( new Object[]{ 1, "Franz", 1 } ) );

statement.executeUpdate( "DROP TABLE IF EXISTS public.pginterfacetesttable" );
}
}
}


/**
* Tests if a prepared statement is correctly executed if the PREPARE and EXECUTE statement are sent together
*
* @throws SQLException
*/
@Test
public void testPreparedAndExecuteInOnePart() throws SQLException {

try ( PsqlJdbcConnection psqlJdbcConnection = new PsqlJdbcConnection( false ) ) {
Connection connection = psqlJdbcConnection.getConnection();
try ( Statement statement = connection.createStatement() ) {
statement.executeUpdate( "DROP TABLE IF EXISTS public.pginterfacetesttable" );
statement.executeUpdate( "CREATE TABLE pginterfacetesttable(PkIdTest INTEGER NOT NULL, VarcharTest VARCHAR(255), IntTest INTEGER,PRIMARY KEY (PkIdTest))" );

//ResultSet rss = statement.executeQuery("PREPARE lol (int) AS SELECT empid FROM public.emps WHERE empid = $1; EXECUTE lol (100);");
statement.executeUpdate( "PREPARE testPrepare (int, text, int) AS INSERT INTO pginterfacetesttable(PkIdTest, VarcharTest, IntTest) VALUES ($1, $2, $3); EXECUTE testPrepare (1, 'Franz', 1);" );
ResultSet rs = statement.executeQuery( "SELECT * FROM pginterfacetesttable;" );

TestHelper.checkResultSet( rs, ImmutableList.of( new Object[]{ 1, "Franz", 1 } ) );

statement.executeUpdate( "DROP TABLE IF EXISTS public.pginterfacetesttable" );
}
}
}


/**
* This feature is not yet supported, but it tests if prepared statement are executed correctly using the JDBC framework
*
* @throws SQLException
*/
@Test
@Ignore
public void testPreparedUsingJdbc() throws SQLException {
//TODO(FF): Prepared Statements using JDBC not yet supported from PGInterface --> read inserted values from bind command (which is not done currently)

try ( PsqlJdbcConnection psqlJdbcConnection = new PsqlJdbcConnection( false ) ) {
Connection connection = psqlJdbcConnection.getConnection();
try ( Statement statement = connection.createStatement() ) {
statement.executeUpdate( "DROP TABLE IF EXISTS public.pginterfacetesttable" );
statement.executeUpdate( "CREATE TABLE pginterfacetesttable(PkIdTest INTEGER NOT NULL, IntTest INTEGER,PRIMARY KEY (PkIdTest))" );

PreparedStatement pst = connection.prepareStatement( "INSERT INTO pginterfacetesttable(PkIdTest, IntTest) VALUES (?, ?)" );
pst.setInt( 1, 100 );
pst.execute();
ResultSet rs = statement.executeQuery( "SELECT * FROM pginterfacetesttable;" );

TestHelper.checkResultSet( rs, ImmutableList.of( new Object[]{ 1, 100 } ) );

statement.executeUpdate( "DROP TABLE IF EXISTS public.pginterfacetesttable" );
}
}
}


/**
* Creates a connection via Postgres-JDBC, autocommit is always enabled, and sslmode disabled
*/
public static class PsqlJdbcConnection implements AutoCloseable {

private final static String dbHost = "localhost";
private final static int port = 5433;

private final Connection conn;


public PsqlJdbcConnection( boolean autoCommit ) throws SQLException {
try {
Class.forName( "org.postgresql.Driver" );
} catch ( ClassNotFoundException e ) {
log.error( "PostgreSQL JDBC Driver not found", e );
}
final String url = "jdbc:postgresql://" + dbHost + ":" + port + "/";
log.debug( "Connecting to database @ {}", url );

Properties connectionProps = new Properties();
connectionProps.setProperty( "sslmode", "disable" );
conn = DriverManager.getConnection( url, connectionProps );

//conn.setAutoCommit( autoCommit );
}


public Connection getConnection() {
return conn;
}


@Override
public void close() throws SQLException {
//conn.commit();
conn.close();
}

}

}
24 changes: 12 additions & 12 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
version: "3.4"
services:
remote-api:
image: polypheny/polypheny-connector
restart: unless-stopped
container_name: polypheny-connector
ports:
- "2376:443"
environment:
- CREATE_CERTS_WITH_PW=supersecret
- CERT_HOSTNAME=localhost
remote-api:
image: polypheny/polypheny-connector
restart: unless-stopped
container_name: polypheny-connector
ports:
- "2376:443"
environment:
- CREATE_CERTS_WITH_PW=supersecret
- CERT_HOSTNAME=localhost
- CERT_EXPIRATION_DAYS=3650
volumes:
- ${POLYPHENY_HOME:-~}/.polypheny/certs/localhost:/data/certs
- /var/run/docker.sock:/var/run/docker.sock:ro
volumes:
- ${POLYPHENY_HOME:-~}/.polypheny/certs/localhost:/data/certs
- /var/run/docker.sock:/var/run/docker.sock:ro
52 changes: 52 additions & 0 deletions plugins/postgresql-interface/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
group "org.polypheny"


configurations {
tests {
extendsFrom testRuntimeOnly
}
}

dependencies {
compileOnly project(":core")
compileOnly project(":monitoring")

////// NETTY
// https://mvnrepository.com/artifact/io.netty/netty-all
implementation group: 'io.netty', name: 'netty-all', version: '4.1.24.Final'


// --- Test Compile ---
testImplementation project(path: ":core", configuration: "tests")

testImplementation group: "junit", name: "junit", version: junit_version
}




/**
* Tests
*/
test {
maxHeapSize = "2g" // Increase heap size (default is 512MB)
}

/**
* JARs
*/
jar {
manifest {
attributes "Manifest-Version": "1.0"
attributes "Copyright": "The Polypheny Project (polypheny.org)"
attributes "Version": "$project.version"
}
}
java {
withJavadocJar()
withSourcesJar()
}

licensee {
allow('Apache-2.0')
}
27 changes: 27 additions & 0 deletions plugins/postgresql-interface/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#
# Copyright 2019-2023 The Polypheny Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

pluginVersion = 0.0.1

pluginId = postgres-interface
pluginClass = org.polypheny.db.postgresql.PostgresqlInterfacePlugin
pluginProvider = The Polypheny Project
pluginDependencies =
pluginUrlPath =
pluginCategories = interface
pluginPolyDependencies =
pluginIsSystemComponent = false
pluginIsUiVisible = true
Loading