|
1 |
SELECT * FROM customer LIMIT 10; |
|
1 |
package com.percona.blog.pljava;<br><br>import java.sql.Connection;<br>import java.sql.DriverManager;<br>import java.sql.PreparedStatement;<br>import java.sql.ResultSet;<br>import java.sql.SQLException;<br><br>import org.postgresql.pljava.ResultSetHandle;<br><br>public class CustomerResultSet implements ResultSetHandle {<br> private Connection conn;<br> private PreparedStatement stmt;<br> private final String m_url = "jdbc:default:connection";<br> private final String sql = "select * FROM customer LIMIT 10";<br><br> public CustomerResultSet() throws SQLException {<br> conn = DriverManager.getConnection(m_url);<br> stmt = conn.prepareStatement(sql);<br> }<br><br> @Override<br> public void close() throws SQLException {<br> stmt.close();<br> conn.close();<br> }<br><br> @Override<br> public ResultSet getResultSet() throws SQLException {<br> return stmt.executeQuery();<br> }<br><br> public static ResultSetHandle getCustomerPayments() throws SQLException {<br> return new CustomerResultSet();<br> }<br>} |
Note that we are implementing the org.postgresql.pljava.ResultSetHandle interface provided by PL/Java. We need it because we are returning a complex object and the ResultSetHandle interface is appropriated when we don’t need to manipulate the returned tuples.
Now that we are using PL/Java objects we need to tell the compiler where to find those references and for this first example here we need the pljava-api jar, which in my case happens to be pljava-api-1.6.2.jar. If you remember from the first post I’ve compiled, the PL/Java I’m using here and my JAR file is located at “~/pljava-1_6_2/pljava-api/target/pljava-api-1.6.2.jar” and the compilation command will be:
|
1 |
javac -cp "~/pljava-1_6_2/pljava-api/target/pljava-api-1.6.2.jar" com/percona/blog/pljava/CustomerResultSet.java<br>jar -c -f /app/pg12/lib/pljavaPart2.jar com/percona/blog/pljava/CustomerResultSet.class |
|
1 |
SELECT sqlj.install_jar( 'file:///app/pg12/lib/pljavaPart2.jar', 'pljavaPart2', true );<br>SELECT sqlj.set_classpath( 'public', 'pljavaPart2' );<br>CREATE OR REPLACE FUNCTION getCustomerLimit10() RETURNS SETOF customer AS 'com.percona.blog.pljava.CustomerResultSet.getCustomerLimit10' LANGUAGE java; |
|
1 |
test=# SELECT * FROM getCustomerLimit10();<br> customer_id | store_id | first_name | last_name | email | address_id | activebool | create_date | last_update | active <br>-------------+----------+------------+-----------+-------------------------------------+------------+------------+-------------+---------------------+--------<br> 1 | 1 | MARY | SMITH | [email protected] | 5 | t | 2006-02-14 | 2006-02-15 09:57:20 | 1<br> 2 | 1 | PATRICIA | JOHNSON | [email protected] | 6 | t | 2006-02-14 | 2006-02-15 09:57:20 | 1<br> 3 | 1 | LINDA | WILLIAMS | [email protected] | 7 | t | 2006-02-14 | 2006-02-15 09:57:20 | 1<br> 4 | 2 | BARBARA | JONES | [email protected] | 8 | t | 2006-02-14 | 2006-02-15 09:57:20 | 1<br> 5 | 1 | ELIZABETH | BROWN | [email protected] | 9 | t | 2006-02-14 | 2006-02-15 09:57:20 | 1<br> 6 | 2 | JENNIFER | DAVIS | [email protected] | 10 | t | 2006-02-14 | 2006-02-15 09:57:20 | 1<br> 7 | 1 | MARIA | MILLER | [email protected] | 11 | t | 2006-02-14 | 2006-02-15 09:57:20 | 1<br> 8 | 2 | SUSAN | WILSON | [email protected] | 12 | t | 2006-02-14 | 2006-02-15 09:57:20 | 1<br> 9 | 2 | MARGARET | MOORE | [email protected] | 13 | t | 2006-02-14 | 2006-02-15 09:57:20 | 1<br> 10 | 1 | DOROTHY | TAYLOR | [email protected] | 14 | t | 2006-02-14 | 2006-02-15 09:57:20 | 1<br>(10 rows)<br><br>test=# |
|
1 |
/**<br> * Crypto helper class that will contain all hashing and cryptographic functions<br> */<br>package com.percona.blog.pljava;<br><br>import java.nio.charset.StandardCharsets;<br>import java.security.MessageDigest;<br>import java.security.NoSuchAlgorithmException;<br><br>public class Crypto {<br> MessageDigest digest;<br> <br> public Crypto() throws NoSuchAlgorithmException {<br> digest = MessageDigest.getInstance("SHA-256");<br> }<br> <br> public String bytesToHex(byte[] hash) {<br> StringBuilder hexString = new StringBuilder(2 * hash.length);<br> for (int i = 0; i < hash.length; i++) {<br> String hex = Integer.toHexString(0xff & hash[i]);<br> if (hex.length() == 1) {<br> hexString.append('0');<br> }<br> hexString.append(hex);<br> }<br> return hexString.toString();<br> }<br> <br> public String encode(String data, int min, int max) {<br> double salt = Math.random();<br> int sbstring = (int) ((Math.random() * ((max - min) + 1)) + min);<br><br> return bytesToHex(digest.digest((data + salt).getBytes(StandardCharsets.UTF_8))).substring(0, sbstring);<br> }<br>}<br><br>/**<br> * CustomerHash class<br> */<br>package com.percona.blog.pljava;<br><br>import java.security.NoSuchAlgorithmException;<br>import java.sql.Connection;<br>import java.sql.DriverManager;<br>import java.sql.PreparedStatement;<br>import java.sql.ResultSet;<br>import java.sql.SQLException;<br>import java.util.logging.Level;<br>import java.util.logging.Logger;<br><br>import org.postgresql.pljava.ResultSetProvider;<br><br>public class CustomerHash implements ResultSetProvider {<br> private final Connection conn;<br> private final PreparedStatement stmt;<br> private final ResultSet rs;<br> private final Crypto crypto;<br> <br> private final String m_url = "jdbc:default:connection";<br><br> public CustomerHash(int id) throws SQLException, NoSuchAlgorithmException {<br> String query;<br> <br> crypto = new Crypto();<br> query = "SELECT * FROM customer WHERE customer_id = ?";<br> conn = DriverManager.getConnection(m_url);<br> stmt = conn.prepareStatement(query);<br> stmt.setInt(1, id);<br> rs = stmt.executeQuery();<br> }<br> <br> @Override<br> public void close() throws SQLException {<br> stmt.close();<br> conn.close();<br> }<br> <br> @Override<br> public boolean assignRowValues(ResultSet receiver, int currentRow) throws SQLException { <br> if (!rs.next())<br> return false;<br> <br> try {<br> receiver.updateInt(1, rs.getInt("customer_id"));<br> receiver.updateInt(2, rs.getInt("store_id"));<br> receiver.updateString(3, crypto.encode(rs.getString("first_name"), 5, 45));<br> receiver.updateString(4, crypto.encode(rs.getString("last_name"), 5, 45));<br> receiver.updateString(5, crypto.encode(rs.getString("email"), 5, 41) + "@mail.com");<br> receiver.updateInt(6, rs.getInt("address_id"));<br> receiver.updateBoolean(7, rs.getBoolean("activebool"));<br> receiver.updateDate(8, rs.getDate("create_date"));<br> receiver.updateTimestamp(9, rs.getTimestamp("last_update"));<br> receiver.updateInt(10, rs.getInt("active"));<br> <br> } catch (Exception e) {<br> Logger.getAnonymousLogger().log(Level.parse("SEVERE"), e.getMessage());<br> }<br> return true;<br> }<br> <br> public static ResultSetProvider getCustomerAnonymized(int id) throws SQLException, NoSuchAlgorithmException {<br> return new CustomerHash(id);<br> }<br><br>} |
|
1 |
javac -cp "~/pljava-1_6_2/build/pljava-api-1.6.2.jar" com/percona/blog/pljava/*.java<br>jar -c -f /app/pg12/lib/pljavaPart2.jar com/percona/blog/pljava/*.class |
|
1 |
test=# SELECT sqlj.replace_jar( 'file:///app/pg12/lib/pljavaPart2.jar', 'pljavaPart2', true );<br> replace_jar <br>-------------<br> <br>(1 row)<br><br>test=# CREATE OR REPLACE FUNCTION getCustomerAnonymized(int) RETURNS SETOF customer AS 'com.percona.blog.pljava.CustomerHash.getCustomerAnonymized' LANGUAGE java;<br>CREATE FUNCTION<br><br>test=# SELECT * FROM getCustomerAnonymized(9);<br> customer_id | store_id | first_name | last_name | email | address_id | activebool | create_date | last_update | ac<br>tive <br>-------------+----------+---------------------+-------------------------------------+-----------------------------------------+------------+------------+-------------+---------------------+---<br>-----<br> 9 | 2 | 72e2616ef0075e81929 | 3559c00ee546ae0062460c8faa4f24960f1 | [email protected] | 13 | t | 2006-02-14 | 2006-02-15 09:57:20 | <br> 1<br>(1 row)<br><br>test=# |
|
1 |
openssl genrsa -out keypair.pem 2048<br>openssl pkcs8 -topk8 -nocrypt -in keypair.pem -outform PEM -out private.pem<br>openssl rsa -in keypair.pem -outform PEM -pubout -out public.pem |
|
1 |
echo -n "CREATE TABLE keys(id int primary key, priv varchar not null, pub varchar not null); INSERT INTO keys VALUES(1, '" > keys.sql<br>cat private.pem | sed '1d;$d' | sed ':a;N;$!ba;s/n//g' | tr -d 'n' >> keys.sql<br>echo -n "', '" >> keys.sql<br>cat public.pem | sed '1d;$d' | sed ':a;N;$!ba;s/n//g' | tr -d 'n' >> keys.sql<br>echo -n "');" >> keys.sql<br><br>psql test < keys.sql |
|
1 |
CREATE TABLE keys(id int primary key, priv varchar not null, pub varchar not null); INSERT INTO keys VALUES(1, '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'); |
|
1 |
/**<br> * This is the relevant part of the Crypto class that will encrypt and decrypt our data using the certificates we generated above.<br> */<br> public PublicKey getPublicKey(String base64PublicKey) {<br> PublicKey publicKey = null;<br> try {<br> X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(base64PublicKey.getBytes()));<br> KeyFactory keyFactory = KeyFactory.getInstance("RSA");<br> publicKey = keyFactory.generatePublic(keySpec);<br> return publicKey;<br> } catch (NoSuchAlgorithmException e) {<br> e.printStackTrace();<br> } catch (InvalidKeySpecException e) {<br> e.printStackTrace();<br> }<br> return publicKey;<br> }<br><br> public PrivateKey getPrivateKey(String base64PrivateKey) {<br> PrivateKey privateKey = null;<br> PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(base64PrivateKey.getBytes()));<br> KeyFactory keyFactory = null;<br> try {<br> keyFactory = KeyFactory.getInstance("RSA");<br> } catch (NoSuchAlgorithmException e) {<br> e.printStackTrace();<br> }<br> try {<br> privateKey = keyFactory.generatePrivate(keySpec);<br> } catch (InvalidKeySpecException e) {<br> e.printStackTrace();<br> }<br> return privateKey;<br> }<br><br> public String encrypt(String data, PublicKey publicKey) throws BadPaddingException, IllegalBlockSizeException,<br> InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException {<br> Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");<br> cipher.init(Cipher.ENCRYPT_MODE, publicKey);<br> return Base64.getEncoder().encodeToString(cipher.doFinal(data.getBytes()));<br> }<br> <br> public String decrypt(String data, PrivateKey privateKey) throws NoSuchPaddingException,<br> NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {<br> Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");<br> cipher.init(Cipher.DECRYPT_MODE, privateKey);<br> return new String(cipher.doFinal(Base64.getDecoder().decode(data)));<br> } |
|
1 |
package com.percona.blog.pljava;<br><br>import java.security.InvalidKeyException;<br>import java.security.NoSuchAlgorithmException;<br>import java.security.PrivateKey;<br>import java.security.PublicKey;<br>import java.sql.Connection;<br>import java.sql.DriverManager;<br>import java.sql.PreparedStatement;<br>import java.sql.ResultSet;<br>import java.sql.SQLException;<br>import java.util.logging.Level;<br>import java.util.logging.Logger;<br><br>import javax.crypto.BadPaddingException;<br>import javax.crypto.IllegalBlockSizeException;<br>import javax.crypto.NoSuchPaddingException;<br><br>import org.postgresql.pljava.ResultSetProvider;<br>import org.postgresql.pljava.TriggerData;<br><br>public class CustomerCrypto implements ResultSetProvider {<br> private final String m_url = "jdbc:default:connection";<br> private final Connection conn;<br> private PreparedStatement stmt;<br> private ResultSet rs;<br><br> //<br> private PrivateKey privateKey;<br> private PublicKey publicKey;<br><br> public CustomerCrypto() throws SQLException, NoSuchAlgorithmException {<br> String query;<br><br> query = "SELECT * FROM keys WHERE id = 1";<br> conn = DriverManager.getConnection(m_url);<br> stmt = conn.prepareStatement(query);<br> rs = stmt.executeQuery();<br> if (!rs.next())<br> throw new SQLException("Keys not found!");<br><br> privateKey = Crypto.getPrivateKey(rs.getString("priv"));<br> publicKey = Crypto.getPublicKey(rs.getString("pub"));<br> }<br> <br> public void processQuery(int id) throws SQLException, NoSuchAlgorithmException {<br> String query;<br> query = "SELECT * FROM customer WHERE customer_id = ?";<br> stmt = conn.prepareStatement(query);<br> stmt.setInt(1, id);<br> rs = stmt.executeQuery();<br> }<br><br> @Override<br> public void close() throws SQLException {<br> stmt.close();<br> conn.close();<br> }<br><br> public static int getLineNumber() {<br> return Thread.currentThread().getStackTrace()[2].getLineNumber();<br> }<br><br> @Override<br> public boolean assignRowValues(ResultSet receiver, int currentRow) throws SQLException {<br> if (!rs.next())<br> return false;<br><br> try {<br> receiver.updateInt(1, rs.getInt("customer_id"));<br> receiver.updateInt(2, rs.getInt("store_id"));<br> receiver.updateString(3, Crypto.decrypt(rs.getString("first_name"), this.privateKey));<br> receiver.updateString(4, Crypto.decrypt(rs.getString("last_name"), this.privateKey));<br> receiver.updateString(5, Crypto.decrypt(rs.getString("email"), this.privateKey));<br> receiver.updateInt(6, rs.getInt("address_id"));<br> receiver.updateBoolean(7, rs.getBoolean("activebool"));<br> receiver.updateDate(8, rs.getDate("create_date"));<br> receiver.updateTimestamp(9, rs.getTimestamp("last_update"));<br> receiver.updateInt(10, rs.getInt("active"));<br><br> } catch (Exception e) {<br> Logger.getAnonymousLogger().log(Level.parse("SEVERE"), e.getMessage());<br> }<br> return true;<br> }<br> <br> private void encryptData(TriggerData td) throws InvalidKeyException, BadPaddingException, IllegalBlockSizeException, NoSuchPaddingException, NoSuchAlgorithmException, SQLException {<br> ResultSet _new = td.getNew();<br> <br> _new.updateString("first_name", Crypto.encrypt(_new.getString("first_name"), this.publicKey));<br> _new.updateString("last_name", Crypto.encrypt(_new.getString("last_name"), this.publicKey));<br> _new.updateString("email", Crypto.encrypt(_new.getString("email"), this.publicKey));<br> }<br> <br> public static void customerBeforeInsertUpdate(TriggerData td) throws SQLException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, NoSuchPaddingException, NoSuchAlgorithmException {<br> CustomerCrypto ret = new CustomerCrypto();<br> ret.encryptData(td);<br> }<br><br> public static ResultSetProvider getCustomerCrypto(int id) throws SQLException, NoSuchAlgorithmException {<br> CustomerCrypto ret = new CustomerCrypto();<br> ret.processQuery(id);<br> <br> return ret;<br> }<br><br>} |
|
1 |
javac -cp "/v01/proj/percona/blog/pljava/pljava-1_6_2/build/pljava-api-1.6.2.jar" com/percona/blog/pljava/*.java<br>jar -c -f /app/pg12/lib/pljavaPart2.jar com/percona/blog/pljava/*.class |
|
1 |
SELECT sqlj.replace_jar( 'file:///app/pg12/lib/pljavaPart2.jar', 'pljavaPart2', true );<br><br>CREATE FUNCTION customerBeforeInsertUpdate()<br> RETURNS trigger<br> AS 'com.percona.blog.pljava.CustomerCrypto.customerBeforeInsertUpdate'<br> LANGUAGE java;<br><br>CREATE TRIGGER tg_customerBeforeInsertUpdate<br> BEFORE INSERT ON customer<br> FOR EACH ROW<br> EXECUTE PROCEDURE customerBeforeInsertUpdate(); |
|
1 |
test=# SELECT * FROM customer LIMIT 3;<br> customer_id | store_id | first_name | last_name | email | address_id | activebool | create_date | last_update | active <br>-------------+----------+------------+-----------+-------------------------------------+------------+------------+-------------+---------------------+--------<br> 1 | 1 | MARY | SMITH | [email protected] | 5 | t | 2006-02-14 | 2006-02-15 09:57:20 | 1<br> 2 | 1 | PATRICIA | JOHNSON | [email protected] | 6 | t | 2006-02-14 | 2006-02-15 09:57:20 | 1<br> 3 | 1 | LINDA | WILLIAMS | [email protected] | 7 | t | 2006-02-14 | 2006-02-15 09:57:20 | 1<br>(3 rows)<br><br>test=# UPDATE customer SET first_name = first_name, last_name = last_name, email = email;<br>UPDATE 599<br><br>test=# SELECT * FROM customer LIMIT 3;<br> customer_id | store_id | <br> first_name | <br> last_name <br> | <br> email <br> | address_id | activebool | create_date | last_update | active <br>-------------+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------<br>-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------<br>------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------<br>----------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------<br>------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------<br>---------------------------------------------------------------------------------------------------------+------------+------------+-------------+----------------------------+--------<br> 3 | 1 | DT8oXb0VQvtFSIOv61zZfmUrpjWWGoeyl8D8tQl7naCLT31WlJn3U+uILYqUedSOdDSO17QdQKwChWG+DrcvYEih9RYyEPR2ja9deN4cn+vwHt/v09HDfmwrsJUt0UgP/fp78hCxkJDAV50KkMUsA23aeH5HRn9nCHOH0P<br>AcuId+7acCgwvU9YP8Sx2KVeVnLaBrzpeRLrsmAczQLUAXilXfdFC8uT2APBfwx1So2eCe+kSOsjcu1yTwlsa95Dnfu/N++Zm1D4knKUrAuNm5svTHjIz+B4HKXFMPz/Yk7KYF6ThB6OshIomyRvSEtKu5torfdwAvT3tsgP2DLWiKgQ== | H0YRoi10z36<br>tnNSXpBs/oYfMQRbAhfUYLIcE885Dhxmy2mbuhecCCqPcye5/++MhUwmEQG2pBgfsqWHLOnAgbqjaG3O0reipVysYK7cMysX1w5RVINsyD5H3vCqgnHESfdRuhW3b00InkR2qCtBYX1QJ1tKJZz89D2AOjoTq5jTum00vcLT06h6ZxVh1RKLNAuGpY9qN57m<br>/9a4JZuff9poYjw2PPQ6kTxhtbFl3bw+B3sJUcLFuFMYUoAAHsVETQRAerH1ncG9Uxi+xQjUtTVBqZdjvED+eydetH7vsnjBuYDtXD9XAn14qmALx5NfvwpU5jfpMOPOM4xP1BRVA2Q== | DpWBfhhii4LRPxZ9XJy8xoNne+qm051wD5Gd9AMHc+oIhx/B<br>ln6H+lcAM3625rKN1Vw/lG6VkQo2EnoZz/bhFtULvAOAUiBxerBDbYe0lYWqI50NxnFJbkexMkjDSiuoglh3ilRBn6Z+WGLc7FfEprOd1+tULW2gcwLI68uoEhfSY7INQZuGXfOUMAM4roB2fWvEfylL1ShbiGTRjX7KGXQbXLJtm7xel8J2VhdCecXzxzY2<br>Mtnu3EXGNpFy9atTXxE/fI0C5AX/u2FDZiOHz9xV7sB3atcqAeXwJB0smpBnPbwI3BN+ptzsWnhyFNNS+ol4QayMDgFhi/tp2+lCAQ== | 7 | t | 2006-02-14 | 2021-08-08 19:10:29.337653 | 1<br> 4 | 2 | jo3zKr6lJ5zMN5f3/BPgENhs9CdzDu7F/uFxAf6uO9MAKc7X+++ipk/OBbvvA8vpaJ7DTgph9LshRvpYIqPMwS6IubkScDOSRDoLBNW9z2oMF3dB46R86LK0pTEVVrGaddjnPzaAEh7Uwzy3LncC1y7pJqGKW1b3RGUE8n<br>4SgstMo/4tRNUe/AUcPn9FXkCoc5jFvn8gPwVoTRKwhYu0oTco2gNKZs1rmFdmkmobGaMjZuhWyWG2PO1oXIVPkpgILmD42yAMDxWkS4DVvgJChXJRukjBzfOitsQwHapjqPqf/q3mfBaQzNUwROcSfGBe6KlI5yfjWU309KRKaCYWNQ== | MMhPovG/N3k<br>Xjou6kS9V7QtEvlA5NS8/n62KVRVVGEnsh5bhwEhBZxlK72AQv8e4niATWPEiJJU6i7Z08NkU5FWNIvuWwlGTdEEW+kK7XQXib6cNAdnmo4RH72SWhDxEp3tMwwoZif2932H8WDEbNdP6bCP69ekBA7Z+nGtXaeh+H9BAaLf1e6XunBj2YN7zs4sFWB2Kxs2<br>IugLWd9g9677BWzUeJIzpJfVLro4HYlzASh9AMKb8wPRU0LlEpxtqUdejj7IY5M1hVhDTCCLSQjSqJscqzG1pYQ04W7KNdGwWxJPMjvyPC2K4H+HQuW0IWVjvFpyYd/5q1eIQX+vjdw== | oF4nyIjtVtWuydg6QiSg3BDadWe48nhbBEZSLrR5GVigA768<br>E3n1npN6sdstzG7bRVnphtfwIZwQ3MUFURWCbUCe0VqioNgVXFhiRvr3DAw2AH64ss/h65B2U5whAygnq4kiy5JvPD0z0omtfs9913QeoO+ilvPVLEc0q3n0jD9ZQlkNVfHSytx1NY86gWnESquTVhkVQ55QDV8GY70YLX9V6nU7ldu+zpNLmf2+rfpxqbRC<br>i16jnHGDcTT7CKeq+AxbiJDeaaAmSPpxTZsrX4sXFW4rpNtSmOyuyHZziy8rkN8xSpyhvrmxjC7EYe4bn6L/+hay108Wn0BSFYe2ow== | 8 | t | 2006-02-14 | 2021-08-08 19:10:29.337653 | 1<br><...><br>(3 rows)<br><br>test=# |
|
1 |
test=# CREATE OR REPLACE FUNCTION getCustomerCrypto(int) RETURNS SETOF customer AS 'com.percona.blog.pljava.CustomerCrypto.getCustomerCrypto' LANGUAGE java;<br>CREATE FUNCTION<br><br>test=# SELECT * FROM getCustomerCrypto(10);<br> customer_id | store_id | first_name | last_name | email | address_id | activebool | create_date | last_update | active <br>-------------+----------+------------+-----------+-----------------------------------+------------+------------+-------------+---------------------+--------<br> 10 | 1 | DOROTHY | TAYLOR | [email protected] | 14 | t | 2006-02-14 | 2006-02-15 09:57:20 | 1<br>(1 row)<br><br>test=# |
[1] https://github.com/elchinoo/blogs/tree/main/pljava
Percona Distribution for PostgreSQL provides the best and most critical enterprise components from the open-source community, in a single distribution, designed and tested to work together.