Skip to content

Commit

Permalink
Merge pull request #184 from jphp-compiler/dbal-extension
Browse files Browse the repository at this point in the history
Implement basic sql extension.
  • Loading branch information
dim-s committed Apr 19, 2015
2 parents 9177e1b + d8d5446 commit 6b8f0c1
Show file tree
Hide file tree
Showing 30 changed files with 1,430 additions and 3 deletions.
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
def javaVersion = '1.6';
def projectVersion = '0.6.5';
def projectVersion = '0.6.6';

buildscript {
repositories {
Expand Down Expand Up @@ -69,6 +69,7 @@ configure([
project(':jphp-xml-ext'),
project(':jphp-gdx-ext'),
project(':jphp-mail-ext'),
project(':jphp-sql-ext'),

project(':jphp-android'),
project(':jphp-scripting'),
Expand Down
2 changes: 1 addition & 1 deletion docs
Submodule docs updated from 99e969 to 3fe946
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import php.runtime.memory.support.operation.iterator.IterableMemoryOperation;
import php.runtime.memory.support.operation.map.HashMapMemoryOperation;
import php.runtime.memory.support.operation.map.MapMemoryOperation;
import php.runtime.memory.support.operation.map.PropertiesMemoryOperation;
import php.runtime.reflection.ParameterEntity;
import php.runtime.reflection.support.ReflectionUtils;

Expand Down Expand Up @@ -302,6 +303,7 @@ public int hashCode() {

register(new MapMemoryOperation());
register(new HashMapMemoryOperation());
register(new PropertiesMemoryOperation());

register(new UrlMemoryOperation());
register(new UriMemoryOperation());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package php.runtime.memory.support.operation.map;

import php.runtime.Memory;
import php.runtime.common.HintType;
import php.runtime.env.Environment;
import php.runtime.env.TraceInfo;
import php.runtime.lang.ForeachIterator;
import php.runtime.memory.ArrayMemory;
import php.runtime.memory.StringMemory;
import php.runtime.memory.support.MemoryOperation;
import php.runtime.reflection.ParameterEntity;

import java.util.Map;
import java.util.Properties;

public class PropertiesMemoryOperation extends MemoryOperation<Properties> {
@Override
public Class<?>[] getOperationClasses() {
return new Class<?>[] { Properties.class };
}

@Override
public Properties convert(Environment env, TraceInfo trace, Memory arg) throws Throwable {
Properties properties = new Properties();

ForeachIterator iterator = arg.getNewIterator(env);

while (iterator.next()) {
if (iterator.getValue().isNull()) {
properties.setProperty(iterator.getKey().toString(), null);
} else {
properties.setProperty(iterator.getKey().toString(), iterator.getValue().toString());
}
}

return properties;
}

@Override
public Memory unconvert(Environment env, TraceInfo trace, Properties arg) throws Throwable {
ArrayMemory result = new ArrayMemory(true);

for (Map.Entry<Object, Object> entry : arg.entrySet()) {
result.putAsKeyString(
entry.getKey().toString(),
entry.getValue() == null ? Memory.NULL : StringMemory.valueOf(entry.getValue().toString())
);
}

return null;
}

@Override
public void applyTypeHinting(ParameterEntity parameter) {
parameter.setType(HintType.ARRAY);
}
}
10 changes: 10 additions & 0 deletions jphp-sql-ext/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

dependencies {
compile project(':jphp-runtime')
compile 'org.apache.commons:commons-lang3:3.4'

testCompile 'org.xerial:sqlite-jdbc:3.8.7'
testCompile 'junit:junit:4.+'
testCompile project(':jphp-zend-ext')
testCompile project(':jphp-core').sourceSets.test.output
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.develnext.jphp.ext.sql;

import org.develnext.jphp.ext.sql.classes.*;
import php.runtime.env.CompileScope;
import php.runtime.ext.support.Extension;

import java.sql.SQLException;

public class SqlExtension extends Extension {
public static final String NS = "php\\sql";

@Override
public Status getStatus() {
return Status.EXPERIMENTAL;
}

@Override
public void onRegister(CompileScope scope) {
registerJavaException(scope, WrapSqlException.class, SQLException.class);

registerClass(scope, PSqlResult.class);
registerClass(scope, PSqlStatement.class);
registerClass(scope, PSqlConnection.class);
registerClass(scope, PSqlDriverManager.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
package org.develnext.jphp.ext.sql.classes;

import org.develnext.jphp.ext.sql.SqlExtension;
import php.runtime.Memory;
import php.runtime.annotation.Reflection.*;
import php.runtime.env.Environment;
import php.runtime.lang.BaseObject;
import php.runtime.memory.ArrayMemory;
import php.runtime.memory.LongMemory;
import php.runtime.memory.ReferenceMemory;
import php.runtime.reflection.ClassEntity;

import java.sql.*;

@Abstract
@Name("SqlConnection")
@Namespace(SqlExtension.NS)
public class PSqlConnection extends BaseObject {
public static final int TRANSACTION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED;
public static final int TRANSACTION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;
public static final int TRANSACTION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ;
public static final int TRANSACTION_NONE = Connection.TRANSACTION_NONE;
public static final int TRANSACTION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE;

protected Connection connection;
protected DatabaseMetaData metaData;

public PSqlConnection(Environment env, Connection connection) {
super(env);
this.connection = connection;
try {
this.metaData = connection.getMetaData();
} catch (SQLException e) {
throw new WrapSqlException(env, e);
}
}

public PSqlConnection(Environment env, ClassEntity clazz) {
super(env, clazz);
}

@Setter
public void setAutoCommit(boolean value) throws SQLException {
connection.setAutoCommit(value);
}

@Getter
public boolean getAutoCommit() throws SQLException {
return connection.getAutoCommit();
}

@Setter
public void setReadOnly(boolean value) throws SQLException {
connection.setReadOnly(value);
}

@Getter
public boolean getReadOnly() throws SQLException {
return connection.isReadOnly();
}

@Setter
public void setTransactionIsolation(int value) throws SQLException {
connection.setTransactionIsolation(value);
}

@Getter
public int getTransactionIsolation() throws SQLException {
return connection.getTransactionIsolation();
}

@Setter
public void setCatalog(String value) throws SQLException {
connection.setCatalog(value);
}

@Getter
public String getCatalog() throws SQLException {
return connection.getCatalog();
}

@Signature
public Memory getCatalogs(Environment env) throws SQLException {
ResultSet catalogs = metaData.getCatalogs();
ArrayMemory r = new ArrayMemory();

while (catalogs.next()) {
r.add(new PSqlResult(env, catalogs).toArray(env));
}

return r.toConstant();
}

@Signature
public Memory getSchemas(Environment env) throws SQLException {
ResultSet schemas = metaData.getSchemas();
ArrayMemory r = new ArrayMemory();

while (schemas.next()) {
r.add(new PSqlResult(env, schemas).toArray(env));
}

return r.toConstant();
}

@Signature
public Memory getMetaData() throws SQLException {
ArrayMemory r = new ArrayMemory();
r.refOfIndex("userName").assign(metaData.getUserName());

r.refOfIndex("driverName").assign(metaData.getDriverName());
r.refOfIndex("driverVersion").assign(metaData.getDriverVersion());
r.refOfIndex("databaseName").assign(metaData.getDatabaseProductName());
r.refOfIndex("databaseVersion").assign(metaData.getDatabaseProductVersion());

r.refOfIndex("catalogSeparator").assign(metaData.getCatalogSeparator());
r.refOfIndex("catalogTerm").assign(metaData.getCatalogTerm());
r.refOfIndex("schemaTerm").assign(metaData.getSchemaTerm());
r.refOfIndex("procedureTerm").assign(metaData.getProcedureTerm());
r.refOfIndex("searchStringEscape").assign(metaData.getSearchStringEscape());

r.refOfIndex("numericFunctions").assign(metaData.getNumericFunctions());
r.refOfIndex("stringFunctions").assign(metaData.getStringFunctions());
r.refOfIndex("timeDateFunctions").assign(metaData.getTimeDateFunctions());
r.refOfIndex("systemFunctions").assign(metaData.getSystemFunctions());

r.refOfIndex("defaultTransactionIsolation").assign(metaData.getDefaultTransactionIsolation());
r.refOfIndex("identifierQuoteString").assign(metaData.getIdentifierQuoteString());

r.refOfIndex("maxBinaryLiteralLength").assign(metaData.getMaxBinaryLiteralLength());
r.refOfIndex("maxCatalogNameLength").assign(metaData.getMaxCatalogNameLength());
r.refOfIndex("maxCharLiteralLength").assign(metaData.getMaxCharLiteralLength());
r.refOfIndex("maxConnections").assign(metaData.getMaxConnections());

r.refOfIndex("maxColumnNameLength").assign(metaData.getMaxColumnNameLength());
r.refOfIndex("maxColumnsInGroupBy").assign(metaData.getMaxColumnsInGroupBy());
r.refOfIndex("maxColumnsInIndex").assign(metaData.getMaxColumnsInIndex());
r.refOfIndex("maxColumnsInOrderBy").assign(metaData.getMaxColumnsInOrderBy());
r.refOfIndex("maxColumnsInSelect").assign(metaData.getMaxColumnsInSelect());
r.refOfIndex("maxColumnsInTable").assign(metaData.getMaxColumnsInTable());

r.refOfIndex("maxCursorNameLength").assign(metaData.getMaxCursorNameLength());
r.refOfIndex("maxIndexLength").assign(metaData.getMaxIndexLength());
r.refOfIndex("maxProcedureNameLength").assign(metaData.getMaxProcedureNameLength());
r.refOfIndex("maxRowSize").assign(metaData.getMaxRowSize());
r.refOfIndex("maxSchemaNameLength").assign(metaData.getMaxSchemaNameLength());
r.refOfIndex("maxStatementLength").assign(metaData.getMaxStatementLength());

r.refOfIndex("maxTableNameLength").assign(metaData.getMaxTableNameLength());
r.refOfIndex("maxTablesInSelect").assign(metaData.getMaxTablesInSelect());

return r.toConstant();
}

@Signature
public PSqlStatement query(Environment env, String sql) throws Throwable {
return query(env, sql, null);
}

@Signature
public PSqlStatement query(Environment env, String sql, @Nullable ArrayMemory args) throws Throwable {
PreparedStatement statement = connection.prepareStatement(sql);
PSqlStatement sqlStatement = new PSqlStatement(env, statement);

if (args != null) {
int index = 0;

for (ReferenceMemory arg : args) {
env.invokeMethod(sqlStatement, "bind", LongMemory.valueOf(index), arg.value);
index += 1;
}
}

return sqlStatement;
}

@Signature
public String identifier(String value) throws SQLException {
String identifierQuoteString = connection.getMetaData().getIdentifierQuoteString();

return identifierQuoteString + value + identifierQuoteString;
}

@Signature
public void close() throws SQLException {
connection.close();
}

@Signature
public void rollback() throws SQLException {
connection.rollback();
}

@Signature
public void commit() throws SQLException {
connection.commit();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package org.develnext.jphp.ext.sql.classes;

import org.develnext.jphp.ext.sql.SqlExtension;
import php.runtime.annotation.Reflection;
import php.runtime.annotation.Reflection.Signature;
import php.runtime.env.Environment;
import php.runtime.lang.BaseObject;
import php.runtime.reflection.ClassEntity;

import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

@Reflection.Name("SqlDriverManager")
@Reflection.Namespace(SqlExtension.NS)
final public class PSqlDriverManager extends BaseObject {
public PSqlDriverManager(Environment env, ClassEntity clazz) {
super(env, clazz);
}

@Signature
private void __construct() {}

@Signature
public static void install(String dbName) throws SQLException {
dbName = dbName.toLowerCase();

String driverClass;

if ("db2".equals(dbName)) {
driverClass = "COM.ibm.db2.jdbc.app.DB2Driver";
} else if ("mysql".equals(dbName)) {
driverClass = "com.mysql.jdbc.Driver";
} else if ("psql".equals(dbName) || "postgres".equals(dbName) || "postgresql".equals(dbName)) {
driverClass = "org.postgresql.Driver";
} else if ("mssql".equals(dbName)) {
driverClass = "com.microsoft.jdbc.sqlserver.SQLServerDriver";
} else if ("sybase".equals(dbName)) {
driverClass = "ncom.sybase.jdbc2.jdbc.SybDriver";
} else if ("firebird".equals(dbName)) {
driverClass = "org.firebirdsql.jdbc.FBDriver";
} else if ("hsql".equals(dbName)) {
driverClass = "org.hsql.jdbcDriver";
} else if ("interbase".equals(dbName)) {
driverClass = "interbase.interclient.Driver";
} else if ("sqlite".equals(dbName)) {
driverClass = "org.sqlite.JDBC";
} else {
driverClass = dbName;
}

try {
Class.forName(driverClass);
} catch (ClassNotFoundException e) {
throw new SQLException("Driver class '" + driverClass + "' is not found in classpath");
}
}

@Signature
public static PSqlConnection getConnection(Environment env, String url) throws SQLException {
return getConnection(env, url, null);
}

@Signature
public static PSqlConnection getConnection(Environment env, String url, Properties properties) throws SQLException {
return new PSqlConnection(env, DriverManager.getConnection("jdbc:" + url, properties == null ? new Properties() : properties));
}
}
Loading

0 comments on commit 6b8f0c1

Please sign in to comment.