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(Connection conn
,
51 Message call
, string sender
,
52 VxColumnInfo
[] colinfo
,
53 object[][] data
, byte[][] nulls
)
55 MessageWriter writer
=
56 VxDbInterfaceRouter
.PrepareRecordsetWriter(colinfo
, data
, nulls
);
57 writer
.Write(call
.serial
);
59 Message signal
= VxDbus
.CreateSignal(sender
, "ChunkRecordsetSig",
64 VxDbus
.MessageDump(" S>> ", signal
);
70 internal static void ExecChunkRecordset(Connection conn
,
71 Message call
, out Message reply
)
73 string connid
= VxDbInterfaceRouter
.GetClientId(call
);
77 reply
= VxDbus
.CreateError(
78 "org.freedesktop.DBus.Error.Failed",
79 "Could not identify the client", call
);
85 string query
= it
.pop();
86 string iquery
= query
.ToLower().Trim();
88 // XXX this is fishy, really... whitespace fucks it up.
90 if (iquery
.StartsWith("list tables"))
91 query
= "exec sp_tables";
92 else if (iquery
.StartsWith("list columns "))
93 query
= String
.Format("exec sp_columns @table_name='{0}'",
95 else if (iquery
.StartsWith("list all table") &&
96 iquery
.StartsWith("list all tablefunction") == false)
97 query
= "select distinct cast(Name as varchar(max)) Name"
99 + " where objectproperty(id,'IsTable')=1 "
102 else if (iquery
.StartsWith("list all"))
103 // Format: list all {view|trigger|procedure|scalarfunction|tablefunction}
104 // Returns: a list of all of whatever
105 query
= String
.Format(
107 + " cast (object_name(id) as varchar(256)) Name "
108 + " from syscomments "
109 + " where objectproperty(id,'Is{0}') = 1 "
111 query
.Split(' ')[2].Trim());
112 else if (iquery
.StartsWith("get object"))
114 // get object {view|trigger|procedure|scalarfunction|tablefunction} name
115 // Returns: the "source code" to the object
116 query
= String
.Format(
117 "select cast(text as varchar(max)) text "
118 + "from syscomments "
119 + "where objectproperty(id, 'Is{0}') = 1 "
120 + "and object_name(id) = '{1}' "
121 + "order by number, colid ",
122 query
.Split(' ')[2].Trim(),
123 query
.Split(' ')[3].Trim());
124 else if (iquery
.StartsWith("drop") || iquery
.StartsWith("create") ||
125 iquery
.StartsWith("insert") || iquery
.StartsWith("update"))
127 //FIXME: Are the above the only ways to modify a DB, aka the only
128 // cases where we have to call the old ExecRecordSet?
129 //FIXME: This is an ugly way to handle these cases, but it works!
130 VxDbInterfaceRouter
.CallExecRecordset(conn
, call
, out reply
);
134 log
.print(WvLog
.L
.Debug3
, "ExecChunkRecordset {0}\n", query
);
136 string sender
= call
.sender
;
140 // FIXME: Sadly, this is stupidly similar to ExecRecordset.
141 // Anything we can do here to identify commonalities?
142 using (var dbi
= VxSqlPool
.create(connid
))
143 using (WvSqlRows resultset
= dbi
.select(query
))
145 List
<object[]> rows
= new List
<object[]>();
146 List
<byte[]> rownulls
= new List
<byte[]>();
148 // Our size here is just an approximation. Start it at 1
149 // to ensure that at least one packet always gets sent.
152 var columns
= resultset
.columns
.ToArray();
153 VxColumnInfo
[] colinfo
= ProcessSchema(columns
);
154 int ncols
= columns
.Count();
156 foreach (WvSqlRow cur_row
in resultset
)
158 object[] row
= new object[ncols
];
159 byte[] rownull
= new byte[ncols
];
160 cursize
+= rownull
.Length
;
162 for (int i
= 0; i
< ncols
; i
++)
164 WvAutoCast cval
= cur_row
[i
];
165 bool isnull
= cval
.IsNull
;
169 rownull
[i
] = isnull
? (byte)1 : (byte)0;
171 switch (colinfo
[i
].VxColumnType
)
173 case VxColumnType
.Int64
:
175 (Int64
)cval
: new Int64();
176 cursize
+= sizeof(Int64
);
178 case VxColumnType
.Int32
:
180 (Int32
)cval
: new Int32();
181 cursize
+= sizeof(Int32
);
183 case VxColumnType
.Int16
:
185 (Int16
)cval
: new Int16();
186 cursize
+= sizeof(Int16
);
188 case VxColumnType
.UInt8
:
190 (Byte
)cval
: new Byte();
191 cursize
+= sizeof(Byte
);
193 case VxColumnType
.Bool
:
195 (bool)cval
: new Boolean();
196 cursize
+= sizeof(Boolean
);
198 case VxColumnType
.Double
:
199 // Might return a Single or Double
200 // FIXME: Check if getting a single causes this
203 (double)cval
: (double)0.0;
204 cursize
+= sizeof(double);
206 case VxColumnType
.Uuid
:
211 ((string)cval
).Length
* sizeof(Char
) : 0;
213 case VxColumnType
.Binary
:
217 row
[i
] = new byte[0];
221 row
[i
] = (byte[])cval
;
222 cursize
+= ((byte[])cval
).Length
;
225 case VxColumnType
.String
:
226 row
[i
] = !isnull
? (string)cval
: "";
228 ((string)cval
).Length
* sizeof(Char
) : 0;
230 case VxColumnType
.DateTime
:
232 new VxDbusDateTime((DateTime
)cval
) :
233 new VxDbusDateTime();
234 cursize
+= System
.Runtime
.InteropServices
.Marshal
.SizeOf((VxDbusDateTime
)row
[i
]);
236 case VxColumnType
.Decimal
:
238 ((Decimal
)cval
).ToString() : "";
239 cursize
+= ((string)(row
[i
])).Length
*
246 rownulls
.Add(rownull
);
248 if (cursize
>= 1024*1024) //approx 1 MB
250 log
.print(WvLog
.L
.Debug4
,
251 "(1 MB reached; {0} rows)\n",
254 SendChunkRecordSignal(conn
, call
, sender
, colinfo
,
258 rows
= new List
<object[]>();
259 rownulls
= new List
<byte[]>();
266 log
.print(WvLog
.L
.Debug4
, "(Remaining data; {0} rows)\n",
269 SendChunkRecordSignal(conn
, call
, sender
, colinfo
,
274 MessageWriter replywriter
= new MessageWriter();
275 replywriter
.Write("ChunkRecordset sent you all your data!");
276 reply
= VxDbus
.CreateReply(call
, "s", replywriter
);
277 } catch (DbException e
) {
278 throw new VxSqlException(e
.Message
, e
);
282 internal static void ExecRecordset(string connid
, string query
,
283 out VxColumnInfo
[] colinfo
, out object[][] data
,
284 out byte[][] nullity
)
288 if (query
.ToLower().StartsWith("list tables"))
289 query
= "exec sp_tables";
290 else if (query
.ToLower().StartsWith("list columns "))
291 query
= String
.Format("exec sp_columns @table_name='{0}'",
292 query
.Substring(13));
293 else if (query
.ToLower().StartsWith("list all table") &&
294 query
.ToLower().StartsWith("list all tablefunction") == false)
295 query
= "select distinct cast(Name as varchar(max)) Name"
296 + " from sysobjects "
297 + " where objectproperty(id,'IsTable')=1 "
300 else if (query
.ToLower().StartsWith("list all"))
301 // Format: list all {view|trigger|procedure|scalarfunction|tablefunction}
302 // Returns: a list of all of whatever
303 query
= String
.Format(
305 + " cast (object_name(id) as varchar(256)) Name "
306 + " from syscomments "
307 + " where objectproperty(id,'Is{0}') = 1 "
309 query
.Split(' ')[2].Trim());
310 else if (query
.ToLower().StartsWith("get object"))
312 // get object {view|trigger|procedure|scalarfunction|tablefunction} name
313 // Returns: the "source code" to the object
314 query
= String
.Format(
315 "select cast(text as varchar(max)) text "
316 + "from syscomments "
317 + "where objectproperty(id, 'Is{0}') = 1 "
318 + "and object_name(id) = '{1}' "
319 + "order by number, colid ",
320 query
.Split(' ')[2].Trim(),
321 query
.Split(' ')[3].Trim());
323 log
.print(WvLog
.L
.Debug3
, "ExecRecordset {0}\n", query
);
326 List
<object[]> rows
= new List
<object[]>();
327 List
<byte[]> rownulls
= new List
<byte[]>();
329 using (var dbi
= VxSqlPool
.create(connid
))
330 using (var result
= dbi
.select(query
))
332 var columns
= result
.columns
.ToArray();
334 if (columns
.Length
<= 0)
335 log
.print("No columns in resulting data set.");
337 colinfo
= ProcessSchema(result
.columns
);
339 foreach (var r
in result
)
341 object[] row
= new object[columns
.Length
];
342 byte[] rownull
= new byte[columns
.Length
];
344 for (int i
= 0; i
< columns
.Length
; i
++)
346 bool isnull
= r
[i
].IsNull
;
348 rownull
[i
] = isnull
? (byte)1 : (byte)0;
350 switch (colinfo
[i
].VxColumnType
)
352 case VxColumnType
.Int64
:
353 row
[i
] = !isnull
? (Int64
)r
[i
] : new Int64();
355 case VxColumnType
.Int32
:
356 row
[i
] = !isnull
? (Int32
)r
[i
] : new Int32();
358 case VxColumnType
.Int16
:
359 row
[i
] = !isnull
? (Int16
)r
[i
] : new Int16();
361 case VxColumnType
.UInt8
:
362 row
[i
] = !isnull
? (Byte
)r
[i
] : new Byte();
364 case VxColumnType
.Bool
:
365 row
[i
] = !isnull
? (bool)r
[i
] : new Boolean();
367 case VxColumnType
.Double
:
368 // Might return a Single or Double
369 // FIXME: Check if getting a single causes this
371 row
[i
] = !isnull
? (double)r
[i
] : (double)0.0;
373 case VxColumnType
.Uuid
:
374 row
[i
] = !isnull
? ((Guid
)r
[i
]).ToString() : "";
376 case VxColumnType
.Binary
:
377 row
[i
] = !isnull
? (byte[])r
[i
] : new byte[0];
379 case VxColumnType
.String
:
380 row
[i
] = !isnull
? (string)r
[i
] : "";
382 case VxColumnType
.DateTime
:
384 new VxDbusDateTime(r
[i
]) :
385 new VxDbusDateTime();
387 case VxColumnType
.Decimal
:
389 ? ((decimal)r
[i
]).ToString() : "";
395 rownulls
.Add(rownull
);
398 data
= rows
.ToArray();
399 nullity
= rownulls
.ToArray();
400 log
.print(WvLog
.L
.Debug4
, "({0} rows)\n", data
.Length
);
401 wv
.assert(nullity
.Length
== data
.Length
);
403 } catch (DbException e
) {
404 throw new VxSqlException(e
.Message
, e
);
408 private static VxColumnInfo
[] ProcessSchema(IEnumerable
<WvColInfo
> columns
)
410 // FIXME: This is stupidly similar to ProcessSchema
411 int ncols
= columns
.Count();
412 VxColumnInfo
[] colinfo
= new VxColumnInfo
[ncols
];
419 foreach (WvColInfo col
in columns
)
421 System
.Type type
= col
.type
;
423 if (type
== typeof(object))
425 // We're not even going to try to handle this yet
426 throw new VxBadSchemaException("Columns of type sql_variant "
427 + "are not supported by Versaplex at this time");
430 VxColumnType coltype
;
432 if (type
== typeof(Int64
)) {
433 coltype
= VxColumnType
.Int64
;
434 } else if (type
== typeof(Int32
)) {
435 coltype
= VxColumnType
.Int32
;
436 } else if (type
== typeof(Int16
)) {
437 coltype
= VxColumnType
.Int16
;
438 } else if (type
== typeof(Byte
)) {
439 coltype
= VxColumnType
.UInt8
;
440 } else if (type
== typeof(Boolean
)) {
441 coltype
= VxColumnType
.Bool
;
442 } else if (type
== typeof(Single
) || type
== typeof(Double
)) {
443 coltype
= VxColumnType
.Double
;
444 } else if (type
== typeof(Guid
)) {
445 coltype
= VxColumnType
.Uuid
;
446 } else if (type
== typeof(Byte
[])) {
447 coltype
= VxColumnType
.Binary
;
448 } else if (type
== typeof(string)) {
449 coltype
= VxColumnType
.String
;
450 } else if (type
== typeof(DateTime
)) {
451 coltype
= VxColumnType
.DateTime
;
452 } else if (type
== typeof(Decimal
)) {
453 coltype
= VxColumnType
.Decimal
;
455 throw new VxBadSchemaException("Columns of type "
456 + type
.ToString() + " are not supported by "
457 + "Versaplex at this time " +
458 "(column " + col
.name
+ ")");
461 colinfo
[i
] = new VxColumnInfo(col
.name
, coltype
,
462 col
.nullable
, col
.size
, col
.precision
, col
.scale
);
471 public class VxDbInterfaceRouter
: VxInterfaceRouter
474 static WvLog log
= new WvLog("VxDbInterfaceRouter");
475 static readonly VxDbInterfaceRouter instance
;
476 public static VxDbInterfaceRouter Instance
{
477 get { return instance; }
480 static VxDbInterfaceRouter() {
481 instance
= new VxDbInterfaceRouter();
484 private VxDbInterfaceRouter() : base("vx.db")
486 methods
.Add("Test", CallTest
);
487 methods
.Add("Quit", CallQuit
);
488 methods
.Add("ExecScalar", CallExecScalar
);
489 methods
.Add("ExecRecordset", CallExecRecordset
);
490 methods
.Add("ExecChunkRecordset", CallExecChunkRecordset
);
491 methods
.Add("GetSchemaChecksums", CallGetSchemaChecksums
);
492 methods
.Add("GetSchema", CallGetSchema
);
493 methods
.Add("PutSchema", CallPutSchema
);
494 methods
.Add("DropSchema", CallDropSchema
);
495 methods
.Add("GetSchemaData", CallGetSchemaData
);
496 methods
.Add("PutSchemaData", CallPutSchemaData
);
499 protected override void ExecuteCall(MethodCallProcessor processor
,
501 Message call
, out Message reply
)
504 processor(conn
, call
, out reply
);
505 } catch (VxRequestException e
) {
506 reply
= VxDbus
.CreateError(e
.DBusErrorType
, e
.Message
, call
);
507 log
.print("SQL result: {0}\n", e
.Short());
508 } catch (Exception e
) {
509 reply
= VxDbus
.CreateError(
511 "An internal error occurred.", call
);
512 log
.print("{0}\n", e
.ToString());
516 static Dictionary
<string,string> usernames
= new Dictionary
<string, string>();
517 static Connection sessionbus
= new Connection(Address
.Session
);
519 public static string GetClientId(Message call
)
521 string sender
= call
.sender
;
523 // For now, the client ID is just the username of the Unix UID that
524 // DBus has associated with the connection.
526 if (!usernames
.TryGetValue(sender
, out username
))
530 // FIXME: We should be using VersaMain.conn here,
531 // not the session bus!!
532 // FIXME: This will likely change as we find a more
533 // universal way to do SSL authentication via D-Bus.
534 username
= VxSqlPool
.GetUsernameForCert(
535 sessionbus
.GetCertFingerprint(sender
));
541 // FIXME: This system call isn't actually standard
542 // FIXME: we should be using VersaMain.conn here,
543 // not the session bus!!
544 username
= sessionbus
.GetUnixUserName(sender
);
550 // FIXME: This system call is standard, but not useful
552 // FIXME: we should be using VersaMain.conn here,
553 // not the session bus!!
554 username
= sessionbus
.GetUnixUser(sender
).ToString();
558 username
= "*"; // use default connection, if any
565 // Remember the result, so we don't have to ask DBus all the time
566 usernames
[sender
] = username
;
568 log
.print(WvLog
.L
.Info
,
569 "New connection '{0}' is user '{1}'\n",
576 private static Message
CreateUnknownMethodReply(Message call
,
579 return VxDbus
.CreateError(
580 "org.freedesktop.DBus.Error.UnknownMethod",
582 "No overload of {0} has signature '{1}'",
583 methodname
, call
.signature
), call
);
586 private static void CallTest(Connection conn
,
587 Message call
, out Message reply
)
589 if (call
.signature
.ne()) {
590 reply
= CreateUnknownMethodReply(call
, "Test");
594 string clientid
= GetClientId(call
);
595 if (clientid
== null)
597 reply
= VxDbus
.CreateError(
598 "org.freedesktop.DBus.Error.Failed",
599 "Could not identify the client", call
);
603 VxColumnInfo
[] colinfo
;
606 VxDb
.ExecRecordset(clientid
, "select 'Works! :D'",
607 out colinfo
, out data
, out nullity
);
609 // FIXME: Add vx.db.toomuchdata error
610 MessageWriter writer
= PrepareRecordsetWriter(colinfo
, data
, nullity
);
612 reply
= VxDbus
.CreateReply(call
, "a(issnny)vaay", writer
);
615 VxDbus
.MessageDump(" >> ", reply
);
618 private static void CallQuit(Connection conn
,
619 Message call
, out Message reply
)
621 // FIXME: Check permissions here
622 MessageWriter writer
= new MessageWriter();
623 writer
.Write("Quit");
624 reply
= VxDbus
.CreateReply(call
, "s", writer
);
625 VersaMain
.want_to_die
= true;
628 VxDbus
.MessageDump(" >> ", reply
);
631 private static void CallExecScalar(Connection conn
,
632 Message call
, out Message reply
)
634 if (call
.signature
!= "s") {
635 reply
= CreateUnknownMethodReply(call
, "ExecScalar");
639 if (call
.Body
== null) {
640 reply
= VxDbus
.CreateError(
641 "org.freedesktop.DBus.Error.InvalidSignature",
642 "Signature provided but no body received", call
);
646 string clientid
= GetClientId(call
);
647 if (clientid
== null)
649 reply
= VxDbus
.CreateError(
650 "org.freedesktop.DBus.Error.Failed",
651 "Could not identify the client", call
);
655 var it
= call
.iter();
656 string query
= it
.pop();
659 VxColumnType coltype
;
660 VxDb
.ExecScalar(clientid
, (string)query
,
661 out coltype
, out result
);
663 MessageWriter writer
= new MessageWriter();
664 writer
.WriteSig(VxColumnTypeToSignature(coltype
));
665 WriteV(writer
, coltype
, result
);
667 reply
= VxDbus
.CreateReply(call
, "v", writer
);
670 VxDbus
.MessageDump(" >> ", reply
);
673 static void WriteColInfo(MessageWriter writer
, VxColumnInfo
[] colinfo
)
676 writer
.WriteArray(8, colinfo
, (w2
, i
) => {
679 w2
.Write(i
.coltype
.ToString());
680 w2
.Write(i
.precision
);
682 w2
.Write(i
.nullable
);
686 public static void CallExecRecordset(Connection conn
,
687 Message call
, out Message reply
)
689 if (call
.signature
!= "s") {
690 reply
= CreateUnknownMethodReply(call
, "ExecRecordset");
694 if (call
.Body
== null) {
695 reply
= VxDbus
.CreateError(
696 "org.freedesktop.DBus.Error.InvalidSignature",
697 "Signature provided but no body received", call
);
701 string clientid
= GetClientId(call
);
702 if (clientid
== null)
704 reply
= VxDbus
.CreateError(
705 "org.freedesktop.DBus.Error.Failed",
706 "Could not identify the client", call
);
710 var it
= call
.iter();
711 string query
= it
.pop();
713 VxColumnInfo
[] colinfo
;
716 VxDb
.ExecRecordset(clientid
, (string)query
,
717 out colinfo
, out data
, out nullity
);
719 // FIXME: Add vx.db.toomuchdata error
720 MessageWriter writer
= PrepareRecordsetWriter(colinfo
, data
, nullity
);
722 reply
= VxDbus
.CreateReply(call
, "a(issnny)vaay", writer
);
725 VxDbus
.MessageDump(" >> ", reply
);
728 private static void CallExecChunkRecordset(Connection conn
,
729 Message call
, out Message reply
)
731 // XXX: Stuff in this comment block shamelessly stolen from
732 // "CallExecRecordset".
733 if (call
.signature
!= "s") {
734 reply
= CreateUnknownMethodReply(call
, "ExecChunkRecordset");
738 if (call
.Body
== null) {
739 reply
= VxDbus
.CreateError(
740 "org.freedesktop.DBus.Error.InvalidSignature",
741 "Signature provided but no body received", call
);
746 VxDb
.ExecChunkRecordset(conn
, call
, out reply
);
749 VxDbus
.MessageDump(" >> ", reply
);
752 static string VxColumnTypeToSignature(VxColumnType t
)
756 case VxColumnType
.Int64
:
758 case VxColumnType
.Int32
:
760 case VxColumnType
.Int16
:
762 case VxColumnType
.UInt8
:
764 case VxColumnType
.Bool
:
766 case VxColumnType
.Double
:
768 case VxColumnType
.Uuid
:
770 case VxColumnType
.Binary
:
772 case VxColumnType
.String
:
774 case VxColumnType
.DateTime
:
776 case VxColumnType
.Decimal
:
779 throw new ArgumentException("Unknown VxColumnType");
783 static string VxColumnInfoToArraySignature(VxColumnInfo
[] vxci
)
785 StringBuilder sig
= new StringBuilder("a(");
786 foreach (VxColumnInfo ci
in vxci
)
787 sig
.Append(VxColumnTypeToSignature(ci
.VxColumnType
));
790 return sig
.ToString();
793 private static void CallGetSchemaChecksums(Connection conn
,
794 Message call
, out Message reply
)
796 if (call
.signature
.ne()) {
797 reply
= CreateUnknownMethodReply(call
, "GetSchemaChecksums");
801 string clientid
= GetClientId(call
);
802 if (clientid
== null)
804 reply
= VxDbus
.CreateError(
805 "org.freedesktop.DBus.Error.Failed",
806 "Could not identify the client", call
);
810 // FIXME: Add vx.db.toomuchdata error
811 MessageWriter writer
= new MessageWriter();
813 using (var dbi
= VxSqlPool
.create(clientid
))
815 VxDbSchema backend
= new VxDbSchema(dbi
);
816 VxSchemaChecksums sums
= backend
.GetChecksums();
817 sums
.WriteChecksums(writer
);
820 reply
= VxDbus
.CreateReply(call
,
821 VxSchemaChecksums
.GetDbusSignature(), writer
);
824 VxDbus
.MessageDump(" >> ", reply
);
827 private static void CallGetSchema(Connection conn
,
828 Message call
, out Message reply
)
830 if (call
.signature
!= "as") {
831 reply
= CreateUnknownMethodReply(call
, "GetSchema");
835 string clientid
= GetClientId(call
);
836 if (clientid
== null)
838 reply
= VxDbus
.CreateError(
839 "org.freedesktop.DBus.Error.Failed",
840 "Could not identify the client", call
);
844 var it
= call
.iter();
845 string[] names
= it
.pop().Cast
<string>().ToArray();
847 MessageWriter writer
= new MessageWriter();
849 using (var dbi
= VxSqlPool
.create(clientid
))
851 VxDbSchema backend
= new VxDbSchema(dbi
);
852 VxSchema schema
= backend
.Get(names
);
853 schema
.WriteSchema(writer
);
856 reply
= VxDbus
.CreateReply(call
, VxSchema
.GetDbusSignature(), writer
);
859 VxDbus
.MessageDump(" >> ", reply
);
862 private static void CallDropSchema(Connection conn
,
863 Message call
, out Message reply
)
865 if (call
.signature
!= "as") {
866 reply
= CreateUnknownMethodReply(call
, "DropSchema");
870 string clientid
= GetClientId(call
);
871 if (clientid
== null)
873 reply
= VxDbus
.CreateError(
874 "org.freedesktop.DBus.Error.Failed",
875 "Could not identify the client", call
);
879 var it
= call
.iter();
880 string[] keys
= it
.pop().Cast
<string>().ToArray();
883 using (var dbi
= VxSqlPool
.create(clientid
))
885 VxDbSchema backend
= new VxDbSchema(dbi
);
886 errs
= backend
.DropSchema(keys
);
889 MessageWriter writer
= new MessageWriter();
890 VxSchemaErrors
.WriteErrors(writer
, errs
);
892 reply
= VxDbus
.CreateReply(call
, VxSchemaErrors
.GetDbusSignature(),
894 if (errs
!= null && errs
.Count
> 0)
896 reply
.type
= MessageType
.Error
;
897 reply
.err
= "org.freedesktop.DBus.Error.Failed";
901 private static void CallPutSchema(Connection conn
,
902 Message call
, out Message reply
)
904 if (call
.signature
!= String
.Format("{0}i",
905 VxSchema
.GetDbusSignature())) {
906 reply
= CreateUnknownMethodReply(call
, "PutSchema");
910 string clientid
= GetClientId(call
);
911 if (clientid
== null)
913 reply
= VxDbus
.CreateError(
914 "org.freedesktop.DBus.Error.Failed",
915 "Could not identify the client", call
);
919 var it
= call
.iter();
920 VxSchema schema
= new VxSchema(it
.pop());
925 using (var dbi
= VxSqlPool
.create(clientid
))
927 VxDbSchema backend
= new VxDbSchema(dbi
);
928 errs
= backend
.Put(schema
, null, (VxPutOpts
)opts
);
931 MessageWriter writer
= new MessageWriter();
932 VxSchemaErrors
.WriteErrors(writer
, errs
);
934 reply
= VxDbus
.CreateReply(call
, VxSchemaErrors
.GetDbusSignature(),
936 if (errs
!= null && errs
.Count
> 0)
938 reply
.type
= MessageType
.Error
;
939 reply
.err
= "org.freedesktop.DBus.Error.Failed";
943 private static void CallGetSchemaData(Connection conn
,
944 Message call
, out Message reply
)
946 if (call
.signature
!= "ss") {
947 reply
= CreateUnknownMethodReply(call
, "GetSchemaData");
951 string clientid
= GetClientId(call
);
952 if (clientid
== null)
954 reply
= VxDbus
.CreateError(
955 "org.freedesktop.DBus.Error.Failed",
956 "Could not identify the client", call
);
960 var it
= call
.iter();
961 string tablename
= it
.pop();
962 string where
= it
.pop();
964 MessageWriter writer
= new MessageWriter();
966 using (var dbi
= VxSqlPool
.create(clientid
))
968 VxDbSchema backend
= new VxDbSchema(dbi
);
969 string schemadata
= backend
.GetSchemaData(tablename
, 0, where
);
970 writer
.Write(schemadata
);
973 reply
= VxDbus
.CreateReply(call
, "s", writer
);
976 private static void CallPutSchemaData(Connection conn
,
977 Message call
, out Message reply
)
979 if (call
.signature
!= "ss") {
980 reply
= CreateUnknownMethodReply(call
, "PutSchemaData");
984 string clientid
= GetClientId(call
);
985 if (clientid
== null)
987 reply
= VxDbus
.CreateError(
988 "org.freedesktop.DBus.Error.Failed",
989 "Could not identify the client", call
);
993 var it
= call
.iter();
994 string tablename
= it
.pop();
995 string text
= it
.pop();
997 using (var dbi
= VxSqlPool
.create(clientid
))
999 VxDbSchema backend
= new VxDbSchema(dbi
);
1000 backend
.PutSchemaData(tablename
, text
, 0);
1003 reply
= VxDbus
.CreateReply(call
);
1006 static void WriteV(MessageWriter w
, VxColumnType t
, object v
)
1010 case VxColumnType
.Int64
:
1013 case VxColumnType
.Int32
:
1016 case VxColumnType
.Int16
:
1019 case VxColumnType
.UInt8
:
1022 case VxColumnType
.Bool
:
1025 case VxColumnType
.Double
:
1028 case VxColumnType
.Binary
:
1031 case VxColumnType
.String
:
1032 case VxColumnType
.Decimal
:
1033 case VxColumnType
.Uuid
:
1036 case VxColumnType
.DateTime
:
1038 var dt
= (VxDbusDateTime
)v
;
1039 w
.Write(dt
.seconds
);
1040 w
.Write(dt
.microseconds
);
1044 throw new ArgumentException("Unknown VxColumnType");
1049 public static MessageWriter
PrepareRecordsetWriter(VxColumnInfo
[] colinfo
,
1053 MessageWriter writer
= new MessageWriter();
1056 WriteColInfo(writer
, colinfo
);
1059 if (colinfo
.Length
<= 0)
1061 // Some clients can't parse a() (empty struct) properly, so
1062 // we'll have an empty array of (i) instead.
1063 writer
.WriteSig("a(i)");
1066 writer
.WriteSig(VxColumnInfoToArraySignature(colinfo
));
1069 writer
.WriteArray(8, data
, (w2
, r
) => {
1070 for (int i
= 0; i
< colinfo
.Length
; i
++)
1071 WriteV(w2
, colinfo
[i
].VxColumnType
, r
[i
]);
1075 writer
.WriteArray(4, nulldata
, (w2
, r
) => {