/** * Get the variable with the specified name and scope. * * @param name the name of the variable; may not be null * @param scope the variable scope; may not be null * @return the variable value; may be null if the variable is not currently set */ public String getVariable(String name, Scope scope) { name = variableName(name); return forScope(scope).get(name); }
/** * Get the name of the character set for the current database, via the "character_set_database" system property. * * @return the name of the character set for the current database, or null if not known ... */ public String currentDatabaseCharset() { String charsetName = systemVariables.getVariable(MySqlSystemVariables.CHARSET_NAME_DATABASE); if (charsetName == null || "DEFAULT".equalsIgnoreCase(charsetName)) { charsetName = systemVariables.getVariable(MySqlSystemVariables.CHARSET_NAME_SERVER); } return charsetName; }
@Override protected SystemVariables createNewSystemVariablesInstance() { return new SystemVariables(); }
/** * Get the variable with the specified name, from the highest priority scope that contain it. * * @param name the name of the variable; may not be null * @return the variable value; may be null if the variable is not currently set */ public String getVariable(String name) { List<ConcurrentMap<String, String>> orderedSystemVariablesByPriority = getOrderedSystemVariablesByScopePriority(); name = variableName(name); for (ConcurrentMap<String, String> variablesByScope : orderedSystemVariablesByPriority) { String variableName = variablesByScope.get(name); if (variableName != null) { return variableName; } } return null; }
@Override public void enterSetCharset(MySqlParser.SetCharsetContext ctx) { String charsetName = ctx.charsetName() != null ? parser.withoutQuotes(ctx.charsetName()) : parser.currentDatabaseCharset(); // Sets variables according to documentation at // https://dev.mysql.com/doc/refman/5.7/en/set-character-set.html // Using default scope for these variables, because this type of set statement you cannot specify // the scope manually parser.systemVariables().setVariable(MySqlSystemVariables.MySqlScope.SESSION, MySqlSystemVariables.CHARSET_NAME_CLIENT, charsetName); parser.systemVariables().setVariable(MySqlSystemVariables.MySqlScope.SESSION, MySqlSystemVariables.CHARSET_NAME_RESULT, charsetName); parser.systemVariables().setVariable(MySqlSystemVariables.MySqlScope.SESSION, MySqlSystemVariables.CHARSET_NAME_CONNECTION, parser.systemVariables().getVariable(MySqlSystemVariables.CHARSET_NAME_DATABASE)); super.enterSetCharset(ctx); }
@Override protected ConcurrentMap<String, String> forScope(Scope scope) { // local and session scope are the same in MySQL if (scope == MySqlScope.LOCAL) { scope = MySqlScope.SESSION; } return super.forScope(scope); } }
/** * Set the system variables on the DDL parser. * * @param variables the system variables; may not be null but may be empty */ public void setSystemVariables(Map<String, String> variables) { variables.forEach((varName, value) -> { ddlParser.systemVariables().setVariable(MySqlScope.SESSION, varName, value); }); }
protected ConcurrentMap<String, String> forScope(Scope scope) { if (scope != null) { return systemVariables.computeIfAbsent(scope, entities -> new ConcurrentHashMap<>()); } // return most prior scope variables if scope is not defined List<ConcurrentMap<String, String>> orderedSystemVariablesByScopePriority = getOrderedSystemVariablesByScopePriority(); return orderedSystemVariablesByScopePriority.isEmpty() ? null : orderedSystemVariablesByScopePriority.get(0); }
charsetName = currentDatabaseCharset(); systemVariables.setVariable(scope.get(), "character_set_client", charsetName); systemVariables.setVariable(scope.get(), "character_set_results", charsetName); systemVariables.setVariable(MySqlScope.SESSION, MySqlSystemVariables.CHARSET_NAME_CONNECTION, systemVariables.getVariable(MySqlSystemVariables.CHARSET_NAME_DATABASE)); charsetName = currentDatabaseCharset(); systemVariables.setVariable(scope.get(), "character_set_client", charsetName); systemVariables.setVariable(scope.get(), "character_set_results", charsetName); systemVariables.setVariable(scope.get(), "character_set_connection", charsetName); systemVariables.setVariable(scope.get(), variableName, value);
/** * Get the variable with the specified name, from the highest priority scope that contain it. * * @param name the name of the variable; may not be null * @return the variable value; may be null if the variable is not currently set */ public String getVariable(String name) { List<ConcurrentMap<String, String>> orderedSystemVariablesByPriority = getOrderedSystemVariablesByScopePriority(); name = variableName(name); for (ConcurrentMap<String, String> variablesByScope : orderedSystemVariablesByPriority) { String variableName = variablesByScope.get(name); if (variableName != null) { return variableName; } } return null; }
protected void parseUse(Marker marker) { tokens.consume("USE"); String dbName = tokens.consume(); setCurrentSchema(dbName); // Every time MySQL switches to a different database, it sets the "character_set_database" and "collation_database" // system variables. We replicate that behavior here (or the variable we care about) so that these variables are always // right for the current database. String charsetForDb = charsetNameForDatabase.get(dbName); systemVariables.setVariable(MySqlScope.GLOBAL, "character_set_database", charsetForDb); }
protected ConcurrentMap<String, String> forScope(Scope scope) { if (scope != null) { return systemVariables.computeIfAbsent(scope, entities -> new ConcurrentHashMap<>()); } // return most prior scope variables if scope is not defined List<ConcurrentMap<String, String>> orderedSystemVariablesByScopePriority = getOrderedSystemVariablesByScopePriority(); return orderedSystemVariablesByScopePriority.isEmpty() ? null : orderedSystemVariablesByScopePriority.get(0); }
/** * Get the name of the character set for the current database, via the "character_set_database" system property. * * @return the name of the character set for the current database, or null if not known ... */ protected String currentDatabaseCharset() { String charsetName = systemVariables.getVariable("character_set_database"); if (charsetName == null || "DEFAULT".equalsIgnoreCase(charsetName)) { charsetName = systemVariables.getVariable(SERVER_CHARSET_NAME); } return charsetName; }
/** * Set the variable with the specified scope. * * @param scope the variable scope; may be null if the session scope is to be used * @param name the name of the variable; may not be null * @param value the variable value; may be null if the value for the named variable is to be removed * @return this object for method chaining purposes; never null */ public SystemVariables setVariable(Scope scope, String name, String value) { name = variableName(name); if (value != null) { forScope(scope).put(name, value); } else { forScope(scope).remove(name); } return this; }
@Override public void enterSetNames(MySqlParser.SetNamesContext ctx) { String charsetName = ctx.charsetName() != null ? parser.withoutQuotes(ctx.charsetName()) : parser.currentDatabaseCharset(); // Sets variables according to documentation at // https://dev.mysql.com/doc/refman/5.7/en/set-names.html // Using default scope for these variables, because this type of set statement you cannot specify // the scope manually parser.systemVariables().setVariable(MySqlSystemVariables.MySqlScope.SESSION, MySqlSystemVariables.CHARSET_NAME_CLIENT, charsetName); parser.systemVariables().setVariable(MySqlSystemVariables.MySqlScope.SESSION, MySqlSystemVariables.CHARSET_NAME_RESULT, charsetName); parser.systemVariables().setVariable(MySqlSystemVariables.MySqlScope.SESSION, MySqlSystemVariables.CHARSET_NAME_CONNECTION, charsetName); super.enterSetNames(ctx); } }
@Override protected SystemVariables createNewSystemVariablesInstance() { return new SystemVariables(); }
@Override public void enterCreateDatabaseOption(MySqlParser.CreateDatabaseOptionContext ctx) { if (ctx.charsetName() != null) { String charsetName = parser.withoutQuotes(ctx.charsetName()); if ("DEFAULT".equalsIgnoreCase(charsetName)) { charsetName = parser.systemVariables().getVariable(MySqlSystemVariables.CHARSET_NAME_SERVER); } parser.charsetNameForDatabase().put(databaseName, charsetName); } super.enterCreateDatabaseOption(ctx); } }
/** * Get the variable with the specified name and scope. * * @param name the name of the variable; may not be null * @param scope the variable scope; may not be null * @return the variable value; may be null if the variable is not currently set */ public String getVariable(String name, Scope scope) { name = variableName(name); return forScope(scope).get(name); }
@Override public void enterUseStatement(MySqlParser.UseStatementContext ctx) { String dbName = parser.parseName(ctx.uid()); parser.setCurrentSchema(dbName); // Every time MySQL switches to a different database, it sets the "character_set_database" and "collation_database" // system variables. We replicate that behavior here (or the variable we care about) so that these variables are always // right for the current database. String charsetForDb = parser.charsetNameForDatabase().get(dbName); parser.systemVariables().setVariable(MySqlSystemVariables.MySqlScope.SESSION, MySqlSystemVariables.CHARSET_NAME_DATABASE, charsetForDb); super.enterUseStatement(ctx); } }
protected void parseDatabaseOptions(Marker start, String dbName) { // Handle the default character set and collation ... tokens.canConsume("DEFAULT"); if (tokens.canConsume("CHARACTER", "SET") || tokens.canConsume("CHARSET")) { tokens.canConsume("="); String charsetName = tokens.consume(); if ("DEFAULT".equalsIgnoreCase(charsetName)) { charsetName = systemVariables.getVariable(SERVER_CHARSET_NAME); } charsetNameForDatabase.put(dbName, charsetName); } if (tokens.canConsume("COLLATE")) { tokens.canConsume("="); tokens.consume(); // collation name } }