public ConnectionPool(string connectionString)
            {
                _disposed         = false;
                _syncRoot         = new object();
                _connectionString = connectionString;
                NuoDbConnectionStringBuilder connBuilder = new NuoDbConnectionStringBuilder(_connectionString);

                _lifeTime    = TimeSpan.FromSeconds(connBuilder.ConnectionLifetimeOrDefault);
                _maxLifeTime = TimeSpan.FromSeconds(connBuilder.MaxLifetimeOrDefault);
                _available   = new Queue <Item>();
                _busy        = new List <NuoDbConnectionInternal>();
            }
Example #2
0
        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;
                }
            }
        }