// Licensed to the .NET Foundation under one or more agreements.// The .NET Foundation licenses this file to you under the Apache 2.0 License.// See the LICENSE file in the project root for more information.//// Copyright (c) Jeff Hardy 2010-2012.//using System;using System.Collections;using System.Diagnostics;using Community.CsharpSqlite;using IronPython.Runtime;using IronPython.Runtime.Operations;using IronPython.Runtime.Types;using sqlite3_stmt = Community.CsharpSqlite.Sqlite3.Vdbe;namespace IronPython.SQLite{internal enum StatementType{Unknown,Select,Insert,Update,Delete,Replace,Other}[DebuggerDisplay("{sql}")]internal class Statement{private readonly Guid uniqueid;private Sqlite3.sqlite3 db;internal sqlite3_stmt st;private object current = null, nextRow = null;private bool started = false;private string sql;private bool bound = false;internal bool in_use = false;public string Tail { get; private set; }public Statement(PythonSQLite.Connection connection, string operation){this.uniqueid = Guid.NewGuid();this.db = connection.db;this.sql = operation;this.st = null;string tail = null;if(Sqlite3.sqlite3_prepare(this.db, this.sql, -1, ref this.st, ref tail) != Sqlite3.SQLITE_OK /*TODO: || too much sql */){Sqlite3.sqlite3_finalize(st);this.st = null;throw PythonSQLite.GetSqliteError(this.db, null);}this.Tail = tail;}private Statement(Sqlite3.sqlite3 db, sqlite3_stmt stmt, string operation, string tail){this.uniqueid = Guid.NewGuid();this.db = db;this.sql = operation;this.st = stmt;this.Tail = tail;}~Statement(){if(this.st != null){Sqlite3.sqlite3_finalize(this.st);}this.st = null;}private StatementType _type = StatementType.Unknown;public StatementType StatementType{get{if(this._type != StatementType.Unknown)return _type;string s = this.sql.TrimStart();if(s.StartsWith("select", StringComparison.InvariantCultureIgnoreCase))this._type = StatementType.Select;else if(s.StartsWith("insert", StringComparison.InvariantCultureIgnoreCase))this._type = StatementType.Insert;else if(s.StartsWith("update", StringComparison.InvariantCultureIgnoreCase))this._type = StatementType.Update;else if(s.StartsWith("delete", StringComparison.InvariantCultureIgnoreCase))this._type = StatementType.Delete;else if(s.StartsWith("replace", StringComparison.InvariantCultureIgnoreCase))this._type = StatementType.Replace;elsethis._type = StatementType.Other;return this._type;}}public void BindParameters(CodeContext context, object parameters){if(bound)this.ClearParameters();int num_params_needed = Sqlite3.sqlite3_bind_parameter_count(this.st);if(parameters == null){if(num_params_needed > 0)throw PythonSQLite.MakeProgrammingError("parameters are required but not specified.");elsereturn;}if(parameters is IDictionary)BindParameters(context, (IDictionary)parameters, num_params_needed);else if(parameters is IList)BindParameters(context, (IList)parameters, num_params_needed);elsethrow PythonSQLite.MakeProgrammingError("unknown parameter type");bound = true;}private void BindParameters(CodeContext context, IDictionary args, int num_params_needed){for(int i = 1; i <= num_params_needed; ++i){string binding_name = Sqlite3.sqlite3_bind_parameter_name(this.st, i);if(string.IsNullOrEmpty(binding_name))throw PythonSQLite.MakeProgrammingError("Binding {0} has no name, but you supplied a dictionary (which has only names).".Format(i));// remove the leading colonbinding_name = binding_name.Substring(1);if(args.Contains(binding_name))BindParameter(context, i, maybeAdapt(context, args[binding_name]));elsethrow PythonSQLite.MakeProgrammingError("You did not supply a value for binding {0}.".Format(i));}}private void BindParameters(CodeContext context, IList args, int num_params_needed){if(num_params_needed != args.Count)throw PythonSQLite.MakeProgrammingError("Incorrect number of bindings supplied.");for(int i = 0; i < args.Count; ++i){BindParameter(context, i + 1, maybeAdapt(context, args[i]));}}private void BindParameter(CodeContext context, int index, object arg){int rc;if(arg == null)rc = Sqlite3.sqlite3_bind_null(st, index);else if(arg is int)rc = Sqlite3.sqlite3_bind_int(st, index, (int)arg);else if(arg is bool)rc = Sqlite3.sqlite3_bind_int(st, index, (bool)arg ? 1 : 0);else if(arg is long)rc = Sqlite3.sqlite3_bind_int64(st, index, (long)arg);else if (arg is System.Numerics.BigInteger)rc = Sqlite3.sqlite3_bind_int64(st, index, (long)((System.Numerics.BigInteger)arg));else if(arg is float)rc = Sqlite3.sqlite3_bind_double(st, index, (float)arg);else if(arg is double)rc = Sqlite3.sqlite3_bind_double(st, index, (double)arg);else if(arg is string)rc = Sqlite3.sqlite3_bind_text(st, index, (string)arg, -1, Sqlite3.SQLITE_TRANSIENT);else if(arg is byte[])rc = Sqlite3.sqlite3_bind_blob(this.st, index, (byte[])arg, -1, Sqlite3.SQLITE_TRANSIENT);elsethrow PythonSQLite.MakeInterfaceError("Unable to bind parameter {0} - unsupported type {1}".Format(index, arg.GetType()));if(rc != Sqlite3.SQLITE_OK)throw PythonSQLite.MakeInterfaceError("Unable to bind parameter {0}: {1}".Format(index, Sqlite3.sqlite3_errmsg(db)));}private object maybeAdapt(CodeContext context, object value){return needsAdaptation(context, value) ? adaptValue(context, value) : value;}private bool needsAdaptation(CodeContext context, object value){// TODO The check for primitive types could probably be cached like pysqlite doesif(value == null ||value is int ||value is bool ||value is long ||value is System.Numerics.BigInteger ||value is float ||value is double ||value is string ||value is byte[]){object proto = DynamicHelpers.GetPythonTypeFromType(typeof(PythonSQLite.PrepareProtocol));object type = DynamicHelpers.GetPythonType(value);object key = new PythonTuple(DefaultContext.Default, new[] { type, proto });return PythonSQLite.adapters.ContainsKey(key);}else{return true;}}private object adaptValue(CodeContext context, object value){object proto = DynamicHelpers.GetPythonTypeFromType(typeof(PythonSQLite.PrepareProtocol));object type = DynamicHelpers.GetPythonType(value);object key = new PythonTuple(DefaultContext.Default, new[] { type, proto });object adapter;if(PythonSQLite.adapters.TryGetValue(key, out adapter)){object adapted = PythonCalls.Call(context, adapter, value);return adapted;}// TODO: Use proto? Any value whatsoever?object conform;if(context.LanguageContext.Operations.TryGetMember(value, "__conform__", out conform)){object adapted = PythonCalls.Call(context, conform, proto);if(adapted != null){return adapted;}}return value;}public int RawStep(){return Util.Step(st);}public int SqliteFinalize(){int rc = Sqlite3.SQLITE_OK;if(this.st != null){rc = Sqlite3.sqlite3_finalize(this.st);this.st = null;}this.in_use = false;return rc;}public int Reset(){int rc = Sqlite3.SQLITE_OK;if(this.in_use && this.st != null){rc = Sqlite3.sqlite3_reset(this.st);if(rc == Sqlite3.SQLITE_OK)this.in_use = false;}return rc;}private void ClearParameters(){if(Sqlite3.sqlite3_clear_bindings(this.st) != Sqlite3.SQLITE_OK)throw PythonSQLite.GetSqliteError(this.db, null);}internal void MarkDirty(){this.in_use = true;}internal int Recompile(CodeContext context, object parameters){sqlite3_stmt new_st = null;string tail = null;int rc = Sqlite3.sqlite3_prepare(this.db, this.sql, -1, ref new_st, ref tail);if(rc == Sqlite3.SQLITE_OK){Statement new_stmt = new Statement(this.st.db, new_st, this.sql, tail);new_stmt.BindParameters(context, parameters);Sqlite3.sqlite3_finalize(this.st);this.st = new_st;}return rc;}}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。