5 using System
.Data
.Common
;
6 using System
.Data
.SqlClient
;
7 using System
.Collections
.Generic
;
11 internal static class VxDb
{
12 static WvLog log
= new WvLog("VxDb", WvLog
.L
.Debug2
);
14 internal static void ExecScalar(string connid
, string query
,
15 out VxColumnType coltype
, out object result
)
17 log
.print(WvLog
.L
.Debug3
, "ExecScalar {0}\n", query
);
21 using (var dbi
= VxSqlPool
.create(connid
))
22 using (var qr
= dbi
.select(query
))
24 var ci
= ProcessSchema(qr
.columns
);
27 coltype
= VxColumnType
.String
;
32 coltype
= ci
[0].VxColumnType
;
33 var en
= qr
.GetEnumerator();
35 result
= en
.Current
[0].inner
;
38 coltype
= VxColumnType
.String
;
45 throw new VxSqlException(e
.Message
, e
);
50 internal static void SendChunkRecordSignal(WvDbus conn
,
51 WvDbusMsg call
, string sender
,
52 VxColumnInfo
[] colinfo
,
53 object[][] data
, byte[][] nulls
)
56 VxDbusRouter
.PrepareRecordsetWriter(colinfo
, data
, nulls
);
57 writer
.Write(call
.serial
);
59 new WvDbusSignal(call
.sender
, call
.path
, "vx.db", "ChunkRecordsetSig",
66 internal static void ExecChunkRecordset(WvDbus conn
,
67 WvDbusMsg call
, out WvDbusMsg reply
)
69 string connid
= VxDbusRouter
.GetClientId(call
);
73 reply
= call
.err_reply(
74 "org.freedesktop.DBus.Error.Failed",
75 "Could not identify the client");
81 string query
= it
.pop();
82 string iquery
= query
.ToLower().Trim();
84 // XXX this is fishy, really... whitespace fucks it up.
86 if (iquery
.StartsWith("list tables"))
87 query
= "exec sp_tables";
88 else if (iquery
.StartsWith("list columns "))
89 query
= String
.Format("exec sp_columns @table_name='{0}'",
91 else if (iquery
.StartsWith("list all table") &&
92 iquery
.StartsWith("list all tablefunction") == false)
93 query
= "select distinct cast(Name as varchar(max)) Name"
95 + " where objectproperty(id,'IsTable')=1 "
98 else if (iquery
.StartsWith("list all"))
99 // Format: list all {view|trigger|procedure|scalarfunction|tablefunction}
100 // Returns: a list of all of whatever
101 query
= String
.Format(
103 + " cast (object_name(id) as varchar(256)) Name "
104 + " from syscomments "
105 + " where objectproperty(id,'Is{0}') = 1 "
107 query
.Split(' ')[2].Trim());
108 else if (iquery
.StartsWith("get object"))
110 // get object {view|trigger|procedure|scalarfunction|tablefunction} name
111 // Returns: the "source code" to the object
112 query
= String
.Format(
113 "select cast(text as varchar(max)) text "
114 + "from syscomments "
115 + "where objectproperty(id, 'Is{0}') = 1 "
116 + "and object_name(id) = '{1}' "
117 + "order by number, colid ",
118 query
.Split(' ')[2].Trim(),
119 query
.Split(' ')[3].Trim());
121 log
.print(WvLog
.L
.Debug3
, "ExecChunkRecordset {0}\n", query
);
123 string sender
= call
.sender
;
127 // FIXME: Sadly, this is stupidly similar to ExecRecordset.
128 // Anything we can do here to identify commonalities?
129 using (var dbi
= VxSqlPool
.create(connid
))
130 using (WvSqlRows resultset
= dbi
.select(query
))
132 List
<object[]> rows
= new List
<object[]>();
133 List
<byte[]> rownulls
= new List
<byte[]>();
135 // Our size here is just an approximation.
138 var columns
= resultset
.columns
.ToArray();
139 VxColumnInfo
[] colinfo
= ProcessSchema(columns
);
140 int ncols
= columns
.Count();
142 foreach (WvSqlRow cur_row
in resultset
)
144 object[] row
= new object[ncols
];
145 byte[] rownull
= new byte[ncols
];
146 cursize
+= rownull
.Length
;
148 for (int i
= 0; i
< ncols
; i
++)
150 WvAutoCast cval
= cur_row
[i
];
151 bool isnull
= cval
.IsNull
;
155 rownull
[i
] = isnull
? (byte)1 : (byte)0;
157 switch (colinfo
[i
].VxColumnType
)
159 case VxColumnType
.Int64
:
161 (Int64
)cval
: new Int64();
162 cursize
+= sizeof(Int64
);
164 case VxColumnType
.Int32
:
166 (Int32
)cval
: new Int32();
167 cursize
+= sizeof(Int32
);
169 case VxColumnType
.Int16
:
171 (Int16
)cval
: new Int16();
172 cursize
+= sizeof(Int16
);
174 case VxColumnType
.UInt8
:
176 (Byte
)cval
: new Byte();
177 cursize
+= sizeof(Byte
);
179 case VxColumnType
.Bool
:
181 (bool)cval
: new Boolean();
182 cursize
+= sizeof(Boolean
);
184 case VxColumnType
.Double
:
185 // Might return a Single or Double
186 // FIXME: Check if getting a single causes this
189 (double)cval
: (double)0.0;
190 cursize
+= sizeof(double);
192 case VxColumnType
.Uuid
:
197 ((string)cval
).Length
* sizeof(Char
) : 0;
199 case VxColumnType
.Binary
:
203 row
[i
] = new byte[0];
207 row
[i
] = (byte[])cval
;
208 cursize
+= ((byte[])cval
).Length
;
211 case VxColumnType
.String
:
212 row
[i
] = !isnull
? (string)cval
: "";
214 ((string)cval
).Length
* sizeof(Char
) : 0;
216 case VxColumnType
.DateTime
:
218 new VxDbusDateTime((DateTime
)cval
) :
219 new VxDbusDateTime();
220 cursize
+= System
.Runtime
.InteropServices
.Marshal
.SizeOf((VxDbusDateTime
)row
[i
]);
222 case VxColumnType
.Decimal
:
224 ((Decimal
)cval
).ToString() : "";
225 cursize
+= ((string)(row
[i
])).Length
*
232 rownulls
.Add(rownull
);
234 if (cursize
>= 1024*1024) //approx 1 MB
236 log
.print(WvLog
.L
.Debug4
,
237 "(1 MB reached; {0} rows)\n",
240 SendChunkRecordSignal(conn
, call
, sender
, colinfo
,
244 rows
= new List
<object[]>();
245 rownulls
= new List
<byte[]>();
250 // OK, we're down to either one more packet or no more data
251 // Package that up in the 'reply' to this message, saving some
254 log
.print(WvLog
.L
.Debug4
, "(Remaining data; {0} rows)\n",
257 // Create reply, either with or with no data
258 WvDbusWriter replywriter
=
259 VxDbusRouter
.PrepareRecordsetWriter(colinfo
,
262 reply
= call
.reply("a(issnny)vaay").write(replywriter
);
264 } catch (DbException e
) {
265 throw new VxSqlException(e
.Message
, e
);
269 internal static void ExecRecordset(string connid
, string query
,
270 out VxColumnInfo
[] colinfo
, out object[][] data
,
271 out byte[][] nullity
)
275 if (query
.ToLower().StartsWith("list tables"))
276 query
= "exec sp_tables";
277 else if (query
.ToLower().StartsWith("list columns "))
278 query
= String
.Format("exec sp_columns @table_name='{0}'",
279 query
.Substring(13));
280 else if (query
.ToLower().StartsWith("list all table") &&
281 query
.ToLower().StartsWith("list all tablefunction") == false)
282 query
= "select distinct cast(Name as varchar(max)) Name"
283 + " from sysobjects "
284 + " where objectproperty(id,'IsTable')=1 "
287 else if (query
.ToLower().StartsWith("list all"))
288 // Format: list all {view|trigger|procedure|scalarfunction|tablefunction}
289 // Returns: a list of all of whatever
290 query
= String
.Format(
292 + " cast (object_name(id) as varchar(256)) Name "
293 + " from syscomments "
294 + " where objectproperty(id,'Is{0}') = 1 "
296 query
.Split(' ')[2].Trim());
297 else if (query
.ToLower().StartsWith("get object"))
299 // get object {view|trigger|procedure|scalarfunction|tablefunction} name
300 // Returns: the "source code" to the object
301 query
= String
.Format(
302 "select cast(text as varchar(max)) text "
303 + "from syscomments "
304 + "where objectproperty(id, 'Is{0}') = 1 "
305 + "and object_name(id) = '{1}' "
306 + "order by number, colid ",
307 query
.Split(' ')[2].Trim(),
308 query
.Split(' ')[3].Trim());
310 log
.print(WvLog
.L
.Debug3
, "ExecRecordset {0}\n", query
);
313 List
<object[]> rows
= new List
<object[]>();
314 List
<byte[]> rownulls
= new List
<byte[]>();
316 using (var dbi
= VxSqlPool
.create(connid
))
317 using (var result
= dbi
.select(query
))
319 var columns
= result
.columns
.ToArray();
321 if (columns
.Length
<= 0)
322 log
.print("No columns in resulting data set.");
324 colinfo
= ProcessSchema(result
.columns
);
326 foreach (var r
in result
)
328 object[] row
= new object[columns
.Length
];
329 byte[] rownull
= new byte[columns
.Length
];
331 for (int i
= 0; i
< columns
.Length
; i
++)
333 bool isnull
= r
[i
].IsNull
;
335 rownull
[i
] = isnull
? (byte)1 : (byte)0;
337 switch (colinfo
[i
].VxColumnType
)
339 case VxColumnType
.Int64
:
340 row
[i
] = !isnull
? (Int64
)r
[i
] : new Int64();
342 case VxColumnType
.Int32
:
343 row
[i
] = !isnull
? (Int32
)r
[i
] : new Int32();
345 case VxColumnType
.Int16
:
346 row
[i
] = !isnull
? (Int16
)r
[i
] : new Int16();
348 case VxColumnType
.UInt8
:
349 row
[i
] = !isnull
? (Byte
)r
[i
] : new Byte();
351 case VxColumnType
.Bool
:
352 row
[i
] = !isnull
? (bool)r
[i
] : new Boolean();
354 case VxColumnType
.Double
:
355 // Might return a Single or Double
356 // FIXME: Check if getting a single causes this
358 row
[i
] = !isnull
? (double)r
[i
] : (double)0.0;
360 case VxColumnType
.Uuid
:
361 row
[i
] = !isnull
? ((Guid
)r
[i
]).ToString() : "";
363 case VxColumnType
.Binary
:
364 row
[i
] = !isnull
? (byte[])r
[i
] : new byte[0];
366 case VxColumnType
.String
:
367 row
[i
] = !isnull
? (string)r
[i
] : "";
369 case VxColumnType
.DateTime
:
371 new VxDbusDateTime(r
[i
]) :
372 new VxDbusDateTime();
374 case VxColumnType
.Decimal
:
376 ? ((decimal)r
[i
]).ToString() : "";
382 rownulls
.Add(rownull
);
385 data
= rows
.ToArray();
386 nullity
= rownulls
.ToArray();
387 log
.print(WvLog
.L
.Debug4
, "({0} rows)\n", data
.Length
);
388 wv
.assert(nullity
.Length
== data
.Length
);
390 } catch (DbException e
) {
391 throw new VxSqlException(e
.Message
, e
);
395 private static VxColumnInfo
[] ProcessSchema(IEnumerable
<WvColInfo
> columns
)
397 // FIXME: This is stupidly similar to ProcessSchema
398 int ncols
= columns
.Count();
399 VxColumnInfo
[] colinfo
= new VxColumnInfo
[ncols
];
406 foreach (WvColInfo col
in columns
)
408 System
.Type type
= col
.type
;
410 if (type
== typeof(object))
412 // We're not even going to try to handle this yet
413 throw new VxBadSchemaException("Columns of type sql_variant "
414 + "are not supported by Versaplex at this time");
417 VxColumnType coltype
;
419 if (type
== typeof(Int64
)) {
420 coltype
= VxColumnType
.Int64
;
421 } else if (type
== typeof(Int32
)) {
422 coltype
= VxColumnType
.Int32
;
423 } else if (type
== typeof(Int16
)) {
424 coltype
= VxColumnType
.Int16
;
425 } else if (type
== typeof(Byte
)) {
426 coltype
= VxColumnType
.UInt8
;
427 } else if (type
== typeof(Boolean
)) {
428 coltype
= VxColumnType
.Bool
;
429 } else if (type
== typeof(Single
) || type
== typeof(Double
)) {
430 coltype
= VxColumnType
.Double
;
431 } else if (type
== typeof(Guid
)) {
432 coltype
= VxColumnType
.Uuid
;
433 } else if (type
== typeof(Byte
[])) {
434 coltype
= VxColumnType
.Binary
;
435 } else if (type
== typeof(string)) {
436 coltype
= VxColumnType
.String
;
437 } else if (type
== typeof(DateTime
)) {
438 coltype
= VxColumnType
.DateTime
;
439 } else if (type
== typeof(Decimal
)) {
440 coltype
= VxColumnType
.Decimal
;
442 throw new VxBadSchemaException("Columns of type "
443 + type
.ToString() + " are not supported by "
444 + "Versaplex at this time " +
445 "(column " + col
.name
+ ")");
448 colinfo
[i
] = new VxColumnInfo(col
.name
, coltype
,
449 col
.nullable
, col
.size
, col
.precision
, col
.scale
);
458 public class VxDbusRouter
460 static WvLog log
= new WvLog("VxDbusRouter");
462 void MethodCallProcessor(WvDbus conn
, WvDbusMsg call
,
463 out WvDbusMsg reply
);
465 public VxDbusRouter()
469 public bool route(WvDbus conn
, WvDbusMsg msg
, out WvDbusMsg reply
)
471 MethodCallProcessor p
;
473 if (msg
.ifc
!= "vx.db" || msg
.path
!= "/db")
479 if (msg
.method
== "Test")
481 else if (msg
.method
== "Quit")
483 else if (msg
.method
== "ExecScalar")
485 else if (msg
.method
== "ExecRecordset")
486 p
= CallExecRecordset
;
487 else if (msg
.method
== "ExecChunkRecordset")
488 p
= CallExecChunkRecordset
;
489 else if (msg
.method
== "GetSchemaChecksums")
490 p
= CallGetSchemaChecksums
;
491 else if (msg
.method
== "GetSchema")
493 else if (msg
.method
== "PutSchema")
495 else if (msg
.method
== "DropSchema")
497 else if (msg
.method
== "GetSchemaData")
498 p
= CallGetSchemaData
;
499 else if (msg
.method
== "PutSchemaData")
500 p
= CallPutSchemaData
;
503 // FIXME: this should be done at a higher level somewhere
504 reply
= msg
.err_reply(
505 "org.freedesktop.DBus.Error.UnknownMethod",
506 "Method name {0} not found on interface {1}",
507 msg
.method
, msg
.ifc
);
510 ExecuteCall(p
, conn
, msg
, out reply
);
514 void ExecuteCall(MethodCallProcessor processor
,
516 WvDbusMsg call
, out WvDbusMsg reply
)
519 processor(conn
, call
, out reply
);
520 } catch (VxRequestException e
) {
521 reply
= call
.err_reply(e
.DBusErrorType
, e
.Message
);
522 log
.print("SQL result: {0}\n", e
.Short());
523 } catch (Exception e
) {
524 reply
= call
.err_reply("vx.db.exception",
525 "An internal error occurred.");
526 log
.print("{0}\n", e
.ToString());
530 static Dictionary
<string,string> usernames
= new Dictionary
<string, string>();
532 public static string GetClientId(WvDbusMsg call
)
534 string sender
= call
.sender
;
536 // For now, the client ID is just the username of the Unix UID that
537 // DBus has associated with the connection.
539 var conn
= VersaMain
.conn
;
540 if (!usernames
.TryGetValue(sender
, out username
))
544 // FIXME: This will likely change as we find a more
545 // universal way to do SSL authentication via D-Bus.
546 username
= VxSqlPool
.GetUsernameForCert(
547 conn
.GetCertFingerprint(sender
));
553 // FIXME: This system call isn't actually standard
554 username
= conn
.GetUnixUserName(sender
);
560 // FIXME: This system call is standard, but not useful
562 username
= conn
.GetUnixUser(sender
).ToString();
566 username
= "*"; // use default connection, if any
573 // Remember the result, so we don't have to ask DBus all the time
574 usernames
[sender
] = username
;
576 log
.print(WvLog
.L
.Info
,
577 "New connection '{0}' is user '{1}'\n",
584 static WvDbusMsg
CreateUnknownMethodReply(WvDbusMsg call
,
587 return call
.err_reply("org.freedesktop.DBus.Error.UnknownMethod",
588 "No overload of {0} has signature '{1}'",
589 methodname
, call
.signature
);
592 static void CallTest(WvDbus conn
,
593 WvDbusMsg call
, out WvDbusMsg reply
)
595 if (call
.signature
.ne()) {
596 reply
= CreateUnknownMethodReply(call
, "Test");
600 string clientid
= GetClientId(call
);
601 if (clientid
== null)
603 reply
= call
.err_reply("org.freedesktop.DBus.Error.Failed",
604 "Could not identify the client");
608 VxColumnInfo
[] colinfo
;
611 VxDb
.ExecRecordset(clientid
, "select 'Works! :D'",
612 out colinfo
, out data
, out nullity
);
614 // FIXME: Add vx.db.toomuchdata error
615 WvDbusWriter writer
= PrepareRecordsetWriter(colinfo
, data
, nullity
);
616 reply
= call
.reply("a(issnny)vaay").write(writer
);
619 static void CallQuit(WvDbus conn
,
620 WvDbusMsg call
, out WvDbusMsg reply
)
622 // FIXME: Check permissions here
623 WvDbusWriter writer
= new WvDbusWriter();
624 writer
.Write("Quit");
625 reply
= call
.reply("s").write(writer
);
626 VersaMain
.want_to_die
= true;
629 static void CallExecScalar(WvDbus conn
,
630 WvDbusMsg call
, out WvDbusMsg reply
)
632 if (call
.signature
!= "s") {
633 reply
= CreateUnknownMethodReply(call
, "ExecScalar");
637 if (call
.Body
== null) {
638 reply
= call
.err_reply
639 ("org.freedesktop.DBus.Error.InvalidSignature",
640 "Signature provided but no body received");
644 string clientid
= GetClientId(call
);
645 if (clientid
== null)
647 reply
= call
.err_reply("org.freedesktop.DBus.Error.Failed",
648 "Could not identify the client");
652 var it
= call
.iter();
653 string query
= it
.pop();
656 VxColumnType coltype
;
657 VxDb
.ExecScalar(clientid
, (string)query
,
658 out coltype
, out result
);
660 WvDbusWriter writer
= new WvDbusWriter();
661 writer
.WriteSig(VxColumnTypeToSignature(coltype
));
662 WriteV(writer
, coltype
, result
);
664 reply
= call
.reply("v").write(writer
);
667 static void WriteColInfo(WvDbusWriter writer
, VxColumnInfo
[] colinfo
)
670 writer
.WriteArray(8, colinfo
, (w2
, i
) => {
673 w2
.Write(i
.coltype
.ToString());
674 w2
.Write(i
.precision
);
676 w2
.Write(i
.nullable
);
680 public static void CallExecRecordset(WvDbus conn
,
681 WvDbusMsg call
, out WvDbusMsg reply
)
683 if (call
.signature
!= "s") {
684 reply
= CreateUnknownMethodReply(call
, "ExecRecordset");
688 if (call
.Body
== null) {
689 reply
= call
.err_reply
690 ("org.freedesktop.DBus.Error.InvalidSignature",
691 "Signature provided but no body received");
695 string clientid
= GetClientId(call
);
696 if (clientid
== null)
698 reply
= call
.err_reply("org.freedesktop.DBus.Error.Failed",
699 "Could not identify the client");
703 var it
= call
.iter();
704 string query
= it
.pop();
706 VxColumnInfo
[] colinfo
;
709 VxDb
.ExecRecordset(clientid
, (string)query
,
710 out colinfo
, out data
, out nullity
);
712 // FIXME: Add vx.db.toomuchdata error
713 WvDbusWriter writer
= PrepareRecordsetWriter(colinfo
, data
, nullity
);
715 reply
= call
.reply("a(issnny)vaay").write(writer
);
718 static void CallExecChunkRecordset(WvDbus conn
,
719 WvDbusMsg call
, out WvDbusMsg reply
)
721 // XXX: Stuff in this comment block shamelessly stolen from
722 // "CallExecRecordset".
723 if (call
.signature
!= "s") {
724 reply
= CreateUnknownMethodReply(call
, "ExecChunkRecordset");
728 if (call
.Body
== null) {
729 reply
= call
.err_reply
730 ("org.freedesktop.DBus.Error.InvalidSignature",
731 "Signature provided but no body received");
736 VxDb
.ExecChunkRecordset(conn
, call
, out reply
);
739 static string VxColumnTypeToSignature(VxColumnType t
)
743 case VxColumnType
.Int64
:
745 case VxColumnType
.Int32
:
747 case VxColumnType
.Int16
:
749 case VxColumnType
.UInt8
:
751 case VxColumnType
.Bool
:
753 case VxColumnType
.Double
:
755 case VxColumnType
.Uuid
:
757 case VxColumnType
.Binary
:
759 case VxColumnType
.String
:
761 case VxColumnType
.DateTime
:
763 case VxColumnType
.Decimal
:
766 throw new ArgumentException("Unknown VxColumnType");
770 static string VxColumnInfoToArraySignature(VxColumnInfo
[] vxci
)
772 StringBuilder sig
= new StringBuilder("a(");
773 foreach (VxColumnInfo ci
in vxci
)
774 sig
.Append(VxColumnTypeToSignature(ci
.VxColumnType
));
777 return sig
.ToString();
780 static void CallGetSchemaChecksums(WvDbus conn
,
781 WvDbusMsg call
, out WvDbusMsg reply
)
783 if (call
.signature
.ne()) {
784 reply
= CreateUnknownMethodReply(call
, "GetSchemaChecksums");
788 string clientid
= GetClientId(call
);
789 if (clientid
== null)
791 reply
= call
.err_reply("org.freedesktop.DBus.Error.Failed",
792 "Could not identify the client");
796 // FIXME: Add vx.db.toomuchdata error
797 WvDbusWriter writer
= new WvDbusWriter();
799 using (var dbi
= VxSqlPool
.create(clientid
))
801 VxDbSchema backend
= new VxDbSchema(dbi
);
802 VxSchemaChecksums sums
= backend
.GetChecksums();
803 sums
.WriteChecksums(writer
);
806 reply
= call
.reply(VxSchemaChecksums
.GetDbusSignature()).write(writer
);
809 static void CallGetSchema(WvDbus conn
,
810 WvDbusMsg call
, out WvDbusMsg reply
)
812 if (call
.signature
!= "as") {
813 reply
= CreateUnknownMethodReply(call
, "GetSchema");
817 string clientid
= GetClientId(call
);
818 if (clientid
== null)
820 reply
= call
.err_reply("org.freedesktop.DBus.Error.Failed",
821 "Could not identify the client");
825 var it
= call
.iter();
826 string[] names
= it
.pop().Cast
<string>().ToArray();
828 WvDbusWriter writer
= new WvDbusWriter();
830 using (var dbi
= VxSqlPool
.create(clientid
))
832 VxDbSchema backend
= new VxDbSchema(dbi
);
833 VxSchema schema
= backend
.Get(names
);
834 schema
.WriteSchema(writer
);
837 reply
= call
.reply(VxSchema
.GetDbusSignature()).write(writer
);
840 static void CallDropSchema(WvDbus conn
,
841 WvDbusMsg call
, out WvDbusMsg reply
)
843 if (call
.signature
!= "as") {
844 reply
= CreateUnknownMethodReply(call
, "DropSchema");
848 string clientid
= GetClientId(call
);
849 if (clientid
== null)
851 reply
= call
.err_reply("org.freedesktop.DBus.Error.Failed",
852 "Could not identify the client");
856 var it
= call
.iter();
857 string[] keys
= it
.pop().Cast
<string>().ToArray();
860 using (var dbi
= VxSqlPool
.create(clientid
))
862 VxDbSchema backend
= new VxDbSchema(dbi
);
863 errs
= backend
.DropSchema(keys
);
866 WvDbusWriter writer
= new WvDbusWriter();
867 VxSchemaErrors
.WriteErrors(writer
, errs
);
869 reply
= call
.reply(VxSchemaErrors
.GetDbusSignature()).write(writer
);
870 if (errs
!= null && errs
.Count
> 0)
872 reply
.type
= Wv
.Dbus
.MType
.Error
;
873 reply
.err
= "org.freedesktop.DBus.Error.Failed";
877 static void CallPutSchema(WvDbus conn
,
878 WvDbusMsg call
, out WvDbusMsg reply
)
880 if (call
.signature
!= String
.Format("{0}i",
881 VxSchema
.GetDbusSignature())) {
882 reply
= CreateUnknownMethodReply(call
, "PutSchema");
886 string clientid
= GetClientId(call
);
887 if (clientid
== null)
889 reply
= call
.err_reply("org.freedesktop.DBus.Error.Failed",
890 "Could not identify the client");
894 var it
= call
.iter();
895 VxSchema schema
= new VxSchema(it
.pop());
900 using (var dbi
= VxSqlPool
.create(clientid
))
902 VxDbSchema backend
= new VxDbSchema(dbi
);
903 errs
= backend
.Put(schema
, null, (VxPutOpts
)opts
);
906 WvDbusWriter writer
= new WvDbusWriter();
907 VxSchemaErrors
.WriteErrors(writer
, errs
);
909 reply
= call
.reply(VxSchemaErrors
.GetDbusSignature()).write(writer
);
910 if (errs
!= null && errs
.Count
> 0)
912 reply
.type
= Wv
.Dbus
.MType
.Error
;
913 reply
.err
= "org.freedesktop.DBus.Error.Failed";
917 static void CallGetSchemaData(WvDbus conn
,
918 WvDbusMsg call
, out WvDbusMsg reply
)
920 if (call
.signature
!= "ss") {
921 reply
= CreateUnknownMethodReply(call
, "GetSchemaData");
925 string clientid
= GetClientId(call
);
926 if (clientid
== null)
928 reply
= call
.err_reply("org.freedesktop.DBus.Error.Failed",
929 "Could not identify the client");
933 var it
= call
.iter();
934 string tablename
= it
.pop();
935 string where
= it
.pop();
937 WvDbusWriter writer
= new WvDbusWriter();
939 using (var dbi
= VxSqlPool
.create(clientid
))
941 VxDbSchema backend
= new VxDbSchema(dbi
);
942 string schemadata
= backend
.GetSchemaData(tablename
, 0, where
);
943 writer
.Write(schemadata
);
946 reply
= call
.reply("s").write(writer
);
949 static void CallPutSchemaData(WvDbus conn
,
950 WvDbusMsg call
, out WvDbusMsg reply
)
952 if (call
.signature
!= "ss") {
953 reply
= CreateUnknownMethodReply(call
, "PutSchemaData");
957 string clientid
= GetClientId(call
);
958 if (clientid
== null)
960 reply
= call
.err_reply("org.freedesktop.DBus.Error.Failed",
961 "Could not identify the client");
965 var it
= call
.iter();
966 string tablename
= it
.pop();
967 string text
= it
.pop();
969 using (var dbi
= VxSqlPool
.create(clientid
))
971 VxDbSchema backend
= new VxDbSchema(dbi
);
972 backend
.PutSchemaData(tablename
, text
, 0);
975 reply
= call
.reply();
978 static void WriteV(WvDbusWriter w
, VxColumnType t
, object v
)
982 case VxColumnType
.Int64
:
985 case VxColumnType
.Int32
:
988 case VxColumnType
.Int16
:
991 case VxColumnType
.UInt8
:
994 case VxColumnType
.Bool
:
997 case VxColumnType
.Double
:
1000 case VxColumnType
.Binary
:
1003 case VxColumnType
.String
:
1004 case VxColumnType
.Decimal
:
1005 case VxColumnType
.Uuid
:
1008 case VxColumnType
.DateTime
:
1010 var dt
= (VxDbusDateTime
)v
;
1011 w
.Write(dt
.seconds
);
1012 w
.Write(dt
.microseconds
);
1016 throw new ArgumentException("Unknown VxColumnType");
1021 public static WvDbusWriter
PrepareRecordsetWriter(VxColumnInfo
[] colinfo
,
1025 WvDbusWriter writer
= new WvDbusWriter();
1028 WriteColInfo(writer
, colinfo
);
1031 if (colinfo
.Length
<= 0)
1033 // Some clients can't parse a() (empty struct) properly, so
1034 // we'll have an empty array of (i) instead.
1035 writer
.WriteSig("a(i)");
1038 writer
.WriteSig(VxColumnInfoToArraySignature(colinfo
));
1041 writer
.WriteArray(8, data
, (w2
, r
) => {
1042 for (int i
= 0; i
< colinfo
.Length
; i
++)
1043 WriteV(w2
, colinfo
[i
].VxColumnType
, r
[i
]);
1047 writer
.WriteArray(4, nulldata
, (w2
, r
) => {