use of cz.startnet.utils.pgdiff.schema.AbstractPgFunction in project pgcodekeeper by pgcodekeeper.
the class FunctionsReader method fillFunction.
private void fillFunction(AbstractPgFunction function, ResultSet res, PgDatabase db, List<Pair<String, GenericColumn>> argsQualTypes) throws SQLException {
function.setLanguageCost(res.getString("lang_name"), res.getFloat("procost"));
// since 9.5 PostgreSQL
if (SupportedVersion.VERSION_9_5.isLE(loader.version)) {
Long[] protrftypes = getColArray(res, "protrftypes");
if (protrftypes != null) {
for (Long s : protrftypes) {
function.addTransform(loader.cachedTypesByOid.get(s).getFullName());
}
}
}
if (SupportedVersion.VERSION_12.isLE(loader.version)) {
String supportFunc = res.getString("support_func");
if (!"-".equals(supportFunc)) {
setFunctionWithDep(AbstractPgFunction::setSupportFunc, function, supportFunc);
}
}
function.setWindow(res.getBoolean("proiswindow"));
// VOLATILE is default
switch(res.getString("provolatile")) {
case "i":
function.setVolatileType("IMMUTABLE");
break;
case "s":
function.setVolatileType("STABLE");
break;
default:
break;
}
function.setStrict(res.getBoolean("proisstrict"));
function.setSecurityDefiner(res.getBoolean("prosecdef"));
function.setLeakproof(res.getBoolean("proleakproof"));
// parallel mode: s - safe, r - restricted, u - unsafe
if (SupportedVersion.VERSION_9_6.isLE(loader.version)) {
String parMode = res.getString("proparallel");
switch(parMode) {
case "s":
function.setParallel("SAFE");
break;
case "r":
function.setParallel("RESTRICTED");
break;
default:
break;
}
}
float rows = res.getFloat("prorows");
if (0.0f != rows) {
function.setRows(rows);
}
String[] proconfig = getColArray(res, "proconfig");
if (proconfig != null) {
for (String param : proconfig) {
int eq = param.indexOf('=');
final String par = param.substring(0, eq);
String val = param.substring(eq + 1);
switch(par) {
case "temp_tablespaces":
case "session_preload_libraries":
case "shared_preload_libraries":
case "local_preload_libraries":
case "search_path":
function.addConfiguration(par, null);
loader.submitAntlrTask(val, SQLParser::vex_eof, ctx -> {
StringBuilder sb = new StringBuilder();
for (VexContext vex : ctx.vex()) {
sb.append(PgDiffUtils.quoteString(vex.getText()));
sb.append(", ");
}
sb.setLength(sb.length() - 2);
function.addConfiguration(par, sb.toString());
});
break;
default:
val = PgDiffUtils.quoteString(val);
function.addConfiguration(PgDiffUtils.getQuotedName(par), val);
break;
}
}
}
String body = "";
String definition = res.getString("prosrc");
String probin = res.getString("probin");
if (probin != null && !probin.isEmpty()) {
StringBuilder sb = new StringBuilder();
sb.append(PgDiffUtils.quoteString(probin));
if (!"-".equals(definition)) {
sb.append(", ");
if (!definition.contains("\'") && !definition.contains("\\")) {
sb.append(PgDiffUtils.quoteString(definition));
} else {
sb.append(PgDiffUtils.quoteStringDollar(definition));
}
}
body = sb.toString();
} else if (definition != null && !definition.isEmpty() && !"-".equals(definition)) {
body = PgDiffUtils.quoteStringDollar(definition);
} else if (SupportedVersion.VERSION_14.isLE(loader.version)) {
String probody = res.getString("prosqlbody");
// must not be null at this point, otherwise function has no body (?)
checkObjectValidity(probody, DbObjType.FUNCTION, function.getBareName());
function.setInStatementBody(true);
body = probody;
}
function.setBody(loader.args, body);
// Parsing the function definition and adding its result context for analysis.
if (function.isInStatementBody()) {
loader.submitAntlrTask(body, SQLParser::function_body, ctx -> db.addAnalysisLauncher(new FuncProcAnalysisLauncher(function, ctx, loader.getCurrentLocation(), argsQualTypes)));
} else if (!"-".equals(definition) && "SQL".equalsIgnoreCase(function.getLanguage())) {
loader.submitAntlrTask(definition, SQLParser::sql, ctx -> db.addAnalysisLauncher(new FuncProcAnalysisLauncher(function, ctx, loader.getCurrentLocation(), argsQualTypes)));
} else if (!"-".equals(definition) && "PLPGSQL".equalsIgnoreCase(function.getLanguage())) {
loader.submitPlpgsqlTask(definition, SQLParser::plpgsql_function, ctx -> db.addAnalysisLauncher(new FuncProcAnalysisLauncher(function, ctx, loader.getCurrentLocation(), argsQualTypes)));
}
}
use of cz.startnet.utils.pgdiff.schema.AbstractPgFunction in project pgcodekeeper by pgcodekeeper.
the class FunctionsReader method getFunc.
private AbstractFunction getFunc(ResultSet res, AbstractSchema schema, String funcName) throws SQLException {
boolean isProc = SupportedVersion.VERSION_11.isLE(loader.version) && (res.getBoolean("proisproc"));
loader.setCurrentObject(new GenericColumn(schema.getName(), funcName, isProc ? DbObjType.PROCEDURE : DbObjType.FUNCTION));
AbstractPgFunction f = isProc ? new PgProcedure(funcName) : new PgFunction(funcName);
PgDatabase db = schema.getDatabase();
fillFunction(f, res, db, fillArguments(f, res));
String defaultValuesAsString = res.getString("default_values_as_string");
if (defaultValuesAsString != null) {
loader.submitAntlrTask(defaultValuesAsString, SQLParser::vex_eof, ctx -> {
List<VexContext> vexCtxList = ctx.vex();
ListIterator<VexContext> vexCtxListIterator = vexCtxList.listIterator(vexCtxList.size());
for (int i = (f.getArguments().size() - 1); i >= 0; i--) {
if (!vexCtxListIterator.hasPrevious()) {
break;
}
Argument a = f.getArguments().get(i);
if (a.getMode().isIn()) {
VexContext vx = vexCtxListIterator.previous();
a.setDefaultExpression(ParserAbstract.getFullCtxText(vx));
db.addAnalysisLauncher(new VexAnalysisLauncher(f, vx, loader.getCurrentLocation()));
}
}
});
}
return f;
}
use of cz.startnet.utils.pgdiff.schema.AbstractPgFunction in project pgcodekeeper by pgcodekeeper.
the class CreateFunction method parseObject.
@Override
public void parseObject() {
List<IdentifierContext> ids = ctx.function_parameters().schema_qualified_name().identifier();
String name = QNameParser.getFirstName(ids);
AbstractPgFunction function = ctx.PROCEDURE() != null ? new PgProcedure(name) : new PgFunction(name);
fillFunction(function);
if (ctx.ret_table != null) {
function.setReturns(getFullCtxText(ctx.ret_table));
for (Function_column_name_typeContext ret_col : ctx.ret_table.function_column_name_type()) {
addPgTypeDepcy(ret_col.data_type(), function);
function.addReturnsColumn(ret_col.identifier().getText(), getTypeName(ret_col.data_type()));
}
} else if (ctx.rettype_data != null) {
function.setReturns(getTypeName(ctx.rettype_data));
addPgTypeDepcy(ctx.rettype_data, function);
}
addSafe(getSchemaSafe(ids), function, ids, parseArguments(ctx.function_parameters().function_args()));
}
use of cz.startnet.utils.pgdiff.schema.AbstractPgFunction in project pgcodekeeper by pgcodekeeper.
the class CreateFunction method analyzeFunctionDefinition.
private void analyzeFunctionDefinition(AbstractPgFunction function, String language, Character_stringContext definition, List<Pair<String, GenericColumn>> funcArgs) {
Pair<String, Token> pair = unquoteQuotedString(definition);
String def = pair.getFirst();
Token start = pair.getSecond();
// Parsing the function definition and adding its result context for analysis.
// Adding contexts of function arguments for analysis.
String name = "function definition of " + function.getBareName();
List<Object> err = new ArrayList<>();
if ("SQL".equalsIgnoreCase(language)) {
AntlrParser.submitAntlrTask(antlrTasks, () -> AntlrParser.makeBasicParser(SQLParser.class, def, name, err, start).sql(), ctx -> {
errors.addAll(err);
FuncProcAnalysisLauncher launcher = new FuncProcAnalysisLauncher(function, ctx, fileName, funcArgs);
launcher.setOffset(start);
db.addAnalysisLauncher(launcher);
});
} else if ("PLPGSQL".equalsIgnoreCase(language)) {
AntlrParser.submitAntlrTask(antlrTasks, () -> {
SQLParser parser = AntlrParser.makeBasicParser(SQLParser.class, def, name, err, start);
AntlrUtils.removeIntoStatements(parser);
return parser.plpgsql_function();
}, ctx -> {
errors.addAll(err);
FuncProcAnalysisLauncher launcher = new FuncProcAnalysisLauncher(function, ctx, fileName, funcArgs);
launcher.setOffset(start);
db.addAnalysisLauncher(launcher);
});
}
}
use of cz.startnet.utils.pgdiff.schema.AbstractPgFunction in project pgcodekeeper by pgcodekeeper.
the class GrantPrivilege method parseFunction.
private void parseFunction(Rule_member_objectContext obj, String permissions, List<String> roles) {
for (Function_parametersContext funct : obj.func_name) {
List<IdentifierContext> funcIds = funct.schema_qualified_name().identifier();
IdentifierContext functNameCtx = QNameParser.getFirstNameCtx(funcIds);
AbstractSchema schema = getSchemaSafe(funcIds);
AbstractPgFunction func = (AbstractPgFunction) getSafe(AbstractSchema::getFunction, schema, parseSignature(functNameCtx.getText(), funct.function_args()), functNameCtx.getStart());
StringBuilder sb = new StringBuilder();
DbObjType type = obj.PROCEDURE() == null ? DbObjType.FUNCTION : DbObjType.PROCEDURE;
addObjReference(funcIds, type, state, parseArguments(funct.function_args()));
if (isRefMode()) {
continue;
}
sb.append(type).append(' ');
sb.append(PgDiffUtils.getQuotedName(schema.getName())).append('.');
// For AGGREGATEs in GRANT/REVOKE the signature will be the same as in FUNCTIONs;
// important: asterisk (*) and 'ORDER BY' are not displayed.
func.appendFunctionSignature(sb, false, true);
for (String role : roles) {
addPrivilege(func, new PgPrivilege(state, permissions, sb.toString(), role, isGO));
}
}
}
Aggregations