Release 11.0.0.17809
[platform/core/csapi/tizenfx.git] / src / Tizen.Data.Tdbc.Driver.Sqlite / Tizen.Data.Tdbc.Driver.Sqlite / Statement.cs
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.ComponentModel;
19 using System.Threading.Tasks;
20
21 namespace Tizen.Data.Tdbc.Driver.Sqlite
22 {
23     [EditorBrowsable(EditorBrowsableState.Never)]
24     public class Statement : IStatement
25     {
26         Connection _conn;
27         private IntPtr _stmt;
28         private bool disposedValue;
29
30         private void Clear()
31         {
32             if (_stmt != IntPtr.Zero)
33             {
34                 Interop.Sqlite.Finalize(_stmt);
35                 _stmt = IntPtr.Zero;
36             }
37         }
38
39         private bool Prepare(Sql sql)
40         {
41             Clear();
42             Console.WriteLine("Prepare: " + sql.Command);
43             int ret = Interop.Sqlite.Prepare(_conn.GetHandle(), sql.Command, -1, out _stmt, IntPtr.Zero);
44             if (ret != (int)Interop.Sqlite.ResultCode.SQLITE_OK)
45             {
46                 Console.WriteLine("Prepare: failed " + ret);
47                 return false;
48             }
49
50             foreach (var i in sql.Bindings)
51             {
52                 string key = i.Key;
53                 Object obj = i.Value;
54                 int pos = Interop.Sqlite.GetParameterIndex(_stmt, key);
55                 if (pos == 0)
56                     throw new InvalidOperationException("Invalid binding");
57
58                 if (typeof(int) == obj.GetType())
59                 {
60                     Interop.Sqlite.BindInt(_stmt, pos, (int)obj);
61                 }
62                 else if (typeof(bool) == obj.GetType())
63                 {
64                     bool val = (bool)obj;
65                     Interop.Sqlite.BindInt(_stmt, pos, val ? 1 : 0);
66                 }
67                 else if (typeof(double) == obj.GetType())
68                 {
69                     Interop.Sqlite.BindDouble(_stmt, pos, (double)obj);
70                 }
71                 else if (typeof(string) == obj.GetType())
72                 {
73                     Interop.Sqlite.BindText(_stmt, pos, (string)obj, -1, (IntPtr)(-1));
74                 }
75                 else if (typeof(byte[]) == obj.GetType())
76                 {
77                     if (obj != null)
78                         Interop.Sqlite.BindData(_stmt, pos, (byte[])obj, ((byte[])obj).Length, IntPtr.Zero);
79                 }
80             }
81
82             return true;
83         }
84
85         internal Statement(Connection conn)
86         {
87             _conn = conn;
88         }
89
90         public bool Execute(Sql sql)
91         {
92             if (!Prepare(sql))
93                 return false;
94             int ret = Interop.Sqlite.Step(_stmt);
95             Console.WriteLine("Execute: " + ret); 
96             if (ret != (int)Interop.Sqlite.ResultCode.SQLITE_ROW &&
97                 ret != (int)Interop.Sqlite.ResultCode.SQLITE_DONE)
98                 return false;
99             return true;
100         }
101
102         public int ExecuteUpdate(Sql sql)
103         {
104             if (!Prepare(sql))
105                 return 0;
106             int ret = Interop.Sqlite.Step(_stmt);
107             if (ret != (int)Interop.Sqlite.ResultCode.SQLITE_ROW &&
108                 ret != (int)Interop.Sqlite.ResultCode.SQLITE_DONE)
109                 return 0;
110             return Interop.Sqlite.Changes(_conn.GetHandle());
111         }
112
113         public IResultSet ExecuteQuery(Sql sql)
114         {
115             bool prepared = Prepare(sql);
116
117             if (!prepared)
118                 throw new InvalidOperationException("Couldn't prepare");
119
120             var set = new ResultSet(_stmt, _conn);
121             _stmt = IntPtr.Zero;
122
123             return set;
124         }
125
126         public async Task<IResultSet> ExecuteQueryAsync(Sql sql)
127         {
128             return await Task.Run(() =>
129             {
130                 return ExecuteQuery(sql);
131             }).ConfigureAwait(false);
132         }
133
134         public async Task<int> ExecuteUpdateAsync(Sql sql)
135         {
136             return await Task.Run(() =>
137             {
138                 return ExecuteUpdate(sql);
139             }).ConfigureAwait(false);
140         }
141
142         public async Task<bool> ExecuteAsync(Sql sql)
143         {
144             return await Task.Run(() =>
145             {
146                 return Execute(sql);
147             }).ConfigureAwait(false);
148         }
149
150         protected virtual void Dispose(bool disposing)
151         {
152             if (!disposedValue)
153             {
154                 if (disposing)
155                 {
156                 }
157
158                 Clear();
159                 disposedValue = true;
160             }
161         }
162
163         ~Statement()
164         {
165             Dispose(disposing: false);
166         }
167
168         public void Dispose()
169         {
170             Dispose(disposing: true);
171             GC.SuppressFinalize(this);
172         }
173     }
174 }