Arka plan : http://sqlfiddle.com (sitem) üzerinde çalışıyorum ve orada olası bir kötüye kullanım yolunu önlemeye çalışıyorum. Şu anda ele aldığım bir soruyu sorarak umarım potansiyel kötüye kullanımı daha da kötüleştirmiyorum, ama ne yapabilirsiniz? Sana güveniyorum millet.
Herhangi bir kullanıcının belirli bir işlem bloğu içinde açık 'taahhüt' çağrıları yapmasını önlemek istiyorum. SQL Fiddle bağlamından işlem bloğu, sağ taraftaki panelde yürütülen koddur. Temel olarak, döngü ve bir düz metin SQL komutları listesi yürütüyorum ve yaptıkları tüm değişikliklerin toplu işlemin sonunda geri alınmasını sağlamak istiyorum. Normalde, değişiklikleri geri alınır, ancak bazen metin içinde açık bir 'kesin' ifadesi vardır ve bu nedenle geri dönmem işe yaramaz. Bu açık işlem büyük olasılıkla SQL Fiddle'daki şemayı kırmaya çalışan bir kullanıcıdan büyük olasılıkla, üzerinde çalışan diğer insanlar hataları görecektir.
Ana İstenen Sonuç : Mümkünse JDBC düzeyinde açık taahhütleri devre dışı bırakmak istiyorum. Bunun nedeni, birden çok veritabanı arka uç satıcısını desteklemem gerektiğidir ve elbette her birinin düşük düzeyde tuhaflıkları vardır.
Yedek seçenek : JDBC'yi açık taahhütleri devre dışı bırakacak şekilde yapılandırmak mümkün değilse, şu arka uçların her biri için bir toplu işlemi işlerken açık taahhütleri tespit etmek için çözümlere açık olurum: SQL Server, Oracle, MySQL ve PostgreSQL.
SQL Server için, bu çözüm düşündüm: Ben çalıştırmadan önce ifade için XML sorgu planı ayrıştırmak ve bu XPath eşleşen bir giriş olup olmadığını kontrol edin:
//*[@StatementType="COMMIT TRANSACTION"]
Bu SQL Server için oldukça iyi çalışacağını düşünüyorum. Ancak, bu yaklaşım diğer DB türleri için geçerli değildir. Oracle'ın açık taahhütler için XML yürütme planı çıktısı, bir taahhüt ifadesi çalıştırdığınıza (ancak bunun yerine yürüttüğü sorgulardan yürütme planı çıktısını tekrarladığına) gönderme yapmaz. PostgreSQL ve MySQL, açık taahhütler için hiçbir yürütme planı çıktısı (XML veya başka türlü) sağlamaz.
Bu beni "taahhüt" kelimesinin gerçek ifadesini kontrol etmeme bırakıyor. Mümkün olan her türlü varyasyon olabilmesi dışında bu işe yarar:
declare @sql varchar(50)
set @sql = 'com' + 'mit'
exec(@sql);
Yukarıdaki SQL Server (ki ben etrafında çalışabilir) için bir örnektir, ancak Oracle, MySQL ve PostgreSQL için benzer şeyler mümkün olacağını tahmin ediyorum. Bu varsayımda yanlış mıyım? Belki "dinamik" taahhüt ifadelerine izin vermezlerdi? Oracle, MySQL ve PostgreSQL'de benzer bir şey yapıp yapamayacağınızı görmek için SQL Fiddle'ı (tercihen örnek şema veya başka birinin üzerinde çalışması muhtemel değildir) kullanmaktan çekinmeyin. Değilse, belki basit dize algılama bunlar için işe yarayabilir.
Yine başka bir olasılık
Başka bir seçenek bana geldi - bu veritabanlarından herhangi birini salt okunur bir moda ayarlamanın bir yolunu biliyorsanız, bu modda hiçbir şey yapılamaz, bu da işe yarayabilir. Ben hala bu modda hiçbir şey taahhüt edilebilir sürece işlemleri başlatmak ve kod içinde çalışmasına izin gerekir. Mümkün mü?
Güncelleme
Son zamanlarda öğrendiklerim - bu aslında PostgreSQL ile ilgili bir sorun değil. Görünüşe göre bir işlem bloğu içinde verilen taahhütler, aynı blok sonunda geri alınırsa (Postgres'te) uygulanmaz. Postgres için Yaşasın!
Phil'in SO yazısına bağlantısı sayesinde, Oracle'ın sonradan ne olduğumu başarmak için DEFERRABLE INITIALLY DEFERRED hackini kullanabileceğimi düşünüyorum (bir taahhüt verildiyse bir hata atılacak, ancak bunun etrafında çalışabilirim). Bu Oracle'a yönelik olmalıdır. (Bir an için iç içe geçmiş işlemlerin burada işe yarayabileceğini düşündüm, ancak Oracle iç içe geçmiş işlemleri desteklemiyor gibi görünüyor mu? Her neyse, bu şekilde çalışan hiçbir şey bulamadım).
MySQL için henüz bir çözümünüz yok. Yuvalanmış işlemler kullanılarak denendi, ancak bu işe yaramıyor. Ciddi MySQL için bir şey izin vermiyor gibi sağ tarafında SELECTs veya bırakarak / DB her sorgu sonra yeniden oluşturma gibi daha sert yaklaşımlar düşünüyorum. İkisi de kulağa hoş gelmiyor.
çözüm
Şimdi, SQL Server ve Oracle için açıklanan çözümleri uyguladım ve bahsettiğim gibi, bu aslında PostgreSQL için bir sorun değil. MySQL için, sorgu panelini yalnızca ifadeleri seçmekle kısıtlamanın biraz talihsiz bir adımını attım. MySQL için DDL ve DML'nin şema paneline (sol taraf) girilmesi yeterlidir. Umarım bu çok fazla eski işi bozmaz, ancak veri tutarlılığını sağlamak için yapılması gereken şey olduğunu düşünüyorum. Teşekkürler!