private void Prepare(bool generatingKeys) { checkConnection(); Close(); StringBuilder sqlString = new StringBuilder(CommandText.Length); NuoDbDataParameterCollection newParams = new NuoDbDataParameterCollection(); int state = 0; string curParamName = ""; bool inSingleQuotes = false, inDoubleQuotes = false, inSmartQuotes = false; foreach (char c in CommandText) { if (c == '\'' && !(inDoubleQuotes || inSmartQuotes)) { inSingleQuotes = !inSingleQuotes; state = 0; sqlString.Append(c); continue; } else if (c == '\"' && !(inSingleQuotes || inSmartQuotes)) { inDoubleQuotes = !inDoubleQuotes; state = 0; sqlString.Append(c); continue; } else if (c == '`' && !(inSingleQuotes || inDoubleQuotes)) { inSmartQuotes = !inSmartQuotes; state = 0; sqlString.Append(c); continue; } if (inSingleQuotes || inDoubleQuotes || inSmartQuotes) { sqlString.Append(c); continue; } if (c == '?') { state = 1; } else if (c == '@') { state = 2; } else if (state == 1) { if (c == '.') { state = 2; } else { // either add a new parameter, or carry over the user-provided one if (parameters.Count > newParams.Count) { newParams.Add(parameters[newParams.Count]); } else { newParams.Add(new NuoDbParameter()); } state = 0; sqlString.Append("?"); sqlString.Append(c); } } else if (state == 2) { if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_' || (curParamName.Length > 0 && ((c >= '0' && c <= '9') || c == '-'))) { curParamName += c; } else { // if the user-provided parameters have a value for this name, preserve it if (parameters.Contains(curParamName)) { newParams.Add(parameters[curParamName]); } else if (parameters.Contains("@" + curParamName)) { newParams.Add(parameters["@" + curParamName]); } else { NuoDbParameter p = new NuoDbParameter(); p.ParameterName = curParamName; newParams.Add(p); } sqlString.Append("?."); sqlString.Append(curParamName); sqlString.Append(c); curParamName = ""; state = 0; } } else { state = 0; sqlString.Append(c); } } // handle the case where the SQL statement ended while parsing a parameter if (state == 1) { // either add a new parameter, or carry over the user-provided one if (parameters.Count > newParams.Count) { newParams.Add(parameters[newParams.Count]); } else { newParams.Add(new NuoDbParameter()); } sqlString.Append("?"); } else if (state == 2) { // if the user-provided parameters have a value for this name, preserve it if (parameters.Contains(curParamName)) { newParams.Add(parameters[curParamName]); } else if (parameters.Contains("@" + curParamName)) { newParams.Add(parameters["@" + curParamName]); } else { NuoDbParameter p = new NuoDbParameter(); p.ParameterName = curParamName; newParams.Add(p); } sqlString.Append("?."); sqlString.Append(curParamName); } string nuodbSqlString = sqlString.ToString().TrimStart(null); // if we are given just the name of the stored procedure, retrieve the number of parameters and generate the full command if (CommandType == CommandType.StoredProcedure && !nuodbSqlString.StartsWith("EXECUTE ", StringComparison.InvariantCultureIgnoreCase) && !nuodbSqlString.StartsWith("CALL ", StringComparison.InvariantCultureIgnoreCase)) { char[] quotes = new char[] { '"' }; string[] parts = nuodbSqlString.Split(new char[] { '.' }); DataTable paramTable = null; if (parts.Length == 2) { paramTable = NuoDbConnectionInternal.GetSchemaHelper(connection, "ProcedureParameters", new string[] { null, parts[0].Trim(quotes), parts[1].Trim(quotes), null }); } else { NuoDbConnectionStringBuilder builder = new NuoDbConnectionStringBuilder(connection.ConnectionString); string schema = builder.Schema; if (schema.Length == 0) { schema = "USER"; } paramTable = NuoDbConnectionInternal.GetSchemaHelper(connection, "ProcedureParameters", new string[] { null, schema, parts[0].Trim(quotes), null }); } int numParams = 0; foreach (DataRow row in paramTable.Select("PARAMETER_DIRECTION <> 3", "ORDINAL_POSITION ASC")) { int ordinal = (int)row["ORDINAL_POSITION"]; if (ordinal != ++numParams) { throw new NuoDbSqlException(String.Format("Internal error: unexpected ordering of the parameters of the procedure {0}", nuodbSqlString)); } int direction = (int)row["PARAMETER_DIRECTION"]; ParameterDirection paramDirection; switch (direction) { case 1: paramDirection = ParameterDirection.Input; break; case 2: paramDirection = ParameterDirection.InputOutput; break; case 4: paramDirection = ParameterDirection.Output; break; default: throw new NuoDbSqlException(String.Format("Internal error: unexpected parameter type for procedure {0}", nuodbSqlString)); } // either add a new parameter, or carry over the user-provided one string paramName = (string)row["PARAMETER_NAME"]; if (parameters.Contains(paramName)) { newParams.Add(parameters[paramName]); } else if (parameters.Contains("@" + paramName)) { newParams.Add(parameters["@" + paramName]); } else if (parameters.Count > newParams.Count) { if (parameters[newParams.Count].ParameterName.Length == 0) { parameters[newParams.Count].ParameterName = paramName; } newParams.Add(parameters[newParams.Count]); } else { NuoDbParameter p = new NuoDbParameter(); p.ParameterName = paramName; newParams.Add(p); } newParams[newParams.Count - 1].DbType = NuoDbConnectionInternal.mapJavaSqlToDbType((int)row["PARAMETER_DATA_TYPE"]); newParams[newParams.Count - 1].Direction = paramDirection; } StringBuilder strBuilder = new StringBuilder("EXECUTE "); strBuilder.Append(nuodbSqlString); strBuilder.Append("("); for (int i = 0; i < numParams; i++) { if (i != 0) { strBuilder.Append(","); } strBuilder.Append("?"); } strBuilder.Append(")"); nuodbSqlString = strBuilder.ToString(); } if (nuodbSqlString.StartsWith("EXECUTE ", StringComparison.InvariantCultureIgnoreCase) || nuodbSqlString.StartsWith("CALL ", StringComparison.InvariantCultureIgnoreCase)) { if (connection.InternalConnection.protocolVersion < Protocol.PROTOCOL_VERSION12) { throw new NuoDbSqlException(String.Format("server protocol {0} doesn't support prepareCall", connection.InternalConnection.protocolVersion)); } EncodedDataStream dataStream = new RemEncodedStream(connection.InternalConnection.protocolVersion); dataStream.startMessage(Protocol.PrepareCall); dataStream.encodeString(nuodbSqlString); connection.InternalConnection.sendAndReceive(dataStream); handle = dataStream.getInt(); connection.InternalConnection.RegisterCommand(handle); int numberParameters = dataStream.getInt(); for (int i = 0; i < numberParameters; i++) { int direction = dataStream.getInt(); String name = dataStream.getString(); switch (direction) { case 0: newParams[i].Direction = ParameterDirection.Input; break; case 1: newParams[i].Direction = ParameterDirection.InputOutput; break; case 2: newParams[i].Direction = ParameterDirection.Output; break; } if (newParams[i].ParameterName.Length == 0) { newParams[i].ParameterName = name; } } parameters = newParams; isPrepared = true; isPreparedWithKeys = generatingKeys; } else { EncodedDataStream dataStream = new RemEncodedStream(connection.InternalConnection.protocolVersion); if (generatingKeys) { dataStream.startMessage(Protocol.PrepareStatementKeys); dataStream.encodeInt(generatingKeys ? 1 : 0); } else { dataStream.startMessage(Protocol.PrepareStatement); } dataStream.encodeString(nuodbSqlString); connection.InternalConnection.sendAndReceive(dataStream); handle = dataStream.getInt(); connection.InternalConnection.RegisterCommand(handle); int numberParameters = dataStream.getInt(); // a prepared DDL command fails to execute if (numberParameters != 0 || nuodbSqlString.StartsWith("SELECT ", StringComparison.InvariantCultureIgnoreCase)) { parameters = newParams; isPrepared = true; isPreparedWithKeys = generatingKeys; } else { Close(); isPrepared = false; } } }
private void Prepare(bool generatingKeys) { checkConnection(); Close(); StringBuilder sqlString = new StringBuilder(CommandText.Length); NuoDbDataParameterCollection newParams = new NuoDbDataParameterCollection(); int state = 0; string curParamName = ""; bool inSingleQuotes = false, inDoubleQuotes = false, inSmartQuotes = false; foreach (char c in CommandText) { if (c == '\'' && !(inDoubleQuotes || inSmartQuotes)) { inSingleQuotes = !inSingleQuotes; state = 0; sqlString.Append(c); continue; } else if (c == '\"' && !(inSingleQuotes || inSmartQuotes)) { inDoubleQuotes = !inDoubleQuotes; state = 0; sqlString.Append(c); continue; } else if (c == '`' && !(inSingleQuotes || inDoubleQuotes)) { inSmartQuotes = !inSmartQuotes; state = 0; sqlString.Append(c); continue; } if (inSingleQuotes || inDoubleQuotes || inSmartQuotes) { sqlString.Append(c); continue; } if (c == '?') state = 1; else if (c == '@') state = 2; else if (state == 1) { if (c == '.') state = 2; else { // either add a new parameter, or carry over the user-provided one if (parameters.Count > newParams.Count) newParams.Add(parameters[newParams.Count]); else newParams.Add(new NuoDbParameter()); state = 0; sqlString.Append("?"); sqlString.Append(c); } } else if (state == 2) { if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_' || (curParamName.Length > 0 && ((c >= '0' && c <= '9') || c == '-'))) { curParamName += c; } else { // if the user-provided parameters have a value for this name, preserve it if (parameters.Contains(curParamName)) newParams.Add(parameters[curParamName]); else if (parameters.Contains("@"+curParamName)) newParams.Add(parameters["@" + curParamName]); else { NuoDbParameter p = new NuoDbParameter(); p.ParameterName = curParamName; newParams.Add(p); } sqlString.Append("?."); sqlString.Append(curParamName); sqlString.Append(c); curParamName = ""; state = 0; } } else { state = 0; sqlString.Append(c); } } // handle the case where the SQL statement ended while parsing a parameter if (state == 1) { // either add a new parameter, or carry over the user-provided one if (parameters.Count > newParams.Count) newParams.Add(parameters[newParams.Count]); else newParams.Add(new NuoDbParameter()); sqlString.Append("?"); } else if (state == 2) { // if the user-provided parameters have a value for this name, preserve it if (parameters.Contains(curParamName)) newParams.Add(parameters[curParamName]); else if (parameters.Contains("@" + curParamName)) newParams.Add(parameters["@" + curParamName]); else { NuoDbParameter p = new NuoDbParameter(); p.ParameterName = curParamName; newParams.Add(p); } sqlString.Append("?."); sqlString.Append(curParamName); } string nuodbSqlString = sqlString.ToString().TrimStart(null); // if we are given just the name of the stored procedure, retrieve the number of parameters and generate the full command if(CommandType == CommandType.StoredProcedure && !nuodbSqlString.StartsWith("EXECUTE ", StringComparison.InvariantCultureIgnoreCase) && !nuodbSqlString.StartsWith("CALL ", StringComparison.InvariantCultureIgnoreCase)) { char[] quotes = new char[] { '"' }; string[] parts = nuodbSqlString.Split(new char[] { '.' }); DataTable paramTable = null; if (parts.Length == 2) paramTable = NuoDbConnectionInternal.GetSchemaHelper(connection, "ProcedureParameters", new string[] { null, parts[0].Trim(quotes), parts[1].Trim(quotes), null }); else { NuoDbConnectionStringBuilder builder = new NuoDbConnectionStringBuilder(connection.ConnectionString); string schema = builder.Schema; if(schema.Length==0) schema = "USER"; paramTable = NuoDbConnectionInternal.GetSchemaHelper(connection, "ProcedureParameters", new string[] { null, schema, parts[0].Trim(quotes), null }); } int numParams = 0; foreach (DataRow row in paramTable.Select("PARAMETER_DIRECTION <> 3", "ORDINAL_POSITION ASC")) { int ordinal = row.Field<int>("ORDINAL_POSITION"); if (ordinal != ++numParams) throw new NuoDbSqlException(String.Format("Internal error: unexpected ordering of the parameters of the procedure {0}", nuodbSqlString)); int direction = row.Field<int>("PARAMETER_DIRECTION"); ParameterDirection paramDirection; switch (direction) { case 1: paramDirection = ParameterDirection.Input; break; case 2: paramDirection = ParameterDirection.InputOutput; break; case 4: paramDirection = ParameterDirection.Output; break; default: throw new NuoDbSqlException(String.Format("Internal error: unexpected parameter type for procedure {0}", nuodbSqlString)); } // either add a new parameter, or carry over the user-provided one string paramName = row.Field<string>("PARAMETER_NAME"); if (parameters.Contains(paramName)) newParams.Add(parameters[paramName]); else if (parameters.Contains("@" + paramName)) newParams.Add(parameters["@" + paramName]); else if (parameters.Count > newParams.Count) { if (parameters[newParams.Count].ParameterName.Length == 0) parameters[newParams.Count].ParameterName = paramName; newParams.Add(parameters[newParams.Count]); } else { NuoDbParameter p = new NuoDbParameter(); p.ParameterName = paramName; newParams.Add(p); } newParams[newParams.Count - 1].DbType = NuoDbConnectionInternal.mapJavaSqlToDbType(row.Field<int>("PARAMETER_DATA_TYPE")); newParams[newParams.Count - 1].Direction = paramDirection; } StringBuilder strBuilder = new StringBuilder("EXECUTE "); strBuilder.Append(nuodbSqlString); strBuilder.Append("("); for (int i = 0; i < numParams; i++) { if (i != 0) strBuilder.Append(","); strBuilder.Append("?"); } strBuilder.Append(")"); nuodbSqlString = strBuilder.ToString(); } if (nuodbSqlString.StartsWith("EXECUTE ", StringComparison.InvariantCultureIgnoreCase) || nuodbSqlString.StartsWith("CALL ", StringComparison.InvariantCultureIgnoreCase)) { if(connection.InternalConnection.protocolVersion < Protocol.PROTOCOL_VERSION12) throw new NuoDbSqlException(String.Format("server protocol {0} doesn't support prepareCall", connection.InternalConnection.protocolVersion)); EncodedDataStream dataStream = new RemEncodedStream(connection.InternalConnection.protocolVersion); dataStream.startMessage(Protocol.PrepareCall); dataStream.encodeString(nuodbSqlString); connection.InternalConnection.sendAndReceive(dataStream); handle = dataStream.getInt(); connection.InternalConnection.RegisterCommand(handle); int numberParameters = dataStream.getInt(); for (int i = 0; i < numberParameters; i++) { int direction = dataStream.getInt(); String name = dataStream.getString(); switch(direction) { case 0: newParams[i].Direction = ParameterDirection.Input; break; case 1: newParams[i].Direction = ParameterDirection.InputOutput; break; case 2: newParams[i].Direction = ParameterDirection.Output; break; } if(newParams[i].ParameterName.Length == 0) newParams[i].ParameterName = name; } parameters = newParams; isPrepared = true; isPreparedWithKeys = generatingKeys; } else { EncodedDataStream dataStream = new RemEncodedStream(connection.InternalConnection.protocolVersion); if (generatingKeys) { dataStream.startMessage(Protocol.PrepareStatementKeys); dataStream.encodeInt(generatingKeys ? 1 : 0); } else dataStream.startMessage(Protocol.PrepareStatement); dataStream.encodeString(nuodbSqlString); connection.InternalConnection.sendAndReceive(dataStream); handle = dataStream.getInt(); connection.InternalConnection.RegisterCommand(handle); int numberParameters = dataStream.getInt(); // a prepared DDL command fails to execute if (numberParameters != 0 || nuodbSqlString.StartsWith("SELECT ", StringComparison.InvariantCultureIgnoreCase)) { parameters = newParams; isPrepared = true; isPreparedWithKeys = generatingKeys; } else { Close(); isPrepared = false; } } }
private void Prepare(bool generatingKeys) { checkConnection(); Close(); StringBuilder sqlString = new StringBuilder(sqlText.Length); NuoDbDataParameterCollection newParams = new NuoDbDataParameterCollection(); int state = 0; string curParamName = ""; bool inSingleQuotes = false, inDoubleQuotes = false, inSmartQuotes = false; foreach (char c in sqlText) { if (c == '\'' && !(inDoubleQuotes || inSmartQuotes)) { inSingleQuotes = !inSingleQuotes; state = 0; sqlString.Append(c); continue; } else if (c == '\"' && !(inSingleQuotes || inSmartQuotes)) { inDoubleQuotes = !inDoubleQuotes; state = 0; sqlString.Append(c); continue; } else if (c == '`' && !(inSingleQuotes || inDoubleQuotes)) { inSmartQuotes = !inSmartQuotes; state = 0; sqlString.Append(c); continue; } if (inSingleQuotes || inDoubleQuotes || inSmartQuotes) { sqlString.Append(c); continue; } if (c == '?') state = 1; else if (c == '@') state = 2; else if (state == 1) { if (c == '.') state = 2; else { // either add a new parameter, or carry over the user-provided one if (parameters.Count > newParams.Count) newParams.Add(parameters[newParams.Count]); else newParams.Add(new NuoDbParameter()); state = 0; sqlString.Append("?"); sqlString.Append(c); } } else if (state == 2) { if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_' || (curParamName.Length > 0 && ((c >= '0' && c <= '9') || c == '-'))) { curParamName += c; } else { // if the user-provided parameters have a value for this name, preserve it if (parameters.Contains(curParamName)) newParams.Add(parameters[curParamName]); else { NuoDbParameter p = new NuoDbParameter(); p.ParameterName = curParamName; newParams.Add(p); } sqlString.Append("?."); sqlString.Append(curParamName); sqlString.Append(c); curParamName = ""; state = 0; } } else { state = 0; sqlString.Append(c); } } // handle the case where the SQL statement ended while parsing a parameter if (state == 1) { // either add a new parameter, or carry over the user-provided one if (parameters.Count > newParams.Count) newParams.Add(parameters[newParams.Count]); else newParams.Add(new NuoDbParameter()); sqlString.Append("?"); } else if (state == 2) { // if the user-provided parameters have a value for this name, preserve it if (parameters.Contains(curParamName)) newParams.Add(parameters[curParamName]); else { NuoDbParameter p = new NuoDbParameter(); p.ParameterName = curParamName; newParams.Add(p); } sqlString.Append("?."); sqlString.Append(curParamName); } EncodedDataStream dataStream = new RemEncodedStream(connection.InternalConnection.protocolVersion); if (generatingKeys) { dataStream.startMessage(Protocol.PrepareStatementKeys); dataStream.encodeInt(generatingKeys ? 1 : 0); } else dataStream.startMessage(Protocol.PrepareStatement); dataStream.encodeString(sqlString.ToString()); connection.InternalConnection.sendAndReceive(dataStream); handle = dataStream.getInt(); connection.InternalConnection.RegisterCommand(handle); int numberParameters = dataStream.getInt(); // a prepared DDL command fails to execute if (numberParameters != 0 || CommandText.TrimStart(null).Substring(0, 6).ToUpper().Equals("SELECT")) { parameters = newParams; isPrepared = true; isPreparedWithKeys = generatingKeys; } else { Close(); isPrepared = false; } }