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
,
17 log
.print(WvLog
.L
.Debug3
, "ExecScalar {0}\n", query
);
21 using (var dbi
= VxSqlPool
.create(connid
))
22 result
= dbi
.select_one(query
).inner
;
26 throw new VxSqlException(e
.Message
, e
);
31 internal static void SendChunkRecordSignal(Connection conn
,
32 Message call
, string sender
,
33 VxColumnInfo
[] colinfo
,
34 object[][] data
, byte[][] nulls
)
36 MessageWriter writer
=
37 VxDbInterfaceRouter
.PrepareRecordsetWriter(colinfo
, data
, nulls
);
38 writer
.Write(typeof(uint), call
.serial
);
40 Message signal
= VxDbus
.CreateSignal(sender
, "ChunkRecordsetSig",
45 VxDbus
.MessageDump(" S>> ", signal
);
51 internal static void ExecChunkRecordset(Connection conn
,
52 Message call
, out Message reply
)
54 string connid
= VxDbInterfaceRouter
.GetClientId(call
);
58 reply
= VxDbus
.CreateError(
59 "org.freedesktop.DBus.Error.Failed",
60 "Could not identify the client", call
);
66 string query
= it
.pop();
67 string iquery
= query
.ToLower().Trim();
69 // XXX this is fishy, really... whitespace fucks it up.
71 if (iquery
.StartsWith("list tables"))
72 query
= "exec sp_tables";
73 else if (iquery
.StartsWith("list columns "))
74 query
= String
.Format("exec sp_columns @table_name='{0}'",
76 else if (iquery
.StartsWith("list all table") &&
77 iquery
.StartsWith("list all tablefunction") == false)
78 query
= "select distinct cast(Name as varchar(max)) Name"
80 + " where objectproperty(id,'IsTable')=1 "
83 else if (iquery
.StartsWith("list all"))
84 // Format: list all {view|trigger|procedure|scalarfunction|tablefunction}
85 // Returns: a list of all of whatever
86 query
= String
.Format(
88 + " cast (object_name(id) as varchar(256)) Name "
89 + " from syscomments "
90 + " where objectproperty(id,'Is{0}') = 1 "
92 query
.Split(' ')[2].Trim());
93 else if (iquery
.StartsWith("get object"))
95 // get object {view|trigger|procedure|scalarfunction|tablefunction} name
96 // Returns: the "source code" to the object
97 query
= String
.Format(
98 "select cast(text as varchar(max)) text "
100 + "where objectproperty(id, 'Is{0}') = 1 "
101 + "and object_name(id) = '{1}' "
102 + "order by number, colid ",
103 query
.Split(' ')[2].Trim(),
104 query
.Split(' ')[3].Trim());
105 else if (iquery
.StartsWith("drop") || iquery
.StartsWith("create") ||
106 iquery
.StartsWith("insert") || iquery
.StartsWith("update"))
108 //FIXME: Are the above the only ways to modify a DB, aka the only
109 // cases where we have to call the old ExecRecordSet?
110 //FIXME: This is an ugly way to handle these cases, but it works!
111 VxDbInterfaceRouter
.CallExecRecordset(conn
, call
, out reply
);
115 log
.print(WvLog
.L
.Debug3
, "ExecChunkRecordset {0}\n", query
);
117 string sender
= call
.sender
;
121 // FIXME: Sadly, this is stupidly similar to ExecRecordset.
122 // Anything we can do here to identify commonalities?
123 using (var dbi
= VxSqlPool
.create(connid
))
124 using (WvSqlRows resultset
= dbi
.select(query
))
126 List
<object[]> rows
= new List
<object[]>();
127 List
<byte[]> rownulls
= new List
<byte[]>();
129 // Our size here is just an approximation. Start it at 1
130 // to ensure that at least one packet always gets sent.
133 var columns
= resultset
.columns
.ToArray();
134 VxColumnInfo
[] colinfo
= ProcessSchema(columns
);
135 int ncols
= columns
.Count();
137 foreach (WvSqlRow cur_row
in resultset
)
139 object[] row
= new object[ncols
];
140 byte[] rownull
= new byte[ncols
];
141 cursize
+= rownull
.Length
;
143 for (int i
= 0; i
< ncols
; i
++)
145 WvAutoCast cval
= cur_row
[i
];
146 bool isnull
= cval
.IsNull
;
150 rownull
[i
] = isnull
? (byte)1 : (byte)0;
152 switch (colinfo
[i
].VxColumnType
)
154 case VxColumnType
.Int64
:
156 (Int64
)cval
: new Int64();
157 cursize
+= sizeof(Int64
);
159 case VxColumnType
.Int32
:
161 (Int32
)cval
: new Int32();
162 cursize
+= sizeof(Int32
);
164 case VxColumnType
.Int16
:
166 (Int16
)cval
: new Int16();
167 cursize
+= sizeof(Int16
);
169 case VxColumnType
.UInt8
:
171 (Byte
)cval
: new Byte();
172 cursize
+= sizeof(Byte
);
174 case VxColumnType
.Bool
:
176 (bool)cval
: new Boolean();
177 cursize
+= sizeof(Boolean
);
179 case VxColumnType
.Double
:
180 // Might return a Single or Double
181 // FIXME: Check if getting a single causes this
184 (double)cval
: (double)0.0;
185 cursize
+= sizeof(double);
187 case VxColumnType
.Uuid
:
192 ((string)cval
).Length
* sizeof(Char
) : 0;
194 case VxColumnType
.Binary
:
198 row
[i
] = new byte[0];
202 row
[i
] = (byte[])cval
;
203 cursize
+= ((byte[])cval
).Length
;
206 case VxColumnType
.String
:
207 row
[i
] = !isnull
? (string)cval
: "";
209 ((string)cval
).Length
* sizeof(Char
) : 0;
211 case VxColumnType
.DateTime
:
213 new VxDbusDateTime((DateTime
)cval
) :
214 new VxDbusDateTime();
215 cursize
+= System
.Runtime
.InteropServices
.Marshal
.SizeOf((VxDbusDateTime
)row
[i
]);
217 case VxColumnType
.Decimal
:
219 ((Decimal
)cval
).ToString() : "";
220 cursize
+= ((string)(row
[i
])).Length
*
227 rownulls
.Add(rownull
);
229 if (cursize
>= 1024*1024) //approx 1 MB
231 log
.print(WvLog
.L
.Debug4
,
232 "(1 MB reached; {0} rows)\n",
235 SendChunkRecordSignal(conn
, call
, sender
, colinfo
,
239 rows
= new List
<object[]>();
240 rownulls
= new List
<byte[]>();
247 log
.print(WvLog
.L
.Debug4
, "(Remaining data; {0} rows)\n",
250 SendChunkRecordSignal(conn
, call
, sender
, colinfo
,
255 MessageWriter replywriter
=
256 new MessageWriter(Connection
.NativeEndianness
);
257 replywriter
.Write(typeof(string), "ChunkRecordset sent you all your data!");
258 reply
= VxDbus
.CreateReply(call
, "s", replywriter
);
259 } catch (DbException e
) {
260 throw new VxSqlException(e
.Message
, e
);
264 internal static void ExecRecordset(string connid
, string query
,
265 out VxColumnInfo
[] colinfo
, out object[][] data
,
266 out byte[][] nullity
)
270 if (query
.ToLower().StartsWith("list tables"))
271 query
= "exec sp_tables";
272 else if (query
.ToLower().StartsWith("list columns "))
273 query
= String
.Format("exec sp_columns @table_name='{0}'",
274 query
.Substring(13));
275 else if (query
.ToLower().StartsWith("list all table") &&
276 query
.ToLower().StartsWith("list all tablefunction") == false)
277 query
= "select distinct cast(Name as varchar(max)) Name"
278 + " from sysobjects "
279 + " where objectproperty(id,'IsTable')=1 "
282 else if (query
.ToLower().StartsWith("list all"))
283 // Format: list all {view|trigger|procedure|scalarfunction|tablefunction}
284 // Returns: a list of all of whatever
285 query
= String
.Format(
287 + " cast (object_name(id) as varchar(256)) Name "
288 + " from syscomments "
289 + " where objectproperty(id,'Is{0}') = 1 "
291 query
.Split(' ')[2].Trim());
292 else if (query
.ToLower().StartsWith("get object"))
294 // get object {view|trigger|procedure|scalarfunction|tablefunction} name
295 // Returns: the "source code" to the object
296 query
= String
.Format(
297 "select cast(text as varchar(max)) text "
298 + "from syscomments "
299 + "where objectproperty(id, 'Is{0}') = 1 "
300 + "and object_name(id) = '{1}' "
301 + "order by number, colid ",
302 query
.Split(' ')[2].Trim(),
303 query
.Split(' ')[3].Trim());
305 log
.print(WvLog
.L
.Debug3
, "ExecRecordset {0}\n", query
);
308 List
<object[]> rows
= new List
<object[]>();
309 List
<byte[]> rownulls
= new List
<byte[]>();
311 using (var dbi
= VxSqlPool
.create(connid
))
312 using (var result
= dbi
.select(query
))
314 var columns
= result
.columns
.ToArray();
316 if (columns
.Length
<= 0)
317 log
.print("No columns in resulting data set.");
319 colinfo
= ProcessSchema(result
.columns
);
321 foreach (var r
in result
)
323 object[] row
= new object[columns
.Length
];
324 byte[] rownull
= new byte[columns
.Length
];
326 for (int i
= 0; i
< columns
.Length
; i
++)
328 bool isnull
= r
[i
].IsNull
;
330 rownull
[i
] = isnull
? (byte)1 : (byte)0;
332 switch (colinfo
[i
].VxColumnType
)
334 case VxColumnType
.Int64
:
335 row
[i
] = !isnull
? (Int64
)r
[i
] : new Int64();
337 case VxColumnType
.Int32
:
338 row
[i
] = !isnull
? (Int32
)r
[i
] : new Int32();
340 case VxColumnType
.Int16
:
341 row
[i
] = !isnull
? (Int16
)r
[i
] : new Int16();
343 case VxColumnType
.UInt8
:
344 row
[i
] = !isnull
? (Byte
)r
[i
] : new Byte();
346 case VxColumnType
.Bool
:
347 row
[i
] = !isnull
? (bool)r
[i
] : new Boolean();
349 case VxColumnType
.Double
:
350 // Might return a Single or Double
351 // FIXME: Check if getting a single causes this
353 row
[i
] = !isnull
? (double)r
[i
] : (double)0.0;
355 case VxColumnType
.Uuid
:
356 row
[i
] = !isnull
? ((Guid
)r
[i
]).ToString() : "";
358 case VxColumnType
.Binary
:
359 row
[i
] = !isnull
? (byte[])r
[i
] : new byte[0];
361 case VxColumnType
.String
:
362 row
[i
] = !isnull
? (string)r
[i
] : "";
364 case VxColumnType
.DateTime
:
366 new VxDbusDateTime(r
[i
]) :
367 new VxDbusDateTime();
369 case VxColumnType
.Decimal
:
371 ? ((decimal)r
[i
]).ToString() : "";
377 rownulls
.Add(rownull
);
380 data
= rows
.ToArray();
381 nullity
= rownulls
.ToArray();
382 log
.print(WvLog
.L
.Debug4
, "({0} rows)\n", data
.Length
);
383 wv
.assert(nullity
.Length
== data
.Length
);
385 } catch (DbException e
) {
386 throw new VxSqlException(e
.Message
, e
);
390 private static VxColumnInfo
[] ProcessSchema(IEnumerable
<WvColInfo
> columns
)
392 // FIXME: This is stupidly similar to ProcessSchema
393 int ncols
= columns
.Count();
394 VxColumnInfo
[] colinfo
= new VxColumnInfo
[ncols
];
401 foreach (WvColInfo col
in columns
)
403 System
.Type type
= col
.type
;
405 if (type
== typeof(object))
407 // We're not even going to try to handle this yet
408 throw new VxBadSchemaException("Columns of type sql_variant "
409 + "are not supported by Versaplex at this time");
412 VxColumnType coltype
;
414 if (type
== typeof(Int64
)) {
415 coltype
= VxColumnType
.Int64
;
416 } else if (type
== typeof(Int32
)) {
417 coltype
= VxColumnType
.Int32
;
418 } else if (type
== typeof(Int16
)) {
419 coltype
= VxColumnType
.Int16
;
420 } else if (type
== typeof(Byte
)) {
421 coltype
= VxColumnType
.UInt8
;
422 } else if (type
== typeof(Boolean
)) {
423 coltype
= VxColumnType
.Bool
;
424 } else if (type
== typeof(Single
) || type
== typeof(Double
)) {
425 coltype
= VxColumnType
.Double
;
426 } else if (type
== typeof(Guid
)) {
427 coltype
= VxColumnType
.Uuid
;
428 } else if (type
== typeof(Byte
[])) {
429 coltype
= VxColumnType
.Binary
;
430 } else if (type
== typeof(string)) {
431 coltype
= VxColumnType
.String
;
432 } else if (type
== typeof(DateTime
)) {
433 coltype
= VxColumnType
.DateTime
;
434 } else if (type
== typeof(Decimal
)) {
435 coltype
= VxColumnType
.Decimal
;
437 throw new VxBadSchemaException("Columns of type "
438 + type
.ToString() + " are not supported by "
439 + "Versaplex at this time " +
440 "(column " + col
.name
+ ")");
443 colinfo
[i
] = new VxColumnInfo(col
.name
, coltype
,
444 col
.nullable
, col
.size
, col
.precision
, col
.scale
);
453 public class VxDbInterfaceRouter
: VxInterfaceRouter
456 static WvLog log
= new WvLog("VxDbInterfaceRouter");
457 static readonly VxDbInterfaceRouter instance
;
458 public static VxDbInterfaceRouter Instance
{
459 get { return instance; }
462 static VxDbInterfaceRouter() {
463 instance
= new VxDbInterfaceRouter();
466 private VxDbInterfaceRouter() : base("vx.db")
468 methods
.Add("Test", CallTest
);
469 methods
.Add("Quit", CallQuit
);
470 methods
.Add("ExecScalar", CallExecScalar
);
471 methods
.Add("ExecRecordset", CallExecRecordset
);
472 methods
.Add("ExecChunkRecordset", CallExecChunkRecordset
);
473 methods
.Add("GetSchemaChecksums", CallGetSchemaChecksums
);
474 methods
.Add("GetSchema", CallGetSchema
);
475 methods
.Add("PutSchema", CallPutSchema
);
476 methods
.Add("DropSchema", CallDropSchema
);
477 methods
.Add("GetSchemaData", CallGetSchemaData
);
478 methods
.Add("PutSchemaData", CallPutSchemaData
);
481 protected override void ExecuteCall(MethodCallProcessor processor
,
483 Message call
, out Message reply
)
486 processor(conn
, call
, out reply
);
487 } catch (VxRequestException e
) {
488 reply
= VxDbus
.CreateError(e
.DBusErrorType
, e
.Message
, call
);
489 log
.print("SQL result: {0}\n", e
.Short());
490 } catch (Exception e
) {
491 reply
= VxDbus
.CreateError(
493 "An internal error occurred.", call
);
494 log
.print("{0}\n", e
.ToString());
498 static Dictionary
<string,string> usernames
= new Dictionary
<string, string>();
500 public static string GetClientId(Message call
)
502 string sender
= call
.sender
;
504 // For now, the client ID is just the username of the Unix UID that
505 // DBus has associated with the connection.
507 if (!usernames
.TryGetValue(sender
, out username
))
511 // FIXME: We should be using VersaMain.conn here,
512 // not the session bus!!
513 // FIXME: This will likely change as we find a more
514 // universal way to do SSL authentication via D-Bus.
515 username
= VxSqlPool
.GetUsernameForCert(
516 Bus
.Session
.GetCertFingerprint(sender
));
522 // FIXME: This system call isn't actually standard
523 // FIXME: we should be using VersaMain.conn here,
524 // not the session bus!!
525 username
= Bus
.Session
.GetUnixUserName(sender
);
531 // FIXME: This system call is standard, but not useful
533 // FIXME: we should be using VersaMain.conn here,
534 // not the session bus!!
535 username
= Bus
.Session
.GetUnixUser(sender
).ToString();
539 username
= "*"; // use default connection, if any
546 // Remember the result, so we don't have to ask DBus all the time
547 usernames
[sender
] = username
;
549 log
.print(WvLog
.L
.Info
,
550 "New connection '{0}' is user '{1}'\n",
557 private static Message
CreateUnknownMethodReply(Message call
,
560 return VxDbus
.CreateError(
561 "org.freedesktop.DBus.Error.UnknownMethod",
563 "No overload of {0} has signature '{1}'",
564 methodname
, call
.Signature
), call
);
567 private static void CallTest(Connection conn
,
568 Message call
, out Message reply
)
570 if (call
.Signature
.ToString() != "") {
571 reply
= CreateUnknownMethodReply(call
, "Test");
575 string clientid
= GetClientId(call
);
576 if (clientid
== null)
578 reply
= VxDbus
.CreateError(
579 "org.freedesktop.DBus.Error.Failed",
580 "Could not identify the client", call
);
584 VxColumnInfo
[] colinfo
;
587 VxDb
.ExecRecordset(clientid
, "select 'Works! :D'",
588 out colinfo
, out data
, out nullity
);
590 // FIXME: Add vx.db.toomuchdata error
591 MessageWriter writer
= PrepareRecordsetWriter(colinfo
, data
, nullity
);
593 reply
= VxDbus
.CreateReply(call
, "a(issnny)vaay", writer
);
596 VxDbus
.MessageDump(" >> ", reply
);
599 private static void CallQuit(Connection conn
,
600 Message call
, out Message reply
)
602 // FIXME: Check permissions here
603 MessageWriter writer
=
604 new MessageWriter(Connection
.NativeEndianness
);
605 writer
.Write(typeof(string), "Quit");
606 reply
= VxDbus
.CreateReply(call
, "s", writer
);
607 VersaMain
.want_to_die
= true;
610 VxDbus
.MessageDump(" >> ", reply
);
613 private static void CallExecScalar(Connection conn
,
614 Message call
, out Message reply
)
616 if (call
.Signature
.ToString() != "s") {
617 reply
= CreateUnknownMethodReply(call
, "ExecScalar");
621 if (call
.Body
== null) {
622 reply
= VxDbus
.CreateError(
623 "org.freedesktop.DBus.Error.InvalidSignature",
624 "Signature provided but no body received", call
);
628 string clientid
= GetClientId(call
);
629 if (clientid
== null)
631 reply
= VxDbus
.CreateError(
632 "org.freedesktop.DBus.Error.Failed",
633 "Could not identify the client", call
);
637 var it
= call
.iter();
638 string query
= it
.pop();
641 VxDb
.ExecScalar(clientid
, (string)query
, out result
);
643 MessageWriter writer
=
644 new MessageWriter(Connection
.NativeEndianness
);
645 writer
.WriteV(result
);
647 reply
= VxDbus
.CreateReply(call
, "v", writer
);
650 VxDbus
.MessageDump(" >> ", reply
);
653 private static void _WriteColInfo(MessageWriter w
,
654 VxColumnInfo
[] colinfo
)
657 foreach (VxColumnInfo c
in colinfo
)
661 private static void WriteColInfo(MessageWriter writer
,
662 VxColumnInfo
[] colinfo
)
664 writer
.WriteDelegatePrependSize(delegate(MessageWriter w
)
666 _WriteColInfo(w
, colinfo
);
670 public static void CallExecRecordset(Connection conn
,
671 Message call
, out Message reply
)
673 if (call
.Signature
.ToString() != "s") {
674 reply
= CreateUnknownMethodReply(call
, "ExecRecordset");
678 if (call
.Body
== null) {
679 reply
= VxDbus
.CreateError(
680 "org.freedesktop.DBus.Error.InvalidSignature",
681 "Signature provided but no body received", call
);
685 string clientid
= GetClientId(call
);
686 if (clientid
== null)
688 reply
= VxDbus
.CreateError(
689 "org.freedesktop.DBus.Error.Failed",
690 "Could not identify the client", call
);
694 var it
= call
.iter();
695 string query
= it
.pop();
697 VxColumnInfo
[] colinfo
;
700 VxDb
.ExecRecordset(clientid
, (string)query
,
701 out colinfo
, out data
, out nullity
);
703 // FIXME: Add vx.db.toomuchdata error
704 MessageWriter writer
= PrepareRecordsetWriter(colinfo
, data
, nullity
);
706 reply
= VxDbus
.CreateReply(call
, "a(issnny)vaay", writer
);
709 VxDbus
.MessageDump(" >> ", reply
);
712 private static void CallExecChunkRecordset(Connection conn
,
713 Message call
, out Message reply
)
715 // XXX: Stuff in this comment block shamelessly stolen from
716 // "CallExecRecordset".
717 if (call
.Signature
.ToString() != "s") {
718 reply
= CreateUnknownMethodReply(call
, "ExecChunkRecordset");
722 if (call
.Body
== null) {
723 reply
= VxDbus
.CreateError(
724 "org.freedesktop.DBus.Error.InvalidSignature",
725 "Signature provided but no body received", call
);
730 VxDb
.ExecChunkRecordset(conn
, call
, out reply
);
733 VxDbus
.MessageDump(" >> ", reply
);
736 private static Signature
VxColumnInfoToArraySignature(VxColumnInfo
[] vxci
)
738 StringBuilder sig
= new StringBuilder("a(");
740 foreach (VxColumnInfo ci
in vxci
) {
741 switch (ci
.VxColumnType
) {
742 case VxColumnType
.Int64
:
745 case VxColumnType
.Int32
:
748 case VxColumnType
.Int16
:
751 case VxColumnType
.UInt8
:
754 case VxColumnType
.Bool
:
757 case VxColumnType
.Double
:
760 case VxColumnType
.Uuid
:
763 case VxColumnType
.Binary
:
766 case VxColumnType
.String
:
769 case VxColumnType
.DateTime
:
772 case VxColumnType
.Decimal
:
776 throw new ArgumentException("Unknown VxColumnType");
782 return new Signature(sig
.ToString());
785 private static Type
[] VxColumnInfoToType(VxColumnInfo
[] vxci
)
787 Type
[] ret
= new Type
[vxci
.Length
];
789 for (int i
=0; i
< vxci
.Length
; i
++) {
790 switch (vxci
[i
].VxColumnType
) {
791 case VxColumnType
.Int64
:
792 ret
[i
] = typeof(Int64
);
794 case VxColumnType
.Int32
:
795 ret
[i
] = typeof(Int32
);
797 case VxColumnType
.Int16
:
798 ret
[i
] = typeof(Int16
);
800 case VxColumnType
.UInt8
:
801 ret
[i
] = typeof(Byte
);
803 case VxColumnType
.Bool
:
804 ret
[i
] = typeof(Boolean
);
806 case VxColumnType
.Double
:
807 ret
[i
] = typeof(Double
);
809 case VxColumnType
.Uuid
:
810 ret
[i
] = typeof(string);
812 case VxColumnType
.Binary
:
813 ret
[i
] = typeof(byte[]);
815 case VxColumnType
.String
:
816 ret
[i
] = typeof(string);
818 case VxColumnType
.DateTime
:
819 ret
[i
] = typeof(VxDbusDateTime
);
821 case VxColumnType
.Decimal
:
822 ret
[i
] = typeof(string);
825 throw new ArgumentException("Unknown VxColumnType");
832 private static void WriteStructArray(MessageWriter writer
,
833 Type
[] types
, object[][] data
)
835 foreach (object[] row
in data
) {
838 for (int i
=0; i
< row
.Length
; i
++) {
839 if (!types
[i
].IsInstanceOfType(row
[i
]))
840 throw new ArgumentException("Data does not match type for "
843 writer
.Write(types
[i
], row
[i
]);
848 private static void CallGetSchemaChecksums(Connection conn
,
849 Message call
, out Message reply
)
851 if (call
.Signature
.ToString() != "") {
852 reply
= CreateUnknownMethodReply(call
, "GetSchemaChecksums");
856 string clientid
= GetClientId(call
);
857 if (clientid
== null)
859 reply
= VxDbus
.CreateError(
860 "org.freedesktop.DBus.Error.Failed",
861 "Could not identify the client", call
);
865 // FIXME: Add vx.db.toomuchdata error
866 MessageWriter writer
= new MessageWriter(Connection
.NativeEndianness
);
868 using (var dbi
= VxSqlPool
.create(clientid
))
870 VxDbSchema backend
= new VxDbSchema(dbi
);
871 VxSchemaChecksums sums
= backend
.GetChecksums();
872 sums
.WriteChecksums(writer
);
875 reply
= VxDbus
.CreateReply(call
,
876 VxSchemaChecksums
.GetDbusSignature(), writer
);
879 VxDbus
.MessageDump(" >> ", reply
);
882 private static void CallGetSchema(Connection conn
,
883 Message call
, out Message reply
)
885 if (call
.Signature
.ToString() != "as") {
886 reply
= CreateUnknownMethodReply(call
, "GetSchema");
890 string clientid
= GetClientId(call
);
891 if (clientid
== null)
893 reply
= VxDbus
.CreateError(
894 "org.freedesktop.DBus.Error.Failed",
895 "Could not identify the client", call
);
899 var it
= call
.iter();
900 string[] names
= it
.pop().Cast
<string>().ToArray();
902 MessageWriter writer
= new MessageWriter(Connection
.NativeEndianness
);
904 using (var dbi
= VxSqlPool
.create(clientid
))
906 VxDbSchema backend
= new VxDbSchema(dbi
);
907 VxSchema schema
= backend
.Get(names
);
908 schema
.WriteSchema(writer
);
911 reply
= VxDbus
.CreateReply(call
, VxSchema
.GetDbusSignature(), writer
);
914 VxDbus
.MessageDump(" >> ", reply
);
917 private static void CallDropSchema(Connection conn
,
918 Message call
, out Message reply
)
920 if (call
.Signature
.ToString() != "as") {
921 reply
= CreateUnknownMethodReply(call
, "DropSchema");
925 string clientid
= GetClientId(call
);
926 if (clientid
== null)
928 reply
= VxDbus
.CreateError(
929 "org.freedesktop.DBus.Error.Failed",
930 "Could not identify the client", call
);
934 var it
= call
.iter();
935 string[] keys
= it
.pop().Cast
<string>().ToArray();
938 using (var dbi
= VxSqlPool
.create(clientid
))
940 VxDbSchema backend
= new VxDbSchema(dbi
);
941 errs
= backend
.DropSchema(keys
);
944 MessageWriter writer
= new MessageWriter(Connection
.NativeEndianness
);
945 VxSchemaErrors
.WriteErrors(writer
, errs
);
947 reply
= VxDbus
.CreateReply(call
, VxSchemaErrors
.GetDbusSignature(),
949 if (errs
!= null && errs
.Count
> 0)
951 reply
.type
= MessageType
.Error
;
952 reply
.err
= "org.freedesktop.DBus.Error.Failed";
956 private static void CallPutSchema(Connection conn
,
957 Message call
, out Message reply
)
959 if (call
.Signature
.ToString() != String
.Format("{0}i",
960 VxSchema
.GetDbusSignature())) {
961 reply
= CreateUnknownMethodReply(call
, "PutSchema");
965 string clientid
= GetClientId(call
);
966 if (clientid
== null)
968 reply
= VxDbus
.CreateError(
969 "org.freedesktop.DBus.Error.Failed",
970 "Could not identify the client", call
);
974 var it
= call
.iter();
975 VxSchema schema
= new VxSchema(it
.pop());
980 using (var dbi
= VxSqlPool
.create(clientid
))
982 VxDbSchema backend
= new VxDbSchema(dbi
);
983 errs
= backend
.Put(schema
, null, (VxPutOpts
)opts
);
986 MessageWriter writer
= new MessageWriter(Connection
.NativeEndianness
);
987 VxSchemaErrors
.WriteErrors(writer
, errs
);
989 reply
= VxDbus
.CreateReply(call
, VxSchemaErrors
.GetDbusSignature(),
991 if (errs
!= null && errs
.Count
> 0)
993 reply
.type
= MessageType
.Error
;
994 reply
.err
= "org.freedesktop.DBus.Error.Failed";
998 private static void CallGetSchemaData(Connection conn
,
999 Message call
, out Message reply
)
1001 if (call
.Signature
.ToString() != "ss") {
1002 reply
= CreateUnknownMethodReply(call
, "GetSchemaData");
1006 string clientid
= GetClientId(call
);
1007 if (clientid
== null)
1009 reply
= VxDbus
.CreateError(
1010 "org.freedesktop.DBus.Error.Failed",
1011 "Could not identify the client", call
);
1015 var it
= call
.iter();
1016 string tablename
= it
.pop();
1017 string where
= it
.pop();
1019 MessageWriter writer
= new MessageWriter(Connection
.NativeEndianness
);
1021 using (var dbi
= VxSqlPool
.create(clientid
))
1023 VxDbSchema backend
= new VxDbSchema(dbi
);
1024 string schemadata
= backend
.GetSchemaData(tablename
, 0, where
);
1025 writer
.Write(schemadata
);
1028 reply
= VxDbus
.CreateReply(call
, "s", writer
);
1031 private static void CallPutSchemaData(Connection conn
,
1032 Message call
, out Message reply
)
1034 if (call
.Signature
.ToString() != "ss") {
1035 reply
= CreateUnknownMethodReply(call
, "PutSchemaData");
1039 string clientid
= GetClientId(call
);
1040 if (clientid
== null)
1042 reply
= VxDbus
.CreateError(
1043 "org.freedesktop.DBus.Error.Failed",
1044 "Could not identify the client", call
);
1048 var it
= call
.iter();
1049 string tablename
= it
.pop();
1050 string text
= it
.pop();
1052 using (var dbi
= VxSqlPool
.create(clientid
))
1054 VxDbSchema backend
= new VxDbSchema(dbi
);
1055 backend
.PutSchemaData(tablename
, text
, 0);
1058 reply
= VxDbus
.CreateReply(call
);
1061 public static MessageWriter
PrepareRecordsetWriter(VxColumnInfo
[] colinfo
,
1065 MessageWriter writer
= new MessageWriter(Connection
.NativeEndianness
);
1067 WriteColInfo(writer
, colinfo
);
1068 if (colinfo
.Length
<= 0)
1070 // Some clients can't parse a() (empty struct) properly, so
1071 // we'll have an empty array of (i) instead.
1072 writer
.Write(typeof(Signature
), new Signature("a(i)"));
1075 writer
.Write(typeof(Signature
), VxColumnInfoToArraySignature(colinfo
));
1076 writer
.WriteDelegatePrependSize(delegate(MessageWriter w
)
1078 WriteStructArray(w
, VxColumnInfoToType(colinfo
), data
);
1080 writer
.Write(typeof(byte[][]), nulldata
);